From c6634d24360e7cafa99b7112c9da7dcc7703952c Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Tue, 17 Sep 2019 14:09:20 -0700 Subject: [PATCH] Cleanup --- src/commands.rs | 12 ++++---- src/lightclient.rs | 46 ++++++++++++++--------------- src/lightwallet.rs | 72 +++++++++++++++++++++++----------------------- src/main.rs | 6 ++-- 4 files changed, 67 insertions(+), 69 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 0620b82..9ab62e8 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -27,7 +27,7 @@ impl Command for SyncCommand { } fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String { - lightclient.do_sync() + lightclient.do_sync(true) } } @@ -116,7 +116,7 @@ impl Command for InfoCommand { } fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String { - lightclient.do_sync(); + lightclient.do_sync(true); lightclient.do_info() } } @@ -139,7 +139,7 @@ impl Command for BalanceCommand { } fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String { - lightclient.do_sync(); + lightclient.do_sync(true); format!("{}", lightclient.do_address().pretty(2)) } @@ -181,7 +181,7 @@ impl Command for SendCommand { let memo = if args.len() == 3 { Some(args[2].to_string()) } else {None}; - lightclient.do_sync(); + lightclient.do_sync(true); lightclient.do_send(args[0], value, memo) } @@ -249,7 +249,7 @@ impl Command for TransactionsCommand { } fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String { - lightclient.do_sync(); + lightclient.do_sync(true); format!("{}", lightclient.do_list_transactions().pretty(2)) } @@ -289,7 +289,7 @@ impl Command for NotesCommand { false }; - lightclient.do_sync(); + lightclient.do_sync(true); format!("{}", lightclient.do_list_notes(all_notes).pretty(2)) } diff --git a/src/lightclient.rs b/src/lightclient.rs index 0911966..295ad4e 100644 --- a/src/lightclient.rs +++ b/src/lightclient.rs @@ -274,6 +274,7 @@ impl LightClient { // Collect UTXOs let utxos = self.wallet.get_utxos().iter() + .filter(|utxo| utxo.unconfirmed_spent.is_none()) // Filter out unconfirmed from the list of utxos .map(|utxo| { object!{ "created_in_block" => utxo.height, @@ -289,25 +290,20 @@ impl LightClient { .collect::>(); // Collect pending UTXOs - let pending_utxos = self.wallet.txs.read().unwrap().iter() - .flat_map( |(txid, wtx)| { - wtx.utxos.iter().filter_map(move |utxo| - if utxo.unconfirmed_spent.is_some() { - Some(object!{ - "created_in_block" => wtx.block, - "created_in_txid" => format!("{}", txid), - "value" => utxo.value, - "scriptkey" => hex::encode(utxo.script.clone()), - "is_change" => false, // TODO: Identify notes as change - "address" => utxo.address.clone(), - "spent" => utxo.spent.map(|spent_txid| format!("{}", spent_txid)), - "unconfirmed_spent" => utxo.unconfirmed_spent.map(|spent_txid| format!("{}", spent_txid)), - }) - } else { - None - } - ) - }) + let pending_utxos = self.wallet.get_utxos().iter() + .filter(|utxo| utxo.unconfirmed_spent.is_some()) // Filter to include only unconfirmed utxos + .map(|utxo| + object!{ + "created_in_block" => utxo.height, + "created_in_txid" => format!("{}", utxo.txid), + "value" => utxo.value, + "scriptkey" => hex::encode(utxo.script.clone()), + "is_change" => false, // TODO: Identify notes as change + "address" => utxo.address.clone(), + "spent" => utxo.spent.map(|spent_txid| format!("{}", spent_txid)), + "unconfirmed_spent" => utxo.unconfirmed_spent.map(|spent_txid| format!("{}", spent_txid)), + } + ) .collect::>();; let mut res = object!{ @@ -430,13 +426,13 @@ impl LightClient { self.set_wallet_initial_state(); // Then, do a sync, which will force a full rescan from the initial state - let response = self.do_sync(); + let response = self.do_sync(true); info!("Rescan finished"); response } - pub fn do_sync(&self) -> String { + pub fn do_sync(&self, print_updates: bool) -> String { // Sync is 3 parts // 1. Get the latest block // 2. Get all the blocks that we don't have @@ -471,7 +467,7 @@ impl LightClient { let local_bytes_downloaded = bytes_downloaded.clone(); // Show updates only if we're syncing a lot of blocks - if end_height - last_scanned_height > 100 { + if print_updates && end_height - last_scanned_height > 100 { print!("Syncing {}/{}\r", last_scanned_height, last_block); io::stdout().flush().ok().expect("Could not flush stdout"); } @@ -505,8 +501,10 @@ impl LightClient { } else if end_height > last_block { end_height = last_block; } - } - println!(); // Print a new line, to finalize the syncing updates + } + if print_updates{ + println!(""); // New line to finish up the updates + } let mut responses = vec![]; diff --git a/src/lightwallet.rs b/src/lightwallet.rs index 9ce5ac2..d1eaead 100644 --- a/src/lightwallet.rs +++ b/src/lightwallet.rs @@ -1235,24 +1235,9 @@ impl LightWallet { // ZecWallet will add all your t-address funds into that transaction, and send them to your shielded // address as change. let tinputs = self.get_utxos().iter() - .map(|utxo| { - let outpoint: OutPoint = utxo.to_outpoint(); - - // Mark this utxo as uncofirmed spent - let mut txs = self.txs.write().unwrap(); - let mut spent_utxo = txs.get_mut(&utxo.txid).unwrap().utxos.iter_mut() - .find(|u| utxo.txid == u.txid && utxo.output_index == u.output_index) - .unwrap(); - spent_utxo.unconfirmed_spent = Some(utxo.txid); - - let coin = TxOut { - value: Amount::from_u64(utxo.value).unwrap(), - script_pubkey: Script { 0: utxo.script.clone() }, - }; - - (outpoint, coin) - }) - .collect::>(); + .filter(|utxo| utxo.unconfirmed_spent.is_none()) // Remove any unconfirmed spends + .map(|utxo| utxo.clone()) + .collect::>(); if let Err(e) = match to { address::RecipientAddress::Shielded(_) => { @@ -1261,20 +1246,28 @@ impl LightWallet { let sk = self.tkeys[0]; // Add all tinputs - tinputs.iter().map( |(outpoint, coin)| { - builder.add_transparent_input(sk, outpoint.clone(), coin.clone()) - }).collect::, _>>() - } - _ => {Ok(vec![])} + tinputs.iter() + .map(|utxo| { + let outpoint: OutPoint = utxo.to_outpoint(); + + let coin = TxOut { + value: Amount::from_u64(utxo.value).unwrap(), + script_pubkey: Script { 0: utxo.script.clone() }, + }; + + builder.add_transparent_input(sk, outpoint.clone(), coin.clone()) + }) + .collect::, _>>() + }, + _ => Ok(vec![]) } { eprintln!("Error adding transparent inputs: {:?}", e); return None; } // Confirm we were able to select sufficient value - // TODO: If we're sending to a t-address, we could also use t-address inputs let selected_value = notes.iter().map(|selected| selected.note.value).sum::() - + tinputs.iter().map::(|(_, coin)| coin.value.into()).sum::(); + + tinputs.iter().map::(|utxo| utxo.value.into()).sum::(); if selected_value < u64::from(target_value) { eprintln!( @@ -1329,17 +1322,24 @@ impl LightWallet { println!("Transaction ID: {}", tx.txid()); // Mark notes as spent. - // TODO: This is only a non-confirmed spend, and the note should be marked as such. - let mut txs = self.txs.write().unwrap(); - for selected in notes { - let mut spent_note = txs - .get_mut(&selected.txid) - .unwrap() - .notes - .iter_mut() - .find(|nd| &nd.nullifier[..] == &selected.nullifier[..]) - .unwrap(); - spent_note.unconfirmed_spent = Some(tx.txid()); + { + // Mark sapling notes as unconfirmed spent + let mut txs = self.txs.write().unwrap(); + for selected in notes { + let mut spent_note = txs.get_mut(&selected.txid).unwrap() + .notes.iter_mut() + .find(|nd| &nd.nullifier[..] == &selected.nullifier[..]) + .unwrap(); + spent_note.unconfirmed_spent = Some(tx.txid()); + } + + // Mark this utxo as unconfirmed spent + for utxo in tinputs { + let mut spent_utxo = txs.get_mut(&utxo.txid).unwrap().utxos.iter_mut() + .find(|u| utxo.txid == u.txid && utxo.output_index == u.output_index) + .unwrap(); + spent_utxo.unconfirmed_spent = Some(tx.txid()); + } } // Return the encoded transaction, so the caller can send it. diff --git a/src/main.rs b/src/main.rs index 50031b2..baf012b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,7 +70,7 @@ pub fn main() { info!("{}", lightclient.do_info()); // At startup, run a sync - let sync_update = lightclient.do_sync(); + let sync_update = lightclient.do_sync(true); println!("{}", sync_update); let (command_tx, command_rx) = std::sync::mpsc::channel::<(String, Vec)>(); @@ -91,8 +91,8 @@ pub fn main() { } }, Err(_) => { - // Timeout. Do a sync to keep the wallet up-to-date - lc.do_sync(); + // Timeout. Do a sync to keep the wallet up-to-date. False to whether to print updates on the console + lc.do_sync(false); } } }