github.com/decred/dcrlnd@v0.7.6/cmd/dcrlncli/cmd_mission_control.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "strconv" 6 7 "github.com/decred/dcrd/dcrutil/v4" 8 "github.com/decred/dcrlnd/lnrpc/routerrpc" 9 "github.com/decred/dcrlnd/lnwire" 10 "github.com/decred/dcrlnd/routing/route" 11 "github.com/urfave/cli" 12 ) 13 14 var getCfgCommand = cli.Command{ 15 Name: "getmccfg", 16 Category: "Mission Control", 17 Usage: "Display mission control's config.", 18 Description: ` 19 Returns the config currently being used by mission control. 20 `, 21 Action: actionDecorator(getCfg), 22 } 23 24 func getCfg(ctx *cli.Context) error { 25 ctxc := getContext() 26 conn := getClientConn(ctx, false) 27 defer conn.Close() 28 29 client := routerrpc.NewRouterClient(conn) 30 31 resp, err := client.GetMissionControlConfig( 32 ctxc, &routerrpc.GetMissionControlConfigRequest{}, 33 ) 34 if err != nil { 35 return err 36 } 37 38 printRespJSON(resp) 39 40 return nil 41 } 42 43 var setCfgCommand = cli.Command{ 44 Name: "setmccfg", 45 Category: "Mission Control", 46 Usage: "Set mission control's config.", 47 Description: ` 48 Update the config values being used by mission control to calculate 49 the probability that payment routes will succeed. 50 `, 51 Flags: []cli.Flag{ 52 cli.DurationFlag{ 53 Name: "halflife", 54 Usage: "the amount of time taken to restore a node " + 55 "or channel to 50% probability of success.", 56 }, 57 cli.Float64Flag{ 58 Name: "hopprob", 59 Usage: "the probability of success assigned " + 60 "to hops that we have no information about", 61 }, 62 cli.Float64Flag{ 63 Name: "weight", 64 Usage: "the degree to which mission control should " + 65 "rely on historical results, expressed as " + 66 "value in [0;1]", 67 }, cli.UintFlag{ 68 Name: "pmtnr", 69 Usage: "the number of payments mission control " + 70 "should store", 71 }, 72 cli.DurationFlag{ 73 Name: "failrelax", 74 Usage: "the amount of time to wait after a failure " + 75 "before raising failure amount", 76 }, 77 }, 78 Action: actionDecorator(setCfg), 79 } 80 81 func setCfg(ctx *cli.Context) error { 82 ctxc := getContext() 83 conn := getClientConn(ctx, false) 84 defer conn.Close() 85 86 client := routerrpc.NewRouterClient(conn) 87 88 resp, err := client.GetMissionControlConfig( 89 ctxc, &routerrpc.GetMissionControlConfigRequest{}, 90 ) 91 if err != nil { 92 return err 93 } 94 95 var haveValue bool 96 97 if ctx.IsSet("halflife") { 98 haveValue = true 99 resp.Config.HalfLifeSeconds = uint64(ctx.Duration( 100 "halflife", 101 ).Seconds()) 102 } 103 104 if ctx.IsSet("hopprob") { 105 haveValue = true 106 resp.Config.HopProbability = float32(ctx.Float64("hopprob")) 107 } 108 109 if ctx.IsSet("weight") { 110 haveValue = true 111 resp.Config.Weight = float32(ctx.Float64("weight")) 112 } 113 114 if ctx.IsSet("pmtnr") { 115 haveValue = true 116 resp.Config.MaximumPaymentResults = uint32(ctx.Int("pmtnr")) 117 } 118 119 if ctx.IsSet("failrelax") { 120 haveValue = true 121 resp.Config.MinimumFailureRelaxInterval = uint64(ctx.Duration( 122 "failrelax", 123 ).Seconds()) 124 } 125 126 if !haveValue { 127 return cli.ShowCommandHelp(ctx, "setmccfg") 128 } 129 130 _, err = client.SetMissionControlConfig( 131 ctxc, &routerrpc.SetMissionControlConfigRequest{ 132 Config: resp.Config, 133 }, 134 ) 135 return err 136 } 137 138 var queryMissionControlCommand = cli.Command{ 139 Name: "querymc", 140 Category: "Mission Control", 141 Usage: "Query the internal mission control state.", 142 Action: actionDecorator(queryMissionControl), 143 } 144 145 func queryMissionControl(ctx *cli.Context) error { 146 ctxc := getContext() 147 conn := getClientConn(ctx, false) 148 defer conn.Close() 149 150 client := routerrpc.NewRouterClient(conn) 151 152 req := &routerrpc.QueryMissionControlRequest{} 153 snapshot, err := client.QueryMissionControl(ctxc, req) 154 if err != nil { 155 return err 156 } 157 158 printRespJSON(snapshot) 159 160 return nil 161 } 162 163 var queryProbCommand = cli.Command{ 164 Name: "queryprob", 165 Category: "Mission Control", 166 Usage: "Estimate a success probability.", 167 ArgsUsage: "from-node to-node amt", 168 Action: actionDecorator(queryProb), 169 } 170 171 func queryProb(ctx *cli.Context) error { 172 ctxc := getContext() 173 args := ctx.Args() 174 175 if len(args) != 3 { 176 return cli.ShowCommandHelp(ctx, "queryprob") 177 } 178 179 fromNode, err := route.NewVertexFromStr(args.Get(0)) 180 if err != nil { 181 return fmt.Errorf("invalid from node key: %v", err) 182 } 183 184 toNode, err := route.NewVertexFromStr(args.Get(1)) 185 if err != nil { 186 return fmt.Errorf("invalid to node key: %v", err) 187 } 188 189 amtAtoms, err := strconv.ParseUint(args.Get(2), 10, 64) 190 if err != nil { 191 return fmt.Errorf("invalid amt: %v", err) 192 } 193 194 amtMAtoms := lnwire.NewMAtomsFromAtoms( 195 dcrutil.Amount(amtAtoms), 196 ) 197 198 conn := getClientConn(ctx, false) 199 defer conn.Close() 200 201 client := routerrpc.NewRouterClient(conn) 202 203 req := &routerrpc.QueryProbabilityRequest{ 204 FromNode: fromNode[:], 205 ToNode: toNode[:], 206 AmtMAtoms: int64(amtMAtoms), 207 } 208 209 response, err := client.QueryProbability(ctxc, req) 210 if err != nil { 211 return err 212 } 213 214 printRespJSON(response) 215 216 return nil 217 } 218 219 var resetMissionControlCommand = cli.Command{ 220 Name: "resetmc", 221 Category: "Mission Control", 222 Usage: "Reset internal mission control state.", 223 Action: actionDecorator(resetMissionControl), 224 } 225 226 func resetMissionControl(ctx *cli.Context) error { 227 ctxc := getContext() 228 conn := getClientConn(ctx, false) 229 defer conn.Close() 230 231 client := routerrpc.NewRouterClient(conn) 232 233 req := &routerrpc.ResetMissionControlRequest{} 234 _, err := client.ResetMissionControl(ctxc, req) 235 return err 236 }