github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/utils/flags.go (about) 1 package utils 2 3 import ( 4 "crypto/ecdsa" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "strconv" 10 "strings" 11 12 "github.com/neatlab/neatio/chain/accounts" 13 "github.com/neatlab/neatio/chain/accounts/keystore" 14 "github.com/neatlab/neatio/chain/consensus" 15 "github.com/neatlab/neatio/chain/core" 16 "github.com/neatlab/neatio/chain/core/vm" 17 "github.com/neatlab/neatio/chain/log" 18 "github.com/neatlab/neatio/neatdb" 19 neatptc "github.com/neatlab/neatio/neatptc" 20 "github.com/neatlab/neatio/neatptc/downloader" 21 "github.com/neatlab/neatio/neatptc/gasprice" 22 "github.com/neatlab/neatio/network/node" 23 "github.com/neatlab/neatio/network/p2p" 24 "github.com/neatlab/neatio/network/p2p/discover" 25 "github.com/neatlab/neatio/network/p2p/nat" 26 "github.com/neatlab/neatio/network/p2p/netutil" 27 "github.com/neatlab/neatio/params" 28 "github.com/neatlab/neatio/utilities/common" 29 "github.com/neatlab/neatio/utilities/common/fdlimit" 30 "github.com/neatlab/neatio/utilities/crypto" 31 "github.com/neatlab/neatio/utilities/metrics" 32 "gopkg.in/urfave/cli.v1" 33 34 tmcfg "github.com/neatlab/neatio/chain/consensus/neatcon/config/neatcon" 35 cfg "github.com/neatlib/config-go" 36 ) 37 38 var ( 39 CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...] 40 {{if .cmd.Description}}{{.cmd.Description}} 41 {{end}}{{if .cmd.Subcommands}} 42 SUBCOMMANDS: 43 {{range .cmd.Subcommands}}{{.cmd.Name}}{{with .cmd.ShortName}}, {{.cmd}}{{end}}{{ "\t" }}{{.cmd.Usage}} 44 {{end}}{{end}}{{if .categorizedFlags}} 45 {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS: 46 {{range $categorized.Flags}}{{"\t"}}{{.}} 47 {{end}} 48 {{end}}{{end}}` 49 ) 50 51 func init() { 52 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 53 54 VERSION: 55 {{.Version}} 56 57 COMMANDS: 58 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 59 {{end}}{{if .Flags}} 60 GLOBAL OPTIONS: 61 {{range .Flags}}{{.}} 62 {{end}}{{end}} 63 ` 64 65 cli.CommandHelpTemplate = CommandHelpTemplate 66 } 67 68 func NewApp(gitCommit, usage string) *cli.App { 69 app := cli.NewApp() 70 app.Name = filepath.Base(os.Args[0]) 71 app.Author = "" 72 app.Email = "" 73 app.Version = params.Version 74 if len(gitCommit) >= 8 { 75 app.Version += "-" + gitCommit[:8] 76 } 77 app.Usage = usage 78 return app 79 } 80 81 var ( 82 DataDirFlag = DirectoryFlag{ 83 Name: "datadir", 84 Usage: "Data directory for the databases and keystore", 85 Value: DirectoryString{node.DefaultDataDir()}, 86 } 87 KeyStoreDirFlag = DirectoryFlag{ 88 Name: "keystore", 89 Usage: "Directory for the keystore (default = inside the datadir)", 90 } 91 NoUSBFlag = cli.BoolFlag{ 92 Name: "nousb", 93 Usage: "Disables monitoring for and managing USB hardware wallets", 94 } 95 NetworkIdFlag = cli.Uint64Flag{ 96 Name: "networkid", 97 Usage: "Network identifier (integer, mainnet=515, testnet=525)", 98 Value: neatptc.DefaultConfig.NetworkId, 99 } 100 TestnetFlag = cli.BoolFlag{ 101 Name: "testnet", 102 Usage: "Test network", 103 } 104 105 DeveloperFlag = cli.BoolFlag{ 106 Name: "dev", 107 Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", 108 } 109 110 IdentityFlag = cli.StringFlag{ 111 Name: "identity", 112 Usage: "Custom node name", 113 } 114 DocRootFlag = DirectoryFlag{ 115 Name: "docroot", 116 Usage: "Document Root for HTTPClient file scheme", 117 Value: DirectoryString{homeDir()}, 118 } 119 FastSyncFlag = cli.BoolFlag{ 120 Name: "fast", 121 Usage: "Enable fast syncing through state downloads", 122 } 123 124 defaultSyncMode = neatptc.DefaultConfig.SyncMode 125 SyncModeFlag = TextMarshalerFlag{ 126 Name: "syncmode", 127 Usage: `Blockchain sync mode ("full")`, 128 Value: &defaultSyncMode, 129 } 130 GCModeFlag = cli.StringFlag{ 131 Name: "gcmode", 132 Usage: `Blockchain garbage collection mode ("full", "archive")`, 133 Value: "archive", 134 } 135 136 TxPoolNoLocalsFlag = cli.BoolFlag{ 137 Name: "txpool.nolocals", 138 Usage: "Disables price exemptions for locally submitted transactions", 139 } 140 TxPoolJournalFlag = cli.StringFlag{ 141 Name: "txpool.journal", 142 Usage: "Disk journal for local transaction to survive node restarts", 143 Value: core.DefaultTxPoolConfig.Journal, 144 } 145 TxPoolRejournalFlag = cli.DurationFlag{ 146 Name: "txpool.rejournal", 147 Usage: "Time interval to regenerate the local transaction journal", 148 Value: core.DefaultTxPoolConfig.Rejournal, 149 } 150 TxPoolPriceLimitFlag = cli.Uint64Flag{ 151 Name: "txpool.pricelimit", 152 Usage: "Minimum gas price limit to enforce for acceptance into the pool", 153 Value: neatptc.DefaultConfig.TxPool.PriceLimit, 154 } 155 TxPoolPriceBumpFlag = cli.Uint64Flag{ 156 Name: "txpool.pricebump", 157 Usage: "Price bump percentage to replace an already existing transaction", 158 Value: neatptc.DefaultConfig.TxPool.PriceBump, 159 } 160 TxPoolAccountSlotsFlag = cli.Uint64Flag{ 161 Name: "txpool.accountslots", 162 Usage: "Minimum number of executable transaction slots guaranteed per account", 163 Value: neatptc.DefaultConfig.TxPool.AccountSlots, 164 } 165 TxPoolGlobalSlotsFlag = cli.Uint64Flag{ 166 Name: "txpool.globalslots", 167 Usage: "Maximum number of executable transaction slots for all accounts", 168 Value: neatptc.DefaultConfig.TxPool.GlobalSlots, 169 } 170 TxPoolAccountQueueFlag = cli.Uint64Flag{ 171 Name: "txpool.accountqueue", 172 Usage: "Maximum number of non-executable transaction slots permitted per account", 173 Value: neatptc.DefaultConfig.TxPool.AccountQueue, 174 } 175 TxPoolGlobalQueueFlag = cli.Uint64Flag{ 176 Name: "txpool.globalqueue", 177 Usage: "Maximum number of non-executable transaction slots for all accounts", 178 Value: neatptc.DefaultConfig.TxPool.GlobalQueue, 179 } 180 TxPoolLifetimeFlag = cli.DurationFlag{ 181 Name: "txpool.lifetime", 182 Usage: "Maximum amount of time non-executable transaction are queued", 183 Value: neatptc.DefaultConfig.TxPool.Lifetime, 184 } 185 CacheFlag = cli.IntFlag{ 186 Name: "cache", 187 Usage: "Megabytes of memory allocated to internal caching", 188 Value: 1024, 189 } 190 CacheDatabaseFlag = cli.IntFlag{ 191 Name: "cache.database", 192 Usage: "Percentage of cache memory allowance to use for database io", 193 Value: 50, 194 } 195 CacheTrieFlag = cli.IntFlag{ 196 Name: "cache.trie", 197 Usage: "Percentage of cache memory allowance to use for trie caching (default = 25% full mode, 50% archive mode)", 198 Value: 25, 199 } 200 CacheGCFlag = cli.IntFlag{ 201 Name: "cache.gc", 202 Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", 203 Value: 25, 204 } 205 MiningEnabledFlag = cli.BoolFlag{ 206 Name: "mine", 207 Usage: "Enable mining", 208 } 209 MinerThreadsFlag = cli.IntFlag{ 210 Name: "miner.threads", 211 Usage: "Number of CPU threads to use for mining", 212 Value: 0, 213 } 214 MinerGasTargetFlag = cli.Uint64Flag{ 215 Name: "miner.gastarget", 216 Usage: "Target gas floor for mined blocks", 217 Value: neatptc.DefaultConfig.MinerGasFloor, 218 } 219 MinerGasLimitFlag = cli.Uint64Flag{ 220 Name: "miner.gaslimit", 221 Usage: "Target gas ceiling for mined blocks", 222 Value: neatptc.DefaultConfig.MinerGasCeil, 223 } 224 MinerGasPriceFlag = BigFlag{ 225 Name: "miner.gasprice", 226 Usage: "Minimal gas price for mining a transactions", 227 Value: neatptc.DefaultConfig.MinerGasPrice, 228 } 229 MinerCoinbaseFlag = cli.StringFlag{ 230 Name: "miner.etherbase", 231 Usage: "Public address for block mining rewards (default = first account)", 232 Value: "0", 233 } 234 ExtraDataFlag = cli.StringFlag{ 235 Name: "extradata", 236 Usage: "Block extra data set by the miner (default = client version)", 237 } 238 UnlockedAccountFlag = cli.StringFlag{ 239 Name: "unlock", 240 Usage: "Comma separated list of accounts to unlock", 241 Value: "", 242 } 243 PasswordFileFlag = cli.StringFlag{ 244 Name: "password", 245 Usage: "Password file to use for non-interactive password input", 246 Value: "", 247 } 248 249 VMEnableDebugFlag = cli.BoolFlag{ 250 Name: "vmdebug", 251 Usage: "Record information useful for VM and contract debugging", 252 } 253 EthStatsURLFlag = cli.StringFlag{ 254 Name: "stats", 255 Usage: "Reporting URL of a stats service (nodename:secret@host:port)", 256 } 257 MetricsEnabledFlag = cli.BoolFlag{ 258 Name: metrics.MetricsEnabledFlag, 259 Usage: "Enable metrics collection and reporting", 260 } 261 262 NoCompactionFlag = cli.BoolFlag{ 263 Name: "nocompaction", 264 Usage: "Disables db compaction after import", 265 } 266 RPCEnabledFlag = cli.BoolFlag{ 267 Name: "rpc", 268 Usage: "Enable the HTTP-RPC server", 269 } 270 RPCListenAddrFlag = cli.StringFlag{ 271 Name: "rpcaddr", 272 Usage: "HTTP-RPC server listening interface", 273 Value: node.DefaultHTTPHost, 274 } 275 RPCPortFlag = cli.IntFlag{ 276 Name: "rpcport", 277 Usage: "HTTP-RPC server listening port", 278 Value: node.DefaultHTTPPort, 279 } 280 RPCCORSDomainFlag = cli.StringFlag{ 281 Name: "rpccorsdomain", 282 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 283 Value: "", 284 } 285 RPCVirtualHostsFlag = cli.StringFlag{ 286 Name: "rpcvhosts", 287 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 288 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 289 } 290 RPCApiFlag = cli.StringFlag{ 291 Name: "rpcapi", 292 Usage: "API's offered over the HTTP-RPC interface", 293 Value: "", 294 } 295 IPCDisabledFlag = cli.BoolFlag{ 296 Name: "ipcdisable", 297 Usage: "Disable the IPC-RPC server", 298 } 299 IPCPathFlag = DirectoryFlag{ 300 Name: "ipcpath", 301 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 302 } 303 WSEnabledFlag = cli.BoolFlag{ 304 Name: "ws", 305 Usage: "Enable the WS-RPC server", 306 } 307 WSListenAddrFlag = cli.StringFlag{ 308 Name: "wsaddr", 309 Usage: "WS-RPC server listening interface", 310 Value: node.DefaultWSHost, 311 } 312 WSPortFlag = cli.IntFlag{ 313 Name: "wsport", 314 Usage: "WS-RPC server listening port", 315 Value: node.DefaultWSPort, 316 } 317 WSApiFlag = cli.StringFlag{ 318 Name: "wsapi", 319 Usage: "API is offered over the WS-RPC interface", 320 Value: "", 321 } 322 WSAllowedOriginsFlag = cli.StringFlag{ 323 Name: "wsorigins", 324 Usage: "Origins from which to accept websockets requests", 325 Value: "", 326 } 327 ExecFlag = cli.StringFlag{ 328 Name: "exec", 329 Usage: "Execute JavaScript statement", 330 } 331 PreloadJSFlag = cli.StringFlag{ 332 Name: "preload", 333 Usage: "Comma separated list of JavaScript files to preload into the console", 334 } 335 336 MaxPeersFlag = cli.IntFlag{ 337 Name: "maxpeers", 338 Usage: "Maximum number of network peers (network disabled if set to 0)", 339 Value: 25, 340 } 341 MaxPendingPeersFlag = cli.IntFlag{ 342 Name: "maxpendpeers", 343 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 344 Value: 0, 345 } 346 ListenPortFlag = cli.IntFlag{ 347 Name: "port", 348 Usage: "Network listening port", 349 Value: 9910, 350 } 351 BootnodesFlag = cli.StringFlag{ 352 Name: "bootnodes", 353 Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)", 354 Value: "", 355 } 356 BootnodesV4Flag = cli.StringFlag{ 357 Name: "bootnodesv4", 358 Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)", 359 Value: "", 360 } 361 BootnodesV5Flag = cli.StringFlag{ 362 Name: "bootnodesv5", 363 Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)", 364 Value: "", 365 } 366 NodeKeyFileFlag = cli.StringFlag{ 367 Name: "nodekey", 368 Usage: "P2P node key file", 369 } 370 NodeKeyHexFlag = cli.StringFlag{ 371 Name: "nodekeyhex", 372 Usage: "P2P node key as hex (for testing)", 373 } 374 NATFlag = cli.StringFlag{ 375 Name: "nat", 376 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 377 Value: "any", 378 } 379 NoDiscoverFlag = cli.BoolFlag{ 380 Name: "nodiscover", 381 Usage: "Disables the peer discovery mechanism (manual peer addition)", 382 } 383 DiscoveryV5Flag = cli.BoolFlag{ 384 Name: "v5disc", 385 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 386 } 387 NetrestrictFlag = cli.StringFlag{ 388 Name: "netrestrict", 389 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 390 } 391 392 JSpathFlag = cli.StringFlag{ 393 Name: "jspath", 394 Usage: "JavaScript root path for `loadScript`", 395 Value: ".", 396 } 397 398 SolcPathFlag = cli.StringFlag{ 399 Name: "solc", 400 Usage: "Solidity compiler command to be used", 401 Value: "solc", 402 } 403 404 GpoBlocksFlag = cli.IntFlag{ 405 Name: "gpoblocks", 406 Usage: "Number of recent blocks to check for gas prices", 407 Value: neatptc.DefaultConfig.GPO.Blocks, 408 } 409 GpoPercentileFlag = cli.IntFlag{ 410 Name: "gpopercentile", 411 Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", 412 Value: neatptc.DefaultConfig.GPO.Percentile, 413 } 414 415 PruneFlag = cli.BoolFlag{ 416 Name: "prune", 417 Usage: "Enable the Data Reduction feature, history state data will be pruned by default", 418 } 419 420 PerfTestFlag = cli.BoolFlag{ 421 Name: "perftest", 422 Usage: "Whether doing performance test, will remove some limitations and cause system more frigile", 423 } 424 425 SideChainFlag = cli.StringFlag{ 426 Name: "sideChain", 427 Usage: "Specify one or more side chain should be start. Ex: side-1,side-2", 428 } 429 430 MonikerFlag = cli.StringFlag{ 431 Name: "moniker", 432 Value: "", 433 Usage: "Node's moniker", 434 } 435 436 NodeLaddrFlag = cli.StringFlag{ 437 Name: "node_laddr", 438 Value: "tcp://0.0.0.0:46656", 439 Usage: "Node listen address. (0.0.0.0:0 means any interface, any port)", 440 } 441 442 SeedsFlag = cli.StringFlag{ 443 Name: "seeds", 444 Value: "", 445 Usage: "Comma delimited host:port seed nodes", 446 } 447 448 SkipUpnpFlag = cli.BoolFlag{ 449 Name: "skip_upnp", 450 Usage: "Skip UPNP configuration", 451 } 452 453 RpcLaddrFlag = cli.StringFlag{ 454 Name: "rpc_laddr", 455 Value: "unix://@neatchainrpcunixsock", 456 Usage: "RPC listen address. Port required", 457 } 458 459 AddrFlag = cli.StringFlag{ 460 Name: "addr", 461 Value: "unix://@neatchainappunixsock", 462 Usage: "TMSP app listen address", 463 } 464 ) 465 466 func MakeDataDir(ctx *cli.Context) string { 467 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 468 return path 469 } 470 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 471 return "" 472 } 473 474 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 475 var ( 476 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 477 file = ctx.GlobalString(NodeKeyFileFlag.Name) 478 key *ecdsa.PrivateKey 479 err error 480 ) 481 switch { 482 case file != "" && hex != "": 483 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 484 case file != "": 485 if key, err = crypto.LoadECDSA(file); err != nil { 486 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 487 } 488 cfg.PrivateKey = key 489 case hex != "": 490 if key, err = crypto.HexToECDSA(hex); err != nil { 491 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 492 } 493 cfg.PrivateKey = key 494 } 495 } 496 497 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 498 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 499 cfg.UserIdent = identity 500 } 501 } 502 503 func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { 504 urls := params.MainnetBootnodes 505 switch { 506 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name): 507 if ctx.GlobalIsSet(BootnodesV4Flag.Name) { 508 urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",") 509 } else { 510 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 511 } 512 case ctx.GlobalBool(TestnetFlag.Name): 513 urls = params.TestnetBootnodes 514 case cfg.BootstrapNodes != nil: 515 return 516 } 517 518 cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls)) 519 for _, url := range urls { 520 node, err := discover.ParseNode(url) 521 if err != nil { 522 log.Error("Bootstrap URL invalid", "enode", url, "err", err) 523 continue 524 } 525 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 526 } 527 } 528 529 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 530 if ctx.GlobalIsSet(ListenPortFlag.Name) { 531 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 532 } 533 } 534 535 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 536 if ctx.GlobalIsSet(NATFlag.Name) { 537 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 538 if err != nil { 539 Fatalf("Option %s: %v", NATFlag.Name, err) 540 } 541 cfg.NAT = natif 542 } 543 } 544 545 func splitAndTrim(input string) []string { 546 result := strings.Split(input, ",") 547 for i, r := range result { 548 result[i] = strings.TrimSpace(r) 549 } 550 return result 551 } 552 553 func SetHTTP(ctx *cli.Context, cfg *node.Config) { 554 if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { 555 cfg.HTTPHost = "127.0.0.1" 556 if ctx.GlobalIsSet(RPCListenAddrFlag.Name) { 557 cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name) 558 } 559 } 560 561 if ctx.GlobalIsSet(RPCPortFlag.Name) { 562 cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) 563 } 564 if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { 565 cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name)) 566 } 567 if ctx.GlobalIsSet(RPCApiFlag.Name) { 568 cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name)) 569 } 570 if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) { 571 cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name)) 572 } 573 } 574 575 func SetWS(ctx *cli.Context, cfg *node.Config) { 576 if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { 577 cfg.WSHost = "127.0.0.1" 578 if ctx.GlobalIsSet(WSListenAddrFlag.Name) { 579 cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) 580 } 581 } 582 583 if ctx.GlobalIsSet(WSPortFlag.Name) { 584 cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) 585 } 586 if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { 587 cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) 588 } 589 if ctx.GlobalIsSet(WSApiFlag.Name) { 590 cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name)) 591 } 592 } 593 594 func setIPC(ctx *cli.Context, cfg *node.Config) { 595 checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 596 switch { 597 case ctx.GlobalBool(IPCDisabledFlag.Name): 598 cfg.IPCPath = "" 599 case ctx.GlobalIsSet(IPCPathFlag.Name): 600 cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) 601 } 602 } 603 604 func makeDatabaseHandles() int { 605 limit, err := fdlimit.Current() 606 if err != nil { 607 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 608 } 609 if limit < 2048 { 610 if err := fdlimit.Raise(2048); err != nil { 611 Fatalf("Failed to raise file descriptor allowance: %v", err) 612 } 613 } 614 if limit > 2048 { // cap database file descriptors even if more is available 615 limit = 2048 616 } 617 return limit / 2 // Leave half for networking and other stuff 618 } 619 620 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 621 if common.IsHexAddress(account) { 622 return accounts.Account{Address: common.HexToAddress(account)}, nil 623 } 624 index, err := strconv.Atoi(account) 625 if err != nil || index < 0 { 626 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 627 } 628 log.Warn("-------------------------------------------------------------------") 629 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 630 log.Warn("This functionality is deprecated and will be removed in the future!") 631 log.Warn("Please use explicit addresses! (can search via `neatio account list`)") 632 log.Warn("-------------------------------------------------------------------") 633 634 accs := ks.Accounts() 635 if len(accs) <= index { 636 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 637 } 638 return accs[index], nil 639 } 640 641 func setCoinbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *neatptc.Config) { 642 var coinbase string 643 if ctx.GlobalIsSet(MinerCoinbaseFlag.Name) { 644 coinbase = ctx.GlobalString(MinerCoinbaseFlag.Name) 645 } 646 if coinbase != "" { 647 if ks != nil { 648 account, err := MakeAddress(ks, coinbase) 649 if err != nil { 650 Fatalf("Invalid miner coinbase: %v", err) 651 } 652 cfg.Coinbase = account.Address 653 } else { 654 Fatalf("No coinbase configured") 655 } 656 } 657 } 658 659 func MakePasswordList(ctx *cli.Context) []string { 660 path := ctx.GlobalString(PasswordFileFlag.Name) 661 if path == "" { 662 return nil 663 } 664 text, err := ioutil.ReadFile(path) 665 if err != nil { 666 Fatalf("Failed to read password file: %v", err) 667 } 668 lines := strings.Split(string(text), "\n") 669 for i := range lines { 670 lines[i] = strings.TrimRight(lines[i], "\r") 671 } 672 return lines 673 } 674 675 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 676 setNodeKey(ctx, cfg) 677 setNAT(ctx, cfg) 678 setListenAddress(ctx, cfg) 679 setBootstrapNodes(ctx, cfg) 680 681 if ctx.GlobalIsSet(MaxPeersFlag.Name) { 682 cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) 683 684 } 685 if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { 686 cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) 687 } 688 if ctx.GlobalIsSet(NoDiscoverFlag.Name) { 689 cfg.NoDiscovery = true 690 } 691 692 if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { 693 cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) 694 } 695 696 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 697 list, err := netutil.ParseNetlist(netrestrict) 698 if err != nil { 699 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 700 } 701 cfg.NetRestrict = list 702 } 703 } 704 705 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 706 SetP2PConfig(ctx, &cfg.P2P) 707 setIPC(ctx, cfg) 708 SetHTTP(ctx, cfg) 709 SetWS(ctx, cfg) 710 setNodeUserIdent(ctx, cfg) 711 712 switch { 713 case ctx.GlobalIsSet(DataDirFlag.Name): 714 cfg.GeneralDataDir = ctx.GlobalString(DataDirFlag.Name) 715 cfg.DataDir = filepath.Join(cfg.GeneralDataDir, cfg.ChainId) 716 case !ctx.GlobalIsSet(DataDirFlag.Name): 717 cfg.DataDir = filepath.Join(cfg.GeneralDataDir, cfg.ChainId) 718 case ctx.GlobalBool(TestnetFlag.Name): 719 cfg.DataDir = filepath.Join(cfg.GeneralDataDir, ctx.GlobalString(TestnetFlag.Name)) 720 } 721 722 if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { 723 cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) 724 } 725 726 if ctx.GlobalIsSet(NoUSBFlag.Name) { 727 cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name) 728 } 729 } 730 731 func setGPO(ctx *cli.Context, cfg *gasprice.Config) { 732 if ctx.GlobalIsSet(GpoBlocksFlag.Name) { 733 cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) 734 } 735 if ctx.GlobalIsSet(GpoPercentileFlag.Name) { 736 cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) 737 } 738 } 739 740 func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { 741 if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) { 742 cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name) 743 } 744 if ctx.GlobalIsSet(TxPoolJournalFlag.Name) { 745 cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name) 746 } 747 if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) { 748 cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name) 749 } 750 if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) { 751 cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name) 752 } 753 if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) { 754 cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name) 755 } 756 if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) { 757 cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name) 758 } 759 if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) { 760 cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name) 761 } 762 if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) { 763 cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name) 764 } 765 if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) { 766 cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name) 767 } 768 if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) { 769 cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name) 770 } 771 } 772 773 func checkExclusive(ctx *cli.Context, args ...interface{}) { 774 set := make([]string, 0, 1) 775 for i := 0; i < len(args); i++ { 776 flag, ok := args[i].(cli.Flag) 777 if !ok { 778 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 779 } 780 name := flag.GetName() 781 782 if i+1 < len(args) { 783 switch option := args[i+1].(type) { 784 case string: 785 if ctx.GlobalString(flag.GetName()) == option { 786 name += "=" + option 787 } 788 i++ 789 790 case cli.Flag: 791 default: 792 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 793 } 794 } 795 // Mark the flag if it's set 796 if ctx.GlobalIsSet(flag.GetName()) { 797 set = append(set, "--"+name) 798 } 799 } 800 if len(set) > 1 { 801 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 802 } 803 } 804 805 func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *neatptc.Config) { 806 checkExclusive(ctx, TestnetFlag) 807 checkExclusive(ctx, FastSyncFlag, SyncModeFlag) 808 809 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 810 setCoinbase(ctx, ks, cfg) 811 setGPO(ctx, &cfg.GPO) 812 setTxPool(ctx, &cfg.TxPool) 813 814 switch { 815 case ctx.GlobalIsSet(SyncModeFlag.Name): 816 cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 817 case ctx.GlobalBool(FastSyncFlag.Name): 818 cfg.SyncMode = downloader.FastSync 819 } 820 821 if ctx.GlobalIsSet(NetworkIdFlag.Name) { 822 cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) 823 } 824 825 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { 826 cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 827 } 828 cfg.DatabaseHandles = makeDatabaseHandles() 829 830 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 831 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 832 } 833 cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" 834 835 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { 836 cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 837 } 838 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 839 cfg.TrieDirtyCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 840 } 841 if ctx.GlobalIsSet(DocRootFlag.Name) { 842 cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) 843 } 844 if ctx.GlobalIsSet(ExtraDataFlag.Name) { 845 cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name)) 846 } 847 if ctx.GlobalIsSet(MinerGasTargetFlag.Name) { 848 cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name) 849 } 850 if ctx.GlobalIsSet(MinerGasLimitFlag.Name) { 851 cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name) 852 } 853 if ctx.GlobalIsSet(MinerGasPriceFlag.Name) { 854 cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name) 855 } 856 if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { 857 cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) 858 } 859 860 switch { 861 case ctx.GlobalBool(TestnetFlag.Name): 862 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 863 cfg.NetworkId = 525 864 } 865 } 866 867 cfg.PruneStateData = ctx.GlobalBool(PruneFlag.Name) 868 } 869 870 func SetGeneralConfig(ctx *cli.Context) { 871 params.GenCfg.PerfTest = ctx.GlobalBool(PerfTestFlag.Name) 872 } 873 874 func RegisterIntService(stack *node.Node, cfg *neatptc.Config, cliCtx *cli.Context, cch core.CrossChainHelper) { 875 var err error 876 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 877 fullNode, err := neatptc.New(ctx, cfg, cliCtx, cch, stack.GetLogger(), cliCtx.GlobalBool(TestnetFlag.Name)) 878 return fullNode, err 879 }) 880 if err != nil { 881 Fatalf("Failed to register the neatio service: %v", err) 882 } 883 } 884 885 func MakeChainDatabase(ctx *cli.Context, stack *node.Node) neatdb.Database { 886 var ( 887 cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 888 handles = makeDatabaseHandles() 889 ) 890 name := "chaindata" 891 chainDb, err := stack.OpenDatabase(name, cache, handles, "") 892 if err != nil { 893 Fatalf("Could not open database: %v", err) 894 } 895 return chainDb 896 } 897 898 func MakeGenesis(ctx *cli.Context) *core.Genesis { 899 var genesis *core.Genesis 900 return genesis 901 } 902 903 func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb neatdb.Database) { 904 var err error 905 chainDb = MakeChainDatabase(ctx, stack) 906 config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) 907 if err != nil { 908 Fatalf("%v", err) 909 } 910 var engine consensus.Engine 911 912 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 913 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 914 } 915 cache := &core.CacheConfig{ 916 TrieCleanLimit: neatptc.DefaultConfig.TrieCleanCache, 917 918 TrieDirtyLimit: neatptc.DefaultConfig.TrieDirtyCache, 919 TrieDirtyDisabled: ctx.GlobalString(GCModeFlag.Name) == "archive", 920 TrieTimeLimit: neatptc.DefaultConfig.TrieTimeout, 921 } 922 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { 923 cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 924 } 925 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 926 cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 927 } 928 vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} 929 chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil) 930 if err != nil { 931 Fatalf("Can't create BlockChain: %v", err) 932 } 933 return chain, chainDb 934 } 935 936 func MakeConsolePreloads(ctx *cli.Context) []string { 937 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 938 return nil 939 } 940 preloads := []string{} 941 942 assets := ctx.GlobalString(JSpathFlag.Name) 943 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 944 preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file))) 945 } 946 return preloads 947 } 948 949 func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { 950 return func(ctx *cli.Context) error { 951 for _, name := range ctx.FlagNames() { 952 if ctx.IsSet(name) { 953 if !ctx.GlobalIsSet(name) { 954 ctx.GlobalSet(name, ctx.String(name)) 955 } 956 } 957 } 958 return action(ctx) 959 } 960 } 961 962 var ( 963 Config cfg.Config 964 ) 965 966 func GetNeatConConfig(chainId string, ctx *cli.Context) cfg.Config { 967 datadir := ctx.GlobalString(DataDirFlag.Name) 968 config := tmcfg.GetConfig(datadir, chainId) 969 970 return config 971 }