@@ -53,6 +53,15 @@ def csv_delay(self):
5353 return self .txin .get_block_based_relative_locktime () or 0
5454
5555
56+ class KeepWatchingTXO (NamedTuple ):
57+ """Used for UTXOs we don't yet know if we want to sweep, such as pending hold-invoices."""
58+ name : str
59+ until_height : int
60+
61+
62+ MaybeSweepInfo = SweepInfo | KeepWatchingTXO
63+
64+
5665def sweep_their_ctx_watchtower (
5766 chan : 'Channel' ,
5867 ctx : Transaction ,
@@ -281,7 +290,7 @@ def sweep_our_ctx(
281290 * , chan : 'AbstractChannel' ,
282291 ctx : Transaction ,
283292 actual_htlc_tx : Transaction = None , # if passed, return second stage htlcs
284- ) -> Dict [str , SweepInfo ]:
293+ ) -> Dict [str , MaybeSweepInfo ]:
285294
286295 """Handle the case where we force-close unilaterally with our latest ctx.
287296
@@ -328,7 +337,7 @@ def sweep_our_ctx(
328337 # other outputs are htlcs
329338 # if they are spent, we need to generate the script
330339 # so, second-stage htlc sweep should not be returned here
331- txs = {} # type: Dict[str, SweepInfo ]
340+ txs = {} # type: Dict[str, MaybeSweepInfo ]
332341
333342 # local anchor
334343 if actual_htlc_tx is None and chan .has_anchors ():
@@ -437,16 +446,27 @@ def txs_htlc(
437446 subject = LOCAL ,
438447 ctn = ctn )
439448 for (direction , htlc ), (ctx_output_idx , htlc_relative_idx ) in htlc_to_ctx_output_idx_map .items ():
440- if direction == RECEIVED :
441- if not chan .lnworker .is_complete_mpp (htlc .payment_hash ):
442- # do not redeem this, it might publish the preimage of an incomplete MPP
443- continue
444- preimage = chan .lnworker .get_preimage (htlc .payment_hash )
445- if not preimage :
446- # we might not have the preimage if this is a hold invoice
447- continue
448- else :
449- preimage = None
449+ preimage = None
450+ if actual_htlc_tx is None : # still in first-stage, so e.g. preimage not revealed yet
451+ if direction == RECEIVED :
452+ if not chan .lnworker .is_complete_mpp (htlc .payment_hash ):
453+ # - do not redeem this, it might publish the preimage of an incomplete MPP
454+ # - OTOH maybe this chan just got closed, and we are still receiving new htlcs
455+ # for this MPP set. So the MPP set might still transition to complete!
456+ # The MPP_TIMEOUT is only around 2 minutes, so this window is short.
457+ # The default keep_watching logic in lnwatcher is sufficient to call us again.
458+ continue
459+ if htlc .payment_hash in chan .lnworker .dont_settle_htlcs :
460+ prevout = ctx .txid () + ':%d' % ctx_output_idx
461+ txs [prevout ] = KeepWatchingTXO (
462+ name = f"our_ctx_htlc_{ ctx_output_idx } _for_hold_invoice" ,
463+ until_height = htlc .cltv_abs ,
464+ )
465+ continue
466+ preimage = chan .lnworker .get_preimage (htlc .payment_hash )
467+ if not preimage :
468+ # we might not have the preimage if this is a hold invoice
469+ continue
450470 try :
451471 txs_htlc (
452472 htlc = htlc ,
@@ -593,7 +613,7 @@ def sweep_their_ctx_to_remote_backup(
593613
594614def sweep_their_ctx (
595615 * , chan : 'Channel' ,
596- ctx : Transaction ) -> Optional [Dict [str , SweepInfo ]]:
616+ ctx : Transaction ) -> Optional [Dict [str , MaybeSweepInfo ]]:
597617 """Handle the case when the remote force-closes with their ctx.
598618 Sweep outputs that do not have a CSV delay ('to_remote' and first-stage HTLCs).
599619 Outputs with CSV delay ('to_local' and second-stage HTLCs) are redeemed by LNWatcher.
@@ -607,7 +627,7 @@ def sweep_their_ctx(
607627
608628 Outputs with CSV/CLTV are redeemed by LNWatcher.
609629 """
610- txs = {} # type: Dict[str, SweepInfo ]
630+ txs = {} # type: Dict[str, MaybeSweepInfo ]
611631 our_conf , their_conf = get_ordered_channel_configs (chan = chan , for_us = True )
612632 x = extract_ctx_secrets (chan , ctx )
613633 if not x :
@@ -737,17 +757,27 @@ def tx_htlc(
737757 subject = REMOTE ,
738758 ctn = ctn )
739759 for (direction , htlc ), (ctx_output_idx , htlc_relative_idx ) in htlc_to_ctx_output_idx_map .items ():
760+ preimage = None
740761 is_received_htlc = direction == RECEIVED
741762 if not is_received_htlc and not is_revocation :
742763 if not chan .lnworker .is_complete_mpp (htlc .payment_hash ):
743- # do not redeem this, it might publish the preimage of an incomplete MPP
764+ # - do not redeem this, it might publish the preimage of an incomplete MPP
765+ # - OTOH maybe this chan just got closed, and we are still receiving new htlcs
766+ # for this MPP set. So the MPP set might still transition to complete!
767+ # The MPP_TIMEOUT is only around 2 minutes, so this window is short.
768+ # The default keep_watching logic in lnwatcher is sufficient to call us again.
769+ continue
770+ if htlc .payment_hash in chan .lnworker .dont_settle_htlcs :
771+ prevout = ctx .txid () + ':%d' % ctx_output_idx
772+ txs [prevout ] = KeepWatchingTXO (
773+ name = f"their_ctx_htlc_{ ctx_output_idx } _for_hold_invoice" ,
774+ until_height = htlc .cltv_abs ,
775+ )
744776 continue
745777 preimage = chan .lnworker .get_preimage (htlc .payment_hash )
746778 if not preimage :
747779 # we might not have the preimage if this is a hold invoice
748780 continue
749- else :
750- preimage = None
751781 tx_htlc (
752782 htlc = htlc ,
753783 is_received_htlc = is_received_htlc ,
0 commit comments