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