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