From 19e9ed5cdf96f6afdf0a17a9e80ae1917e1aae93 Mon Sep 17 00:00:00 2001
From: Elliott Jin <elliott.jin@gmail.com>
Date: Sat, 13 Feb 2021 00:35:07 -0800
Subject: [PATCH] lncli: add updatechanstatus command

The updatechanstatus command calls into the UpdateChanStatus RPC
in the router server.
---
 cmd/lncli/cmd_update_chan_status.go | 94 +++++++++++++++++++++++++++++
 cmd/lncli/routerrpc.go              |  1 +
 2 files changed, 95 insertions(+)
 create mode 100644 cmd/lncli/cmd_update_chan_status.go

diff --git a/cmd/lncli/cmd_update_chan_status.go b/cmd/lncli/cmd_update_chan_status.go
new file mode 100644
index 000000000..e1d08f073
--- /dev/null
+++ b/cmd/lncli/cmd_update_chan_status.go
@@ -0,0 +1,94 @@
+package main
+
+import (
+	"context"
+	"errors"
+
+	"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
+	"github.com/urfave/cli"
+)
+
+var updateChanStatusCommand = cli.Command{
+	Name:     "updatechanstatus",
+	Category: "Channels",
+	Usage:    "Set the status of an existing channel on the network.",
+	Description: `
+	Set the status of an existing channel on the network. The actions can
+	be "enable", "disable", or "auto". If the action changes the status, a
+	message will be broadcast over the network.
+
+	Note that enabling / disabling a channel using this command ONLY affects
+	what's advertised over the network. For example, disabling a channel
+	using this command does not close it.
+
+	If a channel is manually disabled, automatic / background requests to
+	re-enable the channel will be ignored. However, if a channel is
+	manually enabled, automatic / background requests to disable the
+	channel will succeed (such requests are usually made on channel close
+	or when the peer is down).
+
+	The "auto" action restores automatic channel state management. Per
+	the behavior described above, it's only needed to undo the effect of
+	a prior "disable" action, and will be a no-op otherwise.`,
+	ArgsUsage: "funding_txid [output_index] action",
+	Flags: []cli.Flag{
+		cli.StringFlag{
+			Name:  "funding_txid",
+			Usage: "the txid of the channel's funding transaction",
+		},
+		cli.IntFlag{
+			Name: "output_index",
+			Usage: "the output index for the funding output of the funding " +
+				"transaction",
+		},
+		cli.StringFlag{
+			Name: "action",
+			Usage: `the action to take: must be one of "enable", "disable", ` +
+				`or "auto"`,
+		},
+	},
+	Action: actionDecorator(updateChanStatus),
+}
+
+func updateChanStatus(ctx *cli.Context) error {
+	conn := getClientConn(ctx, false)
+	defer conn.Close()
+
+	if ctx.NArg() == 0 && ctx.NumFlags() == 0 {
+		_ = cli.ShowCommandHelp(ctx, "updatechanstatus")
+		return nil
+	}
+
+	channelPoint, err := parseChannelPoint(ctx)
+	if err != nil {
+		return err
+	}
+
+	var action routerrpc.ChanStatusAction
+	switch ctx.String("action") {
+	case "enable":
+		action = routerrpc.ChanStatusAction_ENABLE
+	case "disable":
+		action = routerrpc.ChanStatusAction_DISABLE
+	case "auto":
+		action = routerrpc.ChanStatusAction_AUTO
+	default:
+		return errors.New(`action must be one of "enable", "disable", ` +
+			`or "auto"`)
+	}
+	req := &routerrpc.UpdateChanStatusRequest{
+		ChanPoint: channelPoint,
+		Action:    action,
+	}
+
+	client := routerrpc.NewRouterClient(conn)
+	ctxb := context.Background()
+	resp, err := client.UpdateChanStatus(ctxb, req)
+	if err != nil {
+		return err
+	}
+
+	printRespJSON(resp)
+
+	return nil
+}
diff --git a/cmd/lncli/routerrpc.go b/cmd/lncli/routerrpc.go
index 04c9676ec..4cea75be4 100644
--- a/cmd/lncli/routerrpc.go
+++ b/cmd/lncli/routerrpc.go
@@ -11,5 +11,6 @@ func routerCommands() []cli.Command {
 		buildRouteCommand,
 		getCfgCommand,
 		setCfgCommand,
+		updateChanStatusCommand,
 	}
 }