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