2020-10-13 16:56:51 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
2023-01-03 13:01:26 +01:00
|
|
|
"github.com/lightningnetwork/lnd/routing/route"
|
2020-10-13 16:56:51 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
2023-02-03 13:10:57 +01:00
|
|
|
"go.uber.org/zap/zaptest"
|
2020-10-13 16:56:51 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestProcess(t *testing.T) {
|
2022-10-13 14:06:50 +02:00
|
|
|
defer Timeout()()
|
|
|
|
|
|
|
|
|
|
t.Run("settle", func(t *testing.T) {
|
|
|
|
|
testProcess(t, resolveEventSettle)
|
|
|
|
|
})
|
|
|
|
|
t.Run("forward fail", func(t *testing.T) {
|
|
|
|
|
testProcess(t, resolveEventForwardFail)
|
|
|
|
|
})
|
|
|
|
|
t.Run("link fail", func(t *testing.T) {
|
|
|
|
|
testProcess(t, resolveEventLinkFail)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type resolveEvent int
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
resolveEventSettle resolveEvent = iota
|
|
|
|
|
resolveEventForwardFail
|
|
|
|
|
resolveEventLinkFail
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func testProcess(t *testing.T, event resolveEvent) {
|
2023-10-02 13:50:25 -04:00
|
|
|
client := newLndclientMock(testChannels, nil)
|
2020-10-13 16:56:51 +02:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
2023-10-02 13:06:28 -04:00
|
|
|
db, cleanup := setupTestDb(t, defaultFwdHistoryLimit)
|
2023-08-31 11:50:44 +02:00
|
|
|
defer cleanup()
|
|
|
|
|
|
2023-02-03 13:15:09 +01:00
|
|
|
log := zaptest.NewLogger(t).Sugar()
|
2023-01-03 13:01:26 +01:00
|
|
|
|
|
|
|
|
cfg := &Limits{
|
|
|
|
|
PerPeer: map[route.Vertex]Limit{
|
|
|
|
|
{2}: {
|
|
|
|
|
MaxHourlyRate: 60,
|
|
|
|
|
MaxPending: 1,
|
|
|
|
|
},
|
|
|
|
|
{3}: {
|
|
|
|
|
MaxHourlyRate: 60,
|
|
|
|
|
MaxPending: 1,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-31 11:50:44 +02:00
|
|
|
p := NewProcess(client, log, cfg, db)
|
2022-11-29 14:54:39 +01:00
|
|
|
|
|
|
|
|
resolved := make(chan struct{})
|
|
|
|
|
p.resolvedCallback = func() {
|
|
|
|
|
close(resolved)
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-13 16:56:51 +02:00
|
|
|
exit := make(chan error)
|
|
|
|
|
go func() {
|
2023-01-03 13:01:26 +01:00
|
|
|
exit <- p.Run(ctx)
|
2020-10-13 16:56:51 +02:00
|
|
|
}()
|
|
|
|
|
|
2023-01-03 13:01:26 +01:00
|
|
|
key := circuitKey{
|
|
|
|
|
channel: 2,
|
|
|
|
|
htlc: 5,
|
2020-10-13 16:56:51 +02:00
|
|
|
}
|
2023-01-03 13:01:26 +01:00
|
|
|
client.htlcInterceptorRequests <- &interceptedEvent{
|
|
|
|
|
circuitKey: key,
|
2020-10-13 16:56:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp := <-client.htlcInterceptorResponses
|
2023-01-03 13:01:26 +01:00
|
|
|
require.True(t, resp.resume)
|
2020-10-13 16:56:51 +02:00
|
|
|
|
2023-01-03 13:01:26 +01:00
|
|
|
htlcEvent := &resolvedEvent{
|
2023-07-21 10:44:01 -04:00
|
|
|
incomingCircuitKey: key,
|
2023-09-14 15:09:03 -04:00
|
|
|
outgoingCircuitKey: outgoingKey,
|
2020-10-13 16:56:51 +02:00
|
|
|
}
|
|
|
|
|
|
2022-10-13 14:06:50 +02:00
|
|
|
switch event {
|
|
|
|
|
case resolveEventForwardFail:
|
2023-01-03 13:01:26 +01:00
|
|
|
htlcEvent.settled = false
|
2022-10-13 14:06:50 +02:00
|
|
|
|
|
|
|
|
case resolveEventLinkFail:
|
2023-01-03 13:01:26 +01:00
|
|
|
htlcEvent.settled = false
|
2022-10-13 14:06:50 +02:00
|
|
|
|
|
|
|
|
case resolveEventSettle:
|
2023-01-03 13:01:26 +01:00
|
|
|
htlcEvent.settled = true
|
2022-10-13 14:06:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
client.htlcEvents <- htlcEvent
|
|
|
|
|
|
2022-10-13 13:55:44 +02:00
|
|
|
<-resolved
|
2020-10-13 16:56:51 +02:00
|
|
|
|
|
|
|
|
cancel()
|
2022-11-29 11:42:18 +01:00
|
|
|
require.ErrorIs(t, <-exit, context.Canceled)
|
2020-10-13 16:56:51 +02:00
|
|
|
}
|
2021-09-11 13:51:44 +02:00
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
func TestLimits(t *testing.T) {
|
|
|
|
|
for _, mode := range []Mode{ModeFail, ModeQueue, ModeQueuePeerInitiated} {
|
|
|
|
|
t.Run(mode.String(), func(t *testing.T) {
|
|
|
|
|
t.Run("rate limit", func(t *testing.T) { testRateLimit(t, mode) })
|
|
|
|
|
t.Run("max pending", func(t *testing.T) { testMaxPending(t, mode) })
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func testRateLimit(t *testing.T, mode Mode) {
|
2022-10-13 14:06:50 +02:00
|
|
|
defer Timeout()()
|
|
|
|
|
|
2023-10-02 13:06:28 -04:00
|
|
|
db, cleanup := setupTestDb(t, defaultFwdHistoryLimit)
|
2023-08-31 11:50:44 +02:00
|
|
|
defer cleanup()
|
|
|
|
|
|
2023-01-03 13:01:26 +01:00
|
|
|
cfg := &Limits{
|
|
|
|
|
PerPeer: map[route.Vertex]Limit{
|
|
|
|
|
{2}: {
|
|
|
|
|
MaxHourlyRate: 1800,
|
|
|
|
|
Mode: mode,
|
|
|
|
|
},
|
|
|
|
|
{3}: {
|
|
|
|
|
MaxHourlyRate: 1800,
|
|
|
|
|
Mode: mode,
|
|
|
|
|
},
|
2021-09-11 13:51:44 +02:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-02 13:50:25 -04:00
|
|
|
client := newLndclientMock(testChannels, nil)
|
2021-09-11 13:51:44 +02:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
2023-02-03 13:15:09 +01:00
|
|
|
log := zaptest.NewLogger(t).Sugar()
|
2023-01-03 13:01:26 +01:00
|
|
|
|
2023-08-31 11:50:44 +02:00
|
|
|
p := NewProcess(client, log, cfg, db)
|
2023-01-03 13:01:26 +01:00
|
|
|
p.burstSize = 2
|
2022-11-29 14:54:39 +01:00
|
|
|
|
2021-09-11 13:51:44 +02:00
|
|
|
exit := make(chan error)
|
|
|
|
|
go func() {
|
2023-01-03 13:01:26 +01:00
|
|
|
exit <- p.Run(ctx)
|
2021-09-11 13:51:44 +02:00
|
|
|
}()
|
|
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
var chanId uint64 = 2
|
|
|
|
|
if mode == ModeQueuePeerInitiated {
|
|
|
|
|
// We are the initiator of the channel. Not queueing is expected in this
|
|
|
|
|
// mode.
|
|
|
|
|
chanId = 3
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-03 13:01:26 +01:00
|
|
|
key := circuitKey{
|
|
|
|
|
channel: chanId,
|
|
|
|
|
htlc: 5,
|
2021-09-11 13:51:44 +02:00
|
|
|
}
|
2023-01-03 13:01:26 +01:00
|
|
|
interceptReq := &interceptedEvent{
|
|
|
|
|
circuitKey: key,
|
2021-09-11 13:51:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// First htlc accepted.
|
|
|
|
|
client.htlcInterceptorRequests <- interceptReq
|
|
|
|
|
resp := <-client.htlcInterceptorResponses
|
2023-01-03 13:01:26 +01:00
|
|
|
require.True(t, resp.resume)
|
2021-09-11 13:51:44 +02:00
|
|
|
|
|
|
|
|
// Second htlc right after is also accepted because of burst size 2.
|
2023-01-03 13:01:26 +01:00
|
|
|
interceptReq.circuitKey.htlc++
|
2021-09-11 13:51:44 +02:00
|
|
|
client.htlcInterceptorRequests <- interceptReq
|
|
|
|
|
resp = <-client.htlcInterceptorResponses
|
2023-01-03 13:01:26 +01:00
|
|
|
require.True(t, resp.resume)
|
2021-09-11 13:51:44 +02:00
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
// Third htlc again right after should hit the rate limit.
|
2023-01-03 13:01:26 +01:00
|
|
|
interceptReq.circuitKey.htlc++
|
2021-09-11 13:51:44 +02:00
|
|
|
client.htlcInterceptorRequests <- interceptReq
|
2022-11-29 17:44:55 +01:00
|
|
|
|
|
|
|
|
interceptStart := time.Now()
|
|
|
|
|
|
2021-09-11 13:51:44 +02:00
|
|
|
resp = <-client.htlcInterceptorResponses
|
|
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
if mode == ModeQueue {
|
2023-01-03 13:01:26 +01:00
|
|
|
require.True(t, resp.resume)
|
2022-11-29 17:44:55 +01:00
|
|
|
require.GreaterOrEqual(t, time.Since(interceptStart), time.Second)
|
|
|
|
|
} else {
|
2023-01-03 13:01:26 +01:00
|
|
|
require.False(t, resp.resume)
|
2022-11-29 15:18:13 +01:00
|
|
|
|
2023-01-03 13:01:26 +01:00
|
|
|
htlcEvent := &resolvedEvent{
|
2023-07-21 10:44:01 -04:00
|
|
|
incomingCircuitKey: key,
|
2023-09-14 15:09:03 -04:00
|
|
|
outgoingCircuitKey: outgoingKey,
|
2023-07-21 10:44:01 -04:00
|
|
|
settled: false,
|
2022-11-29 17:44:55 +01:00
|
|
|
}
|
2022-11-29 15:18:13 +01:00
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
client.htlcEvents <- htlcEvent
|
|
|
|
|
|
|
|
|
|
// Allow some time for the peer controller to process the failed forward
|
|
|
|
|
// event.
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
}
|
2022-11-29 15:18:13 +01:00
|
|
|
|
2021-09-11 13:51:44 +02:00
|
|
|
cancel()
|
2022-11-29 11:42:18 +01:00
|
|
|
require.ErrorIs(t, <-exit, context.Canceled)
|
2021-09-11 13:51:44 +02:00
|
|
|
}
|
2022-12-02 14:36:33 +01:00
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
func testMaxPending(t *testing.T, mode Mode) {
|
2022-12-02 14:36:33 +01:00
|
|
|
defer Timeout()()
|
|
|
|
|
|
2023-10-02 13:06:28 -04:00
|
|
|
db, cleanup := setupTestDb(t, defaultFwdHistoryLimit)
|
2023-08-31 11:50:44 +02:00
|
|
|
defer cleanup()
|
|
|
|
|
|
2023-01-03 13:01:26 +01:00
|
|
|
cfg := &Limits{
|
|
|
|
|
PerPeer: map[route.Vertex]Limit{
|
|
|
|
|
{2}: {
|
|
|
|
|
MaxHourlyRate: 60,
|
|
|
|
|
MaxPending: 1,
|
|
|
|
|
Mode: mode,
|
|
|
|
|
},
|
|
|
|
|
{3}: {
|
|
|
|
|
MaxHourlyRate: 60,
|
|
|
|
|
MaxPending: 1,
|
|
|
|
|
Mode: mode,
|
|
|
|
|
},
|
2022-12-02 14:36:33 +01:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-02 13:50:25 -04:00
|
|
|
client := newLndclientMock(testChannels, nil)
|
2022-12-02 14:36:33 +01:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
2023-02-03 13:15:09 +01:00
|
|
|
log := zaptest.NewLogger(t).Sugar()
|
2023-01-03 13:01:26 +01:00
|
|
|
|
2023-08-31 11:50:44 +02:00
|
|
|
p := NewProcess(client, log, cfg, db)
|
2023-01-03 13:01:26 +01:00
|
|
|
p.burstSize = 2
|
2022-12-02 14:36:33 +01:00
|
|
|
|
|
|
|
|
exit := make(chan error)
|
|
|
|
|
go func() {
|
2023-01-03 13:01:26 +01:00
|
|
|
exit <- p.Run(ctx)
|
2022-12-02 14:36:33 +01:00
|
|
|
}()
|
|
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
var chanId uint64 = 2
|
|
|
|
|
if mode == ModeQueuePeerInitiated {
|
|
|
|
|
// We are the initiator of the channel. Not queueing is expected in this
|
|
|
|
|
// mode.
|
|
|
|
|
chanId = 3
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-03 13:01:26 +01:00
|
|
|
key := circuitKey{
|
|
|
|
|
channel: chanId,
|
|
|
|
|
htlc: 5,
|
2022-12-02 14:36:33 +01:00
|
|
|
}
|
2023-01-03 13:01:26 +01:00
|
|
|
interceptReq := &interceptedEvent{
|
|
|
|
|
circuitKey: key,
|
2022-12-02 14:36:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// First htlc accepted.
|
|
|
|
|
client.htlcInterceptorRequests <- interceptReq
|
|
|
|
|
resp := <-client.htlcInterceptorResponses
|
2023-01-03 13:01:26 +01:00
|
|
|
require.True(t, resp.resume)
|
2022-12-02 14:36:33 +01:00
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
// Second htlc should be hitting the max pending htlcs limit.
|
2023-01-03 13:01:26 +01:00
|
|
|
interceptReq.circuitKey.htlc++
|
2022-12-02 14:36:33 +01:00
|
|
|
client.htlcInterceptorRequests <- interceptReq
|
|
|
|
|
|
2022-11-29 17:44:55 +01:00
|
|
|
if mode == ModeQueue {
|
|
|
|
|
select {
|
|
|
|
|
case <-client.htlcInterceptorResponses:
|
|
|
|
|
require.Fail(t, "unexpected response")
|
|
|
|
|
|
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
resp = <-client.htlcInterceptorResponses
|
2023-01-03 13:01:26 +01:00
|
|
|
require.False(t, resp.resume)
|
2022-11-29 17:44:55 +01:00
|
|
|
}
|
2022-12-02 14:36:33 +01:00
|
|
|
|
|
|
|
|
cancel()
|
|
|
|
|
require.ErrorIs(t, <-exit, context.Canceled)
|
|
|
|
|
}
|
2023-02-03 13:10:57 +01:00
|
|
|
|
|
|
|
|
func TestNewPeer(t *testing.T) {
|
|
|
|
|
// Initialize lnd with test channels.
|
2023-10-02 13:50:25 -04:00
|
|
|
client := newLndclientMock(testChannels, nil)
|
2023-02-03 13:10:57 +01:00
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
2023-10-02 13:06:28 -04:00
|
|
|
db, cleanup := setupTestDb(t, defaultFwdHistoryLimit)
|
2023-08-31 11:50:44 +02:00
|
|
|
defer cleanup()
|
|
|
|
|
|
2023-02-03 13:10:57 +01:00
|
|
|
log := zaptest.NewLogger(t).Sugar()
|
|
|
|
|
|
|
|
|
|
cfg := &Limits{}
|
|
|
|
|
|
2023-08-31 11:50:44 +02:00
|
|
|
p := NewProcess(client, log, cfg, db)
|
2023-02-03 13:10:57 +01:00
|
|
|
|
|
|
|
|
// Setup quick peer refresh.
|
|
|
|
|
p.peerRefreshInterval = 100 * time.Millisecond
|
|
|
|
|
|
|
|
|
|
exit := make(chan error)
|
|
|
|
|
go func() {
|
|
|
|
|
exit <- p.Run(ctx)
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
state, err := p.getRateCounters(ctx)
|
|
|
|
|
require.NoError(t, err)
|
2023-09-14 15:09:03 -04:00
|
|
|
require.Len(t, state, 3)
|
2023-02-03 13:10:57 +01:00
|
|
|
|
|
|
|
|
// Add a new peer.
|
|
|
|
|
log.Infow("Add a new peer")
|
|
|
|
|
client.channels[100] = &channel{peer: route.Vertex{100}}
|
|
|
|
|
|
|
|
|
|
// Wait for the peer to be reported.
|
|
|
|
|
require.Eventually(t, func() bool {
|
|
|
|
|
state, err := p.getRateCounters(ctx)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
2023-09-14 15:09:03 -04:00
|
|
|
return len(state) == 4
|
2023-02-03 13:10:57 +01:00
|
|
|
}, time.Second, 100*time.Millisecond)
|
|
|
|
|
|
|
|
|
|
cancel()
|
|
|
|
|
require.ErrorIs(t, <-exit, context.Canceled)
|
|
|
|
|
}
|
2023-02-13 14:28:12 +01:00
|
|
|
|
|
|
|
|
func TestBlocked(t *testing.T) {
|
|
|
|
|
defer Timeout()()
|
|
|
|
|
|
2023-10-02 13:06:28 -04:00
|
|
|
db, cleanup := setupTestDb(t, defaultFwdHistoryLimit)
|
2023-08-31 11:50:44 +02:00
|
|
|
defer cleanup()
|
|
|
|
|
|
2023-02-13 14:28:12 +01:00
|
|
|
cfg := &Limits{
|
|
|
|
|
PerPeer: map[route.Vertex]Limit{
|
|
|
|
|
{2}: {
|
|
|
|
|
MaxHourlyRate: 1800,
|
|
|
|
|
Mode: ModeBlock,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-02 13:50:25 -04:00
|
|
|
client := newLndclientMock(testChannels, nil)
|
2023-02-13 14:28:12 +01:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
|
|
log := zaptest.NewLogger(t).Sugar()
|
|
|
|
|
|
2023-08-31 11:50:44 +02:00
|
|
|
p := NewProcess(client, log, cfg, db)
|
2023-02-13 14:28:12 +01:00
|
|
|
|
|
|
|
|
exit := make(chan error)
|
|
|
|
|
go func() {
|
|
|
|
|
exit <- p.Run(ctx)
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
var chanId uint64 = 2
|
|
|
|
|
|
|
|
|
|
key := circuitKey{
|
|
|
|
|
channel: chanId,
|
|
|
|
|
htlc: 5,
|
|
|
|
|
}
|
|
|
|
|
interceptReq := &interceptedEvent{
|
|
|
|
|
circuitKey: key,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Htlc blocked.
|
|
|
|
|
client.htlcInterceptorRequests <- interceptReq
|
|
|
|
|
resp := <-client.htlcInterceptorResponses
|
|
|
|
|
require.False(t, resp.resume)
|
|
|
|
|
|
|
|
|
|
cancel()
|
|
|
|
|
require.ErrorIs(t, <-exit, context.Canceled)
|
|
|
|
|
}
|
2023-10-11 09:59:38 -04:00
|
|
|
|
2023-10-18 10:31:36 -04:00
|
|
|
// TestChannelNotFound tests that we'll successfully exit when we cannot lookup the
|
|
|
|
|
// channel that a htlc belongs to.
|
2023-10-11 09:59:38 -04:00
|
|
|
func TestChannelNotFound(t *testing.T) {
|
2023-10-02 13:50:25 -04:00
|
|
|
client := newLndclientMock(testChannels, nil)
|
2023-10-11 09:59:38 -04:00
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
2023-10-02 13:06:28 -04:00
|
|
|
db, cleanup := setupTestDb(t, defaultFwdHistoryLimit)
|
2023-10-11 09:59:38 -04:00
|
|
|
defer cleanup()
|
|
|
|
|
|
|
|
|
|
log := zaptest.NewLogger(t).Sugar()
|
|
|
|
|
|
|
|
|
|
cfg := &Limits{}
|
|
|
|
|
|
|
|
|
|
p := NewProcess(client, log, cfg, db)
|
|
|
|
|
|
|
|
|
|
exit := make(chan error)
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
exit <- p.Run(ctx)
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// Next, send a htlc that is from an unknown channel.
|
|
|
|
|
key := circuitKey{
|
|
|
|
|
channel: 99,
|
|
|
|
|
htlc: 4,
|
|
|
|
|
}
|
|
|
|
|
client.htlcInterceptorRequests <- &interceptedEvent{
|
|
|
|
|
circuitKey: key,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case err := <-exit:
|
2023-10-18 10:31:36 -04:00
|
|
|
require.ErrorIs(t, err, errChannelNotFound)
|
2023-10-11 09:59:38 -04:00
|
|
|
|
|
|
|
|
case <-time.After(time.Second * 10):
|
2023-10-18 10:31:36 -04:00
|
|
|
t.Fatalf("timeout on process error")
|
2023-10-11 09:59:38 -04:00
|
|
|
}
|
|
|
|
|
}
|
2023-10-02 13:50:25 -04:00
|
|
|
|
2023-11-27 09:53:17 +00:00
|
|
|
// TestOutgoingChannelNotFound tests the case where the outgoing channel for a htlc is
|
|
|
|
|
// not found in two cases:
|
|
|
|
|
// 1. The HTLC was settled: the channel must exist, so we fail if it's not found
|
|
|
|
|
// 2. The HTLC was failed: the outgoing channel could be bogus, so we handle the error
|
|
|
|
|
func TestOutgoingChannelNotFound(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
settled bool
|
|
|
|
|
outgoingFound bool
|
|
|
|
|
err error
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "outgoing found, settled",
|
|
|
|
|
settled: true,
|
|
|
|
|
outgoingFound: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "outgoing found, not settled",
|
|
|
|
|
settled: false,
|
|
|
|
|
outgoingFound: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "outgoing not found, settled",
|
|
|
|
|
settled: true,
|
|
|
|
|
outgoingFound: false,
|
|
|
|
|
err: errChannelNotFound,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "outgoing not found, not settled",
|
|
|
|
|
settled: false,
|
|
|
|
|
outgoingFound: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
|
testLookupOutgoingChannel(
|
|
|
|
|
t, test.settled, test.outgoingFound, test.err,
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func testLookupOutgoingChannel(t *testing.T, settled, outgoingFound bool,
|
|
|
|
|
exitErr error) {
|
|
|
|
|
|
|
|
|
|
client := newLndclientMock(testChannels, nil)
|
|
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
|
|
db, cleanup := setupTestDb(t, defaultFwdHistoryLimit)
|
|
|
|
|
defer cleanup()
|
|
|
|
|
|
|
|
|
|
log := zaptest.NewLogger(t).Sugar()
|
|
|
|
|
|
|
|
|
|
cfg := &Limits{}
|
|
|
|
|
|
|
|
|
|
p := NewProcess(client, log, cfg, db)
|
|
|
|
|
|
|
|
|
|
resolved := make(chan struct{})
|
|
|
|
|
p.resolvedCallback = func() {
|
|
|
|
|
close(resolved)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exit := make(chan error)
|
|
|
|
|
go func() {
|
|
|
|
|
exit <- p.Run(ctx)
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// Send a htlc with a known incoming channel.
|
|
|
|
|
key := circuitKey{
|
|
|
|
|
channel: 2,
|
|
|
|
|
htlc: 5,
|
|
|
|
|
}
|
|
|
|
|
client.htlcInterceptorRequests <- &interceptedEvent{
|
|
|
|
|
circuitKey: key,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp := <-client.htlcInterceptorResponses
|
|
|
|
|
require.True(t, resp.resume)
|
|
|
|
|
|
|
|
|
|
// Set the outgoing channel based on whether we want it to be found by our
|
|
|
|
|
// lookup or not.
|
|
|
|
|
outgoingKey := outgoingKey
|
|
|
|
|
if !outgoingFound {
|
|
|
|
|
outgoingKey.channel = 9999
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
htlcEvent := &resolvedEvent{
|
|
|
|
|
incomingCircuitKey: key,
|
|
|
|
|
outgoingCircuitKey: outgoingKey,
|
|
|
|
|
settled: settled,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
client.htlcEvents <- htlcEvent
|
|
|
|
|
|
|
|
|
|
// If expected, assert that we exit with an error, otherwise ensure that the htlc
|
|
|
|
|
// is settled and we exit cleanly.
|
|
|
|
|
if exitErr != nil {
|
|
|
|
|
require.ErrorIs(t, <-exit, exitErr)
|
|
|
|
|
} else {
|
|
|
|
|
<-resolved
|
|
|
|
|
|
|
|
|
|
cancel()
|
|
|
|
|
require.ErrorIs(t, <-exit, context.Canceled)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-02 13:50:25 -04:00
|
|
|
// TestClosedChannelHtlc tests that we can handle intercepted htlcs that are associated
|
|
|
|
|
// with closed channels.
|
|
|
|
|
func TestClosedChannelHtlc(t *testing.T) {
|
|
|
|
|
// Initialize lnd with a closed channel.
|
|
|
|
|
var testClosedChannels = map[uint64]*channel{
|
|
|
|
|
5: {peer: route.Vertex{2}},
|
|
|
|
|
}
|
|
|
|
|
client := newLndclientMock(testChannels, testClosedChannels)
|
|
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
|
|
db, cleanup := setupTestDb(t, defaultFwdHistoryLimit)
|
|
|
|
|
defer cleanup()
|
|
|
|
|
|
|
|
|
|
log := zaptest.NewLogger(t).Sugar()
|
|
|
|
|
|
|
|
|
|
cfg := &Limits{}
|
|
|
|
|
|
|
|
|
|
p := NewProcess(client, log, cfg, db)
|
|
|
|
|
|
|
|
|
|
exit := make(chan error)
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
exit <- p.Run(ctx)
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// Send a htlc that is from a closed channel, it should be given the go-ahead to
|
|
|
|
|
// resume.
|
|
|
|
|
key := circuitKey{
|
|
|
|
|
channel: 5,
|
|
|
|
|
htlc: 3,
|
|
|
|
|
}
|
|
|
|
|
client.htlcInterceptorRequests <- &interceptedEvent{
|
|
|
|
|
circuitKey: key,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp := <-client.htlcInterceptorResponses
|
|
|
|
|
require.Equal(t, key, resp.key)
|
|
|
|
|
|
|
|
|
|
cancel()
|
|
|
|
|
require.ErrorIs(t, <-exit, context.Canceled)
|
|
|
|
|
}
|