Explicitly mark Txs as fully scanned

This commit is contained in:
Aditya Kulkarni 2019-09-25 13:42:00 -07:00
parent 5b02282a66
commit df12ccf317
3 changed files with 25 additions and 26 deletions

View File

@ -14,7 +14,6 @@ use std::sync::atomic::{AtomicU64, AtomicI32, AtomicUsize, Ordering};
use json::{object, JsonValue}; use json::{object, JsonValue};
use zcash_primitives::transaction::{TxId, Transaction}; use zcash_primitives::transaction::{TxId, Transaction};
use zcash_primitives::note_encryption::Memo;
use zcash_client_backend::{ use zcash_client_backend::{
constants::testnet, constants::mainnet, constants::regtest, encoding::encode_payment_address, 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 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) // we need to free the read lock from here (Because we'll self.wallet.txs later)
let txids_to_fetch: Vec<(TxId, i32)>; let txids_to_fetch: Vec<(TxId, i32)> = self.wallet.txs.read().unwrap().values()
{ .filter(|wtx| wtx.full_tx_scanned == false)
// First, build a list of all the TxIDs and Memos that we need .map(|wtx| (wtx.txid, wtx.block))
// to fetch. .collect::<Vec<(TxId, i32)>>();
// 1. Get all (txid, Option<Memo>)
// 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::<Vec<(TxId, Option<Memo>, i32)>>() // convert to vector
})
.collect::<Vec<(TxId, Option<Memo>, 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::<Vec<(TxId, i32)>>(); // and convert into Vec
}
info!("Fetching {} new txids", txids_to_fetch.len()); info!("Fetching {} new txids", txids_to_fetch.len());
// And go and fetch the txids, getting the full transaction, so we can // And go and fetch the txids, getting the full transaction, so we can

View File

@ -384,6 +384,8 @@ pub struct WalletTx {
// All outgoing sapling sends to addresses outside this wallet // All outgoing sapling sends to addresses outside this wallet
pub outgoing_metadata: Vec<OutgoingTxMetadata>, pub outgoing_metadata: Vec<OutgoingTxMetadata>,
pub full_tx_scanned: bool,
} }
impl WalletTx { impl WalletTx {
@ -400,6 +402,7 @@ impl WalletTx {
total_shielded_value_spent: 0, total_shielded_value_spent: 0,
total_transparent_value_spent: 0, total_transparent_value_spent: 0,
outgoing_metadata: vec![], outgoing_metadata: vec![],
full_tx_scanned: false,
} }
} }
@ -420,13 +423,17 @@ impl WalletTx {
let total_shielded_value_spent = reader.read_u64::<LittleEndian>()?; let total_shielded_value_spent = reader.read_u64::<LittleEndian>()?;
let total_transparent_value_spent = reader.read_u64::<LittleEndian>()?; let total_transparent_value_spent = reader.read_u64::<LittleEndian>()?;
// Outgoing metadata was only added in version 2 // Outgoing metadata was only added in version 2
let outgoing_metadata = match version { let outgoing_metadata = match version {
1 => vec![], 1 => vec![],
_ => Vector::read(&mut reader, |r| OutgoingTxMetadata::read(r))? _ => Vector::read(&mut reader, |r| OutgoingTxMetadata::read(r))?
}; };
let full_tx_scanned = match version {
1 => false,
_ => reader.read_u8()? > 0,
};
Ok(WalletTx{ Ok(WalletTx{
block, block,
txid, txid,
@ -435,6 +442,7 @@ impl WalletTx {
total_shielded_value_spent, total_shielded_value_spent,
total_transparent_value_spent, total_transparent_value_spent,
outgoing_metadata, outgoing_metadata,
full_tx_scanned
}) })
} }
@ -454,6 +462,8 @@ impl WalletTx {
// Write the outgoing metadata // Write the outgoing metadata
Vector::write(&mut writer, &self.outgoing_metadata, |w, om| om.write(w))?; Vector::write(&mut writer, &self.outgoing_metadata, |w, om| om.write(w))?;
writer.write_u8(if self.full_tx_scanned {1} else {0})?;
Ok(()) Ok(())
} }
} }

View File

@ -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 // 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() { for output in tx.shielded_outputs.iter() {
let ivks: Vec<_> = self.extfvks.iter().map(|extfvk| extfvk.fvk.vk.ivk()).collect(); 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". // Invalidate all blocks including and after "at_height".