Skip to content

Commit a3b7fa5

Browse files
committed
loopin: fail swap when htlc amount is incorrect
Previously the swap would get stuck in a state where it wouldn't ever progress because the server rejected the htlc.
1 parent e33d2fb commit a3b7fa5

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

loopdb/swapstate.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ const (
6060
// StateInvoiceSettled means that the swap invoice has been paid by the
6161
// server.
6262
StateInvoiceSettled SwapState = 9
63+
64+
// StateFailIncorrectHtlcAmt indicates that the amount of an externally
65+
// published loop in htlc didn't match the swap amount.
66+
StateFailIncorrectHtlcAmt SwapState = 10
6367
)
6468

6569
// SwapStateType defines the types of swap states that exist. Every swap state
@@ -127,6 +131,9 @@ func (s SwapState) String() string {
127131
case StateInvoiceSettled:
128132
return "InvoiceSettled"
129133

134+
case StateFailIncorrectHtlcAmt:
135+
return "IncorrectHtlcAmt"
136+
130137
default:
131138
return "Unknown"
132139
}

loopin.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,13 @@ func (s *loopInSwap) executeSwap(globalCtx context.Context) error {
363363
return err
364364
}
365365

366+
// Verify that the confirmed (external) htlc value matches the swap
367+
// amount. Otherwise fail the swap immediately.
368+
if htlcValue != s.LoopInContract.AmountRequested {
369+
s.setState(loopdb.StateFailIncorrectHtlcAmt)
370+
return s.persistAndAnnounceState(globalCtx)
371+
}
372+
366373
// TODO: Add miner fee of htlc tx to swap cost balance.
367374

368375
// The server is expected to see the htlc on-chain and knowing that it

loopin_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,20 @@ func testLoopInTimeout(t *testing.T,
209209
Tx: &htlcTx,
210210
}
211211

212+
// Assert that the swap is failed in case of an invalid amount.
213+
invalidAmt := externalValue != 0 && externalValue != int64(req.Amount)
214+
if invalidAmt {
215+
ctx.assertState(loopdb.StateFailIncorrectHtlcAmt)
216+
ctx.store.assertLoopInState(loopdb.StateFailIncorrectHtlcAmt)
217+
218+
err = <-errChan
219+
if err != nil {
220+
t.Fatal(err)
221+
}
222+
223+
return
224+
}
225+
212226
// Client starts listening for spend of htlc.
213227
<-ctx.lnd.RegisterSpendChannel
214228

@@ -380,6 +394,7 @@ func testLoopInResume(t *testing.T, state loopdb.SwapState, expired bool) {
380394

381395
htlcTx.AddTxOut(&wire.TxOut{
382396
PkScript: htlc.PkScript,
397+
Value: int64(contract.AmountRequested),
383398
})
384399
}
385400

0 commit comments

Comments
 (0)