github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/cmd/utils/flags.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package utils contains internal helper functions for go-ethereum commands. 18 package utils 19 20 import ( 21 "crypto/ecdsa" 22 "fmt" 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "strconv" 27 "strings" 28 29 "github.com/vntchain/go-vnt/accounts" 30 "github.com/vntchain/go-vnt/accounts/keystore" 31 "github.com/vntchain/go-vnt/common" 32 "github.com/vntchain/go-vnt/common/fdlimit" 33 "github.com/vntchain/go-vnt/consensus" 34 "github.com/vntchain/go-vnt/consensus/dpos" 35 "github.com/vntchain/go-vnt/core" 36 "github.com/vntchain/go-vnt/core/state" 37 "github.com/vntchain/go-vnt/core/vm" 38 "github.com/vntchain/go-vnt/crypto" 39 "github.com/vntchain/go-vnt/les" 40 "github.com/vntchain/go-vnt/log" 41 "github.com/vntchain/go-vnt/metrics" 42 "github.com/vntchain/go-vnt/node" 43 "github.com/vntchain/go-vnt/params" 44 "github.com/vntchain/go-vnt/vnt" 45 "github.com/vntchain/go-vnt/vnt/downloader" 46 "github.com/vntchain/go-vnt/vnt/gasprice" 47 "github.com/vntchain/go-vnt/vntdb" 48 "github.com/vntchain/go-vnt/vntp2p" 49 "github.com/vntchain/go-vnt/vntstats" 50 cli "gopkg.in/urfave/cli.v1" 51 52 // "github.com/vntchain/go-vnt/vntp2p/netutil" 53 whisper "github.com/vntchain/go-vnt/whisper/whisperv6" 54 ) 55 56 var ( 57 CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...] 58 {{if .cmd.Description}}{{.cmd.Description}} 59 {{end}}{{if .cmd.Subcommands}} 60 SUBCOMMANDS: 61 {{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 62 {{end}}{{end}}{{if .categorizedFlags}} 63 {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS: 64 {{range $categorized.Flags}}{{"\t"}}{{.}} 65 {{end}} 66 {{end}}{{end}}` 67 ) 68 69 func init() { 70 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 71 72 VERSION: 73 {{.Version}} 74 75 COMMANDS: 76 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 77 {{end}}{{if .Flags}} 78 GLOBAL OPTIONS: 79 {{range .Flags}}{{.}} 80 {{end}}{{end}} 81 ` 82 83 cli.CommandHelpTemplate = CommandHelpTemplate 84 } 85 86 // NewApp creates an app with sane defaults. 87 func NewApp(gitCommit, usage string) *cli.App { 88 app := cli.NewApp() 89 app.Name = filepath.Base(os.Args[0]) 90 app.Author = "" 91 //app.Authors = nil 92 app.Email = "" 93 app.Version = params.Version 94 if len(gitCommit) >= 8 { 95 app.Version += "-" + gitCommit[:8] 96 } 97 app.Usage = usage 98 return app 99 } 100 101 // These are all the command line flags we support. 102 // If you add to this list, please remember to include the 103 // flag in the appropriate command definition. 104 // 105 // The flags are defined here so their names and help texts 106 // are the same for all commands. 107 108 var ( 109 //Temp settings 110 FindNodeFlag = cli.StringFlag{ 111 Name: "findnode", 112 Usage: "Specific a nodeURL to findnode", 113 } 114 VNTBootnodeFlag = cli.StringFlag{ 115 Name: "vntbootnode", 116 Usage: "Specific a vntBootnode to connect", 117 } 118 119 // General settings 120 DataDirFlag = DirectoryFlag{ 121 Name: "datadir", 122 Usage: "Data directory for the databases and keystore", 123 Value: DirectoryString{node.DefaultDataDir()}, 124 } 125 KeyStoreDirFlag = DirectoryFlag{ 126 Name: "keystore", 127 Usage: "Directory for the keystore (default = inside the datadir)", 128 } 129 NetworkIdFlag = cli.Uint64Flag{ 130 Name: "networkid", 131 Usage: "Network identifier (integer, 1=Frontier)", 132 Value: vnt.DefaultConfig.NetworkId, 133 } 134 IdentityFlag = cli.StringFlag{ 135 Name: "identity", 136 Usage: "Custom node name", 137 } 138 DocRootFlag = DirectoryFlag{ 139 Name: "docroot", 140 Usage: "Document Root for HTTPClient file scheme", 141 Value: DirectoryString{homeDir()}, 142 } 143 defaultSyncMode = vnt.DefaultConfig.SyncMode 144 SyncModeFlag = TextMarshalerFlag{ 145 Name: "syncmode", 146 Usage: `Blockchain sync mode ("fast", "full", or "light")`, 147 Value: &defaultSyncMode, 148 } 149 GCModeFlag = cli.StringFlag{ 150 Name: "gcmode", 151 Usage: `Blockchain garbage collection mode ("full", "archive")`, 152 Value: "full", 153 } 154 LightServFlag = cli.IntFlag{ 155 Name: "lightserv", 156 Usage: "Maximum percentage of time allowed for serving LES requests (0-90)", 157 Value: 0, 158 } 159 LightPeersFlag = cli.IntFlag{ 160 Name: "lightpeers", 161 Usage: "Maximum number of LES client peers", 162 Value: vnt.DefaultConfig.LightPeers, 163 } 164 LightKDFFlag = cli.BoolFlag{ 165 Name: "lightkdf", 166 Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", 167 } 168 // Transaction pool settings 169 TxPoolNoLocalsFlag = cli.BoolFlag{ 170 Name: "txpool.nolocals", 171 Usage: "Disables price exemptions for locally submitted transactions", 172 } 173 TxPoolJournalFlag = cli.StringFlag{ 174 Name: "txpool.journal", 175 Usage: "Disk journal for local transaction to survive node restarts", 176 Value: core.DefaultTxPoolConfig.Journal, 177 } 178 TxPoolRejournalFlag = cli.DurationFlag{ 179 Name: "txpool.rejournal", 180 Usage: "Time interval to regenerate the local transaction journal", 181 Value: core.DefaultTxPoolConfig.Rejournal, 182 } 183 TxPoolPriceLimitFlag = cli.Uint64Flag{ 184 Name: "txpool.pricelimit", 185 Usage: "Minimum gas price limit to enforce for acceptance into the pool", 186 Value: vnt.DefaultConfig.TxPool.PriceLimit, 187 } 188 TxPoolPriceBumpFlag = cli.Uint64Flag{ 189 Name: "txpool.pricebump", 190 Usage: "Price bump percentage to replace an already existing transaction", 191 Value: vnt.DefaultConfig.TxPool.PriceBump, 192 } 193 TxPoolAccountSlotsFlag = cli.Uint64Flag{ 194 Name: "txpool.accountslots", 195 Usage: "Minimum number of executable transaction slots guaranteed per account", 196 Value: vnt.DefaultConfig.TxPool.AccountSlots, 197 } 198 TxPoolGlobalSlotsFlag = cli.Uint64Flag{ 199 Name: "txpool.globalslots", 200 Usage: "Maximum number of executable transaction slots for all accounts", 201 Value: vnt.DefaultConfig.TxPool.GlobalSlots, 202 } 203 TxPoolAccountQueueFlag = cli.Uint64Flag{ 204 Name: "txpool.accountqueue", 205 Usage: "Maximum number of non-executable transaction slots permitted per account", 206 Value: vnt.DefaultConfig.TxPool.AccountQueue, 207 } 208 TxPoolGlobalQueueFlag = cli.Uint64Flag{ 209 Name: "txpool.globalqueue", 210 Usage: "Maximum number of non-executable transaction slots for all accounts", 211 Value: vnt.DefaultConfig.TxPool.GlobalQueue, 212 } 213 TxPoolLifetimeFlag = cli.DurationFlag{ 214 Name: "txpool.lifetime", 215 Usage: "Maximum amount of time non-executable transaction are queued", 216 Value: vnt.DefaultConfig.TxPool.Lifetime, 217 } 218 // Performance tuning settings 219 CacheFlag = cli.IntFlag{ 220 Name: "cache", 221 Usage: "Megabytes of memory allocated to internal caching", 222 Value: 1024, 223 } 224 CacheDatabaseFlag = cli.IntFlag{ 225 Name: "cache.database", 226 Usage: "Percentage of cache memory allowance to use for database io", 227 Value: 75, 228 } 229 CacheGCFlag = cli.IntFlag{ 230 Name: "cache.gc", 231 Usage: "Percentage of cache memory allowance to use for trie pruning", 232 Value: 25, 233 } 234 TrieCacheGenFlag = cli.IntFlag{ 235 Name: "trie-cache-gens", 236 Usage: "Number of trie node generations to keep in memory", 237 Value: int(state.MaxTrieCacheGen), 238 } 239 // Producer settings 240 ProducingEnabledFlag = cli.BoolFlag{ 241 Name: "produce", 242 Usage: "Enable block producing", 243 } 244 TargetGasLimitFlag = cli.Uint64Flag{ 245 Name: "targetgaslimit", 246 Usage: "Target gas limit sets the artificial target gas floor for the blocks to produce", 247 Value: params.GenesisGasLimit, 248 } 249 CoinbaseFlag = cli.StringFlag{ 250 Name: "coinbase", 251 Usage: "Public address for block producing and witness rewards (default = first account created)", 252 Value: "0", 253 } 254 GasPriceFlag = BigFlag{ 255 Name: "gasprice", 256 Usage: "Minimal gas price to accept for producing a transactions", 257 Value: vnt.DefaultConfig.GasPrice, 258 } 259 ExtraDataFlag = cli.StringFlag{ 260 Name: "extradata", 261 Usage: "Block extra data set by the block producer (default = client version)", 262 } 263 // Account settings 264 UnlockedAccountFlag = cli.StringFlag{ 265 Name: "unlock", 266 Usage: "Comma separated list of accounts to unlock", 267 Value: "", 268 } 269 PasswordFileFlag = cli.StringFlag{ 270 Name: "password", 271 Usage: "Password file to use for non-interactive password input", 272 Value: "", 273 } 274 275 VMEnableDebugFlag = cli.BoolFlag{ 276 Name: "vmdebug", 277 Usage: "Record information useful for VM and contract debugging", 278 } 279 // Logging and debug settings 280 VntStatsURLFlag = cli.StringFlag{ 281 Name: "vntstats", 282 Usage: "Reporting URL of a vntstats service (nodename:secret@host:port)", 283 } 284 MetricsEnabledFlag = cli.BoolFlag{ 285 Name: metrics.MetricsEnabledFlag, 286 Usage: "Enable metrics collection and reporting", 287 } 288 NoCompactionFlag = cli.BoolFlag{ 289 Name: "nocompaction", 290 Usage: "Disables db compaction after import", 291 } 292 // RPC settings 293 RPCEnabledFlag = cli.BoolFlag{ 294 Name: "rpc", 295 Usage: "Enable the HTTP-RPC server", 296 } 297 RPCListenAddrFlag = cli.StringFlag{ 298 Name: "rpcaddr", 299 Usage: "HTTP-RPC server listening interface", 300 Value: node.DefaultHTTPHost, 301 } 302 RPCPortFlag = cli.IntFlag{ 303 Name: "rpcport", 304 Usage: "HTTP-RPC server listening port", 305 Value: node.DefaultHTTPPort, 306 } 307 RPCCORSDomainFlag = cli.StringFlag{ 308 Name: "rpccorsdomain", 309 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 310 Value: "", 311 } 312 RPCVirtualHostsFlag = cli.StringFlag{ 313 Name: "rpcvhosts", 314 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 315 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 316 } 317 RPCApiFlag = cli.StringFlag{ 318 Name: "rpcapi", 319 Usage: "API's offered over the HTTP-RPC interface", 320 Value: "", 321 } 322 IPCDisabledFlag = cli.BoolFlag{ 323 Name: "ipcdisable", 324 Usage: "Disable the IPC-RPC server", 325 } 326 IPCPathFlag = DirectoryFlag{ 327 Name: "ipcpath", 328 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 329 } 330 WSEnabledFlag = cli.BoolFlag{ 331 Name: "ws", 332 Usage: "Enable the WS-RPC server", 333 } 334 WSListenAddrFlag = cli.StringFlag{ 335 Name: "wsaddr", 336 Usage: "WS-RPC server listening interface", 337 Value: node.DefaultWSHost, 338 } 339 WSPortFlag = cli.IntFlag{ 340 Name: "wsport", 341 Usage: "WS-RPC server listening port", 342 Value: node.DefaultWSPort, 343 } 344 WSApiFlag = cli.StringFlag{ 345 Name: "wsapi", 346 Usage: "API's offered over the WS-RPC interface", 347 Value: "", 348 } 349 WSAllowedOriginsFlag = cli.StringFlag{ 350 Name: "wsorigins", 351 Usage: "Origins from which to accept websockets requests", 352 Value: "", 353 } 354 ExecFlag = cli.StringFlag{ 355 Name: "exec", 356 Usage: "Execute JavaScript statement", 357 } 358 PreloadJSFlag = cli.StringFlag{ 359 Name: "preload", 360 Usage: "Comma separated list of JavaScript files to preload into the console", 361 } 362 363 // Network Settings 364 MaxPeersFlag = cli.IntFlag{ 365 Name: "maxpeers", 366 Usage: "Maximum number of network peers (network disabled if set to 0)", 367 Value: 25, 368 } 369 MaxPendingPeersFlag = cli.IntFlag{ 370 Name: "maxpendpeers", 371 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 372 Value: 0, 373 } 374 ListenPortFlag = cli.IntFlag{ 375 Name: "port", 376 Usage: "Network listening port", 377 Value: 30303, 378 } 379 BootnodesFlag = cli.StringFlag{ 380 Name: "bootnodes", 381 Usage: "Comma separated vnode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)", 382 Value: "", 383 } 384 BootnodesV4Flag = cli.StringFlag{ 385 Name: "bootnodesv4", 386 Usage: "Comma separated vnode URLs for P2P v4 discovery bootstrap (light server, full nodes)", 387 Value: "", 388 } 389 BootnodesV5Flag = cli.StringFlag{ 390 Name: "bootnodesv5", 391 Usage: "Comma separated vnode URLs for P2P v5 discovery bootstrap (light server, light nodes)", 392 Value: "", 393 } 394 NodeKeyFileFlag = cli.StringFlag{ 395 Name: "nodekey", 396 Usage: "P2P node key file", 397 } 398 NodeKeyHexFlag = cli.StringFlag{ 399 Name: "nodekeyhex", 400 Usage: "P2P node key as hex (for testing)", 401 } 402 NATFlag = cli.StringFlag{ 403 Name: "nat", 404 Usage: "NAT port mapping mechanism (any|none)", 405 Value: "any", 406 } 407 NoDiscoverFlag = cli.BoolFlag{ 408 Name: "nodiscover", 409 Usage: "Disables the peer discovery mechanism (manual peer addition)", 410 } 411 DiscoveryV5Flag = cli.BoolFlag{ 412 Name: "v5disc", 413 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 414 } 415 NetrestrictFlag = cli.StringFlag{ 416 Name: "netrestrict", 417 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 418 } 419 420 // ATM the url is left to the user and deployment to 421 JSpathFlag = cli.StringFlag{ 422 Name: "jspath", 423 Usage: "JavaScript root path for `loadScript`", 424 Value: ".", 425 } 426 427 // Gas price oracle settings 428 GpoBlocksFlag = cli.IntFlag{ 429 Name: "gpoblocks", 430 Usage: "Number of recent blocks to check for gas prices", 431 Value: vnt.DefaultConfig.GPO.Blocks, 432 } 433 GpoPercentileFlag = cli.IntFlag{ 434 Name: "gpopercentile", 435 Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", 436 Value: vnt.DefaultConfig.GPO.Percentile, 437 } 438 WhisperEnabledFlag = cli.BoolFlag{ 439 Name: "shh", 440 Usage: "Enable Whisper", 441 } 442 WhisperMaxMessageSizeFlag = cli.IntFlag{ 443 Name: "shh.maxmessagesize", 444 Usage: "Max message size accepted", 445 Value: int(whisper.DefaultMaxMessageSize), 446 } 447 WhisperMinPOWFlag = cli.Float64Flag{ 448 Name: "shh.pow", 449 Usage: "Minimum POW accepted", 450 Value: whisper.DefaultMinimumPoW, 451 } 452 ) 453 454 // MakeDataDir retrieves the currently requested data directory, terminating 455 // if none (or the empty string) is specified. If the node is starting a testnet, 456 // the a subdirectory of the specified datadir will be used. 457 func MakeDataDir(ctx *cli.Context) string { 458 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 459 return path 460 } 461 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 462 return "" 463 } 464 465 // setNodeKey creates a node key from set command line flags, either loading it 466 // from a file or as a specified hex value. If neither flags were provided, this 467 // method returns nil and an emphemeral key is to be generated. 468 func setNodeKey(ctx *cli.Context, cfg *vntp2p.Config) { 469 var ( 470 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 471 file = ctx.GlobalString(NodeKeyFileFlag.Name) 472 key *ecdsa.PrivateKey 473 err error 474 ) 475 switch { 476 case file != "" && hex != "": 477 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 478 case file != "": 479 if key, err = crypto.LoadECDSA(file); err != nil { 480 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 481 } 482 cfg.PrivateKey = key 483 case hex != "": 484 if key, err = crypto.HexToECDSA(hex); err != nil { 485 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 486 } 487 cfg.PrivateKey = key 488 } 489 } 490 491 // setNodeUserIdent creates the user identifier from CLI flags. 492 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 493 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 494 cfg.UserIdent = identity 495 } 496 } 497 498 func setFindNode(ctx *cli.Context, cfg *vntp2p.Config) { 499 // nodeURL := ctx.GlobalString(FindNodeFlag.Name) 500 // cfg.FindNode = nodeURL 501 } 502 503 func setVNTBootnode(ctx *cli.Context, cfg *vntp2p.Config) { 504 505 if ctx.GlobalString(VNTBootnodeFlag.Name) == "" { 506 return 507 } 508 509 urls := strings.Split(ctx.GlobalString(VNTBootnodeFlag.Name), ",") 510 511 cfg.BootstrapNodes = []*vntp2p.Node{} 512 513 for _, url := range urls { 514 addr, peerid, err := vntp2p.GetAddr(url) 515 if err != nil { 516 log.Error("Bootstrap URL invalid", "vntnode", url, "err", err) 517 continue 518 } 519 Node := &vntp2p.Node{Addr: addr, Id: peerid} 520 cfg.BootstrapNodes = append(cfg.BootstrapNodes, Node) 521 } 522 523 } 524 525 // setBootstrapNodes creates a list of bootstrap nodes from the command line 526 // flags, reverting to pre-configured ones if none have been specified. 527 func setBootstrapNodes(ctx *cli.Context, cfg *vntp2p.Config) { 528 urls := params.MainnetBootnodes 529 switch { 530 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name): 531 if ctx.GlobalIsSet(BootnodesV4Flag.Name) { 532 urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",") 533 } else { 534 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 535 } 536 case cfg.BootstrapNodes != nil: 537 return // already set, don't apply defaults. 538 } 539 540 log.Debug("[info] setBootstrapNodes()", "urls", urls, "and url length", len(urls)) 541 542 cfg.BootstrapNodes = make([]*vntp2p.Node, 0, len(urls)) 543 for _, url := range urls { 544 node, err := vntp2p.ParseNode(url) 545 if err != nil { 546 log.Error("Bootstrap URL invalid", "vnode", url, "err", err) 547 continue 548 } 549 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 550 } 551 } 552 553 // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line 554 // flags, reverting to pre-configured ones if none have been specified. 555 // func setBootstrapNodesV5(ctx *cli.Context, cfg *vntp2p.Config) { 556 // urls := params.DiscoveryV5Bootnodes 557 // switch { 558 // case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name): 559 // if ctx.GlobalIsSet(BootnodesV5Flag.Name) { 560 // urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",") 561 // } else { 562 // urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 563 // } 564 // case cfg.BootstrapNodesV5 != nil: 565 // return // already set, don't apply defaults. 566 // } 567 568 // cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls)) 569 // for _, url := range urls { 570 // node, err := discv5.ParseNode(url) 571 // if err != nil { 572 // log.Error("Bootstrap URL invalid", "vnode", url, "err", err) 573 // continue 574 // } 575 // cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) 576 // } 577 // } 578 579 // setListenAddress creates a TCP listening address string from set command 580 // line flags. 581 func setListenAddress(ctx *cli.Context, cfg *vntp2p.Config) { 582 if ctx.GlobalIsSet(ListenPortFlag.Name) { 583 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 584 } 585 } 586 587 // setNAT creates a port mapper from command line flags. 588 func setNAT(ctx *cli.Context, cfg *vntp2p.Config) { 589 if ctx.GlobalIsSet(NATFlag.Name) { 590 natif, err := vntp2p.NATParse(ctx.GlobalString(NATFlag.Name)) 591 if err != nil { 592 Fatalf("Option %s: %v", NATFlag.Name, err) 593 } 594 cfg.NAT = natif 595 } 596 } 597 598 // splitAndTrim splits input separated by a comma 599 // and trims excessive white space from the substrings. 600 func splitAndTrim(input string) []string { 601 result := strings.Split(input, ",") 602 for i, r := range result { 603 result[i] = strings.TrimSpace(r) 604 } 605 return result 606 } 607 608 // setHTTP creates the HTTP RPC listener interface string from the set 609 // command line flags, returning empty if the HTTP endpoint is disabled. 610 func setHTTP(ctx *cli.Context, cfg *node.Config) { 611 if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { 612 cfg.HTTPHost = "127.0.0.1" 613 if ctx.GlobalIsSet(RPCListenAddrFlag.Name) { 614 cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name) 615 } 616 } 617 618 if ctx.GlobalIsSet(RPCPortFlag.Name) { 619 cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) 620 } 621 if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { 622 cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name)) 623 } 624 if ctx.GlobalIsSet(RPCApiFlag.Name) { 625 cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name)) 626 } 627 if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) { 628 cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name)) 629 } 630 } 631 632 // setWS creates the WebSocket RPC listener interface string from the set 633 // command line flags, returning empty if the HTTP endpoint is disabled. 634 func setWS(ctx *cli.Context, cfg *node.Config) { 635 if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { 636 cfg.WSHost = "127.0.0.1" 637 if ctx.GlobalIsSet(WSListenAddrFlag.Name) { 638 cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) 639 } 640 } 641 642 if ctx.GlobalIsSet(WSPortFlag.Name) { 643 cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) 644 } 645 if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { 646 cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) 647 } 648 if ctx.GlobalIsSet(WSApiFlag.Name) { 649 cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name)) 650 } 651 } 652 653 // setIPC creates an IPC path configuration from the set command line flags, 654 // returning an empty string if IPC was explicitly disabled, or the set path. 655 func setIPC(ctx *cli.Context, cfg *node.Config) { 656 checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 657 switch { 658 case ctx.GlobalBool(IPCDisabledFlag.Name): 659 cfg.IPCPath = "" 660 case ctx.GlobalIsSet(IPCPathFlag.Name): 661 cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) 662 } 663 } 664 665 // makeDatabaseHandles raises out the number of allowed file handles per process 666 // for Gvnt and returns half of the allowance to assign to the database. 667 func makeDatabaseHandles() int { 668 limit, err := fdlimit.Current() 669 if err != nil { 670 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 671 } 672 if limit < 2048 { 673 if err := fdlimit.Raise(2048); err != nil { 674 Fatalf("Failed to raise file descriptor allowance: %v", err) 675 } 676 } 677 if limit > 2048 { // cap database file descriptors even if more is available 678 limit = 2048 679 } 680 return limit / 2 // Leave half for networking and other stuff 681 } 682 683 // MakeAddress converts an account specified directly as a hex encoded string or 684 // a key index in the key store to an internal account representation. 685 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 686 // If the specified account is a valid address, return it 687 if common.IsHexAddress(account) { 688 return accounts.Account{Address: common.HexToAddress(account)}, nil 689 } 690 // Otherwise try to interpret the account as a keystore index 691 index, err := strconv.Atoi(account) 692 if err != nil || index < 0 { 693 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 694 } 695 log.Warn("-------------------------------------------------------------------") 696 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 697 log.Warn("This functionality is deprecated and will be removed in the future!") 698 log.Warn("Please use explicit addresses! (can search via `gvnt account list`)") 699 log.Warn("-------------------------------------------------------------------") 700 701 accs := ks.Accounts() 702 if len(accs) <= index { 703 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 704 } 705 return accs[index], nil 706 } 707 708 // setCoinbase retrieves the coinbase either from the directly specified 709 // command line flags or from the keystore if CLI indexed. 710 func setCoinbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *vnt.Config) { 711 if ctx.GlobalIsSet(CoinbaseFlag.Name) { 712 account, err := MakeAddress(ks, ctx.GlobalString(CoinbaseFlag.Name)) 713 if err != nil { 714 Fatalf("Option %q: %v", CoinbaseFlag.Name, err) 715 } 716 cfg.Coinbase = account.Address 717 } 718 } 719 720 // MakePasswordList reads password lines from the file specified by the global --password flag. 721 func MakePasswordList(ctx *cli.Context) []string { 722 path := ctx.GlobalString(PasswordFileFlag.Name) 723 if path == "" { 724 return nil 725 } 726 text, err := ioutil.ReadFile(path) 727 if err != nil { 728 Fatalf("Failed to read password file: %v", err) 729 } 730 lines := strings.Split(string(text), "\n") 731 // Sanitise DOS line endings. 732 for i := range lines { 733 lines[i] = strings.TrimRight(lines[i], "\r") 734 } 735 return lines 736 } 737 738 func SetP2PConfig(ctx *cli.Context, cfg *vntp2p.Config) { 739 setNodeKey(ctx, cfg) 740 setNAT(ctx, cfg) 741 setListenAddress(ctx, cfg) 742 setFindNode(ctx, cfg) 743 setVNTBootnode(ctx, cfg) 744 setBootstrapNodes(ctx, cfg) 745 // setBootstrapNodesV5(ctx, cfg) 746 747 lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light" 748 lightServer := ctx.GlobalInt(LightServFlag.Name) != 0 749 lightPeers := ctx.GlobalInt(LightPeersFlag.Name) 750 751 if ctx.GlobalIsSet(MaxPeersFlag.Name) { 752 cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) 753 if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) { 754 cfg.MaxPeers += lightPeers 755 } 756 } else { 757 if lightServer { 758 cfg.MaxPeers += lightPeers 759 } 760 if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers { 761 cfg.MaxPeers = lightPeers 762 } 763 } 764 if !(lightClient || lightServer) { 765 lightPeers = 0 766 } 767 vntPeers := cfg.MaxPeers - lightPeers 768 if lightClient { 769 vntPeers = 0 770 } 771 log.Info("Maximum peer count", "VNT", vntPeers, "LES", lightPeers, "total", cfg.MaxPeers) 772 773 if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { 774 cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) 775 } 776 if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { 777 cfg.NoDiscovery = true 778 } 779 780 // if we're running a light client or server, force enable the v5 peer discovery 781 // unless it is explicitly disabled with --nodiscover note that explicitly specifying 782 // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery 783 // forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) 784 // if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { 785 // cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) 786 // } else if forceV5Discovery { 787 // cfg.DiscoveryV5 = true 788 // } 789 // fmt.Println(forceV5Discovery) 790 791 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 792 list, err := vntp2p.ParseNetlist(netrestrict) 793 if err != nil { 794 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 795 } 796 cfg.NetRestrict = list 797 } 798 } 799 800 // SetNodeConfig applies node-related command line flags to the config. 801 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 802 SetP2PConfig(ctx, &cfg.P2P) 803 setIPC(ctx, cfg) 804 setHTTP(ctx, cfg) 805 setWS(ctx, cfg) 806 setNodeUserIdent(ctx, cfg) 807 808 switch { 809 case ctx.GlobalIsSet(DataDirFlag.Name): 810 cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) 811 } 812 813 if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { 814 cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) 815 } 816 if ctx.GlobalIsSet(LightKDFFlag.Name) { 817 cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) 818 } 819 } 820 821 func setGPO(ctx *cli.Context, cfg *gasprice.Config) { 822 if ctx.GlobalIsSet(GpoBlocksFlag.Name) { 823 cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) 824 } 825 if ctx.GlobalIsSet(GpoPercentileFlag.Name) { 826 cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) 827 } 828 } 829 830 func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { 831 if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) { 832 cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name) 833 } 834 if ctx.GlobalIsSet(TxPoolJournalFlag.Name) { 835 cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name) 836 } 837 if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) { 838 cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name) 839 } 840 if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) { 841 cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name) 842 } 843 if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) { 844 cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name) 845 } 846 if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) { 847 cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name) 848 } 849 if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) { 850 cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name) 851 } 852 if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) { 853 cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name) 854 } 855 if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) { 856 cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name) 857 } 858 if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) { 859 cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name) 860 } 861 } 862 863 // checkExclusive verifies that only a single isntance of the provided flags was 864 // set by the user. Each flag might optionally be followed by a string type to 865 // specialize it further. 866 func checkExclusive(ctx *cli.Context, args ...interface{}) { 867 set := make([]string, 0, 1) 868 for i := 0; i < len(args); i++ { 869 // Make sure the next argument is a flag and skip if not set 870 flag, ok := args[i].(cli.Flag) 871 if !ok { 872 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 873 } 874 // Check if next arg extends current and expand its name if so 875 name := flag.GetName() 876 877 if i+1 < len(args) { 878 switch option := args[i+1].(type) { 879 case string: 880 // Extended flag, expand the name and shift the arguments 881 if ctx.GlobalString(flag.GetName()) == option { 882 name += "=" + option 883 } 884 i++ 885 886 case cli.Flag: 887 default: 888 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 889 } 890 } 891 // Mark the flag if it's set 892 if ctx.GlobalIsSet(flag.GetName()) { 893 set = append(set, "--"+name) 894 } 895 } 896 if len(set) > 1 { 897 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 898 } 899 } 900 901 // SetShhConfig applies shh-related command line flags to the config. 902 func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) { 903 if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) { 904 cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name)) 905 } 906 if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) { 907 cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name) 908 } 909 } 910 911 // SetVntConfig applies vnt-related command line flags to the config. 912 func SetVntConfig(ctx *cli.Context, stack *node.Node, cfg *vnt.Config) { 913 // Avoid conflicting network flags 914 checkExclusive(ctx, LightServFlag, SyncModeFlag, "light") 915 916 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 917 setCoinbase(ctx, ks, cfg) 918 setGPO(ctx, &cfg.GPO) 919 setTxPool(ctx, &cfg.TxPool) 920 921 switch { 922 case ctx.GlobalIsSet(SyncModeFlag.Name): 923 cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 924 } 925 if ctx.GlobalIsSet(LightServFlag.Name) { 926 cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) 927 } 928 if ctx.GlobalIsSet(LightPeersFlag.Name) { 929 cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) 930 } 931 if ctx.GlobalIsSet(NetworkIdFlag.Name) { 932 cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) 933 } 934 935 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { 936 cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 937 } 938 cfg.DatabaseHandles = makeDatabaseHandles() 939 940 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 941 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 942 } 943 cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" 944 945 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 946 cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 947 } 948 if ctx.GlobalIsSet(DocRootFlag.Name) { 949 cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) 950 } 951 if ctx.GlobalIsSet(ExtraDataFlag.Name) { 952 cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name)) 953 } 954 if ctx.GlobalIsSet(GasPriceFlag.Name) { 955 cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name) 956 } 957 if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { 958 // TODO(fjl): force-enable this in --dev mode 959 cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) 960 } 961 962 // TODO(fjl): move trie cache generations into config 963 if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 { 964 state.MaxTrieCacheGen = uint16(gen) 965 } 966 } 967 968 // RegisterVntService adds an VNT client to the stack. 969 func RegisterVntService(stack *node.Node, cfg *vnt.Config) { 970 var err error 971 if cfg.SyncMode == downloader.LightSync { 972 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 973 return les.New(ctx, cfg) 974 }) 975 } else { 976 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 977 fullNode, err := vnt.New(ctx, cfg, stack) 978 if fullNode != nil && cfg.LightServ > 0 { 979 ls, _ := les.NewLesServer(fullNode, cfg) 980 fullNode.AddLesServer(ls) 981 } 982 return fullNode, err 983 }) 984 } 985 if err != nil { 986 Fatalf("Failed to register the VNT service: %v", err) 987 } 988 } 989 990 // RegisterShhService configures Whisper and adds it to the given node. 991 func RegisterShhService(stack *node.Node, cfg *whisper.Config) { 992 if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) { 993 return whisper.New(cfg), nil 994 }); err != nil { 995 Fatalf("Failed to register the Whisper service: %v", err) 996 } 997 } 998 999 // RegisterVntStatsService configures the VNT Stats daemon and adds it to 1000 // th egiven node. 1001 func RegisterVntStatsService(stack *node.Node, url string) { 1002 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1003 // Retrieve both vnt and les services 1004 var vntServ *vnt.VNT 1005 ctx.Service(&vntServ) 1006 1007 var lesServ *les.LightVnt 1008 ctx.Service(&lesServ) 1009 1010 return vntstats.New(url, vntServ, lesServ) 1011 }); err != nil { 1012 Fatalf("Failed to register the VNT Stats service: %v", err) 1013 } 1014 } 1015 1016 // SetupNetwork configures the system for either the main net or some test network. 1017 func SetupNetwork(ctx *cli.Context) { 1018 // TODO(fjl): move target gas limit into config 1019 params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name) 1020 } 1021 1022 // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. 1023 func MakeChainDatabase(ctx *cli.Context, stack *node.Node) vntdb.Database { 1024 var ( 1025 cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1026 handles = makeDatabaseHandles() 1027 ) 1028 name := "chaindata" 1029 chainDb, err := stack.OpenDatabase(name, cache, handles) 1030 if err != nil { 1031 Fatalf("Could not open database: %v", err) 1032 } 1033 return chainDb 1034 } 1035 1036 func MakeGenesis(ctx *cli.Context) *core.Genesis { 1037 var genesis *core.Genesis 1038 return genesis 1039 } 1040 1041 // MakeChain creates a chain manager from set command line flags. 1042 func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb vntdb.Database) { 1043 var err error 1044 chainDb = MakeChainDatabase(ctx, stack) 1045 1046 config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) 1047 if err != nil { 1048 Fatalf("%v", err) 1049 } 1050 var engine consensus.Engine 1051 if config.Dpos != nil { 1052 engine = dpos.New(config.Dpos, chainDb) 1053 } else { 1054 Fatalf("PoW not support any more") 1055 } 1056 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1057 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1058 } 1059 cache := &core.CacheConfig{ 1060 Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive", 1061 TrieNodeLimit: vnt.DefaultConfig.TrieCache, 1062 TrieTimeLimit: vnt.DefaultConfig.TrieTimeout, 1063 } 1064 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1065 cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1066 } 1067 vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} 1068 chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg) 1069 if err != nil { 1070 Fatalf("Can't create BlockChain: %v", err) 1071 } 1072 return chain, chainDb 1073 } 1074 1075 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 1076 // scripts to preload before starting. 1077 func MakeConsolePreloads(ctx *cli.Context) []string { 1078 // Skip preloading if there's nothing to preload 1079 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 1080 return nil 1081 } 1082 // Otherwise resolve absolute paths and return them 1083 preloads := []string{} 1084 1085 assets := ctx.GlobalString(JSpathFlag.Name) 1086 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 1087 preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file))) 1088 } 1089 return preloads 1090 } 1091 1092 // MigrateFlags sets the global flag from a local flag when it's set. 1093 // This is a temporary function used for migrating old command/flags to the 1094 // new format. 1095 // 1096 // e.g. gvnt account new --keystore /tmp/mykeystore --lightkdf 1097 // 1098 // is equivalent after calling this method with: 1099 // 1100 // gvnt --keystore /tmp/mykeystore --lightkdf account new 1101 // 1102 // This allows the use of the existing configuration functionality. 1103 // When all flags are migrated this function can be removed and the existing 1104 // configuration functionality must be changed that is uses local flags 1105 func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { 1106 return func(ctx *cli.Context) error { 1107 for _, name := range ctx.FlagNames() { 1108 if ctx.IsSet(name) { 1109 ctx.GlobalSet(name, ctx.String(name)) 1110 } 1111 } 1112 return action(ctx) 1113 } 1114 }