From efb6f75d6084ec44ccb3c4431c8a7a0eda406b36 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Fri, 27 May 2022 11:14:16 +0200 Subject: [PATCH] swap: add lasthop, outgoingchanids to swapinfo --- interface.go | 9 +++++++++ loopin.go | 8 ++++++++ loopin_test.go | 17 +++++++++++++++-- loopout.go | 9 +++++++++ loopout_test.go | 10 +++++++++- 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/interface.go b/interface.go index 54e4687..d1caa9e 100644 --- a/interface.go +++ b/interface.go @@ -353,6 +353,15 @@ type SwapInfo struct { // ExternalHtlc is set to true for external loop-in swaps. ExternalHtlc bool + + // LastHop optionally specifies the last hop to use for the loop in + // payment. On a loop out this field is nil. + LastHop *route.Vertex + + // OutgoingChanSet optionally specifies the short channel ids of the + // channels that may be used to loop out. On a loop in this field + // is nil. + OutgoingChanSet loopdb.ChannelSet } // LastUpdate returns the last update time of the swap diff --git a/loopin.go b/loopin.go index eee0bc5..86857af 100644 --- a/loopin.go +++ b/loopin.go @@ -431,6 +431,14 @@ func (s *loopInSwap) sendUpdate(ctx context.Context) error { info.HtlcAddressNP2WSH = s.htlcNP2WSH.Address info.ExternalHtlc = s.ExternalHtlc + // In order to avoid potentially dangerous ownership sharing + // we copy the last hop vertex. + if s.LastHop != nil { + lastHop := &route.Vertex{} + copy(lastHop[:], s.LastHop[:]) + info.LastHop = lastHop + } + select { case s.statusChan <- *info: case <-ctx.Done(): diff --git a/loopin_test.go b/loopin_test.go index cfe42ca..8bfe401 100644 --- a/loopin_test.go +++ b/loopin_test.go @@ -11,6 +11,7 @@ import ( "github.com/lightninglabs/loop/test" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/routing/route" "github.com/stretchr/testify/require" ) @@ -34,9 +35,14 @@ func TestLoopInSuccess(t *testing.T) { cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server) + expectedLastHop := &route.Vertex{0x02} + + req := &testLoopInRequest + req.LastHop = expectedLastHop + initResult, err := newLoopInSwap( context.Background(), cfg, - height, &testLoopInRequest, + height, req, ) if err != nil { t.Fatal(err) @@ -54,7 +60,14 @@ func TestLoopInSuccess(t *testing.T) { errChan <- err }() - ctx.assertState(loopdb.StateInitiated) + swapInfo := <-ctx.statusChan + require.Equal(t, loopdb.StateInitiated, swapInfo.State) + + // Check that the SwapInfo contains the provided last hop. + require.Equal(t, expectedLastHop, swapInfo.LastHop) + + // Check that the SwapInfo does not contain an outgoing chan set. + require.Nil(t, swapInfo.OutgoingChanSet) ctx.assertState(loopdb.StateHtlcPublished) ctx.store.assertLoopInState(loopdb.StateHtlcPublished) diff --git a/loopout.go b/loopout.go index b14e15a..97e8750 100644 --- a/loopout.go +++ b/loopout.go @@ -306,6 +306,15 @@ func (s *loopOutSwap) sendUpdate(ctx context.Context) error { info.HtlcAddressP2WSH = s.htlc.Address + // In order to avoid potentially dangerous ownership sharing + // we copy the outgoing channel set. + if s.OutgoingChanSet != nil { + outgoingChanSet := make(loopdb.ChannelSet, len(s.OutgoingChanSet)) + copy(outgoingChanSet[:], s.OutgoingChanSet[:]) + + info.OutgoingChanSet = outgoingChanSet + } + select { case s.statusChan <- *info: case <-ctx.Done(): diff --git a/loopout_test.go b/loopout_test.go index 2f153fd..992f40e 100644 --- a/loopout_test.go +++ b/loopout_test.go @@ -52,9 +52,11 @@ func TestLoopOutPaymentParameters(t *testing.T) { const maxParts = 5 + chanSet := loopdb.ChannelSet{2, 3} + // Initiate the swap. req := *testRequest - req.OutgoingChanSet = loopdb.ChannelSet{2, 3} + req.OutgoingChanSet = chanSet initResult, err := newLoopOutSwap( context.Background(), cfg, height, &req, @@ -90,6 +92,12 @@ func TestLoopOutPaymentParameters(t *testing.T) { t.Fatal("unexpected state") } + // Check that the SwapInfo contains the outgoing chan set + require.Equal(t, chanSet, state.OutgoingChanSet) + + // Check that the SwapInfo does not contain a last hop + require.Nil(t, state.LastHop) + // Intercept the swap and prepay payments. Order is undefined. payments := []test.RouterPaymentChannelMessage{ <-ctx.Lnd.RouterSendPaymentChannel,