Mark notes as unspent when the transaction they are spent in expires
This commit is contained in:
parent
273881c3b6
commit
2695e8f6fd
|
@ -307,6 +307,12 @@ pub fn scan_cached_blocks<P: AsRef<Path>, Q: AsRef<Path>>(
|
||||||
VALUES (?, ?, ?)",
|
VALUES (?, ?, ?)",
|
||||||
)?;
|
)?;
|
||||||
let mut stmt_prune_witnesses = data.prepare("DELETE FROM sapling_witnesses WHERE block < ?")?;
|
let mut stmt_prune_witnesses = data.prepare("DELETE FROM sapling_witnesses WHERE block < ?")?;
|
||||||
|
let mut stmt_update_expired = data.prepare(
|
||||||
|
"UPDATE received_notes SET spent = NULL WHERE EXISTS (
|
||||||
|
SELECT id_tx FROM transactions
|
||||||
|
WHERE id_tx = received_notes.spent AND block IS NULL AND expiry_height < ?
|
||||||
|
)",
|
||||||
|
)?;
|
||||||
|
|
||||||
// Fetch the CompactBlocks we need to scan
|
// Fetch the CompactBlocks we need to scan
|
||||||
let rows = stmt_blocks.query_map(&[last_height], |row| CompactBlockRow {
|
let rows = stmt_blocks.query_map(&[last_height], |row| CompactBlockRow {
|
||||||
|
@ -515,6 +521,9 @@ pub fn scan_cached_blocks<P: AsRef<Path>, Q: AsRef<Path>>(
|
||||||
// Prune the stored witnesses (we only expect rollbacks of at most 100 blocks).
|
// Prune the stored witnesses (we only expect rollbacks of at most 100 blocks).
|
||||||
stmt_prune_witnesses.execute(&[last_height - 100])?;
|
stmt_prune_witnesses.execute(&[last_height - 100])?;
|
||||||
|
|
||||||
|
// Update now-expired transactions that didn't get mined.
|
||||||
|
stmt_update_expired.execute(&[last_height])?;
|
||||||
|
|
||||||
// Commit the SQL transaction, writing this block's data atomically.
|
// Commit the SQL transaction, writing this block's data atomically.
|
||||||
data.execute("COMMIT", NO_PARAMS)?;
|
data.execute("COMMIT", NO_PARAMS)?;
|
||||||
}
|
}
|
||||||
|
@ -1275,5 +1284,55 @@ mod tests {
|
||||||
"Insufficient balance (have 0, need 12000 including fee)"
|
"Insufficient balance (have 0, need 12000 including fee)"
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mine blocks 2 to 22 (that don't send us funds) until just before the first
|
||||||
|
// transaction expires
|
||||||
|
for i in 2..23 {
|
||||||
|
let (cb, _) = fake_compact_block(
|
||||||
|
i,
|
||||||
|
ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[i as u8])),
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
insert_into_cache(db_cache, &cb);
|
||||||
|
}
|
||||||
|
scan_cached_blocks(db_cache, db_data).unwrap();
|
||||||
|
|
||||||
|
// Second spend still fails
|
||||||
|
match send_to_address(
|
||||||
|
db_data,
|
||||||
|
1,
|
||||||
|
test_prover(),
|
||||||
|
(0, &extsk),
|
||||||
|
&to,
|
||||||
|
Amount(2000),
|
||||||
|
None,
|
||||||
|
) {
|
||||||
|
Ok(_) => panic!("Should have failed"),
|
||||||
|
Err(e) => assert_eq!(
|
||||||
|
e.to_string(),
|
||||||
|
"Insufficient balance (have 0, need 12000 including fee)"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mine block 23 so that the first transaction expires
|
||||||
|
let (cb, _) = fake_compact_block(
|
||||||
|
23,
|
||||||
|
ExtendedFullViewingKey::from(&ExtendedSpendingKey::master(&[23])),
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
insert_into_cache(db_cache, &cb);
|
||||||
|
scan_cached_blocks(db_cache, db_data).unwrap();
|
||||||
|
|
||||||
|
// Second spend should now succeed
|
||||||
|
send_to_address(
|
||||||
|
db_data,
|
||||||
|
1,
|
||||||
|
test_prover(),
|
||||||
|
(0, &extsk),
|
||||||
|
&to,
|
||||||
|
Amount(2000),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue