Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loop out: allow outbound channel set for multi-loops #205

Merged
merged 10 commits into from
May 21, 2020

Conversation

joostjager
Copy link
Contributor

Currently loop out supports multi-loops (looping out multiple channels in one operation using MPP). But there is no control over which channels are used for the payment.

This issue adds the ability for the user to indicate a set of channels which are all allowed to be used in the swap.

Depends lightningnetwork/lnd#4257

@joostjager joostjager added this to the 0.6.3 milestone May 19, 2020
@joostjager joostjager force-pushed the channel-set branch 3 times, most recently from e69c89a to 97cc3b0 Compare May 19, 2020 08:41
@joostjager joostjager marked this pull request as ready for review May 19, 2020 08:53
@joostjager
Copy link
Contributor Author

This is now implemented as an on-the-fly migration, but I am not sure whether it is the best choice. Especially the question of how to test this. Dragging in all the old serialization code mostly brings us back to the old-style migrations. And neither do I like the handling of legacy fields to be around forever.

Copy link
Contributor

@carlaKC carlaKC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tangential, but do we have an official deprecation plan for loop?

Some small comments, nice clean PR overall.

loopdb/store.go Outdated Show resolved Hide resolved
loopdb/store.go Outdated Show resolved Hide resolved
loopdb/store.go Outdated Show resolved Hide resolved
client.go Outdated
var channels string
for i, chanID := range request.OutgoingChanSet {
if i > 0 {
channels += ","
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also just make []string channels here then use strings.Join for the log

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for the strings.Join, would also not add a , at the end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't add , at the end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created ChannelSet struct with String method

loopd/view.go Outdated Show resolved Hide resolved
cmd/loop/loopout.go Show resolved Hide resolved
cmd/loop/loopout.go Outdated Show resolved Hide resolved
@joostjager
Copy link
Contributor Author

Tangential, but do we have an official deprecation plan for loop?

Just created this morning: #206

// each of the past updates to the swap itself.
stateBucket := swapBucket.Bucket(updatesBucketKey)
if stateBucket == nil {
return nil, errors.New("updates bucket not found")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be the right time to also create predefined errors instead of creating them inline (I know this is a common pattern in this file).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not convinced that we should replace every error with a constant. Some errors also have parameters and for those we'd need to create separate error structs to store the parameters. It is useful to assert on in unit tests, but that is not the case for this error.

loopdb/store.go Show resolved Hide resolved
lndclient/router_client.go Outdated Show resolved Hide resolved
loopdb/store_test.go Outdated Show resolved Hide resolved
client.go Outdated
var channels string
for i, chanID := range request.OutgoingChanSet {
if i > 0 {
channels += ","
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for the strings.Join, would also not add a , at the end.

loopdb/loopout.go Outdated Show resolved Hide resolved
loopout.go Outdated Show resolved Hide resolved
chanStrings := strings.Split(ctx.String("channel"), ",")
var outgoingChanSet []uint64
for _, chanString := range chanStrings {
chanID, err := strconv.ParseUint(chanString, 10, 64)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the the passed list/set contains duplicate items?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now handled in loopd

@bhandras
Copy link
Member

Looks good. It would be nice if you could cover the added functionality with at least one test in the PR too.

@joostjager joostjager force-pushed the channel-set branch 2 times, most recently from 5082260 to 74301e0 Compare May 20, 2020 10:29
@joostjager
Copy link
Contributor Author

Added unit test and test for on-the-fly migration

@joostjager
Copy link
Contributor Author

Before release, I want to follow up with an itest covering multi-loop: https://github.com/lightninglabs/nautilus/issues/250

Copy link
Member

@bhandras bhandras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

blockEpochChan := make(chan interface{})
statusChan := make(chan SwapInfo)

const maxParts = 5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about extending this test just a little bit, such that max parts is a parameter and we test that with zero it fails, and then 1, 2, say 5?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't just test that at this level. There is no real lnd or pathfinding involved. The test just asserts passing through the parameter. This more suitable for an itest, although it partially redoes the lnd integration test. In loop we can assume the lnd part of mpp to be working.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining, I missed that. Maybe if LND mock could be parametrized then we could still test our side a bit better. I agree it is much more convenient with itest though.

loopout_test.go Outdated Show resolved Hide resolved
loopdb/store.go Outdated Show resolved Hide resolved
loopdb/store.go Outdated Show resolved Hide resolved
cmd/loop/loopout.go Show resolved Hide resolved
// Parse outgoing channel set.
chanStrings := strings.Split(ctx.String("channel"), ",")
var outgoingChanSet []uint64
for _, chanString := range chanStrings {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any need to check that the set of channels provided are unique? I doubt it, but wanted to check that it won't behave strangely with duplicates on the lnd side.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is checked in loopd

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how seriously we account for the alternate client case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alternate client would still connect to loopd?

Another step in the separation of loop in and loop out. This prepares
for a new loop out-specific key to be added.
Preparation to prevent code duplication in future refactoring.
Split the fetch logic so that it is easier to add loop type-specific
serialization.
Expose the channel set restriction that was introduced in LND 0.10.1 on
the proxy object.
Upgrade the database schema to allow for multiple outgoing channels.
This is implemented as an on-the-fly migration leaving the old key in
place.
Expose the new channel set restriction on the loopd client rpc.
Copy link
Contributor

@carlaKC carlaKC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, awesome feature to support!

@joostjager joostjager merged commit 3316c4b into lightninglabs:master May 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants