Browse Source

Mark confirmed spent notes properly

master
Aditya Kulkarni 5 years ago
parent
commit
8547235b28
  1. 3
      rust-lightclient/src/lightclient.rs
  2. 23
      rust-lightclient/src/lightwallet.rs

3
rust-lightclient/src/lightclient.rs

@ -148,7 +148,8 @@ impl LightClient {
"value" => nd.note.value,
"is_change" => nd.is_change,
"address" => LightWallet::address_from_extfvk(&nd.extfvk, nd.diversifier),
"spent" => nd.spent.map(|spent_txid| format!("{}", spent_txid))
"spent" => nd.spent.map(|spent_txid| format!("{}", spent_txid)),
"unconfirmed_spent" => nd.unconfirmed_spent.map(|spent_txid| format!("{}", spent_txid)),
}
)
})

23
rust-lightclient/src/lightwallet.rs

@ -99,9 +99,11 @@ pub struct SaplingNoteData {
pub note: Note<Bls12>,
witnesses: Vec<IncrementalWitness<Node>>,
nullifier: [u8; 32],
pub spent: Option<TxId>,
pub spent: Option<TxId>, // If this note was confirmed spent
pub unconfirmed_spent: Option<TxId>, // If this note was spent in a send, but has not yet been confirmed.
pub memo: Option<Memo>,
pub is_change: bool,
// TODO: We need to remove the unconfirmed_spent (i.e., set it to None) if the Tx has expired
}
@ -162,6 +164,7 @@ impl SaplingNoteData {
witnesses: vec![witness],
nullifier: nf,
spent: None,
unconfirmed_spent: None,
memo: None,
is_change: output.is_change,
}
@ -196,6 +199,9 @@ impl SaplingNoteData {
let mut nullifier = [0u8; 32];
reader.read_exact(&mut nullifier)?;
// Note that this is only the spent field, we ignore the unconfirmed_spent field.
// The reason is that unconfirmed spents are only in memory, and we need to get the actual value of spent
// from the blockchain anyway.
let spent = Optional::read(&mut reader, |r| {
let mut txid_bytes = [0u8; 32];
r.read_exact(&mut txid_bytes)?;
@ -221,6 +227,7 @@ impl SaplingNoteData {
witnesses,
nullifier,
spent,
unconfirmed_spent: None,
memo,
is_change,
})
@ -334,7 +341,8 @@ struct SpendableNote {
impl SpendableNote {
fn from(txid: TxId, nd: &SaplingNoteData, anchor_offset: usize) -> Option<Self> {
if nd.spent.is_none() {
// Include only notes that haven't been spent, or haven't been included in an unconfirmed spend yet.
if nd.spent.is_none() && nd.unconfirmed_spent.is_none() {
let witness = nd.witnesses.get(nd.witnesses.len() - anchor_offset - 1);
witness.map(|w| SpendableNote {
@ -602,7 +610,7 @@ impl LightWallet {
None => true
}
})
.map(|nd| if nd.spent.is_none() { nd.note.value } else { 0 })
.map(|nd| if nd.spent.is_none() && nd.unconfirmed_spent.is_none() { nd.note.value } else { 0 })
.sum::<u64>()
} else {
0
@ -684,6 +692,8 @@ impl LightWallet {
let mut txs = self.txs.write().unwrap();
// Create a Vec containing all unspent nullifiers.
// Include only the confirmed spent nullifiers, since unconfirmed ones still need to be included
// during scan_block below.
let nfs: Vec<_> = txs
.iter()
.map(|(txid, tx)| {
@ -751,7 +761,11 @@ impl LightWallet {
.iter_mut()
.find(|nd| &nd.nullifier[..] == &spend.nf[..])
.unwrap();
// Mark the note as spent, and remove the unconfirmed part of it
spent_note.spent = Some(tx.txid);
spent_note.unconfirmed_spent = None::<TxId>;
total_shielded_value_spent += spent_note.note.value;
}
@ -904,6 +918,7 @@ 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
@ -913,7 +928,7 @@ impl LightWallet {
.iter_mut()
.find(|nd| &nd.nullifier[..] == &selected.nullifier[..])
.unwrap();
spent_note.spent = Some(tx.txid());
spent_note.unconfirmed_spent = Some(tx.txid());
}
// Return the encoded transaction, so the caller can send it.

Loading…
Cancel
Save