@@ -438,6 +438,12 @@ func (s *loopOutSwap) executeSwap(globalCtx context.Context) error {
438438 return err
439439 }
440440
441+ // If spend details are nil, we resolved the swap without waiting for
442+ // its spend, so we can exit.
443+ if spendDetails == nil {
444+ return nil
445+ }
446+
441447 // Inspect witness stack to see if it is a success transaction. We
442448 // don't just try to match with the hash of our sweep tx, because it
443449 // may be swept by a different (fee) sweep tx from a previous run.
@@ -854,6 +860,14 @@ func (s *loopOutSwap) waitForHtlcSpendConfirmed(globalCtx context.Context,
854860 return nil , err
855861 }
856862
863+ // If the result of our spend func was that the swap
864+ // has reached a final state, then we return nil spend
865+ // details, because there is no further action required
866+ // for this swap.
867+ if s .state .Type () != loopdb .StateTypePending {
868+ return nil , nil
869+ }
870+
857871 // If our off chain payment is not yet complete, we
858872 // try to push our preimage to the server.
859873 if ! paymentComplete {
@@ -889,7 +903,9 @@ func (s *loopOutSwap) pushPreimage(ctx context.Context) {
889903
890904// sweep tries to sweep the given htlc to a destination address. It takes into
891905// account the max miner fee and marks the preimage as revealed when it
892- // published the tx.
906+ // published the tx. If the preimage has not yet been revealed, and the time
907+ // during which we can safely reveal it has passed, the swap will be marked
908+ // as failed, and the function will return.
893909//
894910// TODO: Use lnd sweeper?
895911func (s * loopOutSwap ) sweep (ctx context.Context ,
@@ -900,16 +916,36 @@ func (s *loopOutSwap) sweep(ctx context.Context,
900916 return s .htlc .GenSuccessWitness (sig , s .Preimage )
901917 }
902918
919+ remainingBlocks := s .CltvExpiry - s .height
920+ blocksToLastReveal := remainingBlocks - MinLoopOutPreimageRevealDelta
921+ preimageRevealed := s .state == loopdb .StatePreimageRevealed
922+
923+ // If we have not revealed our preimage, and we don't have time left
924+ // to sweep the swap, we abandon the swap because we can no longer
925+ // sweep the success path (without potentially having to compete with
926+ // the server's timeout sweep), and we have not had any coins pulled
927+ // off-chain.
928+ if blocksToLastReveal <= 0 && ! preimageRevealed {
929+ s .log .Infof ("Preimage can no longer be safely revealed: " +
930+ "expires at: %v, current height: %v" , s .CltvExpiry ,
931+ s .height )
932+
933+ s .state = loopdb .StateFailTimeout
934+ return nil
935+ }
936+
903937 // Calculate the transaction fee based on the confirmation target
904938 // required to sweep the HTLC before the timeout. We'll use the
905939 // confirmation target provided by the client unless we've come too
906940 // close to the expiration height, in which case we'll use the default
907941 // if it is better than what the client provided.
908942 confTarget := s .SweepConfTarget
909- if s . CltvExpiry - s . height <= DefaultSweepConfTargetDelta &&
943+ if remainingBlocks <= DefaultSweepConfTargetDelta &&
910944 confTarget > DefaultSweepConfTarget {
945+
911946 confTarget = DefaultSweepConfTarget
912947 }
948+
913949 fee , err := s .sweeper .GetSweepFee (
914950 ctx , s .htlc .AddSuccessToEstimator , s .DestAddr , confTarget ,
915951 )
@@ -922,7 +958,7 @@ func (s *loopOutSwap) sweep(ctx context.Context,
922958 s .log .Warnf ("Required fee %v exceeds max miner fee of %v" ,
923959 fee , s .MaxMinerFee )
924960
925- if s . state == loopdb . StatePreimageRevealed {
961+ if preimageRevealed {
926962 // The currently required fee exceeds the max, but we
927963 // already revealed the preimage. The best we can do now
928964 // is to republish with the max fee.
0 commit comments