Skip to content

Commit 8d4404a

Browse files
yyforyongyucarlaKC
authored andcommitted
loopout: add test for checking preimage reveal after timeout
1 parent ab9a662 commit 8d4404a

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

loopout_test.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,3 +581,117 @@ func TestPreimagePush(t *testing.T) {
581581

582582
require.NoError(t, <-errChan)
583583
}
584+
585+
// TestExpiryBeforeReveal tests the case where the on-chain HTLC expires before
586+
// we have revealed our preimage. This test demonstrates that the client will
587+
// erroneously reveal the preimage even though we're nearing our timeout.
588+
func TestExpiryBeforeReveal(t *testing.T) {
589+
defer test.Guard(t)()
590+
591+
lnd := test.NewMockLnd()
592+
ctx := test.NewContext(t, lnd)
593+
server := newServerMock(lnd)
594+
595+
testReq := *testRequest
596+
597+
// Set on-chain HTLC CLTV.
598+
testReq.Expiry = ctx.Lnd.Height + testLoopOutMinOnChainCltvDelta
599+
600+
// Set our fee estimate to higher than our max miner fee will allow.
601+
lnd.SetFeeEstimate(testReq.SweepConfTarget, chainfee.SatPerKWeight(
602+
testReq.MaxMinerFee*2,
603+
))
604+
605+
// Setup the cfg using mock server and init a loop out request.
606+
cfg := newSwapConfig(
607+
&lnd.LndServices, newStoreMock(t), server,
608+
)
609+
initResult, err := newLoopOutSwap(
610+
context.Background(), cfg, ctx.Lnd.Height, &testReq,
611+
)
612+
require.NoError(t, err)
613+
swap := initResult.swap
614+
615+
// Set up the required dependencies to execute the swap.
616+
sweeper := &sweep.Sweeper{Lnd: &lnd.LndServices}
617+
blockEpochChan := make(chan interface{})
618+
statusChan := make(chan SwapInfo)
619+
expiryChan := make(chan time.Time)
620+
timerFactory := func(_ time.Duration) <-chan time.Time {
621+
return expiryChan
622+
}
623+
624+
errChan := make(chan error)
625+
cancelCtx, cancel := context.WithCancel(context.Background())
626+
go func() {
627+
err := swap.execute(cancelCtx, &executeConfig{
628+
statusChan: statusChan,
629+
blockEpochChan: blockEpochChan,
630+
timerFactory: timerFactory,
631+
sweeper: sweeper,
632+
}, ctx.Lnd.Height)
633+
if err != nil {
634+
log.Error(err)
635+
}
636+
errChan <- err
637+
}()
638+
639+
// The swap should be found in its initial state.
640+
cfg.store.(*storeMock).assertLoopOutStored()
641+
state := <-statusChan
642+
require.Equal(t, loopdb.StateInitiated, state.State)
643+
644+
// We'll then pay both the swap and prepay invoice, which should trigger
645+
// the server to publish the on-chain HTLC.
646+
signalSwapPaymentResult := ctx.AssertPaid(swapInvoiceDesc)
647+
signalPrepaymentResult := ctx.AssertPaid(prepayInvoiceDesc)
648+
649+
signalSwapPaymentResult(nil)
650+
signalPrepaymentResult(nil)
651+
652+
// Notify the confirmation notification for the HTLC.
653+
ctx.AssertRegisterConf(false, defaultConfirmations)
654+
655+
// Advance the block height to get the HTLC confirmed.
656+
blockEpochChan <- ctx.Lnd.Height + 1
657+
658+
htlcTx := wire.NewMsgTx(2)
659+
htlcTx.AddTxOut(&wire.TxOut{
660+
Value: int64(swap.AmountRequested),
661+
PkScript: swap.htlc.PkScript,
662+
})
663+
ctx.NotifyConf(htlcTx)
664+
665+
// The client should then register for a spend of the HTLC and attempt
666+
// to sweep it using the custom confirmation target.
667+
ctx.AssertRegisterSpendNtfn(swap.htlc.PkScript)
668+
669+
// Assert that we made a query to track our payment, as required for
670+
// preimage push tracking.
671+
ctx.AssertTrackPayment()
672+
673+
// Tick the expiry channel. Because our max miner fee is too high, we
674+
// won't attempt a sweep at this point.
675+
expiryChan <- testTime
676+
677+
// Now we decrease our conf target to less than our max miner fee.
678+
lnd.SetFeeEstimate(testReq.SweepConfTarget, chainfee.SatPerKWeight(
679+
testReq.MaxMinerFee/2,
680+
))
681+
682+
// Advance the block height to the point where we would do timeout
683+
// instead of pushing the preimage.
684+
blockEpochChan <- lnd.Height + testReq.Expiry
685+
686+
// Tick our expiry chan again, this time we expect the swap to
687+
// publish our sweep timeout, despite expiry having passed, and the
688+
// potential for a race with the server.
689+
expiryChan <- testTime
690+
691+
// Expect a signing request for the HTLC success transaction.
692+
<-ctx.Lnd.SignOutputRawChannel
693+
694+
// We just cancel the swap now rather than testing to completion.
695+
cancel()
696+
require.Equal(t, context.Canceled, <-errChan)
697+
}

0 commit comments

Comments
 (0)