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