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