Wallet self-send (#1939)

* add self send function to wallet

* rustfmt

* add destination to self send method

* update usage doc

* doc clarification

* remove localhost send restriction
This commit is contained in:
Yeastplume
2018-11-08 09:46:09 +00:00
committed by GitHub
parent e9c50ccb56
commit ee19cfcf86
8 changed files with 315 additions and 10 deletions
+53 -3
View File
@@ -181,6 +181,7 @@ where
num_change_outputs,
selection_strategy_is_use_all,
&parent_key_id,
false,
)?;
lock_fn_out = lock_fn;
@@ -204,6 +205,50 @@ where
Ok(slate_out)
}
/// Issues a send transaction to the same wallet, without needing communication
/// good for consolidating outputs, or can be extended to split outputs to multiple
/// accounts
pub fn issue_self_tx(
&mut self,
amount: u64,
minimum_confirmations: u64,
max_outputs: usize,
num_change_outputs: usize,
selection_strategy_is_use_all: bool,
src_acct_name: &str,
dest_acct_name: &str,
) -> Result<Slate, Error> {
let mut w = self.wallet.lock();
w.open_with_credentials()?;
let orig_parent_key_id = w.parent_key_id();
w.set_parent_key_id_by_name(src_acct_name)?;
let parent_key_id = w.parent_key_id();
let (mut slate, context, lock_fn) = tx::create_send_tx(
&mut **w,
amount,
minimum_confirmations,
max_outputs,
num_change_outputs,
selection_strategy_is_use_all,
&parent_key_id,
true,
)?;
w.set_parent_key_id_by_name(dest_acct_name)?;
let parent_key_id = w.parent_key_id();
tx::receive_tx(&mut **w, &mut slate, &parent_key_id, true)?;
tx::complete_tx(&mut **w, &mut slate, &context)?;
let tx_hex = util::to_hex(ser::ser_vec(&slate.tx).unwrap());
// lock our inputs
lock_fn(&mut **w, &tx_hex)?;
w.set_parent_key_id(orig_parent_key_id);
w.close()?;
Ok(slate)
}
/// Write a transaction to send to file so a user can transmit it to the
/// receiver in whichever way they see fit (aka carrier pigeon mode).
pub fn send_tx(
@@ -228,6 +273,7 @@ where
num_change_outputs,
selection_strategy_is_use_all,
&parent_key_id,
false,
)?;
if write_to_disk {
let mut pub_tx = File::create(dest)?;
@@ -507,8 +553,12 @@ where
let parent_key_id = wallet.parent_key_id();
// create an output using the amount in the slate
let (_, mut context, receiver_create_fn) =
selection::build_recipient_output_with_slate(&mut **wallet, &mut slate, parent_key_id)?;
let (_, mut context, receiver_create_fn) = selection::build_recipient_output_with_slate(
&mut **wallet,
&mut slate,
parent_key_id,
false,
)?;
// fill public keys
let _ = slate.fill_round_1(
@@ -535,7 +585,7 @@ where
let mut w = self.wallet.lock();
w.open_with_credentials()?;
let parent_key_id = w.parent_key_id();
let res = tx::receive_tx(&mut **w, slate, &parent_key_id);
let res = tx::receive_tx(&mut **w, slate, &parent_key_id, false);
w.close()?;
if let Err(e) = res {
@@ -36,6 +36,7 @@ pub fn build_send_tx_slate<T: ?Sized, C, K>(
change_outputs: usize,
selection_strategy_is_use_all: bool,
parent_key_id: Identifier,
is_self: bool,
) -> Result<
(
Slate,
@@ -98,6 +99,9 @@ where
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);
if is_self {
t.tx_type = TxLogEntryType::TxSentSelf;
}
t.tx_slate_id = Some(slate_id);
t.fee = Some(fee);
t.tx_hex = Some(tx_hex.to_owned());
@@ -144,6 +148,7 @@ pub fn build_recipient_output_with_slate<T: ?Sized, C, K>(
wallet: &mut T,
slate: &mut Slate,
parent_key_id: Identifier,
is_self: bool,
) -> Result<
(
Identifier,
@@ -185,6 +190,9 @@ where
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);
if is_self {
t.tx_type = TxLogEntryType::TxReceivedSelf;
}
t.tx_slate_id = Some(slate_id);
t.amount_credited = amount;
t.num_outputs = 1;
+9 -2
View File
@@ -32,6 +32,7 @@ pub fn receive_tx<T: ?Sized, C, K>(
wallet: &mut T,
slate: &mut Slate,
parent_key_id: &Identifier,
is_self: bool,
) -> Result<(), Error>
where
T: WalletBackend<C, K>,
@@ -39,8 +40,12 @@ where
K: Keychain,
{
// create an output using the amount in the slate
let (_, mut context, receiver_create_fn) =
selection::build_recipient_output_with_slate(wallet, slate, parent_key_id.clone())?;
let (_, mut context, receiver_create_fn) = selection::build_recipient_output_with_slate(
wallet,
slate,
parent_key_id.clone(),
is_self,
)?;
// fill public keys
let _ = slate.fill_round_1(
@@ -69,6 +74,7 @@ pub fn create_send_tx<T: ?Sized, C, K>(
num_change_outputs: usize,
selection_strategy_is_use_all: bool,
parent_key_id: &Identifier,
is_self: bool,
) -> Result<
(
Slate,
@@ -107,6 +113,7 @@ where
num_change_outputs,
selection_strategy_is_use_all,
parent_key_id.clone(),
is_self,
)?;
// Generate a kernel offset and subtract from our context's secret key. Store
+6
View File
@@ -546,6 +546,10 @@ pub enum TxLogEntryType {
TxReceived,
/// Inputs locked + change outputs when a transaction is created
TxSent,
/// As above, but self-transaction
TxReceivedSelf,
/// As Above
TxSentSelf,
/// Received transaction that was rolled back by user
TxReceivedCancelled,
/// Sent transaction that was rolled back by user
@@ -558,6 +562,8 @@ impl fmt::Display for TxLogEntryType {
TxLogEntryType::ConfirmedCoinbase => write!(f, "Confirmed \nCoinbase"),
TxLogEntryType::TxReceived => write!(f, "Received Tx"),
TxLogEntryType::TxSent => write!(f, "Sent Tx"),
TxLogEntryType::TxReceivedSelf => write!(f, "Received Tx (Self)"),
TxLogEntryType::TxSentSelf => write!(f, "Sent Tx (Self)"),
TxLogEntryType::TxReceivedCancelled => write!(f, "Received Tx\n- Cancelled"),
TxLogEntryType::TxSentCancelled => write!(f, "Send Tx\n- Cancelled"),
}