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