From ac696847c4fb33efd17cf48be8275e757e169e28 Mon Sep 17 00:00:00 2001 From: DenioD <41270280+DenioD@users.noreply.github.com> Date: Thu, 1 Oct 2020 17:30:23 +0200 Subject: [PATCH] add shielded command --- lib/src/commands.rs | 55 +++++++++++++++++++++++++++++++++--------- lib/src/lightclient.rs | 29 ++++++++++++++++++++++ lib/src/lightwallet.rs | 1 + 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/lib/src/commands.rs b/lib/src/commands.rs index 33d4d75..9f1934e 100644 --- a/lib/src/commands.rs +++ b/lib/src/commands.rs @@ -475,7 +475,7 @@ impl Command for SendCommand { h.push("OR"); h.push("send '[{'address':
, 'amount': , 'memo': }, ...]'"); h.push(""); - h.push("NOTE: The fee required to send this transaction (currently HUSH 0.0001) is additionally detected from your balance."); + h.push("NOTE: The fee required to send this transaction (currently HUSH 0.0001) is additionally deducted from your balance."); h.push("Example:"); h.push("send ztestsapling1x65nq4dgp0qfywgxcwk9n0fvm4fysmapgr2q00p85ju252h6l7mmxu2jg9cqqhtvzd69jwhgv8d 200000 \"Hello from the command line\""); h.push(""); @@ -548,17 +548,12 @@ impl Command for SendCommand { return self.help() }; - match lightclient.do_sync(true) { - Ok(_) => { - // Convert to the right format. String -> &str. - let tos = send_args.iter().map(|(a, v, m)| (a.as_str(), *v, m.clone()) ).collect::>(); - match lightclient.do_send(tos) { - Ok(txid) => { object!{ "txid" => txid } }, - Err(e) => { object!{ "error" => e } } - }.pretty(2) - }, - Err(e) => e - } + // Convert to the right format. String -> &str. + let tos = send_args.iter().map(|(a, v, m)| (a.as_str(), *v, m.clone()) ).collect::>(); + match lightclient.do_send(tos) { + Ok(txid) => { object!{ "txid" => txid } }, + Err(e) => { object!{ "error" => e } } + }.pretty(2) } } @@ -713,6 +708,41 @@ impl Command for TImportCommand { } } +struct ShieldCommand {} +impl Command for ShieldCommand { + fn help(&self) -> String { + let mut h = vec![]; + h.push("Shield all your transparent funds"); + h.push("Usage:"); + h.push("shield [optional address]"); + h.push(""); + h.push("NOTE: The fee required to send this transaction (currently HUSH 0.0001) is additionally deducted from your balance."); + h.push("Example:"); + h.push("shield"); + h.push(""); + + h.join("\n") + } + + fn short_help(&self) -> String { + "Shield your transparent HUSH into a sapling address".to_string() + } + + fn exec(&self, args: &[&str], lightclient: &LightClient) -> String { + // Parse the address or amount + let address = if args.len() > 0 { + Some(args[0].to_string()) + } else { + None + }; + + match lightclient.do_shield(address) { + Ok(txid) => { object!{ "txid" => txid } }, + Err(e) => { object!{ "error" => e } } + }.pretty(2) + } +} + struct HeightCommand {} impl Command for HeightCommand { fn help(&self) -> String { @@ -881,6 +911,7 @@ pub fn get_commands() -> Box>> { map.insert("info".to_string(), Box::new(InfoCommand{})); map.insert("coinsupply".to_string(), Box::new(CoinsupplyCommand{})); map.insert("send".to_string(), Box::new(SendCommand{})); + map.insert("shield".to_string(), Box::new(ShieldCommand{})); map.insert("save".to_string(), Box::new(SaveCommand{})); map.insert("quit".to_string(), Box::new(QuitCommand{})); map.insert("list".to_string(), Box::new(TransactionsCommand{})); diff --git a/lib/src/lightclient.rs b/lib/src/lightclient.rs index 38c48ea..1e4d668 100644 --- a/lib/src/lightclient.rs +++ b/lib/src/lightclient.rs @@ -1166,6 +1166,34 @@ impl LightClient { } } + pub fn do_shield(&self, address: Option) -> Result { + use zcash_primitives::transaction::components::amount::DEFAULT_FEE; + use std::convert::TryInto; + + let fee = DEFAULT_FEE.try_into().unwrap(); + let tbal = self.wallet.read().unwrap().tbalance(None); + + // Make sure there is a balance, and it is greated than the amount + if tbal <= fee { + return Err(format!("Not enough transparent balance to shield. Have {} puposhis, need more than {} puposhis to cover tx fee", tbal, fee)); + } + + let addr = address.or(self.wallet.read().unwrap().get_all_zaddresses().get(0).map(|s| s.clone())).unwrap(); + + let result = { + let _lock = self.sync_lock.lock().unwrap(); + self.wallet.read().unwrap().send_to_address( + u32::from_str_radix(&self.config.consensus_branch_id, 16).unwrap(), + &self.sapling_spend, &self.sapling_output, + true, + vec![(&addr, tbal - fee, None)], + |txbytes| broadcast_raw_tx(&self.get_server_uri(),self.config.no_cert_verification, txbytes) + ) + }; + + result.map(|(txid, _)| txid) + } + fn do_sync_internal(&self, print_updates: bool, retry_count: u32) -> Result { // We can only do one sync at a time because we sync blocks in serial order // If we allow multiple syncs, they'll all get jumbled up. @@ -1477,6 +1505,7 @@ impl LightClient { self.wallet.write().unwrap().send_to_address( u32::from_str_radix(&self.config.consensus_branch_id, 16).unwrap(), &self.sapling_spend, &self.sapling_output, + false, addrs, |txbytes| broadcast_raw_tx(&self.get_server_uri(), self.config.no_cert_verification, txbytes) ) diff --git a/lib/src/lightwallet.rs b/lib/src/lightwallet.rs index 083f20e..e8f24b9 100644 --- a/lib/src/lightwallet.rs +++ b/lib/src/lightwallet.rs @@ -1992,6 +1992,7 @@ impl LightWallet { consensus_branch_id: u32, spend_params: &[u8], output_params: &[u8], + transparent_only: bool, tos: Vec<(&str, u64, Option)>, broadcast_fn: F ) -> Result<(String, Vec), String>