From 57036d0f634c46e472cece79d7ca6f9cc18cec4c Mon Sep 17 00:00:00 2001 From: ErikEk Date: Mon, 23 Aug 2021 05:00:51 +0200 Subject: [PATCH] neutrinorpc: command interface --- cmd/lncli/main.go | 1 + cmd/lncli/neutrino_active.go | 284 ++++++++++++++++++++++++++++++++++ cmd/lncli/neutrino_default.go | 10 ++ 3 files changed, 295 insertions(+) create mode 100644 cmd/lncli/neutrino_active.go create mode 100644 cmd/lncli/neutrino_default.go diff --git a/cmd/lncli/main.go b/cmd/lncli/main.go index 5db1df4bc..ef6b4eb52 100644 --- a/cmd/lncli/main.go +++ b/cmd/lncli/main.go @@ -395,6 +395,7 @@ func main() { // Add any extra commands determined by build flags. app.Commands = append(app.Commands, autopilotCommands()...) app.Commands = append(app.Commands, invoicesCommands()...) + app.Commands = append(app.Commands, neutrinoCommands()...) app.Commands = append(app.Commands, routerCommands()...) app.Commands = append(app.Commands, walletCommands()...) app.Commands = append(app.Commands, watchtowerCommands()...) diff --git a/cmd/lncli/neutrino_active.go b/cmd/lncli/neutrino_active.go new file mode 100644 index 000000000..9df1360c3 --- /dev/null +++ b/cmd/lncli/neutrino_active.go @@ -0,0 +1,284 @@ +//go:build neutrinorpc +// +build neutrinorpc + +package main + +import ( + "github.com/lightningnetwork/lnd/lnrpc/neutrinorpc" + "github.com/urfave/cli" +) + +func getNeutrinoKitClient(ctx *cli.Context) (neutrinorpc.NeutrinoKitClient, func()) { + conn := getClientConn(ctx, false) + + cleanUp := func() { + conn.Close() + } + + return neutrinorpc.NewNeutrinoKitClient(conn), cleanUp +} + +var getNeutrinoStatusCommand = cli.Command{ + Name: "status", + Usage: "Returns the status of the running neutrino instance.", + Category: "Neutrino", + Description: "Returns the status of the light client neutrino " + + "instance, along with height and hash of the best block, and " + + "a list of connected peers.", + Action: actionDecorator(getNeutrinoStatus), +} + +func getNeutrinoStatus(ctx *cli.Context) error { + ctxc := getContext() + client, cleanUp := getNeutrinoKitClient(ctx) + defer cleanUp() + + req := &neutrinorpc.StatusRequest{} + + resp, err := client.Status(ctxc, req) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var addPeerCommand = cli.Command{ + Name: "addpeer", + Usage: "Add a peer.", + Category: "Neutrino", + Description: "Adds a new peer that has already been connected to the " + + "server.", + ArgsUsage: "address", + Action: actionDecorator(addNeutrinoPeer), +} + +func addNeutrinoPeer(ctx *cli.Context) error { + ctxc := getContext() + + // Display the command's help message if we do not have the expected + // number of arguments/flags. + if ctx.NArg() != 1 || ctx.NumFlags() > 0 { + return cli.ShowCommandHelp(ctx, "addpeer") + } + + client, cleanUp := getNeutrinoKitClient(ctx) + defer cleanUp() + + req := &neutrinorpc.AddPeerRequest{ + PeerAddrs: ctx.Args().First(), + } + + // Add a peer to the neutrino server. + resp, err := client.AddPeer(ctxc, req) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var disconnectPeerCommand = cli.Command{ + Name: "disconnectpeer", + Usage: "Disconnect a peer.", + Category: "Neutrino", + Description: "Disconnects a peer by target address. Both outbound and" + + "inbound nodes will be searched for the target node. An error " + + "message will be returned if the peer was not found.", + ArgsUsage: "address", + Action: actionDecorator(disconnectNeutrinoPeer), +} + +func disconnectNeutrinoPeer(ctx *cli.Context) error { + ctxc := getContext() + + // Display the command's help message if we do not have the expected + // number of arguments/flags. + if ctx.NArg() != 1 || ctx.NumFlags() > 0 { + return cli.ShowCommandHelp(ctx, "disconnectpeer") + } + + client, cleanUp := getNeutrinoKitClient(ctx) + defer cleanUp() + + req := &neutrinorpc.DisconnectPeerRequest{ + PeerAddrs: ctx.Args().First(), + } + + // Disconnect a peer to the neutrino server. + resp, err := client.DisconnectPeer(ctxc, req) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var isBannedCommand = cli.Command{ + Name: "isbanned", + Usage: "Get ban status.", + Category: "Neutrino", + Description: "Returns true if the peer is banned, otherwise false.", + ArgsUsage: "address", + Action: actionDecorator(isBanned), +} + +func isBanned(ctx *cli.Context) error { + ctxc := getContext() + + // Display the command's help message if we do not have the expected + // number of arguments/flags. + if ctx.NArg() != 1 { + return cli.ShowCommandHelp(ctx, "isbanned") + } + client, cleanUp := getNeutrinoKitClient(ctx) + defer cleanUp() + + req := &neutrinorpc.IsBannedRequest{ + PeerAddrs: ctx.Args().First(), + } + + // Check if the peer is banned. + resp, err := client.IsBanned(ctxc, req) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var getBlockHeaderCommand = cli.Command{ + Name: "getblockheader", + Usage: "Get a block header.", + Category: "Neutrino", + Description: "Returns a block header with a particular block hash.", + ArgsUsage: "hash", + Action: actionDecorator(getBlockHeader), +} + +func getBlockHeader(ctx *cli.Context) error { + ctxc := getContext() + args := ctx.Args() + + // Display the command's help message if we do not have the expected + // number of arguments/flags. + if !args.Present() { + return cli.ShowCommandHelp(ctx, "getblockheader") + } + + client, cleanUp := getNeutrinoKitClient(ctx) + defer cleanUp() + + req := &neutrinorpc.GetBlockHeaderRequest{ + Hash: ctx.Args().First(), + } + + resp, err := client.GetBlockHeader(ctxc, req) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var getBlockCommand = cli.Command{ + Name: "getblock", + Usage: "Get a block.", + Category: "Neutrino", + Description: "Returns a block with a particular block hash.", + ArgsUsage: "hash", + Action: actionDecorator(getBlock), +} + +func getBlock(ctx *cli.Context) error { + ctxc := getContext() + args := ctx.Args() + + // Display the command's help message if we do not have the expected + // number of arguments/flags. + if !args.Present() { + return cli.ShowCommandHelp(ctx, "getblock") + } + + client, cleanUp := getNeutrinoKitClient(ctx) + defer cleanUp() + + req := &neutrinorpc.GetBlockRequest{ + Hash: args.First(), + } + + resp, err := client.GetBlock(ctxc, req) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var getCFilterCommand = cli.Command{ + Name: "getcfilter", + Usage: "Get a compact filter.", + Category: "Neutrino", + Description: "Returns a compact filter of a particular block.", + ArgsUsage: "hash", + Action: actionDecorator(getCFilter), +} + +func getCFilter(ctx *cli.Context) error { + ctxc := getContext() + args := ctx.Args() + + // Display the command's help message if we do not have the expected + // number of arguments/flags. + if !args.Present() { + return cli.ShowCommandHelp(ctx, "getcfilter") + } + + client, cleanUp := getNeutrinoKitClient(ctx) + defer cleanUp() + + req := &neutrinorpc.GetCFilterRequest{Hash: args.First()} + + resp, err := client.GetCFilter(ctxc, req) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +// neutrinoCommands will return the set of commands to enable for neutrinorpc +// builds. +func neutrinoCommands() []cli.Command { + return []cli.Command{ + { + Name: "neutrino", + Category: "Neutrino", + Usage: "Interact with a running neutrino instance.", + Description: "", + Subcommands: []cli.Command{ + getNeutrinoStatusCommand, + addPeerCommand, + disconnectPeerCommand, + isBannedCommand, + getBlockCommand, + getBlockHeaderCommand, + getCFilterCommand, + }, + }, + } +} diff --git a/cmd/lncli/neutrino_default.go b/cmd/lncli/neutrino_default.go new file mode 100644 index 000000000..4ca9a4b7f --- /dev/null +++ b/cmd/lncli/neutrino_default.go @@ -0,0 +1,10 @@ +// +build !neutrinorpc + +package main + +import "github.com/urfave/cli" + +// neutrinoCommands will return nil for non-neutrinorpc builds. +func neutrinoCommands() []cli.Command { + return nil +}