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