From df12ccf317ba537ba4251363508de52c2bfd1875 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 25 Sep 2019 13:42:00 -0700 Subject: [PATCH] Explicitly mark Txs as fully scanned --- src/lightclient.rs | 31 +++++-------------------------- src/lightwallet/data.rs | 12 +++++++++++- src/lightwallet/mod.rs | 10 ++++++++++ 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/lightclient.rs b/src/lightclient.rs index 5c16980..57dc254 100644 --- a/src/lightclient.rs +++ b/src/lightclient.rs @@ -14,7 +14,6 @@ use std::sync::atomic::{AtomicU64, AtomicI32, AtomicUsize, Ordering}; use json::{object, JsonValue}; use zcash_primitives::transaction::{TxId, Transaction}; -use zcash_primitives::note_encryption::Memo; use zcash_client_backend::{ constants::testnet, constants::mainnet, constants::regtest, encoding::encode_payment_address, }; @@ -698,31 +697,11 @@ impl LightClient { // We need to first copy over the Txids from the wallet struct, because // we need to free the read lock from here (Because we'll self.wallet.txs later) - let txids_to_fetch: Vec<(TxId, i32)>; - { - // First, build a list of all the TxIDs and Memos that we need - // to fetch. - // 1. Get all (txid, Option) - // 2. Filter out all txids where the Memo is None - // (Which means that particular txid was never fetched. Remember - // that when memos are fetched, if they are empty, they become - // Some(f60000...) - let txids_and_memos = self.wallet.txs.read().unwrap().iter() - .flat_map( |(txid, wtx)| { // flat_map because we're collecting vector of vectors - wtx.notes.iter() - .filter( |nd| nd.memo.is_none()) // only get if memo is None (i.e., it has not been fetched) - .map( |nd| (txid.clone(), nd.memo.clone(), wtx.block) ) // collect (txid, memo, height) Clone everything because we want copies, so we can release the read lock - .collect::, i32)>>() // convert to vector - }) - .collect::, i32)>>(); - - //println!("{:?}", txids_and_memos); - // TODO: Assert that all the memos here are None - - txids_to_fetch = txids_and_memos.iter() - .map( | (txid, _, h) | (txid.clone(), *h) ) // We're only interested in the txids, so drop the Memo, which is None anyway - .collect::>(); // and convert into Vec - } + let txids_to_fetch: Vec<(TxId, i32)> = self.wallet.txs.read().unwrap().values() + .filter(|wtx| wtx.full_tx_scanned == false) + .map(|wtx| (wtx.txid, wtx.block)) + .collect::>(); + info!("Fetching {} new txids", txids_to_fetch.len()); // And go and fetch the txids, getting the full transaction, so we can diff --git a/src/lightwallet/data.rs b/src/lightwallet/data.rs index 81da0d7..d1e4b7e 100644 --- a/src/lightwallet/data.rs +++ b/src/lightwallet/data.rs @@ -384,6 +384,8 @@ pub struct WalletTx { // All outgoing sapling sends to addresses outside this wallet pub outgoing_metadata: Vec, + + pub full_tx_scanned: bool, } impl WalletTx { @@ -400,6 +402,7 @@ impl WalletTx { total_shielded_value_spent: 0, total_transparent_value_spent: 0, outgoing_metadata: vec![], + full_tx_scanned: false, } } @@ -420,12 +423,16 @@ impl WalletTx { let total_shielded_value_spent = reader.read_u64::()?; let total_transparent_value_spent = reader.read_u64::()?; - // Outgoing metadata was only added in version 2 let outgoing_metadata = match version { 1 => vec![], _ => Vector::read(&mut reader, |r| OutgoingTxMetadata::read(r))? }; + + let full_tx_scanned = match version { + 1 => false, + _ => reader.read_u8()? > 0, + }; Ok(WalletTx{ block, @@ -435,6 +442,7 @@ impl WalletTx { total_shielded_value_spent, total_transparent_value_spent, outgoing_metadata, + full_tx_scanned }) } @@ -454,6 +462,8 @@ impl WalletTx { // Write the outgoing metadata Vector::write(&mut writer, &self.outgoing_metadata, |w, om| om.write(w))?; + writer.write_u8(if self.full_tx_scanned {1} else {0})?; + Ok(()) } } diff --git a/src/lightwallet/mod.rs b/src/lightwallet/mod.rs index 48f0041..13b74ed 100644 --- a/src/lightwallet/mod.rs +++ b/src/lightwallet/mod.rs @@ -612,6 +612,9 @@ impl LightWallet { } } + // TODO: Scan t outputs if we spent t or z funds in this Tx, and add it to the + // outgoing metadata + // Scan shielded sapling outputs to see if anyone of them is us, and if it is, extract the memo for output in tx.shielded_outputs.iter() { let ivks: Vec<_> = self.extfvks.iter().map(|extfvk| extfvk.fvk.vk.ivk()).collect(); @@ -693,6 +696,13 @@ impl LightWallet { }; } } + + // Mark this Tx as scanned + { + let mut txs = self.txs.write().unwrap(); + let mut wtx = txs.get_mut(&tx.txid()).unwrap(); + wtx.full_tx_scanned = true; + } } // Invalidate all blocks including and after "at_height".