A failed payout permanently burns a unique sub-link: allowance is consumed before pay_invoice and not restored on failure #5

Open
opened 2026-10-09 17:12:28 +00:00 by padreug · 0 comments
Owner

In api_lnurl_callback the sub-link is removed from usescsv before any payment is attempted (views_lnurl.py:126-128), and the except branch (views_lnurl.py:164-167) only deletes the hash-check mutex. A transient pay_invoice failure (no route, liquidity, node restart) leaves the customer with an error and the link owner one use short with nothing withdrawn; the sub-link can never be retried. For ATM cash-ins this is a stranded customer at the machine with the voucher already spent on our side.

Fix direction: reserve the use before paying (to keep the double-spend window closed) and release it on failure — restore the slot to usescsv and decrement used atomically — so a use is committed only on settlement. Same primitives as the race fix above (sandbox PR #11, release_withdraw_link_use); ship them together.

Found during reforge run #1 (sandbox withdraw#2).

In `api_lnurl_callback` the sub-link is removed from `usescsv` before any payment is attempted (`views_lnurl.py:126-128`), and the `except` branch (`views_lnurl.py:164-167`) only deletes the hash-check mutex. A transient `pay_invoice` failure (no route, liquidity, node restart) leaves the customer with an error and the link owner one use short with nothing withdrawn; the sub-link can never be retried. For ATM cash-ins this is a stranded customer at the machine with the voucher already spent on our side. Fix direction: reserve the use before paying (to keep the double-spend window closed) and release it on failure — restore the slot to `usescsv` and decrement `used` atomically — so a use is committed only on settlement. Same primitives as the race fix above (sandbox PR #11, `release_withdraw_link_use`); ship them together. Found during reforge run #1 (sandbox withdraw#2).
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/withdraw#5
No description provided.