cmd/lncli: move commands and export
We want to export some of our CLI code to re-use in other projects. But in Golang you cannot import code from a `main` package. So we need to move the actual code into its own package and only have the `func main()` in the `main` package.
This commit is contained in:
43 files changed
+841
-674
No files matched your search
@@ -0,0 +1,372 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"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. The estimator type must be
|
||||
provided to set estimator-related parameters.`,
|
||||
Flags: []cli.Flag{
|
||||
// General settings.
|
||||
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",
|
||||
},
|
||||
// Probability estimator.
|
||||
cli.StringFlag{
|
||||
Name: "estimator",
|
||||
Usage: "the probability estimator to use, choose " +
|
||||
"between 'apriori' or 'bimodal' (bimodal is " +
|
||||
"experimental)",
|
||||
},
|
||||
// Apriori config.
|
||||
cli.DurationFlag{
|
||||
Name: "apriorihalflife",
|
||||
Usage: "the amount of time taken to restore a node " +
|
||||
"or channel to 50% probability of success.",
|
||||
},
|
||||
cli.Float64Flag{
|
||||
Name: "apriorihopprob",
|
||||
Usage: "the probability of success assigned " +
|
||||
"to hops that we have no information about",
|
||||
},
|
||||
cli.Float64Flag{
|
||||
Name: "aprioriweight",
|
||||
Usage: "the degree to which mission control should " +
|
||||
"rely on historical results, expressed as " +
|
||||
"value in [0, 1]",
|
||||
},
|
||||
cli.Float64Flag{
|
||||
Name: "aprioricapacityfraction",
|
||||
Usage: "the fraction of channels' capacities that is " +
|
||||
"considered liquid in pathfinding, a value " +
|
||||
"between [0.75-1.0]. a value of 1.0 disables " +
|
||||
"this feature.",
|
||||
},
|
||||
// Bimodal config.
|
||||
cli.DurationFlag{
|
||||
Name: "bimodaldecaytime",
|
||||
Usage: "the time span after which we phase out " +
|
||||
"learnings from previous payment attempts",
|
||||
},
|
||||
cli.Uint64Flag{
|
||||
Name: "bimodalscale",
|
||||
Usage: "controls the assumed channel liquidity " +
|
||||
"imbalance in the network, measured in msat. " +
|
||||
"a low value (compared to typical channel " +
|
||||
"capacity) anticipates unbalanced channels.",
|
||||
},
|
||||
cli.Float64Flag{
|
||||
Name: "bimodalweight",
|
||||
Usage: "controls the degree to which the probability " +
|
||||
"estimator takes into account other channels " +
|
||||
"of a router",
|
||||
},
|
||||
},
|
||||
Action: actionDecorator(setCfg),
|
||||
}
|
||||
|
||||
func setCfg(ctx *cli.Context) error {
|
||||
ctxc := getContext()
|
||||
conn := getClientConn(ctx, false)
|
||||
defer conn.Close()
|
||||
|
||||
client := routerrpc.NewRouterClient(conn)
|
||||
|
||||
// Fetch current mission control config which we update to create our
|
||||
// response.
|
||||
mcCfg, err := client.GetMissionControlConfig(
|
||||
ctxc, &routerrpc.GetMissionControlConfigRequest{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// haveValue is a helper variable to determine if a flag has been set or
|
||||
// the help should be displayed.
|
||||
var haveValue bool
|
||||
|
||||
// Handle general mission control settings.
|
||||
if ctx.IsSet("pmtnr") {
|
||||
haveValue = true
|
||||
mcCfg.Config.MaximumPaymentResults = uint32(ctx.Int("pmtnr"))
|
||||
}
|
||||
if ctx.IsSet("failrelax") {
|
||||
haveValue = true
|
||||
mcCfg.Config.MinimumFailureRelaxInterval = uint64(ctx.Duration(
|
||||
"failrelax",
|
||||
).Seconds())
|
||||
}
|
||||
|
||||
// We switch between estimators and set corresponding configs. If
|
||||
// estimator is not set, we ignore the values.
|
||||
if ctx.IsSet("estimator") {
|
||||
switch ctx.String("estimator") {
|
||||
case routing.AprioriEstimatorName:
|
||||
haveValue = true
|
||||
|
||||
// If we switch from another estimator, initialize with
|
||||
// default values.
|
||||
if mcCfg.Config.Model !=
|
||||
routerrpc.MissionControlConfig_APRIORI {
|
||||
|
||||
dCfg := routing.DefaultAprioriConfig()
|
||||
aParams := &routerrpc.AprioriParameters{
|
||||
HalfLifeSeconds: uint64(
|
||||
dCfg.PenaltyHalfLife.Seconds(),
|
||||
),
|
||||
HopProbability: dCfg.
|
||||
AprioriHopProbability,
|
||||
Weight: dCfg.AprioriWeight,
|
||||
CapacityFraction: dCfg.CapacityFraction,
|
||||
}
|
||||
|
||||
// We make sure the correct config is set.
|
||||
mcCfg.Config.EstimatorConfig =
|
||||
&routerrpc.MissionControlConfig_Apriori{
|
||||
Apriori: aParams,
|
||||
}
|
||||
}
|
||||
|
||||
// We update all values for the apriori estimator.
|
||||
mcCfg.Config.Model = routerrpc.
|
||||
MissionControlConfig_APRIORI
|
||||
|
||||
aCfg := mcCfg.Config.GetApriori()
|
||||
if ctx.IsSet("apriorihalflife") {
|
||||
aCfg.HalfLifeSeconds = uint64(ctx.Duration(
|
||||
"apriorihalflife",
|
||||
).Seconds())
|
||||
}
|
||||
|
||||
if ctx.IsSet("apriorihopprob") {
|
||||
aCfg.HopProbability = ctx.Float64(
|
||||
"apriorihopprob",
|
||||
)
|
||||
}
|
||||
|
||||
if ctx.IsSet("aprioriweight") {
|
||||
aCfg.Weight = ctx.Float64("aprioriweight")
|
||||
}
|
||||
|
||||
if ctx.IsSet("aprioricapacityfraction") {
|
||||
aCfg.CapacityFraction =
|
||||
ctx.Float64("aprioricapacityfraction")
|
||||
}
|
||||
|
||||
case routing.BimodalEstimatorName:
|
||||
haveValue = true
|
||||
|
||||
// If we switch from another estimator, initialize with
|
||||
// default values.
|
||||
if mcCfg.Config.Model !=
|
||||
routerrpc.MissionControlConfig_BIMODAL {
|
||||
|
||||
dCfg := routing.DefaultBimodalConfig()
|
||||
bParams := &routerrpc.BimodalParameters{
|
||||
DecayTime: uint64(
|
||||
dCfg.BimodalDecayTime.Seconds(),
|
||||
),
|
||||
ScaleMsat: uint64(
|
||||
dCfg.BimodalScaleMsat,
|
||||
),
|
||||
NodeWeight: dCfg.BimodalNodeWeight,
|
||||
}
|
||||
|
||||
// We make sure the correct config is set.
|
||||
mcCfg.Config.EstimatorConfig =
|
||||
&routerrpc.MissionControlConfig_Bimodal{
|
||||
Bimodal: bParams,
|
||||
}
|
||||
}
|
||||
|
||||
// We update all values for the bimodal estimator.
|
||||
mcCfg.Config.Model = routerrpc.
|
||||
MissionControlConfig_BIMODAL
|
||||
|
||||
bCfg := mcCfg.Config.GetBimodal()
|
||||
if ctx.IsSet("bimodaldecaytime") {
|
||||
bCfg.DecayTime = uint64(ctx.Duration(
|
||||
"bimodaldecaytime",
|
||||
).Seconds())
|
||||
}
|
||||
|
||||
if ctx.IsSet("bimodalscale") {
|
||||
bCfg.ScaleMsat = ctx.Uint64("bimodalscale")
|
||||
}
|
||||
|
||||
if ctx.IsSet("bimodalweight") {
|
||||
bCfg.NodeWeight = ctx.Float64(
|
||||
"bimodalweight",
|
||||
)
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown estimator %v",
|
||||
ctx.String("estimator"))
|
||||
}
|
||||
}
|
||||
|
||||
if !haveValue {
|
||||
return cli.ShowCommandHelp(ctx, "setmccfg")
|
||||
}
|
||||
|
||||
_, err = client.SetMissionControlConfig(
|
||||
ctxc, &routerrpc.SetMissionControlConfigRequest{
|
||||
Config: mcCfg.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: "Deprecated. Estimate a success probability.",
|
||||
ArgsUsage: "from-node to-node amt",
|
||||
Action: actionDecorator(queryProb),
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
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: %w", err)
|
||||
}
|
||||
|
||||
toNode, err := route.NewVertexFromStr(args.Get(1))
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid to node key: %w", err)
|
||||
}
|
||||
|
||||
amtSat, err := strconv.ParseUint(args.Get(2), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid amt: %w", 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
|
||||
}
|
||||
Reference in new issue
Block a user