upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/wallet_sqlite.cpp
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-08-23 07:35:31 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-08-23 07:35:31 +0000
commit63740a1b00d78441713a2b909aa40429098184d2 (patch)
treef5d05afee1d424f3f74a2099285000fd80c16798 /src/wallet_sqlite.cpp
parent33f2e8a164d0b8a508dc97372a3592d126b96a1a (diff)
payout: stop grandfathered zero-hash rounds answering for each other
Every ledger lookup identified an entry by its block hash alone -- ReconcilePayouts, the payout thread's already-paid check, RecordPayoutTxid, ForfeitPayoutRecipient, ForgetPayment's still-in-flight test, and SamePayment. Entries restored from a file written before payouts were keyed by hash all carry hash 0. Two of them therefore compare equal, and the first one found answers for the second: - RecordPayoutTxid writes a txid against the wrong round. That round can then satisfy PayoutFullyPaid and be erased from the ledger while the debt it recorded is still owed, and nothing on disk remembers it. - ReconcilePayouts drops a live in-flight record on startup because a different zero-hash round had already paid that same address. SamePayoutRound() decides it properly: a non-zero hash is unique and settles the question on its own, a zero hash falls back to the block height (which LoadPendingPayouts supplies for any entry able to name its own maturity), and a zero hash never matches a real one. Refusing to match is the safe direction at all six sites, because each treats a match as "this debt is already handled". The orphan-void scan is deliberately left alone: PayoutBlockStillOnChain returns true for a zero hash, so a grandfathered entry can never enter the orphaned list and there is nothing there to cross-match. For the residual case where an entry has neither hash nor height -- which no file this tree has written can produce -- FlushMaturePayouts now refuses to explode it and logs why, rather than paying against an identity that could belong to another round. Not paying is recoverable; recording a payment against the wrong debt is not. PayoutIdForBlock's grandfathered "block-<height>" fallback is unchanged and still safe: that id is only ever matched against pool_payout_id, which no pre-upgrade transaction carries. No on-disk format change.
Diffstat (limited to 'src/wallet_sqlite.cpp')
0 files changed, 0 insertions, 0 deletions