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