Skip to content

routing: add build route functionality#3440

Merged
Roasbeef merged 6 commits intolightningnetwork:masterfrom
joostjager:buildroute
Sep 25, 2019
Merged

routing: add build route functionality#3440
Roasbeef merged 6 commits intolightningnetwork:masterfrom
joostjager:buildroute

Conversation

@joostjager
Copy link
Contributor

@joostjager joostjager commented Aug 30, 2019

This PR adds a new rpc for advanced users that allows them to build a fully specified route from a list of pubkeys. The call looks up the relevant channel policies from the graph and calculates the required fees and time lock values.

Route building is exposed via lncli. Example command to build a two hop route:

lncli buildroute --hops <pubkey1>,<pubkey2> --amt 500

It is also possible to leave out the --amt parameter. In that case, a route is built for the minimum amount that it can carry. This option is useful to execute probe payments for which the primary objective is to pick up black holes (stuck htlc). If the payment gets stuck, the time-locked amount is minimal.

@joostjager joostjager force-pushed the buildroute branch 2 times, most recently from 1158ce8 to 038d33b Compare August 30, 2019 08:55
@joostjager joostjager requested review from halseth and wpaulino August 30, 2019 08:59
@wpaulino wpaulino added enhancement Improvements to existing features / behaviour routing rpc Related to the RPC interface v0.8.0 labels Aug 30, 2019
@wpaulino wpaulino added this to the 0.8.0 milestone Aug 30, 2019
@joostjager joostjager force-pushed the buildroute branch 7 times, most recently from 7da0d23 to c175ba8 Compare September 2, 2019 22:00
@joostjager joostjager force-pushed the buildroute branch 2 times, most recently from 769d394 to e24a703 Compare September 3, 2019 07:20
Copy link
Contributor

@halseth halseth left a comment

Choose a reason for hiding this comment

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

Looks pretty good to me :)

@joostjager joostjager force-pushed the buildroute branch 2 times, most recently from ba36796 to 94bbee4 Compare September 16, 2019 18:00
Copy link
Contributor

Choose a reason for hiding this comment

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

Asserts fields of error as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added

@joostjager joostjager force-pushed the buildroute branch 2 times, most recently from 35ad463 to 396c5b6 Compare September 17, 2019 09:40
@joostjager joostjager requested a review from wpaulino September 17, 2019 09:41
@joostjager joostjager force-pushed the buildroute branch 2 times, most recently from 8e8fa7c to 8712e88 Compare September 18, 2019 06:46
@joostjager
Copy link
Contributor Author

Also extended the test so that it also exercises selecting the best channel when there are multiple channels between a pair of nodes.

@joostjager joostjager requested a review from wpaulino September 18, 2019 06:47
Copy link
Contributor

Choose a reason for hiding this comment

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

Should use HasMaxHtlc?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed. This is the confusion that I think we shouldn't need to have.

Copy link
Contributor Author

@joostjager joostjager Sep 18, 2019

Choose a reason for hiding this comment

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

Hmm, looking in the link, it also checks for MaxHTLC == 0. I left the check identical to what happens in the link.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's because the link uses ForwardingPolicy, which doesn't contain information about whether the bit is set or not. I'm in favor of adding the check for the bit being set here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, it is indeed a good idea, because this function is also used for non-local channels. Changed

Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't we fix that? Should this be a TODO, or is there another reason?

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 would complicate path finding while we expect this situation to be rare. The spec recommends to keep all policies towards a peer identical. If that is the case, there isn't a better channel that we should have selected.

Added this as a comment

Copy link
Contributor

@halseth halseth left a comment

Choose a reason for hiding this comment

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

Only a few nits and suggestions from me, LGTM 🏆

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe this had would been less confusing if the param was called findMinAmt or similar.

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 purposely renamed it to canIncreaseAmt because I realized that it is a more generic function here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would it work to not pass this bool to the method, and instead let the caller check the returned amount? So if the amount has increased, but we cannot increase it, it will take action.

It should be equivalent, I just find the current branching within the prependChannel a bit confusing.

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 understand your suggestion, but I think it may be confusing in another way. The current code has already seen a few earlier iterations. If there isn't a way that very clearly improves the readability, I'd rather leave it as is.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this an expected error? If not maybe log as Warn

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it can happen if channels have distinct policies. If all of them do not match, we return a proper error. Warn is definitely too heavy in this situation.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's just that if this is expected to happen, and it leads us to not be able to build a route, the reason will likely never surface, as it's on trace.

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 trace log is intended for use during development. The problem with reporting the exact reason to the caller is similar to the situation that we have in path finding. There may be multiple reasons. I am afraid that just exposing a random one of them will lead to the same incorrect assumptions that we currently have for path finding.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To be clear, even if the call succeeds in building a route, some channels may have been skipped. We can't log it on Warn, because it may really not be a warning.

@wpaulino wpaulino removed their request for review September 24, 2019 00:28
Copy link
Contributor

@wpaulino wpaulino left a comment

Choose a reason for hiding this comment

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

LGTM 💫

if hasAmt {
amtMsat = ctx.Int64("amt") * 1000
if amtMsat == 0 {
return fmt.Errorf("non-zero amount required")
Copy link
Contributor

Choose a reason for hiding this comment

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

One last nit: do we still need all of this? Seems like AmtMsat can just be ctx.Uint64("amt") * 1000.

@Roasbeef Roasbeef merged commit 18f88cb into lightningnetwork:master Sep 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvements to existing features / behaviour routing rpc Related to the RPC interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants