@@ -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,29 @@ 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 ():
449+ preimage = None
440450 if direction == RECEIVED :
451+ # note: it is the first stage (witness of htlc_tx) that reveals the preimage,
452+ # so if we are already in second stage, it is already revealed.
453+ # However, here, we don't make a distinction.
441454 if not chan .lnworker .is_complete_mpp (htlc .payment_hash ):
442- # do not redeem this, it might publish the preimage of an incomplete MPP
455+ # - do not redeem this, it might publish the preimage of an incomplete MPP
456+ # - OTOH maybe this chan just got closed, and we are still receiving new htlcs
457+ # for this MPP set. So the MPP set might still transition to complete!
458+ # The MPP_TIMEOUT is only around 2 minutes, so this window is short.
459+ # The default keep_watching logic in lnwatcher is sufficient to call us again.
460+ continue
461+ if htlc .payment_hash in chan .lnworker .dont_settle_htlcs :
462+ prevout = ctx .txid () + ':%d' % ctx_output_idx
463+ txs [prevout ] = KeepWatchingTXO (
464+ name = f"our_ctx_htlc_{ ctx_output_idx } _for_hold_invoice" ,
465+ until_height = htlc .cltv_abs ,
466+ )
443467 continue
444468 preimage = chan .lnworker .get_preimage (htlc .payment_hash )
445469 if not preimage :
446470 # we might not have the preimage if this is a hold invoice
447471 continue
448- else :
449- preimage = None
450472 try :
451473 txs_htlc (
452474 htlc = htlc ,
@@ -593,7 +615,7 @@ def sweep_their_ctx_to_remote_backup(
593615
594616def sweep_their_ctx (
595617 * , chan : 'Channel' ,
596- ctx : Transaction ) -> Optional [Dict [str , SweepInfo ]]:
618+ ctx : Transaction ) -> Optional [Dict [str , MaybeSweepInfo ]]:
597619 """Handle the case when the remote force-closes with their ctx.
598620 Sweep outputs that do not have a CSV delay ('to_remote' and first-stage HTLCs).
599621 Outputs with CSV delay ('to_local' and second-stage HTLCs) are redeemed by LNWatcher.
@@ -607,7 +629,7 @@ def sweep_their_ctx(
607629
608630 Outputs with CSV/CLTV are redeemed by LNWatcher.
609631 """
610- txs = {} # type: Dict[str, SweepInfo ]
632+ txs = {} # type: Dict[str, MaybeSweepInfo ]
611633 our_conf , their_conf = get_ordered_channel_configs (chan = chan , for_us = True )
612634 x = extract_ctx_secrets (chan , ctx )
613635 if not x :
@@ -737,17 +759,27 @@ def tx_htlc(
737759 subject = REMOTE ,
738760 ctn = ctn )
739761 for (direction , htlc ), (ctx_output_idx , htlc_relative_idx ) in htlc_to_ctx_output_idx_map .items ():
762+ preimage = None
740763 is_received_htlc = direction == RECEIVED
741764 if not is_received_htlc and not is_revocation :
742765 if not chan .lnworker .is_complete_mpp (htlc .payment_hash ):
743- # do not redeem this, it might publish the preimage of an incomplete MPP
766+ # - do not redeem this, it might publish the preimage of an incomplete MPP
767+ # - OTOH maybe this chan just got closed, and we are still receiving new htlcs
768+ # for this MPP set. So the MPP set might still transition to complete!
769+ # The MPP_TIMEOUT is only around 2 minutes, so this window is short.
770+ # The default keep_watching logic in lnwatcher is sufficient to call us again.
771+ continue
772+ if htlc .payment_hash in chan .lnworker .dont_settle_htlcs :
773+ prevout = ctx .txid () + ':%d' % ctx_output_idx
774+ txs [prevout ] = KeepWatchingTXO (
775+ name = f"their_ctx_htlc_{ ctx_output_idx } _for_hold_invoice" ,
776+ until_height = htlc .cltv_abs ,
777+ )
744778 continue
745779 preimage = chan .lnworker .get_preimage (htlc .payment_hash )
746780 if not preimage :
747781 # we might not have the preimage if this is a hold invoice
748782 continue
749- else :
750- preimage = None
751783 tx_htlc (
752784 htlc = htlc ,
753785 is_received_htlc = is_received_htlc ,
0 commit comments