mirror of
https://github.com/mimblewimble/grin-wallet.git
synced 2025-01-21 03:21:08 +03:00
Remove callbacks from transaction API functions (#22)
* remove callbacks from transaction creation * rustfmt * add missing functions to owner api rpc * comment fix
This commit is contained in:
parent
baa5e46d7d
commit
8cca9821bd
17 changed files with 300 additions and 180 deletions
|
@ -119,9 +119,7 @@ where
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (_, mut create_fn) =
|
tx::add_output_to_slate(&mut *w, slate, &parent_key_id, 1, message)?;
|
||||||
tx::add_output_to_slate(&mut *w, slate, &parent_key_id, 1, message)?;
|
|
||||||
create_fn(&mut *w, &slate.tx, PhantomData, PhantomData)?;
|
|
||||||
tx::update_message(&mut *w, slate)?;
|
tx::update_message(&mut *w, slate)?;
|
||||||
w.close()?;
|
w.close()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -35,11 +35,10 @@ use crate::core::core::hash::Hashed;
|
||||||
use crate::core::core::Transaction;
|
use crate::core::core::Transaction;
|
||||||
use crate::core::ser;
|
use crate::core::ser;
|
||||||
use crate::keychain::{Identifier, Keychain};
|
use crate::keychain::{Identifier, Keychain};
|
||||||
use crate::libwallet::internal::{keys, tx, updater};
|
use crate::libwallet::internal::{keys, selection, tx, updater};
|
||||||
use crate::libwallet::slate::Slate;
|
use crate::libwallet::slate::Slate;
|
||||||
use crate::libwallet::types::{
|
use crate::libwallet::types::{
|
||||||
AcctPathMapping, NodeClient, OutputData, OutputLockFn, TxLogEntry, TxWrapper, WalletBackend,
|
AcctPathMapping, NodeClient, OutputData, TxLogEntry, TxWrapper, WalletBackend, WalletInfo,
|
||||||
WalletInfo,
|
|
||||||
};
|
};
|
||||||
use crate::libwallet::{Error, ErrorKind};
|
use crate::libwallet::{Error, ErrorKind};
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
@ -625,7 +624,7 @@ where
|
||||||
selection_strategy_is_use_all: bool,
|
selection_strategy_is_use_all: bool,
|
||||||
message: Option<String>,
|
message: Option<String>,
|
||||||
target_slate_version: Option<u16>,
|
target_slate_version: Option<u16>,
|
||||||
) -> Result<(Slate, OutputLockFn<W, C, K>), Error> {
|
) -> Result<Slate, Error> {
|
||||||
let mut w = self.wallet.lock();
|
let mut w = self.wallet.lock();
|
||||||
w.open_with_credentials()?;
|
w.open_with_credentials()?;
|
||||||
let parent_key_id = match src_acct_name {
|
let parent_key_id = match src_acct_name {
|
||||||
|
@ -649,7 +648,7 @@ where
|
||||||
|
|
||||||
let mut slate = tx::new_tx_slate(&mut *w, amount, 2)?;
|
let mut slate = tx::new_tx_slate(&mut *w, amount, 2)?;
|
||||||
|
|
||||||
let (context, lock_fn) = tx::add_inputs_to_slate(
|
let context = tx::add_inputs_to_slate(
|
||||||
&mut *w,
|
&mut *w,
|
||||||
&mut slate,
|
&mut slate,
|
||||||
minimum_confirmations,
|
minimum_confirmations,
|
||||||
|
@ -674,7 +673,7 @@ where
|
||||||
if let Some(v) = target_slate_version {
|
if let Some(v) = target_slate_version {
|
||||||
slate.version_info.orig_version = v;
|
slate.version_info.orig_version = v;
|
||||||
}
|
}
|
||||||
Ok((slate, lock_fn))
|
Ok(slate)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Estimates the amount to be locked and fee for the transaction without creating one
|
/// Estimates the amount to be locked and fee for the transaction without creating one
|
||||||
|
@ -746,14 +745,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lock outputs associated with a given slate/transaction
|
/// Lock outputs associated with a given slate/transaction
|
||||||
pub fn tx_lock_outputs(
|
/// and create any outputs needed
|
||||||
&self,
|
pub fn tx_lock_outputs(&self, slate: &Slate) -> Result<(), Error> {
|
||||||
slate: &Slate,
|
|
||||||
mut lock_fn: OutputLockFn<W, C, K>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mut w = self.wallet.lock();
|
let mut w = self.wallet.lock();
|
||||||
w.open_with_credentials()?;
|
w.open_with_credentials()?;
|
||||||
lock_fn(&mut *w, &slate.tx, PhantomData, PhantomData)?;
|
let context = w.get_private_context(slate.id.as_bytes())?;
|
||||||
|
w.open_with_credentials()?;
|
||||||
|
selection::lock_tx_context(&mut *w, slate, &context)?;
|
||||||
|
w.close()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
//! JSON-RPC Stub generation for the Foreign API
|
//! JSON-RPC Stub generation for the Owner API
|
||||||
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -202,6 +202,42 @@ pub trait OwnerRpc {
|
||||||
minimum_confirmations: u64,
|
minimum_confirmations: u64,
|
||||||
) -> Result<(bool, WalletInfo), ErrorKind>;
|
) -> Result<(bool, WalletInfo), ErrorKind>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Networked version of [Owner::estimate_initiate_tx](struct.Owner.html#method.initiate_tx).
|
||||||
|
|
||||||
|
```
|
||||||
|
# grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!(
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "initiate_tx",
|
||||||
|
"params": [null, 0, 0, 10, 0, false, "my message", null],
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": {
|
||||||
|
"Err": {
|
||||||
|
"CallbackImpl": "Error opening wallet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
# );
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
|
||||||
|
fn initiate_tx(
|
||||||
|
&self,
|
||||||
|
src_acct_name: Option<String>,
|
||||||
|
amount: u64,
|
||||||
|
minimum_confirmations: u64,
|
||||||
|
max_outputs: usize,
|
||||||
|
num_change_outputs: usize,
|
||||||
|
selection_strategy_is_use_all: bool,
|
||||||
|
message: Option<String>,
|
||||||
|
target_slate_version: Option<u16>,
|
||||||
|
) -> Result<Slate, ErrorKind>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Networked version of [Owner::estimate_initiate_tx](struct.Owner.html#method.estimate_initiate_tx).
|
Networked version of [Owner::estimate_initiate_tx](struct.Owner.html#method.estimate_initiate_tx).
|
||||||
|
|
||||||
|
@ -236,6 +272,53 @@ pub trait OwnerRpc {
|
||||||
selection_strategy_is_use_all: bool,
|
selection_strategy_is_use_all: bool,
|
||||||
) -> Result<(/* total */ u64, /* fee */ u64), ErrorKind>;
|
) -> Result<(/* total */ u64, /* fee */ u64), ErrorKind>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Networked version of [Owner::tx_lock_outputs](struct.Owner.html#method.tx_lock_outputs).
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
# grin_wallet_api::doctest_helper_json_rpc_owner_assert_response!(
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "tx_lock_outputs",
|
||||||
|
"params": [{
|
||||||
|
"version_info": {
|
||||||
|
"version": 2,
|
||||||
|
"orig_version": 2,
|
||||||
|
"min_compat_version": 0
|
||||||
|
},
|
||||||
|
"amount": 0,
|
||||||
|
"fee": 0,
|
||||||
|
"height": 0,
|
||||||
|
"id": "414bad48-3386-4fa7-8483-72384c886ba3",
|
||||||
|
"lock_height": 0,
|
||||||
|
"num_participants": 2,
|
||||||
|
"participant_data": [],
|
||||||
|
"tx": {
|
||||||
|
"body": {
|
||||||
|
"inputs": [],
|
||||||
|
"kernels": [],
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
"offset": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"result": {
|
||||||
|
"Err": {
|
||||||
|
"CallbackImpl": "Error opening wallet"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
# );
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
fn tx_lock_outputs(&self, slate: Slate) -> Result<(), ErrorKind>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Networked version of [Owner::finalize_tx](struct.Owner.html#method.finalize_tx).
|
Networked version of [Owner::finalize_tx](struct.Owner.html#method.finalize_tx).
|
||||||
|
|
||||||
|
@ -555,6 +638,31 @@ where
|
||||||
.map_err(|e| e.kind())
|
.map_err(|e| e.kind())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn initiate_tx(
|
||||||
|
&self,
|
||||||
|
src_acct_name: Option<String>,
|
||||||
|
amount: u64,
|
||||||
|
minimum_confirmations: u64,
|
||||||
|
max_outputs: usize,
|
||||||
|
num_change_outputs: usize,
|
||||||
|
selection_strategy_is_use_all: bool,
|
||||||
|
message: Option<String>,
|
||||||
|
target_slate_version: Option<u16>,
|
||||||
|
) -> Result<Slate, ErrorKind> {
|
||||||
|
Owner::initiate_tx(
|
||||||
|
self,
|
||||||
|
src_acct_name.as_ref().map(String::as_str),
|
||||||
|
amount,
|
||||||
|
minimum_confirmations,
|
||||||
|
max_outputs,
|
||||||
|
num_change_outputs,
|
||||||
|
selection_strategy_is_use_all,
|
||||||
|
message,
|
||||||
|
target_slate_version,
|
||||||
|
)
|
||||||
|
.map_err(|e| e.kind())
|
||||||
|
}
|
||||||
|
|
||||||
fn estimate_initiate_tx(
|
fn estimate_initiate_tx(
|
||||||
&self,
|
&self,
|
||||||
src_acct_name: Option<String>,
|
src_acct_name: Option<String>,
|
||||||
|
@ -581,6 +689,10 @@ where
|
||||||
Ok(slate)
|
Ok(slate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tx_lock_outputs(&self, mut slate: Slate) -> Result<(), ErrorKind> {
|
||||||
|
Owner::tx_lock_outputs(self, &mut slate).map_err(|e| e.kind())
|
||||||
|
}
|
||||||
|
|
||||||
fn cancel_tx(&self, tx_id: Option<u32>, tx_slate_id: Option<Uuid>) -> Result<(), ErrorKind> {
|
fn cancel_tx(&self, tx_id: Option<u32>, tx_slate_id: Option<Uuid>) -> Result<(), ErrorKind> {
|
||||||
Owner::cancel_tx(self, tx_id, tx_slate_id).map_err(|e| e.kind())
|
Owner::cancel_tx(self, tx_id, tx_slate_id).map_err(|e| e.kind())
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
//! Selection of inputs for building transactions
|
//! Selection of inputs for building transactions
|
||||||
|
|
||||||
use crate::core::core::{amount_to_hr_string, Transaction};
|
use crate::core::core::amount_to_hr_string;
|
||||||
use crate::core::libtx::{build, tx_fee};
|
use crate::core::libtx::{build, tx_fee};
|
||||||
use crate::error::{Error, ErrorKind};
|
use crate::error::{Error, ErrorKind};
|
||||||
use crate::internal::keys;
|
use crate::internal::keys;
|
||||||
|
@ -22,7 +22,6 @@ use crate::keychain::{Identifier, Keychain};
|
||||||
use crate::slate::Slate;
|
use crate::slate::Slate;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
/// Initialize a transaction on the sender side, returns a corresponding
|
/// Initialize a transaction on the sender side, returns a corresponding
|
||||||
/// libwallet transaction slate with the appropriate inputs selected,
|
/// libwallet transaction slate with the appropriate inputs selected,
|
||||||
|
@ -37,7 +36,7 @@ pub fn build_send_tx<T: ?Sized, C, K>(
|
||||||
change_outputs: usize,
|
change_outputs: usize,
|
||||||
selection_strategy_is_use_all: bool,
|
selection_strategy_is_use_all: bool,
|
||||||
parent_key_id: Identifier,
|
parent_key_id: Identifier,
|
||||||
) -> Result<(Context, OutputLockFn<T, C, K>), Error>
|
) -> Result<Context, Error>
|
||||||
where
|
where
|
||||||
T: WalletBackend<C, K>,
|
T: WalletBackend<C, K>,
|
||||||
C: NodeClient,
|
C: NodeClient,
|
||||||
|
@ -64,87 +63,104 @@ where
|
||||||
let mut context = Context::new(
|
let mut context = Context::new(
|
||||||
wallet.keychain().secp(),
|
wallet.keychain().secp(),
|
||||||
blinding.secret_key(&keychain.secp()).unwrap(),
|
blinding.secret_key(&keychain.secp()).unwrap(),
|
||||||
|
&parent_key_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
context.fee = fee;
|
||||||
|
|
||||||
// Store our private identifiers for each input
|
// Store our private identifiers for each input
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
context.add_input(&input.key_id, &input.mmr_index);
|
context.add_input(&input.key_id, &input.mmr_index, input.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut commits: HashMap<Identifier, Option<String>> = HashMap::new();
|
let mut commits: HashMap<Identifier, Option<String>> = HashMap::new();
|
||||||
|
|
||||||
// Store change output(s) and cached commits
|
// Store change output(s) and cached commits
|
||||||
for (change_amount, id, mmr_index) in &change_amounts_derivations {
|
for (change_amount, id, mmr_index) in &change_amounts_derivations {
|
||||||
context.add_output(&id, &mmr_index);
|
context.add_output(&id, &mmr_index, *change_amount);
|
||||||
commits.insert(
|
commits.insert(
|
||||||
id.clone(),
|
id.clone(),
|
||||||
wallet.calc_commit_for_cache(*change_amount, &id)?,
|
wallet.calc_commit_for_cache(*change_amount, &id)?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lock_inputs_in = context.get_inputs().clone();
|
Ok(context)
|
||||||
let _lock_outputs = context.get_outputs().clone();
|
}
|
||||||
let messages_in = Some(slate.participant_messages());
|
|
||||||
let slate_id_in = slate.id.clone();
|
|
||||||
let height_in = slate.height;
|
|
||||||
|
|
||||||
// Return a closure to acquire wallet lock and lock the coins being spent
|
/// Locks all corresponding outputs in the context, creates
|
||||||
// so we avoid accidental double spend attempt.
|
/// change outputs and tx log entry
|
||||||
let update_sender_wallet_fn =
|
pub fn lock_tx_context<T: ?Sized, C, K>(
|
||||||
move |wallet: &mut T, tx: &Transaction, _: PhantomData<C>, _: PhantomData<K>| {
|
wallet: &mut T,
|
||||||
let tx_entry = {
|
slate: &Slate,
|
||||||
// These ensure the closure remains FnMut
|
context: &Context,
|
||||||
let lock_inputs = lock_inputs_in.clone();
|
) -> Result<(), Error>
|
||||||
let messages = messages_in.clone();
|
where
|
||||||
let slate_id = slate_id_in.clone();
|
T: WalletBackend<C, K>,
|
||||||
let height = height_in.clone();
|
C: NodeClient,
|
||||||
let mut batch = wallet.batch()?;
|
K: Keychain,
|
||||||
let log_id = batch.next_tx_log_id(&parent_key_id)?;
|
{
|
||||||
let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxSent, log_id);
|
let mut output_commits: HashMap<Identifier, (Option<String>, u64)> = HashMap::new();
|
||||||
t.tx_slate_id = Some(slate_id.clone());
|
// Store cached commits before locking wallet
|
||||||
let filename = format!("{}.grintx", slate_id);
|
for (id, _, change_amount) in &context.get_outputs() {
|
||||||
t.stored_tx = Some(filename);
|
output_commits.insert(
|
||||||
t.fee = Some(fee);
|
id.clone(),
|
||||||
let mut amount_debited = 0;
|
(
|
||||||
t.num_inputs = lock_inputs.len();
|
wallet.calc_commit_for_cache(*change_amount, &id)?,
|
||||||
for id in lock_inputs {
|
*change_amount,
|
||||||
let mut coin = batch.get(&id.0, &id.1).unwrap();
|
),
|
||||||
coin.tx_log_entry = Some(log_id);
|
);
|
||||||
amount_debited = amount_debited + coin.value;
|
}
|
||||||
batch.lock_output(&mut coin)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
t.amount_debited = amount_debited;
|
let tx_entry = {
|
||||||
t.messages = messages;
|
let lock_inputs = context.get_inputs().clone();
|
||||||
|
let messages = Some(slate.participant_messages());
|
||||||
|
let slate_id = slate.id;
|
||||||
|
let height = slate.height;
|
||||||
|
let parent_key_id = context.parent_key_id.clone();
|
||||||
|
let mut batch = wallet.batch()?;
|
||||||
|
let log_id = batch.next_tx_log_id(&parent_key_id)?;
|
||||||
|
let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxSent, log_id);
|
||||||
|
t.tx_slate_id = Some(slate_id.clone());
|
||||||
|
let filename = format!("{}.grintx", slate_id);
|
||||||
|
t.stored_tx = Some(filename);
|
||||||
|
t.fee = Some(slate.fee);
|
||||||
|
let mut amount_debited = 0;
|
||||||
|
t.num_inputs = lock_inputs.len();
|
||||||
|
for id in lock_inputs {
|
||||||
|
let mut coin = batch.get(&id.0, &id.1).unwrap();
|
||||||
|
coin.tx_log_entry = Some(log_id);
|
||||||
|
amount_debited = amount_debited + coin.value;
|
||||||
|
batch.lock_output(&mut coin)?;
|
||||||
|
}
|
||||||
|
|
||||||
// write the output representing our change
|
t.amount_debited = amount_debited;
|
||||||
for (change_amount, id, _) in &change_amounts_derivations {
|
t.messages = messages;
|
||||||
t.num_outputs += 1;
|
|
||||||
t.amount_credited += change_amount;
|
|
||||||
let commit = commits.get(&id).unwrap().clone();
|
|
||||||
batch.save(OutputData {
|
|
||||||
root_key_id: parent_key_id.clone(),
|
|
||||||
key_id: id.clone(),
|
|
||||||
n_child: id.to_path().last_path_index(),
|
|
||||||
commit: commit,
|
|
||||||
mmr_index: None,
|
|
||||||
value: change_amount.clone(),
|
|
||||||
status: OutputStatus::Unconfirmed,
|
|
||||||
height: height,
|
|
||||||
lock_height: 0,
|
|
||||||
is_coinbase: false,
|
|
||||||
tx_log_entry: Some(log_id),
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
batch.save_tx_log_entry(t.clone(), &parent_key_id)?;
|
|
||||||
batch.commit()?;
|
|
||||||
t
|
|
||||||
};
|
|
||||||
wallet.store_tx(&format!("{}", tx_entry.tx_slate_id.unwrap()), tx)?;
|
|
||||||
Ok(())
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((context, Box::new(update_sender_wallet_fn)))
|
// write the output representing our change
|
||||||
|
for (id, _, _) in &context.get_outputs() {
|
||||||
|
t.num_outputs += 1;
|
||||||
|
let (commit, change_amount) = output_commits.get(&id).unwrap().clone();
|
||||||
|
t.amount_credited += change_amount;
|
||||||
|
batch.save(OutputData {
|
||||||
|
root_key_id: parent_key_id.clone(),
|
||||||
|
key_id: id.clone(),
|
||||||
|
n_child: id.to_path().last_path_index(),
|
||||||
|
commit: commit,
|
||||||
|
mmr_index: None,
|
||||||
|
value: change_amount.clone(),
|
||||||
|
status: OutputStatus::Unconfirmed,
|
||||||
|
height: height,
|
||||||
|
lock_height: 0,
|
||||||
|
is_coinbase: false,
|
||||||
|
tx_log_entry: Some(log_id),
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
batch.save_tx_log_entry(t.clone(), &parent_key_id)?;
|
||||||
|
batch.commit()?;
|
||||||
|
t
|
||||||
|
};
|
||||||
|
wallet.store_tx(&format!("{}", tx_entry.tx_slate_id.unwrap()), &slate.tx)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new output in the wallet for the recipient,
|
/// Creates a new output in the wallet for the recipient,
|
||||||
|
@ -155,7 +171,7 @@ pub fn build_recipient_output<T: ?Sized, C, K>(
|
||||||
wallet: &mut T,
|
wallet: &mut T,
|
||||||
slate: &mut Slate,
|
slate: &mut Slate,
|
||||||
parent_key_id: Identifier,
|
parent_key_id: Identifier,
|
||||||
) -> Result<(Identifier, Context, OutputLockFn<T, C, K>), Error>
|
) -> Result<(Identifier, Context), Error>
|
||||||
where
|
where
|
||||||
T: WalletBackend<C, K>,
|
T: WalletBackend<C, K>,
|
||||||
C: NodeClient,
|
C: NodeClient,
|
||||||
|
@ -179,45 +195,36 @@ where
|
||||||
blinding
|
blinding
|
||||||
.secret_key(wallet.keychain().clone().secp())
|
.secret_key(wallet.keychain().clone().secp())
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
&parent_key_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
context.add_output(&key_id, &None);
|
context.add_output(&key_id, &None, amount);
|
||||||
let messages_in = Some(slate.participant_messages());
|
let messages = Some(slate.participant_messages());
|
||||||
|
let commit = wallet.calc_commit_for_cache(amount, &key_id_inner)?;
|
||||||
|
let mut batch = wallet.batch()?;
|
||||||
|
let log_id = batch.next_tx_log_id(&parent_key_id)?;
|
||||||
|
let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxReceived, log_id);
|
||||||
|
t.tx_slate_id = Some(slate_id);
|
||||||
|
t.amount_credited = amount;
|
||||||
|
t.num_outputs = 1;
|
||||||
|
t.messages = messages;
|
||||||
|
batch.save(OutputData {
|
||||||
|
root_key_id: parent_key_id.clone(),
|
||||||
|
key_id: key_id_inner.clone(),
|
||||||
|
mmr_index: None,
|
||||||
|
n_child: key_id_inner.to_path().last_path_index(),
|
||||||
|
commit: commit,
|
||||||
|
value: amount,
|
||||||
|
status: OutputStatus::Unconfirmed,
|
||||||
|
height: height,
|
||||||
|
lock_height: 0,
|
||||||
|
is_coinbase: false,
|
||||||
|
tx_log_entry: Some(log_id),
|
||||||
|
})?;
|
||||||
|
batch.save_tx_log_entry(t, &parent_key_id)?;
|
||||||
|
batch.commit()?;
|
||||||
|
|
||||||
// Create closure that adds the output to recipient's wallet
|
Ok((key_id, context))
|
||||||
// (up to the caller to decide when to do)
|
|
||||||
let wallet_add_fn =
|
|
||||||
move |wallet: &mut T, _tx: &Transaction, _: PhantomData<C>, _: PhantomData<K>| {
|
|
||||||
// Ensure closure remains FnMut
|
|
||||||
let messages = messages_in.clone();
|
|
||||||
let commit = wallet.calc_commit_for_cache(amount, &key_id_inner)?;
|
|
||||||
let mut batch = wallet.batch()?;
|
|
||||||
let log_id = batch.next_tx_log_id(&parent_key_id)?;
|
|
||||||
let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxReceived, log_id);
|
|
||||||
t.tx_slate_id = Some(slate_id);
|
|
||||||
t.amount_credited = amount;
|
|
||||||
t.num_outputs = 1;
|
|
||||||
t.messages = messages;
|
|
||||||
batch.save(OutputData {
|
|
||||||
root_key_id: parent_key_id.clone(),
|
|
||||||
key_id: key_id_inner.clone(),
|
|
||||||
mmr_index: None,
|
|
||||||
n_child: key_id_inner.to_path().last_path_index(),
|
|
||||||
commit: commit,
|
|
||||||
value: amount,
|
|
||||||
status: OutputStatus::Unconfirmed,
|
|
||||||
height: height,
|
|
||||||
lock_height: 0,
|
|
||||||
is_coinbase: false,
|
|
||||||
tx_log_entry: Some(log_id),
|
|
||||||
})?;
|
|
||||||
batch.save_tx_log_entry(t, &parent_key_id)?;
|
|
||||||
batch.commit()?;
|
|
||||||
//TODO: Check whether we want to call this
|
|
||||||
//wallet.store_tx(&format!("{}", t.tx_slate_id.unwrap()), tx)?;
|
|
||||||
Ok(())
|
|
||||||
};
|
|
||||||
Ok((key_id, context, Box::new(wallet_add_fn)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a transaction to send to someone from the HD seed associated with the
|
/// Builds a transaction to send to someone from the HD seed associated with the
|
||||||
|
|
|
@ -19,7 +19,7 @@ use uuid::Uuid;
|
||||||
use crate::internal::{selection, updater};
|
use crate::internal::{selection, updater};
|
||||||
use crate::keychain::{Identifier, Keychain};
|
use crate::keychain::{Identifier, Keychain};
|
||||||
use crate::slate::Slate;
|
use crate::slate::Slate;
|
||||||
use crate::types::{Context, NodeClient, OutputLockFn, TxLogEntryType, WalletBackend};
|
use crate::types::{Context, NodeClient, TxLogEntryType, WalletBackend};
|
||||||
use crate::{Error, ErrorKind};
|
use crate::{Error, ErrorKind};
|
||||||
|
|
||||||
/// Creates a new slate for a transaction, can be called by anyone involved in
|
/// Creates a new slate for a transaction, can be called by anyone involved in
|
||||||
|
@ -99,7 +99,7 @@ pub fn add_inputs_to_slate<T: ?Sized, C, K>(
|
||||||
parent_key_id: &Identifier,
|
parent_key_id: &Identifier,
|
||||||
participant_id: usize,
|
participant_id: usize,
|
||||||
message: Option<String>,
|
message: Option<String>,
|
||||||
) -> Result<(Context, OutputLockFn<T, C, K>), Error>
|
) -> Result<Context, Error>
|
||||||
where
|
where
|
||||||
T: WalletBackend<C, K>,
|
T: WalletBackend<C, K>,
|
||||||
C: NodeClient,
|
C: NodeClient,
|
||||||
|
@ -115,7 +115,7 @@ where
|
||||||
// according to plan
|
// according to plan
|
||||||
// This function is just a big helper to do all of that, in theory
|
// This function is just a big helper to do all of that, in theory
|
||||||
// this process can be split up in any way
|
// this process can be split up in any way
|
||||||
let (mut context, sender_lock_fn) = selection::build_send_tx(
|
let mut context = selection::build_send_tx(
|
||||||
wallet,
|
wallet,
|
||||||
slate,
|
slate,
|
||||||
minimum_confirmations,
|
minimum_confirmations,
|
||||||
|
@ -136,7 +136,7 @@ where
|
||||||
message,
|
message,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok((context, sender_lock_fn))
|
Ok(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add outputs to the slate, becoming the recipient
|
/// Add outputs to the slate, becoming the recipient
|
||||||
|
@ -146,15 +146,14 @@ pub fn add_output_to_slate<T: ?Sized, C, K>(
|
||||||
parent_key_id: &Identifier,
|
parent_key_id: &Identifier,
|
||||||
participant_id: usize,
|
participant_id: usize,
|
||||||
message: Option<String>,
|
message: Option<String>,
|
||||||
) -> Result<(Context, OutputLockFn<T, C, K>), Error>
|
) -> Result<Context, Error>
|
||||||
where
|
where
|
||||||
T: WalletBackend<C, K>,
|
T: WalletBackend<C, K>,
|
||||||
C: NodeClient,
|
C: NodeClient,
|
||||||
K: Keychain,
|
K: Keychain,
|
||||||
{
|
{
|
||||||
// create an output using the amount in the slate
|
// create an output using the amount in the slate
|
||||||
let (_, mut context, create_fn) =
|
let (_, mut context) = selection::build_recipient_output(wallet, slate, parent_key_id.clone())?;
|
||||||
selection::build_recipient_output(wallet, slate, parent_key_id.clone())?;
|
|
||||||
|
|
||||||
// fill public keys
|
// fill public keys
|
||||||
let _ = slate.fill_round_1(
|
let _ = slate.fill_round_1(
|
||||||
|
@ -173,7 +172,7 @@ where
|
||||||
participant_id,
|
participant_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok((context, create_fn))
|
Ok(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Complete a transaction as the sender
|
/// Complete a transaction as the sender
|
||||||
|
|
|
@ -30,13 +30,8 @@ use serde;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
/// Lock function type
|
|
||||||
pub type OutputLockFn<T, C, K> =
|
|
||||||
Box<dyn FnMut(&mut T, &Transaction, PhantomData<C>, PhantomData<K>) -> Result<(), Error>>;
|
|
||||||
|
|
||||||
/// Combined trait to allow dynamic wallet dispatch
|
/// Combined trait to allow dynamic wallet dispatch
|
||||||
pub trait WalletInst<C, K>: WalletBackend<C, K> + Send + Sync + 'static
|
pub trait WalletInst<C, K>: WalletBackend<C, K> + Send + Sync + 'static
|
||||||
where
|
where
|
||||||
|
@ -377,23 +372,28 @@ impl fmt::Display for OutputStatus {
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
/// Holds the context for a single aggsig transaction
|
/// Holds the context for a single aggsig transaction
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
|
/// Parent key id
|
||||||
|
pub parent_key_id: Identifier,
|
||||||
/// Secret key (of which public is shared)
|
/// Secret key (of which public is shared)
|
||||||
pub sec_key: SecretKey,
|
pub sec_key: SecretKey,
|
||||||
/// Secret nonce (of which public is shared)
|
/// Secret nonce (of which public is shared)
|
||||||
/// (basically a SecretKey)
|
/// (basically a SecretKey)
|
||||||
pub sec_nonce: SecretKey,
|
pub sec_nonce: SecretKey,
|
||||||
/// store my outputs between invocations
|
/// store my outputs + amounts between invocations
|
||||||
pub output_ids: Vec<(Identifier, Option<u64>)>,
|
/// Id, mmr_index (if known), amount
|
||||||
|
pub output_ids: Vec<(Identifier, Option<u64>, u64)>,
|
||||||
/// store my inputs
|
/// store my inputs
|
||||||
pub input_ids: Vec<(Identifier, Option<u64>)>,
|
/// Id, mmr_index (if known), amount
|
||||||
|
pub input_ids: Vec<(Identifier, Option<u64>, u64)>,
|
||||||
/// store the calculated fee
|
/// store the calculated fee
|
||||||
pub fee: u64,
|
pub fee: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Create a new context with defaults
|
/// Create a new context with defaults
|
||||||
pub fn new(secp: &secp::Secp256k1, sec_key: SecretKey) -> Context {
|
pub fn new(secp: &secp::Secp256k1, sec_key: SecretKey, parent_key_id: &Identifier) -> Context {
|
||||||
Context {
|
Context {
|
||||||
|
parent_key_id: parent_key_id.clone(),
|
||||||
sec_key: sec_key,
|
sec_key: sec_key,
|
||||||
sec_nonce: aggsig::create_secnonce(secp).unwrap(),
|
sec_nonce: aggsig::create_secnonce(secp).unwrap(),
|
||||||
input_ids: vec![],
|
input_ids: vec![],
|
||||||
|
@ -406,23 +406,25 @@ impl Context {
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Tracks an output contributing to my excess value (if it needs to
|
/// Tracks an output contributing to my excess value (if it needs to
|
||||||
/// be kept between invocations
|
/// be kept between invocations
|
||||||
pub fn add_output(&mut self, output_id: &Identifier, mmr_index: &Option<u64>) {
|
pub fn add_output(&mut self, output_id: &Identifier, mmr_index: &Option<u64>, amount: u64) {
|
||||||
self.output_ids.push((output_id.clone(), mmr_index.clone()));
|
self.output_ids
|
||||||
|
.push((output_id.clone(), mmr_index.clone(), amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all stored outputs
|
/// Returns all stored outputs
|
||||||
pub fn get_outputs(&self) -> Vec<(Identifier, Option<u64>)> {
|
pub fn get_outputs(&self) -> Vec<(Identifier, Option<u64>, u64)> {
|
||||||
self.output_ids.clone()
|
self.output_ids.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tracks IDs of my inputs into the transaction
|
/// Tracks IDs of my inputs into the transaction
|
||||||
/// be kept between invocations
|
/// be kept between invocations
|
||||||
pub fn add_input(&mut self, input_id: &Identifier, mmr_index: &Option<u64>) {
|
pub fn add_input(&mut self, input_id: &Identifier, mmr_index: &Option<u64>, amount: u64) {
|
||||||
self.input_ids.push((input_id.clone(), mmr_index.clone()));
|
self.input_ids
|
||||||
|
.push((input_id.clone(), mmr_index.clone(), amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all stored input identifiers
|
/// Returns all stored input identifiers
|
||||||
pub fn get_inputs(&self) -> Vec<(Identifier, Option<u64>)> {
|
pub fn get_inputs(&self) -> Vec<(Identifier, Option<u64>, u64)> {
|
||||||
self.input_ids.clone()
|
self.input_ids.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
//! core::libtx specific tests
|
//! core::libtx specific tests
|
||||||
use self::core::core::transaction;
|
use self::core::core::transaction;
|
||||||
use self::core::libtx::{aggsig, proof};
|
use self::core::libtx::{aggsig, proof};
|
||||||
use self::keychain::{BlindSum, BlindingFactor, ExtKeychain, Keychain};
|
use self::keychain::{BlindSum, BlindingFactor, ExtKeychain, ExtKeychainPath, Keychain};
|
||||||
use self::util::secp;
|
use self::util::secp;
|
||||||
use self::util::secp::key::{PublicKey, SecretKey};
|
use self::util::secp::key::{PublicKey, SecretKey};
|
||||||
use grin_core as core;
|
use grin_core as core;
|
||||||
|
@ -29,6 +29,7 @@ fn kernel_sig_msg() -> secp::Message {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn aggsig_sender_receiver_interaction() {
|
fn aggsig_sender_receiver_interaction() {
|
||||||
|
let parent = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();
|
||||||
let sender_keychain = ExtKeychain::from_random_seed(true).unwrap();
|
let sender_keychain = ExtKeychain::from_random_seed(true).unwrap();
|
||||||
let receiver_keychain = ExtKeychain::from_random_seed(true).unwrap();
|
let receiver_keychain = ExtKeychain::from_random_seed(true).unwrap();
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ fn aggsig_sender_receiver_interaction() {
|
||||||
|
|
||||||
let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
|
let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
|
||||||
|
|
||||||
s_cx = Context::new(&keychain.secp(), blind);
|
s_cx = Context::new(&keychain.secp(), blind, &parent);
|
||||||
s_cx.get_public_keys(&keychain.secp())
|
s_cx.get_public_keys(&keychain.secp())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,9 +86,9 @@ fn aggsig_sender_receiver_interaction() {
|
||||||
// let blind = blind_sum.secret_key(&keychain.secp())?;
|
// let blind = blind_sum.secret_key(&keychain.secp())?;
|
||||||
let blind = keychain.derive_key(0, &key_id).unwrap();
|
let blind = keychain.derive_key(0, &key_id).unwrap();
|
||||||
|
|
||||||
rx_cx = Context::new(&keychain.secp(), blind);
|
rx_cx = Context::new(&keychain.secp(), blind, &parent);
|
||||||
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
|
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
|
||||||
rx_cx.add_output(&key_id, &None);
|
rx_cx.add_output(&key_id, &None, 0);
|
||||||
|
|
||||||
pub_nonce_sum = PublicKey::from_combination(
|
pub_nonce_sum = PublicKey::from_combination(
|
||||||
keychain.secp(),
|
keychain.secp(),
|
||||||
|
@ -233,6 +234,7 @@ fn aggsig_sender_receiver_interaction() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn aggsig_sender_receiver_interaction_offset() {
|
fn aggsig_sender_receiver_interaction_offset() {
|
||||||
|
let parent = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();
|
||||||
let sender_keychain = ExtKeychain::from_random_seed(true).unwrap();
|
let sender_keychain = ExtKeychain::from_random_seed(true).unwrap();
|
||||||
let receiver_keychain = ExtKeychain::from_random_seed(true).unwrap();
|
let receiver_keychain = ExtKeychain::from_random_seed(true).unwrap();
|
||||||
|
|
||||||
|
@ -288,7 +290,7 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||||
|
|
||||||
let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
|
let blind = blinding_factor.secret_key(&keychain.secp()).unwrap();
|
||||||
|
|
||||||
s_cx = Context::new(&keychain.secp(), blind);
|
s_cx = Context::new(&keychain.secp(), blind, &parent);
|
||||||
s_cx.get_public_keys(&keychain.secp())
|
s_cx.get_public_keys(&keychain.secp())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -301,9 +303,9 @@ fn aggsig_sender_receiver_interaction_offset() {
|
||||||
|
|
||||||
let blind = keychain.derive_key(0, &key_id).unwrap();
|
let blind = keychain.derive_key(0, &key_id).unwrap();
|
||||||
|
|
||||||
rx_cx = Context::new(&keychain.secp(), blind);
|
rx_cx = Context::new(&keychain.secp(), blind, &parent);
|
||||||
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
|
let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp());
|
||||||
rx_cx.add_output(&key_id, &None);
|
rx_cx.add_output(&key_id, &None, 0);
|
||||||
|
|
||||||
pub_nonce_sum = PublicKey::from_combination(
|
pub_nonce_sum = PublicKey::from_combination(
|
||||||
keychain.secp(),
|
keychain.secp(),
|
||||||
|
|
|
@ -244,7 +244,7 @@ pub fn send(
|
||||||
args.message.clone(),
|
args.message.clone(),
|
||||||
args.target_slate_version,
|
args.target_slate_version,
|
||||||
);
|
);
|
||||||
let (mut slate, lock_fn) = match result {
|
let mut slate = match result {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
info!(
|
info!(
|
||||||
"Tx created: {} grin to {} (strategy '{}')",
|
"Tx created: {} grin to {} (strategy '{}')",
|
||||||
|
@ -268,7 +268,7 @@ pub fn send(
|
||||||
};
|
};
|
||||||
if adapter.supports_sync() {
|
if adapter.supports_sync() {
|
||||||
slate = adapter.send_tx_sync(&args.dest, &slate)?;
|
slate = adapter.send_tx_sync(&args.dest, &slate)?;
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
if args.method == "self" {
|
if args.method == "self" {
|
||||||
controller::foreign_single_use(wallet, |api| {
|
controller::foreign_single_use(wallet, |api| {
|
||||||
api.receive_tx(&mut slate, Some(&args.dest), None)?;
|
api.receive_tx(&mut slate, Some(&args.dest), None)?;
|
||||||
|
@ -282,7 +282,7 @@ pub fn send(
|
||||||
api.finalize_tx(&mut slate)?;
|
api.finalize_tx(&mut slate)?;
|
||||||
} else {
|
} else {
|
||||||
adapter.send_tx_async(&args.dest, &slate)?;
|
adapter.send_tx_async(&args.dest, &slate)?;
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
}
|
}
|
||||||
if adapter.supports_sync() {
|
if adapter.supports_sync() {
|
||||||
let result = api.post_tx(&slate.tx, args.fluff);
|
let result = api.post_tx(&slate.tx, args.fluff);
|
||||||
|
|
|
@ -331,7 +331,7 @@ where
|
||||||
args.message,
|
args.message,
|
||||||
args.target_slate_version,
|
args.target_slate_version,
|
||||||
);
|
);
|
||||||
let (mut slate, lock_fn) = match result {
|
let mut slate = match result {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
info!(
|
info!(
|
||||||
"Tx created: {} grin to {} (strategy '{}')",
|
"Tx created: {} grin to {} (strategy '{}')",
|
||||||
|
@ -371,7 +371,7 @@ where
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
if args.method != "file" {
|
if args.method != "file" {
|
||||||
api.finalize_tx(&mut slate)?;
|
api.finalize_tx(&mut slate)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ where
|
||||||
C: NodeClient,
|
C: NodeClient,
|
||||||
K: keychain::Keychain,
|
K: keychain::Keychain,
|
||||||
{
|
{
|
||||||
let (slate_i, lock_fn) = api.initiate_tx(
|
let slate_i = api.initiate_tx(
|
||||||
None, // account
|
None, // account
|
||||||
amount, // amount
|
amount, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -204,7 +204,7 @@ where
|
||||||
None, None,
|
None, None,
|
||||||
)?;
|
)?;
|
||||||
let mut slate = client.send_tx_slate_direct(dest, &slate_i)?;
|
let mut slate = client.send_tx_slate_direct(dest, &slate_i)?;
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
api.finalize_tx(&mut slate)?;
|
api.finalize_tx(&mut slate)?;
|
||||||
api.post_tx(&slate.tx, false)?; // mines a block
|
api.post_tx(&slate.tx, false)?; // mines a block
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -177,7 +177,7 @@ fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
let (mut slate, lock_fn) = api.initiate_tx(
|
let mut slate = api.initiate_tx(
|
||||||
None, reward, // amount
|
None, reward, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
500, // max outputs
|
500, // max outputs
|
||||||
|
@ -186,7 +186,7 @@ fn accounts_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None, None,
|
None, None,
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate)?;
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
api.finalize_tx(&mut slate)?;
|
api.finalize_tx(&mut slate)?;
|
||||||
api.post_tx(&slate.tx, false)?;
|
api.post_tx(&slate.tx, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -155,7 +155,7 @@ fn check_repair_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
// perform a transaction, but don't let it finish
|
// perform a transaction, but don't let it finish
|
||||||
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
wallet::controller::owner_single_use(wallet1.clone(), |api| {
|
||||||
// send to send
|
// send to send
|
||||||
let (mut slate, lock_fn) = api.initiate_tx(
|
let mut slate = api.initiate_tx(
|
||||||
None,
|
None,
|
||||||
reward * 2, // amount
|
reward * 2, // amount
|
||||||
cm, // minimum confirmations
|
cm, // minimum confirmations
|
||||||
|
@ -169,7 +169,7 @@ fn check_repair_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
let file_adapter = FileWalletCommAdapter::new();
|
let file_adapter = FileWalletCommAdapter::new();
|
||||||
let send_file = format!("{}/part_tx_1.tx", test_dir);
|
let send_file = format!("{}/part_tx_1.tx", test_dir);
|
||||||
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||||
assert_eq!(wallet1_info.total, bh * reward);
|
assert_eq!(wallet1_info.total, bh * reward);
|
||||||
// send to send
|
// send to send
|
||||||
let (mut slate, lock_fn) = api.initiate_tx(
|
let mut slate = api.initiate_tx(
|
||||||
Some("mining"),
|
Some("mining"),
|
||||||
reward * 2, // amount
|
reward * 2, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -116,7 +116,7 @@ fn file_exchange_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
// output tx file
|
// output tx file
|
||||||
let file_adapter = FileWalletCommAdapter::new();
|
let file_adapter = FileWalletCommAdapter::new();
|
||||||
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||||
assert_eq!(wallet1_info.total, bh * reward);
|
assert_eq!(wallet1_info.total, bh * reward);
|
||||||
// send to send
|
// send to send
|
||||||
let (mut slate, lock_fn) = api.initiate_tx(
|
let mut slate = api.initiate_tx(
|
||||||
Some("mining"),
|
Some("mining"),
|
||||||
reward * 2, // amount
|
reward * 2, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -114,7 +114,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
// output tx file
|
// output tx file
|
||||||
let file_adapter = FileWalletCommAdapter::new();
|
let file_adapter = FileWalletCommAdapter::new();
|
||||||
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
file_adapter.send_tx_async(&send_file, &mut slate)?;
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
|
|
||||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||||
// note this will increment the block count as part of the transaction "Posting"
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
let slate_i = sender_api.initiate_tx(
|
||||||
None,
|
None,
|
||||||
amount * 2, // amount
|
amount * 2, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -209,7 +209,7 @@ fn file_repost_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
|
@ -235,7 +235,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
let mut slate = Slate::blank(1);
|
let mut slate = Slate::blank(1);
|
||||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||||
// note this will increment the block count as part of the transaction "Posting"
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
let slate_i = sender_api.initiate_tx(
|
||||||
None, amount, // amount
|
None, amount, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
500, // max outputs
|
500, // max outputs
|
||||||
|
@ -244,7 +244,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None, None,
|
None, None,
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
sender_api.post_tx(&slate.tx, false)?;
|
sender_api.post_tx(&slate.tx, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -256,7 +256,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
// Send some to wallet 3
|
// Send some to wallet 3
|
||||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||||
// note this will increment the block count as part of the transaction "Posting"
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
let slate_i = sender_api.initiate_tx(
|
||||||
None,
|
None,
|
||||||
amount * 2, // amount
|
amount * 2, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -267,7 +267,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet3", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet3", &slate_i)?;
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
sender_api.post_tx(&slate.tx, false)?;
|
sender_api.post_tx(&slate.tx, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -279,7 +279,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
// Wallet3 to wallet 2
|
// Wallet3 to wallet 2
|
||||||
wallet::controller::owner_single_use(wallet3.clone(), |sender_api| {
|
wallet::controller::owner_single_use(wallet3.clone(), |sender_api| {
|
||||||
// note this will increment the block count as part of the transaction "Posting"
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
let slate_i = sender_api.initiate_tx(
|
||||||
None,
|
None,
|
||||||
amount * 3, // amount
|
amount * 3, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -290,7 +290,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
sender_api.post_tx(&slate.tx, false)?;
|
sender_api.post_tx(&slate.tx, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -308,7 +308,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
// Wallet3 to wallet 2 again (to another account)
|
// Wallet3 to wallet 2 again (to another account)
|
||||||
wallet::controller::owner_single_use(wallet3.clone(), |sender_api| {
|
wallet::controller::owner_single_use(wallet3.clone(), |sender_api| {
|
||||||
// note this will increment the block count as part of the transaction "Posting"
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
let slate_i = sender_api.initiate_tx(
|
||||||
None,
|
None,
|
||||||
amount * 3, // amount
|
amount * 3, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -319,7 +319,7 @@ fn setup_restore(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client3.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
sender_api.post_tx(&slate.tx, false)?;
|
sender_api.post_tx(&slate.tx, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -84,7 +84,7 @@ fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||||
assert_eq!(wallet1_info.total, bh * reward);
|
assert_eq!(wallet1_info.total, bh * reward);
|
||||||
// send to send
|
// send to send
|
||||||
let (mut slate, lock_fn) = api.initiate_tx(
|
let mut slate = api.initiate_tx(
|
||||||
Some("mining"),
|
Some("mining"),
|
||||||
reward * 2, // amount
|
reward * 2, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -94,7 +94,7 @@ fn self_send_test_impl(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
api.tx_lock_outputs(&slate, lock_fn)?;
|
api.tx_lock_outputs(&slate)?;
|
||||||
// Send directly to self
|
// Send directly to self
|
||||||
wallet::controller::foreign_single_use(wallet1.clone(), |api| {
|
wallet::controller::foreign_single_use(wallet1.clone(), |api| {
|
||||||
api.receive_tx(&mut slate, Some("listener"), None)?;
|
api.receive_tx(&mut slate, Some("listener"), None)?;
|
||||||
|
|
|
@ -97,7 +97,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
let mut slate = Slate::blank(1);
|
let mut slate = Slate::blank(1);
|
||||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||||
// note this will increment the block count as part of the transaction "Posting"
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
let slate_i = sender_api.initiate_tx(
|
||||||
None, amount, // amount
|
None, amount, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
500, // max outputs
|
500, // max outputs
|
||||||
|
@ -106,7 +106,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None, None,
|
None, None,
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -129,6 +129,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
assert!(!tx.confirmed);
|
assert!(!tx.confirmed);
|
||||||
assert!(tx.confirmation_ts.is_none());
|
assert!(tx.confirmation_ts.is_none());
|
||||||
assert_eq!(tx.amount_debited - tx.amount_credited, fee + amount);
|
assert_eq!(tx.amount_debited - tx.amount_credited, fee + amount);
|
||||||
|
println!("tx: {:?}", tx);
|
||||||
assert_eq!(Some(fee), tx.fee);
|
assert_eq!(Some(fee), tx.fee);
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -258,7 +259,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
// the stored transaction instead
|
// the stored transaction instead
|
||||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||||
// note this will increment the block count as part of the transaction "Posting"
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
let slate_i = sender_api.initiate_tx(
|
||||||
None,
|
None,
|
||||||
amount * 2, // amount
|
amount * 2, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
|
@ -269,7 +270,7 @@ fn basic_transaction_api(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -357,7 +358,7 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
let mut slate = Slate::blank(1);
|
let mut slate = Slate::blank(1);
|
||||||
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
wallet::controller::owner_single_use(wallet1.clone(), |sender_api| {
|
||||||
// note this will increment the block count as part of the transaction "Posting"
|
// note this will increment the block count as part of the transaction "Posting"
|
||||||
let (slate_i, lock_fn) = sender_api.initiate_tx(
|
let slate_i = sender_api.initiate_tx(
|
||||||
None, amount, // amount
|
None, amount, // amount
|
||||||
2, // minimum confirmations
|
2, // minimum confirmations
|
||||||
500, // max outputs
|
500, // max outputs
|
||||||
|
@ -366,7 +367,7 @@ fn tx_rollback(test_dir: &str) -> Result<(), libwallet::Error> {
|
||||||
None, None,
|
None, None,
|
||||||
)?;
|
)?;
|
||||||
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
slate = client1.send_tx_slate_direct("wallet2", &slate_i)?;
|
||||||
sender_api.tx_lock_outputs(&slate, lock_fn)?;
|
sender_api.tx_lock_outputs(&slate)?;
|
||||||
sender_api.finalize_tx(&mut slate)?;
|
sender_api.finalize_tx(&mut slate)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
Loading…
Reference in a new issue