What changed, and why it matters
This commit tidies up internal bookkeeping after a Bitcoin/Lightning submarine swap completes. It removes a watcher callback and deletes a payment bundle/hold-invoice that are no longer needed. The change appears to be a cleanup/hygiene fix rather than a direct security patch, but leaving stale callbacks and payment state around could theoretically contribute to memory growth, unexpected re-triggering of events, or minor information leakage about completed swaps.
Treat as routine maintenance with minor defensive value. Review whether the cleanup order is safe (marking redeemed before removing callbacks) and verify that no code path still expects the payment bundle or hold invoice after this point. No urgent action required.
Security signals we found
Resource lifecycle cleanup after swap completion
Removal of stale hold-invoice and payment-bundle state
Potential reduction of attack surface from lingering callbacks/state
No explicit security framing by vendor in commit message
Evidence from the diff
In electrum/submarine_swaps.py, after a submarine swap’s lockup transaction is confirmed and the REDEEM_AFTER_DOUBLE_SPENT_DELAY has passed, the code now marks the swap redeemed first, then removes the lnwatcher callback and, for non-reverse swaps, deletes the payment bundle and unregisters the hold invoice. Previously only the callback was removed. The new lines clean up lingering Lightning state that is no longer referenced.
Changed components
electrum/submarine_swaps.pySwapManagerlnwatcher callback registrylnworker payment bundle storelnworker hold invoice registryInspect captured patch +5 / −1
diff --git a/electrum/submarine_swaps.py b/electrum/submarine_swaps.py
index e5acbdd..bdad968 100644
--- a/electrum/submarine_swaps.py
+++ b/electrum/submarine_swaps.py
@@ -439,8 +439,12 @@ class SwapManager(Logger):
if spent_height > 0:
if current_height - spent_height > REDEEM_AFTER_DOUBLE_SPENT_DELAY:
self.logger.info(f'stop watching swap {swap.lockup_address}')
- self.lnwatcher.remove_callback(swap.lockup_address)
swap.is_redeemed = True
+ # cleanup
+ self.lnwatcher.remove_callback(swap.lockup_address)
+ if not swap.is_reverse:
+ self.lnworker.delete_payment_bundle(swap.payment_hash)
+ self.lnworker.unregister_hold_invoice(swap.payment_hash)
if not swap.is_reverse:
if swap.preimage is None and spent_height is not None:
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.