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