github.com/hyperion-hyn/go-ethereum@v2.4.0+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 "strconv" 28 "strings" 29 30 "github.com/ethereum/go-ethereum/permission" 31 32 "time" 33 34 "github.com/ethereum/go-ethereum/accounts" 35 "github.com/ethereum/go-ethereum/accounts/keystore" 36 "github.com/ethereum/go-ethereum/common" 37 "github.com/ethereum/go-ethereum/common/fdlimit" 38 "github.com/ethereum/go-ethereum/consensus" 39 "github.com/ethereum/go-ethereum/consensus/clique" 40 "github.com/ethereum/go-ethereum/consensus/ethash" 41 "github.com/ethereum/go-ethereum/core" 42 "github.com/ethereum/go-ethereum/core/state" 43 "github.com/ethereum/go-ethereum/core/vm" 44 "github.com/ethereum/go-ethereum/crypto" 45 "github.com/ethereum/go-ethereum/dashboard" 46 "github.com/ethereum/go-ethereum/eth" 47 "github.com/ethereum/go-ethereum/eth/downloader" 48 "github.com/ethereum/go-ethereum/eth/gasprice" 49 "github.com/ethereum/go-ethereum/ethdb" 50 "github.com/ethereum/go-ethereum/ethstats" 51 "github.com/ethereum/go-ethereum/les" 52 "github.com/ethereum/go-ethereum/log" 53 "github.com/ethereum/go-ethereum/metrics" 54 "github.com/ethereum/go-ethereum/metrics/influxdb" 55 "github.com/ethereum/go-ethereum/node" 56 "github.com/ethereum/go-ethereum/p2p" 57 "github.com/ethereum/go-ethereum/p2p/discv5" 58 "github.com/ethereum/go-ethereum/p2p/enode" 59 "github.com/ethereum/go-ethereum/p2p/nat" 60 "github.com/ethereum/go-ethereum/p2p/netutil" 61 "github.com/ethereum/go-ethereum/params" 62 whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" 63 "gopkg.in/urfave/cli.v1" 64 ) 65 66 var ( 67 CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...] 68 {{if .cmd.Description}}{{.cmd.Description}} 69 {{end}}{{if .cmd.Subcommands}} 70 SUBCOMMANDS: 71 {{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 72 {{end}}{{end}}{{if .categorizedFlags}} 73 {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS: 74 {{range $categorized.Flags}}{{"\t"}}{{.}} 75 {{end}} 76 {{end}}{{end}}` 77 ) 78 79 func init() { 80 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 81 82 VERSION: 83 {{.Version}} 84 85 COMMANDS: 86 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 87 {{end}}{{if .Flags}} 88 GLOBAL OPTIONS: 89 {{range .Flags}}{{.}} 90 {{end}}{{end}} 91 ` 92 93 cli.CommandHelpTemplate = CommandHelpTemplate 94 } 95 96 // NewApp creates an app with sane defaults. 97 func NewApp(gitCommit, usage string) *cli.App { 98 app := cli.NewApp() 99 app.Name = filepath.Base(os.Args[0]) 100 app.Author = "" 101 //app.Authors = nil 102 app.Email = "" 103 app.Version = params.VersionWithMeta 104 if len(gitCommit) >= 8 { 105 app.Version += "-" + gitCommit[:8] 106 } 107 app.Usage = usage 108 return app 109 } 110 111 // These are all the command line flags we support. 112 // If you add to this list, please remember to include the 113 // flag in the appropriate command definition. 114 // 115 // The flags are defined here so their names and help texts 116 // are the same for all commands. 117 118 var ( 119 // General settings 120 DataDirFlag = DirectoryFlag{ 121 Name: "datadir", 122 Usage: "Data directory for the databases and keystore", 123 Value: DirectoryString{node.DefaultDataDir()}, 124 } 125 KeyStoreDirFlag = DirectoryFlag{ 126 Name: "keystore", 127 Usage: "Directory for the keystore (default = inside the datadir)", 128 } 129 NoUSBFlag = cli.BoolFlag{ 130 Name: "nousb", 131 Usage: "Disables monitoring for and managing USB hardware wallets", 132 } 133 NetworkIdFlag = cli.Uint64Flag{ 134 Name: "networkid", 135 Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby, 5=Ottoman)", 136 Value: eth.DefaultConfig.NetworkId, 137 } 138 TestnetFlag = cli.BoolFlag{ 139 Name: "testnet", 140 Usage: "Ropsten network: pre-configured proof-of-work test network", 141 } 142 RinkebyFlag = cli.BoolFlag{ 143 Name: "rinkeby", 144 Usage: "Rinkeby network: pre-configured proof-of-authority test network", 145 } 146 OttomanFlag = cli.BoolFlag{ 147 Name: "ottoman", 148 Usage: "Ottoman network: pre-configured istanbul bft test network", 149 } 150 DeveloperFlag = cli.BoolFlag{ 151 Name: "dev", 152 Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", 153 } 154 DeveloperPeriodFlag = cli.IntFlag{ 155 Name: "dev.period", 156 Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", 157 } 158 IdentityFlag = cli.StringFlag{ 159 Name: "identity", 160 Usage: "Custom node name", 161 } 162 DocRootFlag = DirectoryFlag{ 163 Name: "docroot", 164 Usage: "Document Root for HTTPClient file scheme", 165 Value: DirectoryString{homeDir()}, 166 } 167 defaultSyncMode = eth.DefaultConfig.SyncMode 168 SyncModeFlag = TextMarshalerFlag{ 169 Name: "syncmode", 170 Usage: `Blockchain sync mode ("fast", "full", or "light")`, 171 Value: &defaultSyncMode, 172 } 173 GCModeFlag = cli.StringFlag{ 174 Name: "gcmode", 175 Usage: `Blockchain garbage collection mode ("full", "archive")`, 176 Value: "full", 177 } 178 LightServFlag = cli.IntFlag{ 179 Name: "lightserv", 180 Usage: "Maximum percentage of time allowed for serving LES requests (0-90)", 181 Value: 0, 182 } 183 LightPeersFlag = cli.IntFlag{ 184 Name: "lightpeers", 185 Usage: "Maximum number of LES client peers", 186 Value: eth.DefaultConfig.LightPeers, 187 } 188 LightKDFFlag = cli.BoolFlag{ 189 Name: "lightkdf", 190 Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", 191 } 192 // Dashboard settings 193 DashboardEnabledFlag = cli.BoolFlag{ 194 Name: metrics.DashboardEnabledFlag, 195 Usage: "Enable the dashboard", 196 } 197 DashboardAddrFlag = cli.StringFlag{ 198 Name: "dashboard.addr", 199 Usage: "Dashboard listening interface", 200 Value: dashboard.DefaultConfig.Host, 201 } 202 DashboardPortFlag = cli.IntFlag{ 203 Name: "dashboard.host", 204 Usage: "Dashboard listening port", 205 Value: dashboard.DefaultConfig.Port, 206 } 207 DashboardRefreshFlag = cli.DurationFlag{ 208 Name: "dashboard.refresh", 209 Usage: "Dashboard metrics collection refresh rate", 210 Value: dashboard.DefaultConfig.Refresh, 211 } 212 // Ethash settings 213 EthashCacheDirFlag = DirectoryFlag{ 214 Name: "ethash.cachedir", 215 Usage: "Directory to store the ethash verification caches (default = inside the datadir)", 216 } 217 EthashCachesInMemoryFlag = cli.IntFlag{ 218 Name: "ethash.cachesinmem", 219 Usage: "Number of recent ethash caches to keep in memory (16MB each)", 220 Value: eth.DefaultConfig.Ethash.CachesInMem, 221 } 222 EthashCachesOnDiskFlag = cli.IntFlag{ 223 Name: "ethash.cachesondisk", 224 Usage: "Number of recent ethash caches to keep on disk (16MB each)", 225 Value: eth.DefaultConfig.Ethash.CachesOnDisk, 226 } 227 EthashDatasetDirFlag = DirectoryFlag{ 228 Name: "ethash.dagdir", 229 Usage: "Directory to store the ethash mining DAGs (default = inside home folder)", 230 Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir}, 231 } 232 EthashDatasetsInMemoryFlag = cli.IntFlag{ 233 Name: "ethash.dagsinmem", 234 Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)", 235 Value: eth.DefaultConfig.Ethash.DatasetsInMem, 236 } 237 EthashDatasetsOnDiskFlag = cli.IntFlag{ 238 Name: "ethash.dagsondisk", 239 Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)", 240 Value: eth.DefaultConfig.Ethash.DatasetsOnDisk, 241 } 242 // Transaction pool settings 243 TxPoolLocalsFlag = cli.StringFlag{ 244 Name: "txpool.locals", 245 Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", 246 } 247 TxPoolNoLocalsFlag = cli.BoolFlag{ 248 Name: "txpool.nolocals", 249 Usage: "Disables price exemptions for locally submitted transactions", 250 } 251 TxPoolJournalFlag = cli.StringFlag{ 252 Name: "txpool.journal", 253 Usage: "Disk journal for local transaction to survive node restarts", 254 Value: core.DefaultTxPoolConfig.Journal, 255 } 256 TxPoolRejournalFlag = cli.DurationFlag{ 257 Name: "txpool.rejournal", 258 Usage: "Time interval to regenerate the local transaction journal", 259 Value: core.DefaultTxPoolConfig.Rejournal, 260 } 261 TxPoolPriceLimitFlag = cli.Uint64Flag{ 262 Name: "txpool.pricelimit", 263 Usage: "Minimum gas price limit to enforce for acceptance into the pool", 264 Value: eth.DefaultConfig.TxPool.PriceLimit, 265 } 266 TxPoolPriceBumpFlag = cli.Uint64Flag{ 267 Name: "txpool.pricebump", 268 Usage: "Price bump percentage to replace an already existing transaction", 269 Value: eth.DefaultConfig.TxPool.PriceBump, 270 } 271 TxPoolAccountSlotsFlag = cli.Uint64Flag{ 272 Name: "txpool.accountslots", 273 Usage: "Minimum number of executable transaction slots guaranteed per account", 274 Value: eth.DefaultConfig.TxPool.AccountSlots, 275 } 276 TxPoolGlobalSlotsFlag = cli.Uint64Flag{ 277 Name: "txpool.globalslots", 278 Usage: "Maximum number of executable transaction slots for all accounts", 279 Value: eth.DefaultConfig.TxPool.GlobalSlots, 280 } 281 TxPoolAccountQueueFlag = cli.Uint64Flag{ 282 Name: "txpool.accountqueue", 283 Usage: "Maximum number of non-executable transaction slots permitted per account", 284 Value: eth.DefaultConfig.TxPool.AccountQueue, 285 } 286 TxPoolGlobalQueueFlag = cli.Uint64Flag{ 287 Name: "txpool.globalqueue", 288 Usage: "Maximum number of non-executable transaction slots for all accounts", 289 Value: eth.DefaultConfig.TxPool.GlobalQueue, 290 } 291 TxPoolLifetimeFlag = cli.DurationFlag{ 292 Name: "txpool.lifetime", 293 Usage: "Maximum amount of time non-executable transaction are queued", 294 Value: eth.DefaultConfig.TxPool.Lifetime, 295 } 296 // Performance tuning settings 297 CacheFlag = cli.IntFlag{ 298 Name: "cache", 299 Usage: "Megabytes of memory allocated to internal caching", 300 Value: 1024, 301 } 302 CacheDatabaseFlag = cli.IntFlag{ 303 Name: "cache.database", 304 Usage: "Percentage of cache memory allowance to use for database io", 305 Value: 75, 306 } 307 CacheGCFlag = cli.IntFlag{ 308 Name: "cache.gc", 309 Usage: "Percentage of cache memory allowance to use for trie pruning", 310 Value: 25, 311 } 312 TrieCacheGenFlag = cli.IntFlag{ 313 Name: "trie-cache-gens", 314 Usage: "Number of trie node generations to keep in memory", 315 Value: int(state.MaxTrieCacheGen), 316 } 317 // Miner settings 318 MiningEnabledFlag = cli.BoolFlag{ 319 Name: "mine", 320 Usage: "Enable mining", 321 } 322 MinerThreadsFlag = cli.IntFlag{ 323 Name: "miner.threads", 324 Usage: "Number of CPU threads to use for mining", 325 Value: 0, 326 } 327 MinerLegacyThreadsFlag = cli.IntFlag{ 328 Name: "minerthreads", 329 Usage: "Number of CPU threads to use for mining (deprecated, use --miner.threads)", 330 Value: 0, 331 } 332 MinerNotifyFlag = cli.StringFlag{ 333 Name: "miner.notify", 334 Usage: "Comma separated HTTP URL list to notify of new work packages", 335 } 336 MinerGasTargetFlag = cli.Uint64Flag{ 337 Name: "miner.gastarget", 338 Usage: "Target gas floor for mined blocks", 339 Value: eth.DefaultConfig.MinerGasFloor, 340 } 341 MinerLegacyGasTargetFlag = cli.Uint64Flag{ 342 Name: "targetgaslimit", 343 Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)", 344 Value: eth.DefaultConfig.MinerGasFloor, 345 } 346 MinerGasLimitFlag = cli.Uint64Flag{ 347 Name: "miner.gaslimit", 348 Usage: "Target gas ceiling for mined blocks", 349 Value: eth.DefaultConfig.MinerGasCeil, 350 } 351 MinerGasPriceFlag = BigFlag{ 352 Name: "miner.gasprice", 353 Usage: "Minimum gas price for mining a transaction", 354 Value: eth.DefaultConfig.MinerGasPrice, 355 } 356 MinerLegacyGasPriceFlag = BigFlag{ 357 Name: "gasprice", 358 Usage: "Minimum gas price for mining a transaction (deprecated, use --miner.gasprice)", 359 Value: eth.DefaultConfig.MinerGasPrice, 360 } 361 MinerEtherbaseFlag = cli.StringFlag{ 362 Name: "miner.etherbase", 363 Usage: "Public address for block mining rewards (default = first account)", 364 Value: "0", 365 } 366 MinerLegacyEtherbaseFlag = cli.StringFlag{ 367 Name: "etherbase", 368 Usage: "Public address for block mining rewards (default = first account, deprecated, use --miner.etherbase)", 369 Value: "0", 370 } 371 MinerExtraDataFlag = cli.StringFlag{ 372 Name: "miner.extradata", 373 Usage: "Block extra data set by the miner (default = client version)", 374 } 375 MinerLegacyExtraDataFlag = cli.StringFlag{ 376 Name: "extradata", 377 Usage: "Block extra data set by the miner (default = client version, deprecated, use --miner.extradata)", 378 } 379 MinerRecommitIntervalFlag = cli.DurationFlag{ 380 Name: "miner.recommit", 381 Usage: "Time interval to recreate the block being mined", 382 Value: eth.DefaultConfig.MinerRecommit, 383 } 384 MinerNoVerfiyFlag = cli.BoolFlag{ 385 Name: "miner.noverify", 386 Usage: "Disable remote sealing verification", 387 } 388 // Account settings 389 UnlockedAccountFlag = cli.StringFlag{ 390 Name: "unlock", 391 Usage: "Comma separated list of accounts to unlock", 392 Value: "", 393 } 394 PasswordFileFlag = cli.StringFlag{ 395 Name: "password", 396 Usage: "Password file to use for non-interactive password input", 397 Value: "", 398 } 399 400 VMEnableDebugFlag = cli.BoolFlag{ 401 Name: "vmdebug", 402 Usage: "Record information useful for VM and contract debugging", 403 } 404 // Logging and debug settings 405 EthStatsURLFlag = cli.StringFlag{ 406 Name: "ethstats", 407 Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", 408 } 409 FakePoWFlag = cli.BoolFlag{ 410 Name: "fakepow", 411 Usage: "Disables proof-of-work verification", 412 } 413 NoCompactionFlag = cli.BoolFlag{ 414 Name: "nocompaction", 415 Usage: "Disables db compaction after import", 416 } 417 // RPC settings 418 RPCEnabledFlag = cli.BoolFlag{ 419 Name: "rpc", 420 Usage: "Enable the HTTP-RPC server", 421 } 422 RPCListenAddrFlag = cli.StringFlag{ 423 Name: "rpcaddr", 424 Usage: "HTTP-RPC server listening interface", 425 Value: node.DefaultHTTPHost, 426 } 427 RPCPortFlag = cli.IntFlag{ 428 Name: "rpcport", 429 Usage: "HTTP-RPC server listening port", 430 Value: node.DefaultHTTPPort, 431 } 432 RPCCORSDomainFlag = cli.StringFlag{ 433 Name: "rpccorsdomain", 434 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 435 Value: "", 436 } 437 RPCVirtualHostsFlag = cli.StringFlag{ 438 Name: "rpcvhosts", 439 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 440 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 441 } 442 RPCApiFlag = cli.StringFlag{ 443 Name: "rpcapi", 444 Usage: "API's offered over the HTTP-RPC interface", 445 Value: "", 446 } 447 IPCDisabledFlag = cli.BoolFlag{ 448 Name: "ipcdisable", 449 Usage: "Disable the IPC-RPC server", 450 } 451 IPCPathFlag = DirectoryFlag{ 452 Name: "ipcpath", 453 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 454 } 455 WSEnabledFlag = cli.BoolFlag{ 456 Name: "ws", 457 Usage: "Enable the WS-RPC server", 458 } 459 WSListenAddrFlag = cli.StringFlag{ 460 Name: "wsaddr", 461 Usage: "WS-RPC server listening interface", 462 Value: node.DefaultWSHost, 463 } 464 WSPortFlag = cli.IntFlag{ 465 Name: "wsport", 466 Usage: "WS-RPC server listening port", 467 Value: node.DefaultWSPort, 468 } 469 WSApiFlag = cli.StringFlag{ 470 Name: "wsapi", 471 Usage: "API's offered over the WS-RPC interface", 472 Value: "", 473 } 474 WSAllowedOriginsFlag = cli.StringFlag{ 475 Name: "wsorigins", 476 Usage: "Origins from which to accept websockets requests", 477 Value: "", 478 } 479 ExecFlag = cli.StringFlag{ 480 Name: "exec", 481 Usage: "Execute JavaScript statement", 482 } 483 PreloadJSFlag = cli.StringFlag{ 484 Name: "preload", 485 Usage: "Comma separated list of JavaScript files to preload into the console", 486 } 487 488 // Network Settings 489 MaxPeersFlag = cli.IntFlag{ 490 Name: "maxpeers", 491 Usage: "Maximum number of network peers (network disabled if set to 0)", 492 Value: 25, 493 } 494 MaxPendingPeersFlag = cli.IntFlag{ 495 Name: "maxpendpeers", 496 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 497 Value: 0, 498 } 499 ListenPortFlag = cli.IntFlag{ 500 Name: "port", 501 Usage: "Network listening port", 502 Value: 30303, 503 } 504 BootnodesFlag = cli.StringFlag{ 505 Name: "bootnodes", 506 Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)", 507 Value: "", 508 } 509 BootnodesV4Flag = cli.StringFlag{ 510 Name: "bootnodesv4", 511 Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)", 512 Value: "", 513 } 514 BootnodesV5Flag = cli.StringFlag{ 515 Name: "bootnodesv5", 516 Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)", 517 Value: "", 518 } 519 NodeKeyFileFlag = cli.StringFlag{ 520 Name: "nodekey", 521 Usage: "P2P node key file", 522 } 523 NodeKeyHexFlag = cli.StringFlag{ 524 Name: "nodekeyhex", 525 Usage: "P2P node key as hex (for testing)", 526 } 527 NATFlag = cli.StringFlag{ 528 Name: "nat", 529 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 530 Value: "any", 531 } 532 NoDiscoverFlag = cli.BoolFlag{ 533 Name: "nodiscover", 534 Usage: "Disables the peer discovery mechanism (manual peer addition)", 535 } 536 DiscoveryV5Flag = cli.BoolFlag{ 537 Name: "v5disc", 538 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 539 } 540 NetrestrictFlag = cli.StringFlag{ 541 Name: "netrestrict", 542 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 543 } 544 545 // ATM the url is left to the user and deployment to 546 JSpathFlag = cli.StringFlag{ 547 Name: "jspath", 548 Usage: "JavaScript root path for `loadScript`", 549 Value: ".", 550 } 551 552 // Gas price oracle settings 553 GpoBlocksFlag = cli.IntFlag{ 554 Name: "gpoblocks", 555 Usage: "Number of recent blocks to check for gas prices", 556 Value: eth.DefaultConfig.GPO.Blocks, 557 } 558 GpoPercentileFlag = cli.IntFlag{ 559 Name: "gpopercentile", 560 Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", 561 Value: eth.DefaultConfig.GPO.Percentile, 562 } 563 WhisperEnabledFlag = cli.BoolFlag{ 564 Name: "shh", 565 Usage: "Enable Whisper", 566 } 567 WhisperMaxMessageSizeFlag = cli.IntFlag{ 568 Name: "shh.maxmessagesize", 569 Usage: "Max message size accepted", 570 Value: int(whisper.DefaultMaxMessageSize), 571 } 572 WhisperMinPOWFlag = cli.Float64Flag{ 573 Name: "shh.pow", 574 Usage: "Minimum POW accepted", 575 Value: whisper.DefaultMinimumPoW, 576 } 577 WhisperRestrictConnectionBetweenLightClientsFlag = cli.BoolFlag{ 578 Name: "shh.restrict-light", 579 Usage: "Restrict connection between two whisper light clients", 580 } 581 582 // Raft flags 583 RaftModeFlag = cli.BoolFlag{ 584 Name: "raft", 585 Usage: "If enabled, uses Raft instead of Quorum Chain for consensus", 586 } 587 RaftBlockTimeFlag = cli.IntFlag{ 588 Name: "raftblocktime", 589 Usage: "Amount of time between raft block creations in milliseconds", 590 Value: 50, 591 } 592 RaftJoinExistingFlag = cli.IntFlag{ 593 Name: "raftjoinexisting", 594 Usage: "The raft ID to assume when joining an pre-existing cluster", 595 Value: 0, 596 } 597 598 EmitCheckpointsFlag = cli.BoolFlag{ 599 Name: "emitcheckpoints", 600 Usage: "If enabled, emit specially formatted logging checkpoints", 601 } 602 RaftPortFlag = cli.IntFlag{ 603 Name: "raftport", 604 Usage: "The port to bind for the raft transport", 605 Value: 50400, 606 } 607 RaftDNSEnabledFlag = cli.BoolFlag{ 608 Name: "raftdnsenable", 609 Usage: "Enable DNS resolution of peers", 610 } 611 612 // Quorum 613 EnableNodePermissionFlag = cli.BoolFlag{ 614 Name: "permissioned", 615 Usage: "If enabled, the node will allow only a defined list of nodes to connect", 616 } 617 618 // Istanbul settings 619 IstanbulRequestTimeoutFlag = cli.Uint64Flag{ 620 Name: "istanbul.requesttimeout", 621 Usage: "Timeout for each Istanbul round in milliseconds", 622 Value: eth.DefaultConfig.Istanbul.RequestTimeout, 623 } 624 IstanbulBlockPeriodFlag = cli.Uint64Flag{ 625 Name: "istanbul.blockperiod", 626 Usage: "Default minimum difference between two consecutive block's timestamps in seconds", 627 Value: eth.DefaultConfig.Istanbul.BlockPeriod, 628 } 629 630 // Metrics flags 631 MetricsEnabledFlag = cli.BoolFlag{ 632 Name: metrics.MetricsEnabledFlag, 633 Usage: "Enable metrics collection and reporting", 634 } 635 MetricsEnableInfluxDBFlag = cli.BoolFlag{ 636 Name: "metrics.influxdb", 637 Usage: "Enable metrics export/push to an external InfluxDB database", 638 } 639 MetricsInfluxDBEndpointFlag = cli.StringFlag{ 640 Name: "metrics.influxdb.endpoint", 641 Usage: "InfluxDB API endpoint to report metrics to", 642 Value: "http://localhost:8086", 643 } 644 MetricsInfluxDBDatabaseFlag = cli.StringFlag{ 645 Name: "metrics.influxdb.database", 646 Usage: "InfluxDB database name to push reported metrics to", 647 Value: "geth", 648 } 649 MetricsInfluxDBUsernameFlag = cli.StringFlag{ 650 Name: "metrics.influxdb.username", 651 Usage: "Username to authorize access to the database", 652 Value: "test", 653 } 654 MetricsInfluxDBPasswordFlag = cli.StringFlag{ 655 Name: "metrics.influxdb.password", 656 Usage: "Password to authorize access to the database", 657 Value: "test", 658 } 659 // The `host` tag is part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB. 660 // It is used so that we can group all nodes and average a measurement across all of them, but also so 661 // that we can select a specific node and inspect its measurements. 662 // https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key 663 MetricsInfluxDBHostTagFlag = cli.StringFlag{ 664 Name: "metrics.influxdb.host.tag", 665 Usage: "InfluxDB `host` tag attached to all measurements", 666 Value: "localhost", 667 } 668 669 EWASMInterpreterFlag = cli.StringFlag{ 670 Name: "vm.ewasm", 671 Usage: "External ewasm configuration (default = built-in interpreter)", 672 Value: "", 673 } 674 EVMInterpreterFlag = cli.StringFlag{ 675 Name: "vm.evm", 676 Usage: "External EVM configuration (default = built-in interpreter)", 677 Value: "", 678 } 679 ) 680 681 // MakeDataDir retrieves the currently requested data directory, terminating 682 // if none (or the empty string) is specified. If the node is starting a testnet, 683 // the a subdirectory of the specified datadir will be used. 684 func MakeDataDir(ctx *cli.Context) string { 685 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 686 if ctx.GlobalBool(TestnetFlag.Name) { 687 return filepath.Join(path, "testnet") 688 } 689 if ctx.GlobalBool(RinkebyFlag.Name) { 690 return filepath.Join(path, "rinkeby") 691 } 692 if ctx.GlobalBool(OttomanFlag.Name) { 693 return filepath.Join(path, "ottoman") 694 } 695 return path 696 } 697 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 698 return "" 699 } 700 701 // setNodeKey creates a node key from set command line flags, either loading it 702 // from a file or as a specified hex value. If neither flags were provided, this 703 // method returns nil and an emphemeral key is to be generated. 704 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 705 var ( 706 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 707 file = ctx.GlobalString(NodeKeyFileFlag.Name) 708 key *ecdsa.PrivateKey 709 err error 710 ) 711 switch { 712 case file != "" && hex != "": 713 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 714 case file != "": 715 if key, err = crypto.LoadECDSA(file); err != nil { 716 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 717 } 718 cfg.PrivateKey = key 719 case hex != "": 720 if key, err = crypto.HexToECDSA(hex); err != nil { 721 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 722 } 723 cfg.PrivateKey = key 724 } 725 } 726 727 // setNodeUserIdent creates the user identifier from CLI flags. 728 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 729 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 730 cfg.UserIdent = identity 731 } 732 } 733 734 // setBootstrapNodes creates a list of bootstrap nodes from the command line 735 // flags, reverting to pre-configured ones if none have been specified. 736 func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { 737 urls := params.MainnetBootnodes 738 switch { 739 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name): 740 if ctx.GlobalIsSet(BootnodesV4Flag.Name) { 741 urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",") 742 } else { 743 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 744 } 745 case ctx.GlobalBool(TestnetFlag.Name): 746 urls = params.TestnetBootnodes 747 case ctx.GlobalBool(RinkebyFlag.Name): 748 urls = params.RinkebyBootnodes 749 case ctx.GlobalBool(OttomanFlag.Name): 750 urls = params.OttomanBootnodes 751 case cfg.BootstrapNodes != nil: 752 return // already set, don't apply defaults. 753 } 754 755 cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls)) 756 for _, url := range urls { 757 node, err := enode.ParseV4(url) 758 if err != nil { 759 log.Crit("Bootstrap URL invalid", "enode", url, "err", err) 760 } 761 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 762 } 763 } 764 765 // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line 766 // flags, reverting to pre-configured ones if none have been specified. 767 func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { 768 urls := params.DiscoveryV5Bootnodes 769 switch { 770 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name): 771 if ctx.GlobalIsSet(BootnodesV5Flag.Name) { 772 urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",") 773 } else { 774 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 775 } 776 case ctx.GlobalBool(RinkebyFlag.Name): 777 urls = params.RinkebyBootnodes 778 case cfg.BootstrapNodesV5 != nil: 779 return // already set, don't apply defaults. 780 } 781 782 cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls)) 783 for _, url := range urls { 784 node, err := discv5.ParseNode(url) 785 if err != nil { 786 log.Error("Bootstrap URL invalid", "enode", url, "err", err) 787 continue 788 } 789 cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) 790 } 791 } 792 793 // setListenAddress creates a TCP listening address string from set command 794 // line flags. 795 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 796 if ctx.GlobalIsSet(ListenPortFlag.Name) { 797 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 798 } 799 } 800 801 // setNAT creates a port mapper from command line flags. 802 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 803 if ctx.GlobalIsSet(NATFlag.Name) { 804 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 805 if err != nil { 806 Fatalf("Option %s: %v", NATFlag.Name, err) 807 } 808 cfg.NAT = natif 809 } 810 } 811 812 // splitAndTrim splits input separated by a comma 813 // and trims excessive white space from the substrings. 814 func splitAndTrim(input string) []string { 815 result := strings.Split(input, ",") 816 for i, r := range result { 817 result[i] = strings.TrimSpace(r) 818 } 819 return result 820 } 821 822 // setHTTP creates the HTTP RPC listener interface string from the set 823 // command line flags, returning empty if the HTTP endpoint is disabled. 824 func setHTTP(ctx *cli.Context, cfg *node.Config) { 825 if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { 826 cfg.HTTPHost = "127.0.0.1" 827 if ctx.GlobalIsSet(RPCListenAddrFlag.Name) { 828 cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name) 829 } 830 } 831 832 if ctx.GlobalIsSet(RPCPortFlag.Name) { 833 cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) 834 } 835 if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { 836 cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name)) 837 } 838 if ctx.GlobalIsSet(RPCApiFlag.Name) { 839 cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name)) 840 } 841 if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) { 842 cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name)) 843 } 844 } 845 846 // setWS creates the WebSocket RPC listener interface string from the set 847 // command line flags, returning empty if the HTTP endpoint is disabled. 848 func setWS(ctx *cli.Context, cfg *node.Config) { 849 if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { 850 cfg.WSHost = "127.0.0.1" 851 if ctx.GlobalIsSet(WSListenAddrFlag.Name) { 852 cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) 853 } 854 } 855 856 if ctx.GlobalIsSet(WSPortFlag.Name) { 857 cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) 858 } 859 if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { 860 cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) 861 } 862 if ctx.GlobalIsSet(WSApiFlag.Name) { 863 cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name)) 864 } 865 } 866 867 // setIPC creates an IPC path configuration from the set command line flags, 868 // returning an empty string if IPC was explicitly disabled, or the set path. 869 func setIPC(ctx *cli.Context, cfg *node.Config) { 870 checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 871 switch { 872 case ctx.GlobalBool(IPCDisabledFlag.Name): 873 cfg.IPCPath = "" 874 case ctx.GlobalIsSet(IPCPathFlag.Name): 875 cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) 876 } 877 } 878 879 // makeDatabaseHandles raises out the number of allowed file handles per process 880 // for Geth and returns half of the allowance to assign to the database. 881 func makeDatabaseHandles() int { 882 limit, err := fdlimit.Maximum() 883 if err != nil { 884 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 885 } 886 raised, err := fdlimit.Raise(uint64(limit)) 887 if err != nil { 888 Fatalf("Failed to raise file descriptor allowance: %v", err) 889 } 890 return int(raised / 2) // Leave half for networking and other stuff 891 } 892 893 // MakeAddress converts an account specified directly as a hex encoded string or 894 // a key index in the key store to an internal account representation. 895 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 896 // If the specified account is a valid address, return it 897 if common.IsHexAddress(account) { 898 return accounts.Account{Address: common.HexToAddress(account)}, nil 899 } 900 // Otherwise try to interpret the account as a keystore index 901 index, err := strconv.Atoi(account) 902 if err != nil || index < 0 { 903 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 904 } 905 log.Warn("-------------------------------------------------------------------") 906 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 907 log.Warn("This functionality is deprecated and will be removed in the future!") 908 log.Warn("Please use explicit addresses! (can search via `geth account list`)") 909 log.Warn("-------------------------------------------------------------------") 910 911 accs := ks.Accounts() 912 if len(accs) <= index { 913 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 914 } 915 return accs[index], nil 916 } 917 918 // setEtherbase retrieves the etherbase either from the directly specified 919 // command line flags or from the keystore if CLI indexed. 920 func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) { 921 // Extract the current etherbase, new flag overriding legacy one 922 var etherbase string 923 if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) { 924 etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name) 925 } 926 if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) { 927 etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name) 928 } 929 // Convert the etherbase into an address and configure it 930 if etherbase != "" { 931 account, err := MakeAddress(ks, etherbase) 932 if err != nil { 933 Fatalf("Invalid miner etherbase: %v", err) 934 } 935 cfg.Etherbase = account.Address 936 } 937 } 938 939 // MakePasswordList reads password lines from the file specified by the global --password flag. 940 func MakePasswordList(ctx *cli.Context) []string { 941 path := ctx.GlobalString(PasswordFileFlag.Name) 942 if path == "" { 943 return nil 944 } 945 text, err := ioutil.ReadFile(path) 946 if err != nil { 947 Fatalf("Failed to read password file: %v", err) 948 } 949 lines := strings.Split(string(text), "\n") 950 // Sanitise DOS line endings. 951 for i := range lines { 952 lines[i] = strings.TrimRight(lines[i], "\r") 953 } 954 return lines 955 } 956 957 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 958 setNodeKey(ctx, cfg) 959 setNAT(ctx, cfg) 960 setListenAddress(ctx, cfg) 961 setBootstrapNodes(ctx, cfg) 962 setBootstrapNodesV5(ctx, cfg) 963 964 lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light" 965 lightServer := ctx.GlobalInt(LightServFlag.Name) != 0 966 lightPeers := ctx.GlobalInt(LightPeersFlag.Name) 967 968 if ctx.GlobalIsSet(MaxPeersFlag.Name) { 969 cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) 970 if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) { 971 cfg.MaxPeers += lightPeers 972 } 973 } else { 974 if lightServer { 975 cfg.MaxPeers += lightPeers 976 } 977 if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers { 978 cfg.MaxPeers = lightPeers 979 } 980 } 981 if !(lightClient || lightServer) { 982 lightPeers = 0 983 } 984 ethPeers := cfg.MaxPeers - lightPeers 985 if lightClient { 986 ethPeers = 0 987 } 988 log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers) 989 990 if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { 991 cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) 992 } 993 if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { 994 cfg.NoDiscovery = true 995 } 996 997 // if we're running a light client or server, force enable the v5 peer discovery 998 // unless it is explicitly disabled with --nodiscover note that explicitly specifying 999 // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery 1000 forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) 1001 if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { 1002 cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) 1003 } else if forceV5Discovery { 1004 cfg.DiscoveryV5 = true 1005 } 1006 1007 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 1008 list, err := netutil.ParseNetlist(netrestrict) 1009 if err != nil { 1010 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 1011 } 1012 cfg.NetRestrict = list 1013 } 1014 1015 if ctx.GlobalBool(DeveloperFlag.Name) { 1016 // --dev mode can't use p2p networking. 1017 cfg.MaxPeers = 0 1018 cfg.ListenAddr = ":0" 1019 cfg.NoDiscovery = true 1020 cfg.DiscoveryV5 = false 1021 } 1022 } 1023 1024 // SetNodeConfig applies node-related command line flags to the config. 1025 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 1026 SetP2PConfig(ctx, &cfg.P2P) 1027 setIPC(ctx, cfg) 1028 setHTTP(ctx, cfg) 1029 setWS(ctx, cfg) 1030 setNodeUserIdent(ctx, cfg) 1031 1032 cfg.EnableNodePermission = ctx.GlobalBool(EnableNodePermissionFlag.Name) 1033 1034 switch { 1035 case ctx.GlobalIsSet(DataDirFlag.Name): 1036 cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) 1037 case ctx.GlobalBool(DeveloperFlag.Name): 1038 cfg.DataDir = "" // unless explicitly requested, use memory databases 1039 case ctx.GlobalBool(TestnetFlag.Name): 1040 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet") 1041 case ctx.GlobalBool(RinkebyFlag.Name): 1042 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby") 1043 case ctx.GlobalBool(OttomanFlag.Name): 1044 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ottoman") 1045 } 1046 1047 if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { 1048 cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) 1049 } 1050 if ctx.GlobalIsSet(LightKDFFlag.Name) { 1051 cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) 1052 } 1053 if ctx.GlobalIsSet(NoUSBFlag.Name) { 1054 cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name) 1055 } 1056 } 1057 1058 func setGPO(ctx *cli.Context, cfg *gasprice.Config) { 1059 if ctx.GlobalIsSet(GpoBlocksFlag.Name) { 1060 cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) 1061 } 1062 if ctx.GlobalIsSet(GpoPercentileFlag.Name) { 1063 cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) 1064 } 1065 } 1066 1067 func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { 1068 if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) { 1069 locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",") 1070 for _, account := range locals { 1071 if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) { 1072 Fatalf("Invalid account in --txpool.locals: %s", trimmed) 1073 } else { 1074 cfg.Locals = append(cfg.Locals, common.HexToAddress(account)) 1075 } 1076 } 1077 } 1078 if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) { 1079 cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name) 1080 } 1081 if ctx.GlobalIsSet(TxPoolJournalFlag.Name) { 1082 cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name) 1083 } 1084 if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) { 1085 cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name) 1086 } 1087 if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) { 1088 cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name) 1089 } 1090 if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) { 1091 cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name) 1092 } 1093 if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) { 1094 cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name) 1095 } 1096 if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) { 1097 cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name) 1098 } 1099 if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) { 1100 cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name) 1101 } 1102 if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) { 1103 cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name) 1104 } 1105 if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) { 1106 cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name) 1107 } 1108 } 1109 1110 func setEthash(ctx *cli.Context, cfg *eth.Config) { 1111 if ctx.GlobalIsSet(EthashCacheDirFlag.Name) { 1112 cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name) 1113 } 1114 if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) { 1115 cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name) 1116 } 1117 if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) { 1118 cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name) 1119 } 1120 if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) { 1121 cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name) 1122 } 1123 if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) { 1124 cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name) 1125 } 1126 if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) { 1127 cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name) 1128 } 1129 } 1130 1131 func setIstanbul(ctx *cli.Context, cfg *eth.Config) { 1132 if ctx.GlobalIsSet(IstanbulRequestTimeoutFlag.Name) { 1133 cfg.Istanbul.RequestTimeout = ctx.GlobalUint64(IstanbulRequestTimeoutFlag.Name) 1134 } 1135 if ctx.GlobalIsSet(IstanbulBlockPeriodFlag.Name) { 1136 cfg.Istanbul.BlockPeriod = ctx.GlobalUint64(IstanbulBlockPeriodFlag.Name) 1137 } 1138 } 1139 1140 // checkExclusive verifies that only a single instance of the provided flags was 1141 // set by the user. Each flag might optionally be followed by a string type to 1142 // specialize it further. 1143 func checkExclusive(ctx *cli.Context, args ...interface{}) { 1144 set := make([]string, 0, 1) 1145 for i := 0; i < len(args); i++ { 1146 // Make sure the next argument is a flag and skip if not set 1147 flag, ok := args[i].(cli.Flag) 1148 if !ok { 1149 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 1150 } 1151 // Check if next arg extends current and expand its name if so 1152 name := flag.GetName() 1153 1154 if i+1 < len(args) { 1155 switch option := args[i+1].(type) { 1156 case string: 1157 // Extended flag check, make sure value set doesn't conflict with passed in option 1158 if ctx.GlobalString(flag.GetName()) == option { 1159 name += "=" + option 1160 set = append(set, "--"+name) 1161 } 1162 // shift arguments and continue 1163 i++ 1164 continue 1165 1166 case cli.Flag: 1167 default: 1168 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 1169 } 1170 } 1171 // Mark the flag if it's set 1172 if ctx.GlobalIsSet(flag.GetName()) { 1173 set = append(set, "--"+name) 1174 } 1175 } 1176 if len(set) > 1 { 1177 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 1178 } 1179 } 1180 1181 // SetShhConfig applies shh-related command line flags to the config. 1182 func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) { 1183 if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) { 1184 cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name)) 1185 } 1186 if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) { 1187 cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name) 1188 } 1189 if ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) { 1190 cfg.RestrictConnectionBetweenLightClients = true 1191 } 1192 } 1193 1194 // SetEthConfig applies eth-related command line flags to the config. 1195 func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { 1196 // Avoid conflicting network flags 1197 checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag) 1198 checkExclusive(ctx, LightServFlag, SyncModeFlag, "light") 1199 1200 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 1201 setEtherbase(ctx, ks, cfg) 1202 setGPO(ctx, &cfg.GPO) 1203 setTxPool(ctx, &cfg.TxPool) 1204 setEthash(ctx, cfg) 1205 setIstanbul(ctx, cfg) 1206 1207 if ctx.GlobalIsSet(SyncModeFlag.Name) { 1208 cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 1209 } 1210 if ctx.GlobalIsSet(LightServFlag.Name) { 1211 cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) 1212 } 1213 if ctx.GlobalIsSet(LightPeersFlag.Name) { 1214 cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) 1215 } 1216 if ctx.GlobalIsSet(NetworkIdFlag.Name) { 1217 cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) 1218 } 1219 1220 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { 1221 cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1222 } 1223 cfg.DatabaseHandles = makeDatabaseHandles() 1224 1225 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1226 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1227 } 1228 cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" 1229 1230 1231 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1232 cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1233 } 1234 if ctx.GlobalIsSet(MinerNotifyFlag.Name) { 1235 cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",") 1236 } 1237 if ctx.GlobalIsSet(DocRootFlag.Name) { 1238 cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) 1239 } 1240 if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) { 1241 cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name)) 1242 } 1243 if ctx.GlobalIsSet(MinerExtraDataFlag.Name) { 1244 cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name)) 1245 } 1246 if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) { 1247 cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name) 1248 } 1249 if ctx.GlobalIsSet(MinerGasTargetFlag.Name) { 1250 cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name) 1251 } 1252 if ctx.GlobalIsSet(MinerGasLimitFlag.Name) { 1253 cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name) 1254 } 1255 if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { 1256 cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name) 1257 } 1258 if ctx.GlobalIsSet(MinerGasPriceFlag.Name) { 1259 cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name) 1260 } 1261 if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) { 1262 cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name) 1263 } 1264 if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) { 1265 cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name) 1266 } 1267 if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { 1268 // TODO(fjl): force-enable this in --dev mode 1269 cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) 1270 } 1271 1272 if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) { 1273 cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name) 1274 } 1275 1276 if ctx.GlobalIsSet(EVMInterpreterFlag.Name) { 1277 cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name) 1278 } 1279 1280 // Override any default configs for hard coded networks. 1281 switch { 1282 case ctx.GlobalBool(TestnetFlag.Name): 1283 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1284 cfg.NetworkId = 3 1285 } 1286 cfg.Genesis = core.DefaultTestnetGenesisBlock() 1287 case ctx.GlobalBool(RinkebyFlag.Name): 1288 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1289 cfg.NetworkId = 4 1290 } 1291 cfg.Genesis = core.DefaultRinkebyGenesisBlock() 1292 case ctx.GlobalBool(OttomanFlag.Name): 1293 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1294 cfg.NetworkId = 5 1295 } 1296 cfg.Genesis = core.DefaultOttomanGenesisBlock() 1297 case ctx.GlobalBool(DeveloperFlag.Name): 1298 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1299 cfg.NetworkId = 1337 1300 } 1301 // Create new developer account or reuse existing one 1302 var ( 1303 developer accounts.Account 1304 err error 1305 ) 1306 if accs := ks.Accounts(); len(accs) > 0 { 1307 developer = ks.Accounts()[0] 1308 } else { 1309 developer, err = ks.NewAccount("") 1310 if err != nil { 1311 Fatalf("Failed to create developer account: %v", err) 1312 } 1313 } 1314 if err := ks.Unlock(developer, ""); err != nil { 1315 Fatalf("Failed to unlock developer account: %v", err) 1316 } 1317 log.Info("Using developer account", "address", developer.Address) 1318 1319 cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address) 1320 if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { 1321 cfg.MinerGasPrice = big.NewInt(1) 1322 } 1323 } 1324 // TODO(fjl): move trie cache generations into config 1325 if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 { 1326 state.MaxTrieCacheGen = uint16(gen) 1327 } 1328 } 1329 1330 // SetDashboardConfig applies dashboard related command line flags to the config. 1331 func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) { 1332 cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name) 1333 cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name) 1334 cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name) 1335 } 1336 1337 // RegisterEthService adds an Ethereum client to the stack. 1338 func RegisterEthService(stack *node.Node, cfg *eth.Config) <-chan *eth.Ethereum { 1339 nodeChan := make(chan *eth.Ethereum, 1) 1340 var err error 1341 if cfg.SyncMode == downloader.LightSync { 1342 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1343 return les.New(ctx, cfg) 1344 }) 1345 } else { 1346 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1347 fullNode, err := eth.New(ctx, cfg) 1348 if fullNode != nil && cfg.LightServ > 0 { 1349 ls, _ := les.NewLesServer(fullNode, cfg) 1350 fullNode.AddLesServer(ls) 1351 } 1352 nodeChan <- fullNode 1353 return fullNode, err 1354 }) 1355 } 1356 if err != nil { 1357 Fatalf("Failed to register the Ethereum service: %v", err) 1358 } 1359 1360 return nodeChan 1361 } 1362 1363 // RegisterDashboardService adds a dashboard to the stack. 1364 func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) { 1365 stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1366 return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil 1367 }) 1368 } 1369 1370 // RegisterShhService configures Whisper and adds it to the given node. 1371 func RegisterShhService(stack *node.Node, cfg *whisper.Config) { 1372 if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) { 1373 return whisper.New(cfg), nil 1374 }); err != nil { 1375 Fatalf("Failed to register the Whisper service: %v", err) 1376 } 1377 } 1378 1379 // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to 1380 // the given node. 1381 func RegisterEthStatsService(stack *node.Node, url string) { 1382 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1383 // Retrieve both eth and les services 1384 var ethServ *eth.Ethereum 1385 ctx.Service(ðServ) 1386 1387 var lesServ *les.LightEthereum 1388 ctx.Service(&lesServ) 1389 1390 return ethstats.New(url, ethServ, lesServ) 1391 }); err != nil { 1392 Fatalf("Failed to register the Ethereum Stats service: %v", err) 1393 } 1394 } 1395 1396 // Quorum 1397 // 1398 // Configure smart-contract-based permissioning service 1399 func RegisterPermissionService(ctx *cli.Context, stack *node.Node) { 1400 if err := stack.Register(func(sctx *node.ServiceContext) (node.Service, error) { 1401 permissionConfig, err := permission.ParsePermissionConfig(stack.DataDir()) 1402 if err != nil { 1403 return nil, fmt.Errorf("loading of %s failed due to %v", params.PERMISSION_MODEL_CONFIG, err) 1404 } 1405 // start the permissions management service 1406 pc, err := permission.NewQuorumPermissionCtrl(stack, &permissionConfig) 1407 if err != nil { 1408 return nil, fmt.Errorf("failed to load the permission contracts as given in %s due to %v", params.PERMISSION_MODEL_CONFIG, err) 1409 } 1410 return pc, nil 1411 }); err != nil { 1412 Fatalf("Failed to register the permission service: %v", err) 1413 } 1414 log.Info("permission service registered") 1415 } 1416 1417 func SetupMetrics(ctx *cli.Context) { 1418 if metrics.Enabled { 1419 log.Info("Enabling metrics collection") 1420 var ( 1421 enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name) 1422 endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name) 1423 database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name) 1424 username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name) 1425 password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name) 1426 hosttag = ctx.GlobalString(MetricsInfluxDBHostTagFlag.Name) 1427 ) 1428 1429 if enableExport { 1430 log.Info("Enabling metrics export to InfluxDB") 1431 go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", map[string]string{ 1432 "host": hosttag, 1433 }) 1434 } 1435 } 1436 } 1437 1438 // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. 1439 func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { 1440 var ( 1441 cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1442 handles = makeDatabaseHandles() 1443 ) 1444 name := "chaindata" 1445 if ctx.GlobalString(SyncModeFlag.Name) == "light" { 1446 name = "lightchaindata" 1447 } 1448 chainDb, err := stack.OpenDatabase(name, cache, handles) 1449 if err != nil { 1450 Fatalf("Could not open database: %v", err) 1451 } 1452 return chainDb 1453 } 1454 1455 func MakeGenesis(ctx *cli.Context) *core.Genesis { 1456 var genesis *core.Genesis 1457 switch { 1458 case ctx.GlobalBool(TestnetFlag.Name): 1459 genesis = core.DefaultTestnetGenesisBlock() 1460 case ctx.GlobalBool(RinkebyFlag.Name): 1461 genesis = core.DefaultRinkebyGenesisBlock() 1462 case ctx.GlobalBool(OttomanFlag.Name): 1463 genesis = core.DefaultOttomanGenesisBlock() 1464 case ctx.GlobalBool(DeveloperFlag.Name): 1465 Fatalf("Developer chains are ephemeral") 1466 } 1467 return genesis 1468 } 1469 1470 // MakeChain creates a chain manager from set command line flags. 1471 func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { 1472 var err error 1473 chainDb = MakeChainDatabase(ctx, stack) 1474 1475 config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) 1476 if err != nil { 1477 Fatalf("%v", err) 1478 } 1479 var engine consensus.Engine 1480 if config.Clique != nil { 1481 engine = clique.New(config.Clique, chainDb) 1482 } else { 1483 engine = ethash.NewFaker() 1484 if !ctx.GlobalBool(FakePoWFlag.Name) { 1485 engine = ethash.New(ethash.Config{ 1486 CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir), 1487 CachesInMem: eth.DefaultConfig.Ethash.CachesInMem, 1488 CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk, 1489 DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir), 1490 DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem, 1491 DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, 1492 }, nil, false) 1493 } 1494 } 1495 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1496 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1497 } 1498 1499 cache := &core.CacheConfig{ 1500 Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive", 1501 TrieNodeLimit: eth.DefaultConfig.TrieCache, 1502 TrieTimeLimit: eth.DefaultConfig.TrieTimeout, 1503 } 1504 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1505 cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1506 } 1507 vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} 1508 chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil) 1509 if err != nil { 1510 Fatalf("Can't create BlockChain: %v", err) 1511 } 1512 return chain, chainDb 1513 } 1514 1515 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 1516 // scripts to preload before starting. 1517 func MakeConsolePreloads(ctx *cli.Context) []string { 1518 // Skip preloading if there's nothing to preload 1519 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 1520 return nil 1521 } 1522 // Otherwise resolve absolute paths and return them 1523 preloads := []string{} 1524 1525 assets := ctx.GlobalString(JSpathFlag.Name) 1526 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 1527 preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file))) 1528 } 1529 return preloads 1530 } 1531 1532 // MigrateFlags sets the global flag from a local flag when it's set. 1533 // This is a temporary function used for migrating old command/flags to the 1534 // new format. 1535 // 1536 // e.g. geth account new --keystore /tmp/mykeystore --lightkdf 1537 // 1538 // is equivalent after calling this method with: 1539 // 1540 // geth --keystore /tmp/mykeystore --lightkdf account new 1541 // 1542 // This allows the use of the existing configuration functionality. 1543 // When all flags are migrated this function can be removed and the existing 1544 // configuration functionality must be changed that is uses local flags 1545 func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { 1546 return func(ctx *cli.Context) error { 1547 for _, name := range ctx.FlagNames() { 1548 if ctx.IsSet(name) { 1549 ctx.GlobalSet(name, ctx.String(name)) 1550 } 1551 } 1552 return action(ctx) 1553 } 1554 }