2021-09-07 13:14:57 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
|
2022-02-23 14:48:00 +01:00
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
2021-09-07 13:14:57 +02:00
|
|
|
"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",
|
2022-11-24 16:17:04 +01:00
|
|
|
Usage: "Deprecated. Estimate a success probability.",
|
2021-09-07 13:14:57 +02:00
|
|
|
ArgsUsage: "from-node to-node amt",
|
|
|
|
Action: actionDecorator(queryProb),
|
2022-11-24 16:17:04 +01:00
|
|
|
Hidden: true,
|
2021-09-07 13:14:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|