Don't accidentally rediscover an already forfeited vtxo

This commit is contained in:
Steven Roose
2024-02-06 15:50:21 +00:00
parent e0d74991a0
commit c97baf086f
2 changed files with 21 additions and 0 deletions

View File

@@ -12,6 +12,7 @@ use crate::exit;
// Trees
const VTXO_TREE: &str = "noah_vtxos";
const FORFEIT_VTXO_TREE: &str = "noah_forfeited_vtxos";
// Top-level entries
@@ -93,4 +94,14 @@ impl Db {
self.db.insert(LAST_ARK_SYNC_HEIGHT, height.to_be_bytes().to_vec())?;
Ok(())
}
pub fn store_forfeited_vtxo(&self, id: VtxoId, height: u32) -> anyhow::Result<()> {
self.db.open_tree(VTXO_TREE)?.insert(id, height.to_be_bytes().to_vec())?;
Ok(())
}
pub fn has_forfeited_vtxo(&self, id: VtxoId) -> anyhow::Result<bool> {
Ok(self.db.open_tree(VTXO_TREE)?.get(id)?.is_some())
}
//TODO(stevenroose) regularly prune forfeit vtxos based on height
}

View File

@@ -226,6 +226,12 @@ impl Wallet {
leaf_idx: leaf_idx,
exit_branch: exit_branch,
};
if self.db.has_forfeited_vtxo(vtxo.id())? {
debug!("Not adding vtxo {} because we previously forfeited it", vtxo.id());
return Ok(());
}
if self.db.get_vtxo(vtxo.id()).ok().flatten().is_none() {
debug!("Storing new vtxo {} with value {}", vtxo.id(), vtxo.spec().amount);
self.db.store_vtxo(vtxo).context("failed to store vtxo")?;
@@ -290,6 +296,7 @@ impl Wallet {
pub async fn send_payment(&mut self, destination: Destination) -> anyhow::Result<()> {
self.sync_ark().await.context("ark sync error")?;
let current_height = self.onchain.tip()?.0;
//TODO(stevenroose) impl key derivation
let vtxo_key = self.vtxo_seed.to_keypair(&SECP);
@@ -297,6 +304,7 @@ impl Wallet {
// Prepare the payment.
let input_vtxos = self.db.get_all_vtxos()?;
let vtxo_ids = input_vtxos.iter().map(|v| v.id()).collect::<HashSet<_>>();
debug!("Spending vtxos: {:?}", vtxo_ids);
let change = {
let sum = input_vtxos.iter().map(|v| v.amount()).sum::<Amount>();
if sum < destination.amount {
@@ -515,6 +523,8 @@ impl Wallet {
// And remove the input vtxos.
for v in input_vtxos {
self.db.remove_vtxo(v.id()).context("failed to drop input vtxo")?;
self.db.store_forfeited_vtxo(v.id(), current_height)
.context("failed to store forfeited vtxo")?;
}
info!("Finished payment");