Skip to content

Commit 2032d79

Browse files
committed
loop+test: add loop-in route hint regression
1 parent 71aa10f commit 2032d79

3 files changed

Lines changed: 85 additions & 6 deletions

File tree

loopin_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import (
1010
"github.com/btcsuite/btcd/wire"
1111
"github.com/lightninglabs/lndclient"
1212
"github.com/lightninglabs/loop/loopdb"
13+
"github.com/lightninglabs/loop/swap"
1314
"github.com/lightninglabs/loop/test"
1415
"github.com/lightninglabs/loop/utils"
1516
"github.com/lightningnetwork/lnd/chainntnfs"
1617
"github.com/lightningnetwork/lnd/clock"
1718
invpkg "github.com/lightningnetwork/lnd/invoices"
1819
"github.com/lightningnetwork/lnd/lntypes"
1920
"github.com/lightningnetwork/lnd/routing/route"
21+
"github.com/lightningnetwork/lnd/zpay32"
2022
"github.com/stretchr/testify/require"
2123
)
2224

@@ -124,6 +126,39 @@ func TestLoopInSuccess(t *testing.T) {
124126
})
125127
}
126128

129+
// TestLoopInSwapInvoiceRouteHintsMatchProbe asserts that explicit route hints
130+
// are preserved on both loop-in invoices. The probe invoice already keeps the
131+
// requested hints, while the swap invoice currently loses them via the
132+
// lndclient AddInvoice wrapper.
133+
func TestLoopInSwapInvoiceRouteHintsMatchProbe(t *testing.T) {
134+
t.Parallel()
135+
136+
ctx := newLoopInTestContext(t)
137+
cfg := newSwapConfig(
138+
&ctx.lnd.LndServices, ctx.store, ctx.server, nil,
139+
clock.NewTestClock(time.Unix(123, 0)),
140+
)
141+
142+
req := testLoopInRequest
143+
req.RouteHints = testLoopInRouteHints()
144+
145+
_, err := newLoopInSwap(t.Context(), cfg, 600, &req)
146+
require.NoError(t, err)
147+
148+
_, swapRouteHints, _, _, err := swap.DecodeInvoice(
149+
ctx.lnd.ChainParams, ctx.server.swapInvoice,
150+
)
151+
require.NoError(t, err)
152+
153+
_, probeRouteHints, _, _, err := swap.DecodeInvoice(
154+
ctx.lnd.ChainParams, ctx.server.probeInvoice,
155+
)
156+
require.NoError(t, err)
157+
158+
test.RequireRouteHintsEqual(t, req.RouteHints, probeRouteHints)
159+
test.RequireRouteHintsEqual(t, probeRouteHints, swapRouteHints)
160+
}
161+
127162
func testLoopInSuccess(t *testing.T) {
128163
defer test.Guard(t)()
129164

@@ -233,6 +268,42 @@ func testLoopInSuccess(t *testing.T) {
233268
require.NoError(t, <-errChan)
234269
}
235270

271+
// testLoopInRouteHints returns deterministic explicit route hints that can be
272+
// encoded into loop-in invoices for regression tests.
273+
func testLoopInRouteHints() [][]zpay32.HopHint {
274+
_, pubKey1 := test.CreateKey(11)
275+
_, pubKey2 := test.CreateKey(12)
276+
_, pubKey3 := test.CreateKey(13)
277+
278+
return [][]zpay32.HopHint{
279+
{
280+
{
281+
NodeID: pubKey1,
282+
ChannelID: 1,
283+
FeeBaseMSat: 10,
284+
FeeProportionalMillionths: 20,
285+
CLTVExpiryDelta: 30,
286+
},
287+
{
288+
NodeID: pubKey2,
289+
ChannelID: 2,
290+
FeeBaseMSat: 11,
291+
FeeProportionalMillionths: 21,
292+
CLTVExpiryDelta: 31,
293+
},
294+
},
295+
{
296+
{
297+
NodeID: pubKey3,
298+
ChannelID: 3,
299+
FeeBaseMSat: 12,
300+
FeeProportionalMillionths: 22,
301+
CLTVExpiryDelta: 32,
302+
},
303+
},
304+
}
305+
}
306+
236307
// TestLoopInTimeout tests scenarios where the server doesn't sweep the htlc
237308
// and the client is forced to reclaim the funds using the timeout tx.
238309
func TestLoopInTimeout(t *testing.T) {

server_mock_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ type serverMock struct {
4040

4141
height int32
4242

43-
swapInvoice string
44-
swapHash lntypes.Hash
45-
prepayHash lntypes.Hash
43+
swapInvoice string
44+
probeInvoice string
45+
swapHash lntypes.Hash
46+
prepayHash lntypes.Hash
4647

4748
// preimagePush is a channel that preimage pushes are sent into.
4849
preimagePush chan lntypes.Preimage
@@ -157,7 +158,7 @@ func getInvoice(hash lntypes.Hash, amt btcutil.Amount, memo string) (string, err
157158
}
158159

159160
func (s *serverMock) NewLoopInSwap(_ context.Context, swapHash lntypes.Hash,
160-
amount btcutil.Amount, _, _ [33]byte, swapInvoice, _ string,
161+
amount btcutil.Amount, _, _ [33]byte, swapInvoice, probeInvoice string,
161162
_ *route.Vertex, _ string) (*newLoopInResponse, error) {
162163

163164
_, receiverKey := test.CreateKey(101)
@@ -175,6 +176,7 @@ func (s *serverMock) NewLoopInSwap(_ context.Context, swapHash lntypes.Hash,
175176
)
176177

177178
s.swapInvoice = swapInvoice
179+
s.probeInvoice = probeInvoice
178180
s.swapHash = swapHash
179181

180182
// Simulate the server paying the probe invoice and expect the client to

test/invoices_mock.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,17 @@ func (s *mockInvoices) AddHoldInvoice(ctx context.Context,
8383
// Create and encode the payment request as a bech32 (zpay32) string.
8484
creationDate := time.Now()
8585

86-
payReq, err := zpay32.NewInvoice(
87-
s.lnd.ChainParams, *hash, creationDate,
86+
options := []func(*zpay32.Invoice){
8887
zpay32.Description(in.Memo),
8988
zpay32.CLTVExpiry(in.CltvExpiry),
9089
zpay32.Amount(in.Value),
90+
}
91+
for _, routeHint := range in.RouteHints {
92+
options = append(options, zpay32.RouteHint(routeHint))
93+
}
94+
95+
payReq, err := zpay32.NewInvoice(
96+
s.lnd.ChainParams, *hash, creationDate, options...,
9197
)
9298
if err != nil {
9399
return "", err

0 commit comments

Comments
 (0)