Skip to content

repro: a failed spending-transaction fetch loses the detected spend - #2722

Draft
dorianvp wants to merge 1 commit into
devfrom
repro/spend-detection-loses-nullifier-on-fetch-error
Draft

repro: a failed spending-transaction fetch loses the detected spend#2722
dorianvp wants to merge 1 commit into
devfrom
repro/spend-detection-loses-nullifier-on-fetch-error

Conversation

@dorianvp

Copy link
Copy Markdown
Member

Claim

update_shielded_spends in pepper-sync/src/sync/spend.rs (lines 42 to 135) consumes the matching nullifier from the wallet's live NullifierMap inside detect_shielded_spends (remove_entry, lines 256 to 267, called at lines 65 to 72) before scan_spending_transactions (line 112, body at lines 146 to 215) awaits the network (client::get_compact_block at line 189 and scan_transactions at line 201). When that fetch returns Err, the function returns at line 123 before update_spent_notes (line 126) runs. The nullifier is gone from the map and the note is never marked spent, so the wallet reports a spent note as spendable and a later sync cannot re-detect it from the map.

What the test does

sync::test::spend_reset_lifecycle::failed_spending_transaction_fetch_must_not_lose_the_detected_spend in pepper-sync/src/sync.rs builds a MockWallet with one confirmed funding transaction holding a sapling note with a known nullifier, and a nullifier map entry mapping that nullifier to a ScanTarget for a spending txid that is not in the wallet. It drops the FetchRequest receiver so every fetch fails with FetcherDropped, calls update_shielded_spends with an empty scanned_blocks map, asserts the call returns Err, and then asserts that the spend is still recoverable: either the note carries the spending txid or the nullifier is still mapped.

Observed failing output

test sync::test::spend_reset_lifecycle::failed_spending_transaction_fetch_must_not_lose_the_detected_spend ... FAILED

thread '...' panicked at pepper-sync/src/sync.rs:3416:13:
the spend observation was lost: the note is unspent (spending_transaction = None) and the nullifier is no longer mapped

This PR is a reproduction and not a fix. The sync-bench A/B rule was not run because the commit adds a test only.

🤖 Generated with Claude Code

… leaves the note unspent

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant