lnd/cmd/lncli/cmd_mission_control.go
Oliver Gugger 1d103f1f55
cmd/lncli: group all Mission Control cmds into own file
Having one file per sub command seems a bit too excessive and isn't
really implemented for any of the other commands. So we just group the
Mission Control commands into their own file for now.
2021-09-23 16:59:41 +02:00

237 lines
5.1 KiB
Go

package main
import (
"fmt"
"strconv"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/urfave/cli"
)
var getCfgCommand = cli.Command{
Name: "getmccfg",
Category: "Mission Control",
Usage: "Display mission control's config.",
Description: `
Returns the config currently being used by mission control.
`,
Action: actionDecorator(getCfg),
}
func getCfg(ctx *cli.Context) error {
ctxc := getContext()
conn := getClientConn(ctx, false)
defer conn.Close()
client := routerrpc.NewRouterClient(conn)
resp, err := client.GetMissionControlConfig(
ctxc, &routerrpc.GetMissionControlConfigRequest{},
)
if err != nil {
return err
}
printRespJSON(resp)
return nil
}
var setCfgCommand = cli.Command{
Name: "setmccfg",
Category: "Mission Control",
Usage: "Set mission control's config.",
Description: `
Update the config values being used by mission control to calculate
the probability that payment routes will succeed.
`,
Flags: []cli.Flag{
cli.DurationFlag{
Name: "halflife",
Usage: "the amount of time taken to restore a node " +
"or channel to 50% probability of success.",
},
cli.Float64Flag{
Name: "hopprob",
Usage: "the probability of success assigned " +
"to hops that we have no information about",
},
cli.Float64Flag{
Name: "weight",
Usage: "the degree to which mission control should " +
"rely on historical results, expressed as " +
"value in [0;1]",
}, cli.UintFlag{
Name: "pmtnr",
Usage: "the number of payments mission control " +
"should store",
},
cli.DurationFlag{
Name: "failrelax",
Usage: "the amount of time to wait after a failure " +
"before raising failure amount",
},
},
Action: actionDecorator(setCfg),
}
func setCfg(ctx *cli.Context) error {
ctxc := getContext()
conn := getClientConn(ctx, false)
defer conn.Close()
client := routerrpc.NewRouterClient(conn)
resp, err := client.GetMissionControlConfig(
ctxc, &routerrpc.GetMissionControlConfigRequest{},
)
if err != nil {
return err
}
var haveValue bool
if ctx.IsSet("halflife") {
haveValue = true
resp.Config.HalfLifeSeconds = uint64(ctx.Duration(
"halflife",
).Seconds())
}
if ctx.IsSet("hopprob") {
haveValue = true
resp.Config.HopProbability = float32(ctx.Float64("hopprob"))
}
if ctx.IsSet("weight") {
haveValue = true
resp.Config.Weight = float32(ctx.Float64("weight"))
}
if ctx.IsSet("pmtnr") {
haveValue = true
resp.Config.MaximumPaymentResults = uint32(ctx.Int("pmtnr"))
}
if ctx.IsSet("failrelax") {
haveValue = true
resp.Config.MinimumFailureRelaxInterval = uint64(ctx.Duration(
"failrelax",
).Seconds())
}
if !haveValue {
return cli.ShowCommandHelp(ctx, "setmccfg")
}
_, err = client.SetMissionControlConfig(
ctxc, &routerrpc.SetMissionControlConfigRequest{
Config: resp.Config,
},
)
return err
}
var queryMissionControlCommand = cli.Command{
Name: "querymc",
Category: "Mission Control",
Usage: "Query the internal mission control state.",
Action: actionDecorator(queryMissionControl),
}
func queryMissionControl(ctx *cli.Context) error {
ctxc := getContext()
conn := getClientConn(ctx, false)
defer conn.Close()
client := routerrpc.NewRouterClient(conn)
req := &routerrpc.QueryMissionControlRequest{}
snapshot, err := client.QueryMissionControl(ctxc, req)
if err != nil {
return err
}
printRespJSON(snapshot)
return nil
}
var queryProbCommand = cli.Command{
Name: "queryprob",
Category: "Mission Control",
Usage: "Estimate a success probability.",
ArgsUsage: "from-node to-node amt",
Action: actionDecorator(queryProb),
}
func queryProb(ctx *cli.Context) error {
ctxc := getContext()
args := ctx.Args()
if len(args) != 3 {
return cli.ShowCommandHelp(ctx, "queryprob")
}
fromNode, err := route.NewVertexFromStr(args.Get(0))
if err != nil {
return fmt.Errorf("invalid from node key: %v", err)
}
toNode, err := route.NewVertexFromStr(args.Get(1))
if err != nil {
return fmt.Errorf("invalid to node key: %v", err)
}
amtSat, err := strconv.ParseUint(args.Get(2), 10, 64)
if err != nil {
return fmt.Errorf("invalid amt: %v", err)
}
amtMsat := lnwire.NewMSatFromSatoshis(
btcutil.Amount(amtSat),
)
conn := getClientConn(ctx, false)
defer conn.Close()
client := routerrpc.NewRouterClient(conn)
req := &routerrpc.QueryProbabilityRequest{
FromNode: fromNode[:],
ToNode: toNode[:],
AmtMsat: int64(amtMsat),
}
response, err := client.QueryProbability(ctxc, req)
if err != nil {
return err
}
printRespJSON(response)
return nil
}
var resetMissionControlCommand = cli.Command{
Name: "resetmc",
Category: "Mission Control",
Usage: "Reset internal mission control state.",
Action: actionDecorator(resetMissionControl),
}
func resetMissionControl(ctx *cli.Context) error {
ctxc := getContext()
conn := getClientConn(ctx, false)
defer conn.Close()
client := routerrpc.NewRouterClient(conn)
req := &routerrpc.ResetMissionControlRequest{}
_, err := client.ResetMissionControl(ctxc, req)
return err
}