lnsweep: factor out "maybe_reveal_preimage_for_htlc"
What changed, and why it matters
This commit is a simple code cleanup in Electrum's Lightning Network sweep logic. It moves a repeated block of code into a new helper function without changing what the code actually does. There is no security fix or behavior change visible in the diff.
No security action required; this is a non-functional refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change refactors preimage-revealing checks for received HTLCs into a new helper _maybe_reveal_preimage_for_htlc. The same three checks (MPP completeness, dont_settle_htlcs exclusion, and preimage availability) are preserved in the same order, and the helper is called from both sweep_our_ctx and sweep_their_ctx. The commit message explicitly states ‘no functional changes’.
Changed components
electrum/lnsweep.pyInspect captured patch +32 / −19
diff --git a/electrum/lnsweep.py b/electrum/lnsweep.py
index 9fededb..28f74f3 100644
--- a/electrum/lnsweep.py
+++ b/electrum/lnsweep.py
@@ -417,7 +417,8 @@ def sweep_our_ctx(
privkey=our_localdelayed_privkey.get_secret_bytes(),
is_revocation=False,
):
- txs[actual_htlc_tx.txid() + f':{output_idx}'] = SweepInfo(
+ prevout = actual_htlc_tx.txid() + f':{output_idx}'
+ txs[prevout] = SweepInfo(
name=f'second-stage-htlc:{output_idx}',
cltv_abs=0,
txin=sweep_txin,
@@ -437,18 +438,16 @@ def sweep_our_ctx(
subject=LOCAL,
ctn=ctn)
for (direction, htlc), (ctx_output_idx, htlc_relative_idx) in htlc_to_ctx_output_idx_map.items():
+ preimage = None
if direction == RECEIVED:
- if not chan.lnworker.is_complete_mpp(htlc.payment_hash):
- # do not redeem this, it might publish the preimage of an incomplete MPP
- continue
- preimage = chan.lnworker.get_preimage(htlc.payment_hash)
+ # note: it is the first stage (witness of htlc_tx) that reveals the preimage,
+ # so if we are already in second stage, it is already revealed.
+ # However, here, we don't make a distinction.
+ preimage = _maybe_reveal_preimage_for_htlc(
+ chan=chan, htlc=htlc,
+ )
if not preimage:
- # we might not have the preimage if this is a hold invoice
- continue
- if htlc.payment_hash in chan.lnworker.dont_settle_htlcs:
continue
- else:
- preimage = None
try:
txs_htlc(
htlc=htlc,
@@ -461,6 +460,25 @@ def sweep_our_ctx(
return txs
+def _maybe_reveal_preimage_for_htlc(
+ *,
+ chan: 'AbstractChannel',
+ htlc: 'UpdateAddHtlc',
+) -> Optional[bytes]:
+ """Given a Remote-added-HTLC, return the preimage if it's okay to reveal it on-chain."""
+ if not chan.lnworker.is_complete_mpp(htlc.payment_hash):
+ # - do not redeem this, it might publish the preimage of an incomplete MPP
+ # - OTOH maybe this chan just got closed, and we are still receiving new htlcs
+ # for this MPP set. So the MPP set might still transition to complete!
+ # The MPP_TIMEOUT is only around 2 minutes, so this window is short.
+ # The default keep_watching logic in lnwatcher is sufficient to call us again.
+ return None
+ if htlc.payment_hash in chan.lnworker.dont_settle_htlcs:
+ return None
+ preimage = chan.lnworker.get_preimage(htlc.payment_hash)
+ return preimage
+
+
def extract_ctx_secrets(chan: 'Channel', ctx: Transaction):
# note: the remote sometimes has two valid non-revoked commitment transactions,
# either of which could be broadcast
@@ -739,19 +757,14 @@ def sweep_their_ctx(
subject=REMOTE,
ctn=ctn)
for (direction, htlc), (ctx_output_idx, htlc_relative_idx) in htlc_to_ctx_output_idx_map.items():
+ preimage = None
is_received_htlc = direction == RECEIVED
if not is_received_htlc and not is_revocation:
- if not chan.lnworker.is_complete_mpp(htlc.payment_hash):
- # do not redeem this, it might publish the preimage of an incomplete MPP
- continue
- preimage = chan.lnworker.get_preimage(htlc.payment_hash)
+ preimage = _maybe_reveal_preimage_for_htlc(
+ chan=chan, htlc=htlc,
+ )
if not preimage:
- # we might not have the preimage if this is a hold invoice
continue
- if htlc.payment_hash in chan.lnworker.dont_settle_htlcs:
- continue
- else:
- preimage = None
tx_htlc(
htlc=htlc,
is_received_htlc=is_received_htlc,
Why this scored 15/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.