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

routing: add support for pegged hops in findPaths #2444

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 54 additions & 5 deletions cmd/lncli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -2824,11 +2824,37 @@ func getNodeInfo(ctx *cli.Context) error {
}

var queryRoutesCommand = cli.Command{
Name: "queryroutes",
Category: "Payments",
Usage: "Query a route to a destination.",
Description: "Queries the channel router for a potential path to the destination that has sufficient flow for the amount including fees",
ArgsUsage: "dest amt",
Name: "queryroutes",
Category: "Payments",
Usage: "Query a route to a destination.",
Description: `
Queries the channel router for a potential path to the destination that
has sufficient flow for the amount including fees.

A series of nodes and channels the route must pass through can optionally
be provided. The node id is mandatory. The channel leading to this node
can optionally be pegged too, otherwise the channel id should be set to 0.
The resulting route is composed of segments connecting between the pegged
nodes. Each segment does not have loops, but the entire path may. The
route selection assures that no edge will be transversed twice at the
same direction.
The alternate routes are stitched from N-1 shortest segment paths and
one alternate segment path.

Below is an example of a query using routing pegs:

lncli queryroutes --pegs='{"hop_pegs": [
{
"node_id": "026a52eadd42eabb70e9b0481af7001d299f7d7b41030977bb37a2faac7bbe0012",
"chan_id": "2043992116101120"
}
]
}' "034a15c028970d4070c60f532018cfdb943b584ba267c83fe333ef1ad70b10feaf" 333

Note the single quote used to encapsulate the pegs.
`,

ArgsUsage: "dest amt",
Flags: []cli.Flag{
cli.StringFlag{
Name: "dest",
Expand Down Expand Up @@ -2859,6 +2885,14 @@ var queryRoutesCommand = cli.Command{
Usage: "(optional) number of blocks the last hop has to reveal " +
"the preimage",
},
cli.StringFlag{
Name: "pegs",
Usage: "(optional) a json array string of nodes and channels the " +
"route must path through. Each pegged hop must contain the " +
"public key of the node that the route must path through, " +
"and optionally a channel id leading to that node that the " +
"route should path through, or otherwise set as 0.",
},
},
Action: actionDecorator(queryRoutes),
}
Expand Down Expand Up @@ -2903,12 +2937,27 @@ func queryRoutes(ctx *cli.Context) error {
return err
}

var routePeg *lnrpc.RoutePeg
if ctx.IsSet("pegs") {
jsonPegs := ctx.String("pegs")
pegs := &lnrpc.RoutePeg{}
err = jsonpb.UnmarshalString(jsonPegs, pegs)
if err != nil {
return fmt.Errorf("unable to unmarshal json string "+
"from incoming array of pegs: %v", err)
}
routePeg = &lnrpc.RoutePeg{
HopPegs: pegs.HopPegs,
}
}

req := &lnrpc.QueryRoutesRequest{
PubKey: dest,
Amt: amt,
FeeLimit: feeLimit,
NumRoutes: int32(ctx.Int("num_max_routes")),
FinalCltvDelta: int32(ctx.Int("final_cltv_delta")),
RoutePeg: routePeg,
}

route, err := client.QueryRoutes(ctxb, req)
Expand Down
1,236 changes: 670 additions & 566 deletions lnrpc/rpc.pb.go

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions lnrpc/rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,11 @@ message QueryRoutesRequest {
send the payment.
*/
FeeLimit fee_limit = 5;

/**
An optional list of nodes and channels the route must pass through in that order.
*/
RoutePeg route_peg = 6;
}
message QueryRoutesResponse {
repeated Route routes = 1 [json_name = "routes"];
Expand Down Expand Up @@ -1719,6 +1724,21 @@ message ClosedChannelUpdate {
ChannelPoint chan_point = 4;
}

message HopPeg {
/// The public key of the pegged node.
string node_id = 1 [json_name = "node_id"];

/// Optional. If not 0, the unique identifier of the pegged channel leading to the node.
uint64 chan_id = 2 [json_name = "chan_id"];
}

message RoutePeg {
/**
A list of hop pegs that that the selected route needs to pass through in that order.
*/
repeated HopPeg hop_pegs = 1 [json_name = "hop_pegs"];
}

message HopHint {
/// The public key of the node at the start of the channel.
string node_id = 1 [json_name = "node_id"];
Expand Down
5 changes: 5 additions & 0 deletions routing/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ const (
// the channel graph.
ErrTargetNotInNetwork

// ErrPegNotInNetwork is returned when one or more of the pegged nodes
// or channels requested from path-finding isn't known to be within
// the current version of the channel graph.
ErrPegNotInNetwork

// ErrOutdated is returned when the routing update already have
// been applied, or a newer update is already known.
ErrOutdated
Expand Down
Loading