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