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