github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/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/atheioschain/go-atheios/accounts" 32 "github.com/atheioschain/go-atheios/accounts/keystore" 33 "github.com/atheioschain/go-atheios/common" 34 "github.com/atheioschain/go-atheios/core" 35 "github.com/atheioschain/go-atheios/core/state" 36 "github.com/atheioschain/go-atheios/core/vm" 37 "github.com/atheioschain/go-atheios/crypto" 38 "github.com/atheioschain/go-atheios/eth" 39 "github.com/atheioschain/go-atheios/ethdb" 40 "github.com/atheioschain/go-atheios/ethstats" 41 "github.com/atheioschain/go-atheios/event" 42 "github.com/atheioschain/go-atheios/les" 43 "github.com/atheioschain/go-atheios/logger" 44 "github.com/atheioschain/go-atheios/logger/glog" 45 "github.com/atheioschain/go-atheios/metrics" 46 "github.com/atheioschain/go-atheios/node" 47 "github.com/atheioschain/go-atheios/p2p/discover" 48 "github.com/atheioschain/go-atheios/p2p/discv5" 49 "github.com/atheioschain/go-atheios/p2p/nat" 50 "github.com/atheioschain/go-atheios/p2p/netutil" 51 "github.com/atheioschain/go-atheios/params" 52 "github.com/atheioschain/go-atheios/pow" 53 "github.com/atheioschain/go-atheios/rpc" 54 whisper "github.com/atheioschain/go-atheios/whisper/whisperv2" 55 "github.com/ethereum/ethash" 56 "gopkg.in/urfave/cli.v1" 57 ) 58 59 func init() { 60 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 61 62 VERSION: 63 {{.Version}} 64 65 COMMANDS: 66 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 67 {{end}}{{if .Flags}} 68 GLOBAL OPTIONS: 69 {{range .Flags}}{{.}} 70 {{end}}{{end}} 71 ` 72 73 cli.CommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...] 74 {{if .Description}}{{.Description}} 75 {{end}}{{if .Subcommands}} 76 SUBCOMMANDS: 77 {{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 78 {{end}}{{end}}{{if .Flags}} 79 OPTIONS: 80 {{range .Flags}}{{.}} 81 {{end}}{{end}} 82 ` 83 } 84 85 // NewApp creates an app with sane defaults. 86 func NewApp(gitCommit, usage string) *cli.App { 87 app := cli.NewApp() 88 app.Name = filepath.Base(os.Args[0]) 89 app.Author = "" 90 //app.Authors = nil 91 app.Email = "" 92 app.Version = params.Version 93 if gitCommit != "" { 94 app.Version += "-" + gitCommit[:8] 95 } 96 app.Usage = usage 97 return app 98 } 99 100 // These are all the command line flags we support. 101 // If you add to this list, please remember to include the 102 // flag in the appropriate command definition. 103 // 104 // The flags are defined here so their names and help texts 105 // are the same for all commands. 106 107 var ( 108 // General settings 109 DataDirFlag = DirectoryFlag{ 110 Name: "datadir", 111 Usage: "Data directory for the databases and keystore", 112 Value: DirectoryString{node.DefaultDataDir()}, 113 } 114 KeyStoreDirFlag = DirectoryFlag{ 115 Name: "keystore", 116 Usage: "Directory for the keystore (default = inside the datadir)", 117 } 118 NetworkIdFlag = cli.IntFlag{ 119 Name: "networkid", 120 Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten)", 121 Value: eth.NetworkId, 122 } 123 TestNetFlag = cli.BoolFlag{ 124 Name: "testnet", 125 Usage: "Ropsten network: pre-configured test network", 126 } 127 DevModeFlag = cli.BoolFlag{ 128 Name: "dev", 129 Usage: "Developer mode: pre-configured private network with several debugging flags", 130 } 131 IdentityFlag = cli.StringFlag{ 132 Name: "identity", 133 Usage: "Custom node name", 134 } 135 DocRootFlag = DirectoryFlag{ 136 Name: "docroot", 137 Usage: "Document Root for HTTPClient file scheme", 138 Value: DirectoryString{homeDir()}, 139 } 140 FastSyncFlag = cli.BoolFlag{ 141 Name: "fast", 142 Usage: "Enable fast syncing through state downloads - Currently UNSUPPORTED", 143 } 144 LightModeFlag = cli.BoolFlag{ 145 Name: "light", 146 Usage: "Enable light client mode", 147 } 148 LightServFlag = cli.IntFlag{ 149 Name: "lightserv", 150 Usage: "Maximum percentage of time allowed for serving LES requests (0-90)", 151 Value: 0, 152 } 153 LightPeersFlag = cli.IntFlag{ 154 Name: "lightpeers", 155 Usage: "Maximum number of LES client peers", 156 Value: 20, 157 } 158 LightKDFFlag = cli.BoolFlag{ 159 Name: "lightkdf", 160 Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", 161 } 162 // Performance tuning settings 163 CacheFlag = cli.IntFlag{ 164 Name: "cache", 165 Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)", 166 Value: 128, 167 } 168 TrieCacheGenFlag = cli.IntFlag{ 169 Name: "trie-cache-gens", 170 Usage: "Number of trie node generations to keep in memory", 171 Value: int(state.MaxTrieCacheGen), 172 } 173 // Miner settings 174 MiningEnabledFlag = cli.BoolFlag{ 175 Name: "mine", 176 Usage: "Enable mining", 177 } 178 MinerThreadsFlag = cli.IntFlag{ 179 Name: "minerthreads", 180 Usage: "Number of CPU threads to use for mining", 181 Value: runtime.NumCPU(), 182 } 183 TargetGasLimitFlag = cli.StringFlag{ 184 Name: "targetgaslimit", 185 Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine", 186 Value: params.GenesisGasLimit.String(), 187 } 188 AutoDAGFlag = cli.BoolFlag{ 189 Name: "autodag", 190 Usage: "Enable automatic DAG pregeneration", 191 } 192 EtherbaseFlag = cli.StringFlag{ 193 Name: "etherbase", 194 Usage: "Public address for block mining rewards (default = first account created)", 195 Value: "0", 196 } 197 GasPriceFlag = cli.StringFlag{ 198 Name: "gasprice", 199 Usage: "Minimal gas price to accept for mining a transactions", 200 Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(), 201 } 202 ExtraDataFlag = cli.StringFlag{ 203 Name: "extradata", 204 Usage: "Block extra data set by the miner (default = client version)", 205 } 206 // Account settings 207 UnlockedAccountFlag = cli.StringFlag{ 208 Name: "unlock", 209 Usage: "Comma separated list of accounts to unlock", 210 Value: "", 211 } 212 PasswordFileFlag = cli.StringFlag{ 213 Name: "password", 214 Usage: "Password file to use for non-inteactive password input", 215 Value: "", 216 } 217 218 VMForceJitFlag = cli.BoolFlag{ 219 Name: "forcejit", 220 Usage: "Force the JIT VM to take precedence", 221 } 222 VMJitCacheFlag = cli.IntFlag{ 223 Name: "jitcache", 224 Usage: "Amount of cached JIT VM programs", 225 Value: 64, 226 } 227 VMEnableJitFlag = cli.BoolFlag{ 228 Name: "jitvm", 229 Usage: "Enable the JIT VM", 230 } 231 VMEnableDebugFlag = cli.BoolFlag{ 232 Name: "vmdebug", 233 Usage: "Record information useful for VM and contract debugging", 234 } 235 // Logging and debug settings 236 EthStatsURLFlag = cli.StringFlag{ 237 Name: "ethstats", 238 Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", 239 } 240 MetricsEnabledFlag = cli.BoolFlag{ 241 Name: metrics.MetricsEnabledFlag, 242 Usage: "Enable metrics collection and reporting", 243 } 244 FakePoWFlag = cli.BoolFlag{ 245 Name: "fakepow", 246 Usage: "Disables proof-of-work verification", 247 } 248 249 // RPC settings 250 RPCEnabledFlag = cli.BoolFlag{ 251 Name: "rpc", 252 Usage: "Enable the HTTP-RPC server", 253 } 254 RPCListenAddrFlag = cli.StringFlag{ 255 Name: "rpcaddr", 256 Usage: "HTTP-RPC server listening interface", 257 Value: node.DefaultHTTPHost, 258 } 259 RPCPortFlag = cli.IntFlag{ 260 Name: "rpcport", 261 Usage: "HTTP-RPC server listening port", 262 Value: node.DefaultHTTPPort, 263 } 264 RPCCORSDomainFlag = cli.StringFlag{ 265 Name: "rpccorsdomain", 266 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 267 Value: "", 268 } 269 RPCApiFlag = cli.StringFlag{ 270 Name: "rpcapi", 271 Usage: "API's offered over the HTTP-RPC interface", 272 Value: rpc.DefaultHTTPApis, 273 } 274 IPCDisabledFlag = cli.BoolFlag{ 275 Name: "ipcdisable", 276 Usage: "Disable the IPC-RPC server", 277 } 278 IPCApiFlag = cli.StringFlag{ 279 Name: "ipcapi", 280 Usage: "APIs offered over the IPC-RPC interface", 281 Value: rpc.DefaultIPCApis, 282 } 283 IPCPathFlag = DirectoryFlag{ 284 Name: "ipcpath", 285 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 286 Value: DirectoryString{"gath.ipc"}, 287 } 288 WSEnabledFlag = cli.BoolFlag{ 289 Name: "ws", 290 Usage: "Enable the WS-RPC server", 291 } 292 WSListenAddrFlag = cli.StringFlag{ 293 Name: "wsaddr", 294 Usage: "WS-RPC server listening interface", 295 Value: node.DefaultWSHost, 296 } 297 WSPortFlag = cli.IntFlag{ 298 Name: "wsport", 299 Usage: "WS-RPC server listening port", 300 Value: node.DefaultWSPort, 301 } 302 WSApiFlag = cli.StringFlag{ 303 Name: "wsapi", 304 Usage: "API's offered over the WS-RPC interface", 305 Value: rpc.DefaultHTTPApis, 306 } 307 WSAllowedOriginsFlag = cli.StringFlag{ 308 Name: "wsorigins", 309 Usage: "Origins from which to accept websockets requests", 310 Value: "", 311 } 312 ExecFlag = cli.StringFlag{ 313 Name: "exec", 314 Usage: "Execute JavaScript statement (only in combination with console/attach)", 315 } 316 PreloadJSFlag = cli.StringFlag{ 317 Name: "preload", 318 Usage: "Comma separated list of JavaScript files to preload into the console", 319 } 320 321 // Network Settings 322 MaxPeersFlag = cli.IntFlag{ 323 Name: "maxpeers", 324 Usage: "Maximum number of network peers (network disabled if set to 0)", 325 Value: 25, 326 } 327 MaxPendingPeersFlag = cli.IntFlag{ 328 Name: "maxpendpeers", 329 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 330 Value: 0, 331 } 332 ListenPortFlag = cli.IntFlag{ 333 Name: "port", 334 Usage: "Network listening port", 335 Value: 30696, 336 } 337 BootnodesFlag = cli.StringFlag{ 338 Name: "bootnodes", 339 Usage: "Comma separated enode URLs for P2P discovery bootstrap", 340 Value: "", 341 } 342 NodeKeyFileFlag = cli.StringFlag{ 343 Name: "nodekey", 344 Usage: "P2P node key file", 345 } 346 NodeKeyHexFlag = cli.StringFlag{ 347 Name: "nodekeyhex", 348 Usage: "P2P node key as hex (for testing)", 349 } 350 NATFlag = cli.StringFlag{ 351 Name: "nat", 352 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 353 Value: "any", 354 } 355 NoDiscoverFlag = cli.BoolFlag{ 356 Name: "nodiscover", 357 Usage: "Disables the peer discovery mechanism (manual peer addition)", 358 } 359 DiscoveryV5Flag = cli.BoolFlag{ 360 Name: "v5disc", 361 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 362 } 363 NetrestrictFlag = cli.StringFlag{ 364 Name: "netrestrict", 365 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 366 } 367 368 WhisperEnabledFlag = cli.BoolFlag{ 369 Name: "shh", 370 Usage: "Enable Whisper", 371 } 372 373 // ATM the url is left to the user and deployment to 374 JSpathFlag = cli.StringFlag{ 375 Name: "jspath", 376 Usage: "JavaScript root path for `loadScript`", 377 Value: ".", 378 } 379 SolcPathFlag = cli.StringFlag{ 380 Name: "solc", 381 Usage: "Solidity compiler command to be used", 382 Value: "solc", 383 } 384 385 // Gas price oracle settings 386 GpoMinGasPriceFlag = cli.StringFlag{ 387 Name: "gpomin", 388 Usage: "Minimum suggested gas price", 389 Value: new(big.Int).Mul(big.NewInt(20), common.Shannon).String(), 390 } 391 GpoMaxGasPriceFlag = cli.StringFlag{ 392 Name: "gpomax", 393 Usage: "Maximum suggested gas price", 394 Value: new(big.Int).Mul(big.NewInt(500), common.Shannon).String(), 395 } 396 GpoFullBlockRatioFlag = cli.IntFlag{ 397 Name: "gpofull", 398 Usage: "Full block threshold for gas price calculation (%)", 399 Value: 80, 400 } 401 GpobaseStepDownFlag = cli.IntFlag{ 402 Name: "gpobasedown", 403 Usage: "Suggested gas price base step down ratio (1/1000)", 404 Value: 10, 405 } 406 GpobaseStepUpFlag = cli.IntFlag{ 407 Name: "gpobaseup", 408 Usage: "Suggested gas price base step up ratio (1/1000)", 409 Value: 100, 410 } 411 GpobaseCorrectionFactorFlag = cli.IntFlag{ 412 Name: "gpobasecf", 413 Usage: "Suggested gas price base correction factor (%)", 414 Value: 110, 415 } 416 ) 417 418 // MakeDataDir retrieves the currently requested data directory, terminating 419 // if none (or the empty string) is specified. If the node is starting a testnet, 420 // the a subdirectory of the specified datadir will be used. 421 func MakeDataDir(ctx *cli.Context) string { 422 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 423 // TODO: choose a different location outside of the regular datadir. 424 if ctx.GlobalBool(TestNetFlag.Name) { 425 return filepath.Join(path, "testnet") 426 } 427 return path 428 } 429 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 430 return "" 431 } 432 433 // MakeIPCPath creates an IPC path configuration from the set command line flags, 434 // returning an empty string if IPC was explicitly disabled, or the set path. 435 func MakeIPCPath(ctx *cli.Context) string { 436 if ctx.GlobalBool(IPCDisabledFlag.Name) { 437 return "" 438 } 439 return ctx.GlobalString(IPCPathFlag.Name) 440 } 441 442 // MakeNodeKey creates a node key from set command line flags, either loading it 443 // from a file or as a specified hex value. If neither flags were provided, this 444 // method returns nil and an emphemeral key is to be generated. 445 func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey { 446 var ( 447 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 448 file = ctx.GlobalString(NodeKeyFileFlag.Name) 449 450 key *ecdsa.PrivateKey 451 err error 452 ) 453 switch { 454 case file != "" && hex != "": 455 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 456 457 case file != "": 458 if key, err = crypto.LoadECDSA(file); err != nil { 459 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 460 } 461 462 case hex != "": 463 if key, err = crypto.HexToECDSA(hex); err != nil { 464 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 465 } 466 } 467 return key 468 } 469 470 // makeNodeUserIdent creates the user identifier from CLI flags. 471 func makeNodeUserIdent(ctx *cli.Context) string { 472 var comps []string 473 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 474 comps = append(comps, identity) 475 } 476 if ctx.GlobalBool(VMEnableJitFlag.Name) { 477 comps = append(comps, "JIT") 478 } 479 return strings.Join(comps, "/") 480 } 481 482 // MakeBootstrapNodes creates a list of bootstrap nodes from the command line 483 // flags, reverting to pre-configured ones if none have been specified. 484 func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node { 485 urls := params.MainnetBootnodes 486 if ctx.GlobalIsSet(BootnodesFlag.Name) { 487 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 488 } else if ctx.GlobalBool(TestNetFlag.Name) { 489 urls = params.TestnetBootnodes 490 } 491 492 bootnodes := make([]*discover.Node, 0, len(urls)) 493 for _, url := range urls { 494 node, err := discover.ParseNode(url) 495 if err != nil { 496 glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err) 497 continue 498 } 499 bootnodes = append(bootnodes, node) 500 } 501 return bootnodes 502 } 503 504 // MakeBootstrapNodesV5 creates a list of bootstrap nodes from the command line 505 // flags, reverting to pre-configured ones if none have been specified. 506 func MakeBootstrapNodesV5(ctx *cli.Context) []*discv5.Node { 507 urls := params.DiscoveryV5Bootnodes 508 if ctx.GlobalIsSet(BootnodesFlag.Name) { 509 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 510 } 511 512 bootnodes := make([]*discv5.Node, 0, len(urls)) 513 for _, url := range urls { 514 node, err := discv5.ParseNode(url) 515 if err != nil { 516 glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err) 517 continue 518 } 519 bootnodes = append(bootnodes, node) 520 } 521 return bootnodes 522 } 523 524 // MakeListenAddress creates a TCP listening address string from set command 525 // line flags. 526 func MakeListenAddress(ctx *cli.Context) string { 527 return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 528 } 529 530 // MakeDiscoveryV5Address creates a UDP listening address string from set command 531 // line flags for the V5 discovery protocol. 532 func MakeDiscoveryV5Address(ctx *cli.Context) string { 533 return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)+1) 534 } 535 536 // MakeNAT creates a port mapper from set command line flags. 537 func MakeNAT(ctx *cli.Context) nat.Interface { 538 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 539 if err != nil { 540 Fatalf("Option %s: %v", NATFlag.Name, err) 541 } 542 return natif 543 } 544 545 // MakeRPCModules splits input separated by a comma and trims excessive white 546 // space from the substrings. 547 func MakeRPCModules(input string) []string { 548 result := strings.Split(input, ",") 549 for i, r := range result { 550 result[i] = strings.TrimSpace(r) 551 } 552 return result 553 } 554 555 // MakeHTTPRpcHost creates the HTTP RPC listener interface string from the set 556 // command line flags, returning empty if the HTTP endpoint is disabled. 557 func MakeHTTPRpcHost(ctx *cli.Context) string { 558 if !ctx.GlobalBool(RPCEnabledFlag.Name) { 559 return "" 560 } 561 return ctx.GlobalString(RPCListenAddrFlag.Name) 562 } 563 564 // MakeWSRpcHost creates the WebSocket RPC listener interface string from the set 565 // command line flags, returning empty if the HTTP endpoint is disabled. 566 func MakeWSRpcHost(ctx *cli.Context) string { 567 if !ctx.GlobalBool(WSEnabledFlag.Name) { 568 return "" 569 } 570 return ctx.GlobalString(WSListenAddrFlag.Name) 571 } 572 573 // MakeDatabaseHandles raises out the number of allowed file handles per process 574 // for gath and returns half of the allowance to assign to the database. 575 func MakeDatabaseHandles() int { 576 if err := raiseFdLimit(2048); err != nil { 577 Fatalf("Failed to raise file descriptor allowance: %v", err) 578 } 579 limit, err := getFdLimit() 580 if err != nil { 581 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 582 } 583 if limit > 2048 { // cap database file descriptors even if more is available 584 limit = 2048 585 } 586 return limit / 2 // Leave half for networking and other stuff 587 } 588 589 // MakeAddress converts an account specified directly as a hex encoded string or 590 // a key index in the key store to an internal account representation. 591 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 592 // If the specified account is a valid address, return it 593 if common.IsHexAddress(account) { 594 return accounts.Account{Address: common.HexToAddress(account)}, nil 595 } 596 // Otherwise try to interpret the account as a keystore index 597 index, err := strconv.Atoi(account) 598 if err != nil || index < 0 { 599 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 600 } 601 accs := ks.Accounts() 602 if len(accs) <= index { 603 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 604 } 605 return accs[index], nil 606 } 607 608 // MakeEtherbase retrieves the etherbase either from the directly specified 609 // command line flags or from the keystore if CLI indexed. 610 func MakeEtherbase(ks *keystore.KeyStore, ctx *cli.Context) common.Address { 611 accounts := ks.Accounts() 612 if !ctx.GlobalIsSet(EtherbaseFlag.Name) && len(accounts) == 0 { 613 glog.V(logger.Error).Infoln("WARNING: No etherbase set and no accounts found as default") 614 return common.Address{} 615 } 616 etherbase := ctx.GlobalString(EtherbaseFlag.Name) 617 if etherbase == "" { 618 return common.Address{} 619 } 620 // If the specified etherbase is a valid address, return it 621 account, err := MakeAddress(ks, etherbase) 622 if err != nil { 623 Fatalf("Option %q: %v", EtherbaseFlag.Name, err) 624 } 625 return account.Address 626 } 627 628 // MakeMinerExtra resolves extradata for the miner from the set command line flags 629 // or returns a default one composed on the client, runtime and OS metadata. 630 func MakeMinerExtra(extra []byte, ctx *cli.Context) []byte { 631 if ctx.GlobalIsSet(ExtraDataFlag.Name) { 632 return []byte(ctx.GlobalString(ExtraDataFlag.Name)) 633 } 634 return extra 635 } 636 637 // MakePasswordList reads password lines from the file specified by --password. 638 func MakePasswordList(ctx *cli.Context) []string { 639 path := ctx.GlobalString(PasswordFileFlag.Name) 640 if path == "" { 641 return nil 642 } 643 text, err := ioutil.ReadFile(path) 644 if err != nil { 645 Fatalf("Failed to read password file: %v", err) 646 } 647 lines := strings.Split(string(text), "\n") 648 // Sanitise DOS line endings. 649 for i := range lines { 650 lines[i] = strings.TrimRight(lines[i], "\r") 651 } 652 return lines 653 } 654 655 // MakeNode configures a node with no services from command line flags. 656 func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node { 657 vsn := params.Version 658 if gitCommit != "" { 659 vsn += "-" + gitCommit[:8] 660 } 661 662 // if we're running a light client or server, force enable the v5 peer discovery unless it is explicitly disabled with --nodiscover 663 // note that explicitly specifying --v5disc overrides --nodiscover, in which case the later only disables v4 discovery 664 forceV5Discovery := (ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0) && !ctx.GlobalBool(NoDiscoverFlag.Name) 665 666 config := &node.Config{ 667 DataDir: MakeDataDir(ctx), 668 KeyStoreDir: ctx.GlobalString(KeyStoreDirFlag.Name), 669 UseLightweightKDF: ctx.GlobalBool(LightKDFFlag.Name), 670 PrivateKey: MakeNodeKey(ctx), 671 Name: name, 672 Version: vsn, 673 UserIdent: makeNodeUserIdent(ctx), 674 NoDiscovery: ctx.GlobalBool(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name), // always disable v4 discovery in light client mode 675 DiscoveryV5: ctx.GlobalBool(DiscoveryV5Flag.Name) || forceV5Discovery, 676 DiscoveryV5Addr: MakeDiscoveryV5Address(ctx), 677 BootstrapNodes: MakeBootstrapNodes(ctx), 678 BootstrapNodesV5: MakeBootstrapNodesV5(ctx), 679 ListenAddr: MakeListenAddress(ctx), 680 NAT: MakeNAT(ctx), 681 MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name), 682 MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name), 683 IPCPath: MakeIPCPath(ctx), 684 HTTPHost: MakeHTTPRpcHost(ctx), 685 HTTPPort: ctx.GlobalInt(RPCPortFlag.Name), 686 HTTPCors: ctx.GlobalString(RPCCORSDomainFlag.Name), 687 HTTPModules: MakeRPCModules(ctx.GlobalString(RPCApiFlag.Name)), 688 WSHost: MakeWSRpcHost(ctx), 689 WSPort: ctx.GlobalInt(WSPortFlag.Name), 690 WSOrigins: ctx.GlobalString(WSAllowedOriginsFlag.Name), 691 WSModules: MakeRPCModules(ctx.GlobalString(WSApiFlag.Name)), 692 } 693 if ctx.GlobalBool(DevModeFlag.Name) { 694 if !ctx.GlobalIsSet(DataDirFlag.Name) { 695 config.DataDir = filepath.Join(os.TempDir(), "/ethereum_dev_mode") 696 } 697 // --dev mode does not need p2p networking. 698 config.MaxPeers = 0 699 config.ListenAddr = ":0" 700 } 701 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 702 list, err := netutil.ParseNetlist(netrestrict) 703 if err != nil { 704 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 705 } 706 config.NetRestrict = list 707 } 708 709 stack, err := node.New(config) 710 if err != nil { 711 Fatalf("Failed to create the protocol stack: %v", err) 712 } 713 return stack 714 } 715 716 // RegisterEthService configures eth.Ethereum from command line flags and adds it to the 717 // given node. 718 func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) { 719 // Avoid conflicting network flags 720 networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag} 721 for _, flag := range netFlags { 722 if ctx.GlobalBool(flag.Name) { 723 networks++ 724 } 725 } 726 if networks > 1 { 727 Fatalf("The %v flags are mutually exclusive", netFlags) 728 } 729 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 730 731 ethConf := ð.Config{ 732 Etherbase: MakeEtherbase(ks, ctx), 733 ChainConfig: MakeChainConfig(ctx, stack), 734 FastSync: false, 735 LightMode: ctx.GlobalBool(LightModeFlag.Name), 736 LightServ: ctx.GlobalInt(LightServFlag.Name), 737 LightPeers: ctx.GlobalInt(LightPeersFlag.Name), 738 MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name), 739 DatabaseCache: ctx.GlobalInt(CacheFlag.Name), 740 DatabaseHandles: MakeDatabaseHandles(), 741 NetworkId: ctx.GlobalInt(NetworkIdFlag.Name), 742 MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name), 743 ExtraData: MakeMinerExtra(extra, ctx), 744 DocRoot: ctx.GlobalString(DocRootFlag.Name), 745 GasPrice: common.String2Big(ctx.GlobalString(GasPriceFlag.Name)), 746 GpoMinGasPrice: common.String2Big(ctx.GlobalString(GpoMinGasPriceFlag.Name)), 747 GpoMaxGasPrice: common.String2Big(ctx.GlobalString(GpoMaxGasPriceFlag.Name)), 748 GpoFullBlockRatio: ctx.GlobalInt(GpoFullBlockRatioFlag.Name), 749 GpobaseStepDown: ctx.GlobalInt(GpobaseStepDownFlag.Name), 750 GpobaseStepUp: ctx.GlobalInt(GpobaseStepUpFlag.Name), 751 GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name), 752 SolcPath: ctx.GlobalString(SolcPathFlag.Name), 753 AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name), 754 EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name), 755 } 756 757 // Override any default configs in dev mode or the test net 758 switch { 759 case ctx.GlobalBool(TestNetFlag.Name): 760 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 761 ethConf.NetworkId = 11235813 762 } 763 ethConf.Genesis = core.DefaultTestnetGenesisBlock() 764 765 case ctx.GlobalBool(DevModeFlag.Name): 766 ethConf.Genesis = core.DevGenesisBlock() 767 if !ctx.GlobalIsSet(GasPriceFlag.Name) { 768 ethConf.GasPrice = new(big.Int) 769 } 770 ethConf.PowTest = true 771 } 772 // Override any global options pertaining to the Ethereum protocol 773 if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 { 774 state.MaxTrieCacheGen = uint16(gen) 775 } 776 777 if ethConf.LightMode { 778 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 779 return les.New(ctx, ethConf) 780 }); err != nil { 781 Fatalf("Failed to register the Ethereum light node service: %v", err) 782 } 783 } else { 784 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 785 fullNode, err := eth.New(ctx, ethConf) 786 if fullNode != nil && ethConf.LightServ > 0 { 787 ls, _ := les.NewLesServer(fullNode, ethConf) 788 fullNode.AddLesServer(ls) 789 } 790 return fullNode, err 791 }); err != nil { 792 Fatalf("Failed to register the Ethereum full node service: %v", err) 793 } 794 } 795 } 796 797 // RegisterShhService configures Whisper and adds it to the given node. 798 func RegisterShhService(stack *node.Node) { 799 if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil { 800 Fatalf("Failed to register the Whisper service: %v", err) 801 } 802 } 803 804 // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to 805 // th egiven node. 806 func RegisterEthStatsService(stack *node.Node, url string) { 807 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 808 // Retrieve both eth and les services 809 var ethServ *eth.Ethereum 810 ctx.Service(ðServ) 811 812 var lesServ *les.LightEthereum 813 ctx.Service(&lesServ) 814 815 return ethstats.New(url, ethServ, lesServ) 816 }); err != nil { 817 Fatalf("Failed to register the Ethereum Stats service: %v", err) 818 } 819 } 820 821 // SetupNetwork configures the system for either the main net or some test network. 822 func SetupNetwork(ctx *cli.Context) { 823 params.TargetGasLimit = common.String2Big(ctx.GlobalString(TargetGasLimitFlag.Name)) 824 } 825 826 // MakeChainConfig reads the chain configuration from the database in ctx.Datadir. 827 func MakeChainConfig(ctx *cli.Context, stack *node.Node) *params.ChainConfig { 828 db := MakeChainDatabase(ctx, stack) 829 defer db.Close() 830 831 return MakeChainConfigFromDb(ctx, db) 832 } 833 834 // MakeChainConfigFromDb reads the chain configuration from the given database. 835 func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *params.ChainConfig { 836 // If the chain is already initialized, use any existing chain configs 837 config := new(params.ChainConfig) 838 839 genesis := core.GetBlock(db, core.GetCanonicalHash(db, 0), 0) 840 if genesis != nil { 841 storedConfig, err := core.GetChainConfig(db, genesis.Hash()) 842 switch err { 843 case nil: 844 config = storedConfig 845 case core.ChainConfigNotFoundErr: 846 // No configs found, use empty, will populate below 847 default: 848 Fatalf("Could not make chain configuration: %v", err) 849 } 850 } 851 // set chain id in case it's zero. 852 if config.ChainId == nil { 853 config.ChainId = new(big.Int) 854 } 855 // Check whether we are allowed to set default config params or not: 856 // - If no genesis is set, we're running either mainnet or testnet (private nets use `gath init`) 857 // - If a genesis is already set, ensure we have a configuration for it (mainnet or testnet) 858 defaults := genesis == nil || 859 (genesis.Hash() == params.MainNetGenesisHash && !ctx.GlobalBool(TestNetFlag.Name)) || 860 (genesis.Hash() == params.TestNetGenesisHash && ctx.GlobalBool(TestNetFlag.Name)) 861 862 if defaults { 863 if ctx.GlobalBool(TestNetFlag.Name) { 864 config = params.TestnetChainConfig 865 } else { 866 // Homestead fork 867 config.HomesteadBlock = params.MainNetHomesteadBlock 868 869 // DoS reprice fork 870 config.EIP150Block = params.MainNetHomesteadGasRepriceBlock 871 config.EIP150Hash = params.MainNetHomesteadGasRepriceHash 872 873 // DoS state cleanup fork 874 config.EIP155Block = params.MainNetSpuriousDragon 875 config.EIP158Block = params.MainNetSpuriousDragon 876 config.ChainId = params.MainNetChainID 877 } 878 } 879 return config 880 } 881 882 func ChainDbName(ctx *cli.Context) string { 883 if ctx.GlobalBool(LightModeFlag.Name) { 884 return "lightchaindata" 885 } else { 886 return "chaindata" 887 } 888 } 889 890 // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. 891 func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { 892 var ( 893 cache = ctx.GlobalInt(CacheFlag.Name) 894 handles = MakeDatabaseHandles() 895 name = ChainDbName(ctx) 896 ) 897 898 chainDb, err := stack.OpenDatabase(name, cache, handles) 899 if err != nil { 900 Fatalf("Could not open database: %v", err) 901 } 902 return chainDb 903 } 904 905 // MakeChain creates a chain manager from set command line flags. 906 func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { 907 var err error 908 chainDb = MakeChainDatabase(ctx, stack) 909 910 if ctx.GlobalBool(TestNetFlag.Name) { 911 _, err := core.WriteTestNetGenesisBlock(chainDb) 912 if err != nil { 913 glog.Fatalln(err) 914 } 915 } 916 917 chainConfig := MakeChainConfigFromDb(ctx, chainDb) 918 919 pow := pow.PoW(core.FakePow{}) 920 if !ctx.GlobalBool(FakePoWFlag.Name) { 921 pow = ethash.New() 922 } 923 chain, err = core.NewBlockChain(chainDb, chainConfig, pow, new(event.TypeMux), vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}) 924 if err != nil { 925 Fatalf("Could not start chainmanager: %v", err) 926 } 927 return chain, chainDb 928 } 929 930 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 931 // scripts to preload before starting. 932 func MakeConsolePreloads(ctx *cli.Context) []string { 933 // Skip preloading if there's nothing to preload 934 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 935 return nil 936 } 937 // Otherwise resolve absolute paths and return them 938 preloads := []string{} 939 940 assets := ctx.GlobalString(JSpathFlag.Name) 941 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 942 preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file))) 943 } 944 return preloads 945 }