From 6328b2e9898e7c04a1e854b39609ab8809fe3bc4 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 29 Aug 2019 13:03:37 +0200 Subject: [PATCH] lncli: add BuildRoute function --- cmd/lncli/cmd_build_route.go | 94 +++++++++++++++++++++++++++++++++++ cmd/lncli/routerrpc_active.go | 6 ++- 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 cmd/lncli/cmd_build_route.go diff --git a/cmd/lncli/cmd_build_route.go b/cmd/lncli/cmd_build_route.go new file mode 100644 index 00000000..64cda08f --- /dev/null +++ b/cmd/lncli/cmd_build_route.go @@ -0,0 +1,94 @@ +// +build routerrpc + +package main + +import ( + "context" + "errors" + "fmt" + "strings" + + "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" + "github.com/lightningnetwork/lnd/routing/route" + "github.com/urfave/cli" +) + +var buildRouteCommand = cli.Command{ + Name: "buildroute", + Category: "Payments", + Usage: "Build a route from a list of hop pubkeys.", + Action: actionDecorator(buildRoute), + Flags: []cli.Flag{ + cli.Int64Flag{ + Name: "amt", + Usage: "the amount to send expressed in satoshis. If" + + "not set, the minimum routable amount is used", + }, + cli.Int64Flag{ + Name: "final_cltv_delta", + Usage: "number of blocks the last hop has to reveal " + + "the preimage", + Value: lnd.DefaultBitcoinTimeLockDelta, + }, + cli.StringFlag{ + Name: "hops", + Usage: "comma separated hex pubkeys", + }, + cli.Uint64Flag{ + Name: "outgoing_chan_id", + Usage: "short channel id of the outgoing channel to " + + "use for the first hop of the payment", + Value: 0, + }, + }, +} + +func buildRoute(ctx *cli.Context) error { + conn := getClientConn(ctx, false) + defer conn.Close() + + client := routerrpc.NewRouterClient(conn) + + if !ctx.IsSet("hops") { + return errors.New("hops required") + } + + // Build list of hop addresses for the rpc. + hops := strings.Split(ctx.String("hops"), ",") + rpcHops := make([][]byte, 0, len(hops)) + for _, k := range hops { + pubkey, err := route.NewVertexFromStr(k) + if err != nil { + return fmt.Errorf("error parsing %v: %v", k, err) + } + rpcHops = append(rpcHops, pubkey[:]) + } + + var amtMsat int64 + hasAmt := ctx.IsSet("amt") + if hasAmt { + amtMsat = ctx.Int64("amt") * 1000 + if amtMsat == 0 { + return fmt.Errorf("non-zero amount required") + } + } + + // Call BuildRoute rpc. + req := &routerrpc.BuildRouteRequest{ + AmtMsat: amtMsat, + FinalCltvDelta: int32(ctx.Int64("final_cltv_delta")), + HopPubkeys: rpcHops, + OutgoingChanId: ctx.Uint64("outgoing_chan_id"), + } + + rpcCtx := context.Background() + route, err := client.BuildRoute(rpcCtx, req) + if err != nil { + return err + } + + printJSON(route) + + return nil +} diff --git a/cmd/lncli/routerrpc_active.go b/cmd/lncli/routerrpc_active.go index f323aed1..4d217267 100644 --- a/cmd/lncli/routerrpc_active.go +++ b/cmd/lncli/routerrpc_active.go @@ -6,5 +6,9 @@ import "github.com/urfave/cli" // routerCommands will return nil for non-routerrpc builds. func routerCommands() []cli.Command { - return []cli.Command{queryMissionControlCommand, resetMissionControlCommand} + return []cli.Command{ + queryMissionControlCommand, + resetMissionControlCommand, + buildRouteCommand, + } }