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