fix(lite-backend): keep witnesses current for notes in a pending send
Notes spent by a send still in the mempool stopped getting witness updates. After a restart (pending flags are not saved), or a reorg that un-mined the send, those notes were spendable again but with stale witnesses, so the next send from them used an anchor that is not on chain and failed until a rescan. Deterministic note selection made this sticky: the stale note was picked every time it was the best fit. Witnesses now advance for every note that is not spent on chain, pending or not. Witness clearing still keys on the mined spend only, so pending notes are never cleared. The wallet file format is unchanged; an old build reading a file written while a send was pending can now spend from it (verified offline). The oracle reloads and reorgs inside the pending window and compares every unspent note's witnesses byte for byte; reverting the fix fails 9 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2323,12 +2323,14 @@ pub fn scan_full_mempool_tx(&self, tx: &Transaction, height: i32, _datetime: u64
|
||||
|
||||
// Create a single mutable slice of all the newly-added witnesses.
|
||||
// A block without shielded outputs appends nothing to any witness: don't un-share (deep-clone) them.
|
||||
// Advance every note whose nullifier is still tracked (spent.is_none(), the `nfs` set), pending
|
||||
// ones included: a reload, or a reorg of the block that mined the send, makes them spendable again.
|
||||
let block_has_outputs = block.vtx.iter().any(|t| !t.outputs.is_empty());
|
||||
let mut witness_refs: Vec<&mut IncrementalWitness<Node>> = if block_has_outputs {
|
||||
txs
|
||||
.values_mut()
|
||||
.map(|tx| tx.notes.iter_mut().filter_map(
|
||||
|nd| if nd.spent.is_none() && nd.unconfirmed_spent.is_none() { nd.witnesses.last_mut().map(|w| Arc::make_mut(w)) } else { None }))
|
||||
|nd| if nd.spent.is_none() { nd.witnesses.last_mut().map(|w| Arc::make_mut(w)) } else { None }))
|
||||
.flatten()
|
||||
.collect()
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user