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