github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/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 "os" 26 "path/filepath" 27 "strconv" 28 "strings" 29 "text/tabwriter" 30 "text/template" 31 "time" 32 33 pcsclite "github.com/gballet/go-libpcsclite" 34 "gopkg.in/urfave/cli.v1" 35 36 "github.com/unicornultrafoundation/go-u2u/accounts" 37 "github.com/unicornultrafoundation/go-u2u/accounts/keystore" 38 "github.com/unicornultrafoundation/go-u2u/common" 39 "github.com/unicornultrafoundation/go-u2u/common/fdlimit" 40 "github.com/unicornultrafoundation/go-u2u/crypto" 41 "github.com/unicornultrafoundation/go-u2u/eth/ethconfig" 42 core "github.com/unicornultrafoundation/go-u2u/evmcore" 43 "github.com/unicornultrafoundation/go-u2u/flags" 44 "github.com/unicornultrafoundation/go-u2u/log" 45 "github.com/unicornultrafoundation/go-u2u/metrics" 46 "github.com/unicornultrafoundation/go-u2u/metrics/exp" 47 "github.com/unicornultrafoundation/go-u2u/metrics/influxdb" 48 "github.com/unicornultrafoundation/go-u2u/node" 49 "github.com/unicornultrafoundation/go-u2u/p2p" 50 "github.com/unicornultrafoundation/go-u2u/p2p/enode" 51 "github.com/unicornultrafoundation/go-u2u/p2p/nat" 52 "github.com/unicornultrafoundation/go-u2u/p2p/netutil" 53 ) 54 55 func init() { 56 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 57 58 VERSION: 59 {{.Version}} 60 61 COMMANDS: 62 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 63 {{end}}{{if .Flags}} 64 GLOBAL OPTIONS: 65 {{range .Flags}}{{.}} 66 {{end}}{{end}} 67 ` 68 cli.CommandHelpTemplate = flags.CommandHelpTemplate 69 cli.HelpPrinter = printHelp 70 } 71 72 func printHelp(out io.Writer, templ string, data interface{}) { 73 funcMap := template.FuncMap{"join": strings.Join} 74 t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) 75 w := tabwriter.NewWriter(out, 38, 8, 2, ' ', 0) 76 err := t.Execute(w, data) 77 if err != nil { 78 panic(err) 79 } 80 w.Flush() 81 } 82 83 // These are all the command line flags we support. 84 // If you add to this list, please remember to include the 85 // flag in the appropriate command definition. 86 // 87 // The flags are defined here so their names and help texts 88 // are the same for all commands. 89 90 var ( 91 // General settings 92 DataDirFlag = DirectoryFlag{ 93 Name: "datadir", 94 Usage: "Data directory for the databases and keystore", 95 Value: DirectoryString(node.DefaultDataDir()), 96 } 97 AncientFlag = DirectoryFlag{ 98 Name: "datadir.ancient", 99 Usage: "Data directory for ancient chain segments (default = inside chaindata)", 100 } 101 MinFreeDiskSpaceFlag = DirectoryFlag{ 102 Name: "datadir.minfreedisk", 103 Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = 8192 MB, 0 = disabled)", 104 } 105 KeyStoreDirFlag = DirectoryFlag{ 106 Name: "keystore", 107 Usage: "Directory for the keystore (default = inside the datadir)", 108 } 109 USBFlag = cli.BoolFlag{ 110 Name: "usb", 111 Usage: "Enable monitoring and management of USB hardware wallets", 112 } 113 SmartCardDaemonPathFlag = cli.StringFlag{ 114 Name: "pcscdpath", 115 Usage: "Path to the smartcard daemon (pcscd) socket file", 116 Value: pcsclite.PCSCDSockName, 117 } 118 NetworkIdFlag = cli.Uint64Flag{ 119 Name: "networkid", 120 Usage: "Explicitly set network id (integer)(For testnets: use --ropsten, --rinkeby, --goerli instead)", 121 Value: ethconfig.Defaults.NetworkId, 122 } 123 MainnetFlag = cli.BoolFlag{ 124 Name: "mainnet", 125 Usage: "Ethereum mainnet", 126 } 127 GoerliFlag = cli.BoolFlag{ 128 Name: "goerli", 129 Usage: "Görli network: pre-configured proof-of-authority test network", 130 } 131 RinkebyFlag = cli.BoolFlag{ 132 Name: "rinkeby", 133 Usage: "Rinkeby network: pre-configured proof-of-authority test network", 134 } 135 RopstenFlag = cli.BoolFlag{ 136 Name: "ropsten", 137 Usage: "Ropsten network: pre-configured proof-of-work test network", 138 } 139 DeveloperFlag = cli.BoolFlag{ 140 Name: "dev", 141 Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", 142 } 143 DeveloperPeriodFlag = cli.IntFlag{ 144 Name: "dev.period", 145 Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", 146 } 147 IdentityFlag = cli.StringFlag{ 148 Name: "identity", 149 Usage: "Custom node name", 150 } 151 DocRootFlag = DirectoryFlag{ 152 Name: "docroot", 153 Usage: "Document Root for HTTPClient file scheme", 154 Value: DirectoryString(HomeDir()), 155 } 156 ExitWhenSyncedFlag = cli.BoolFlag{ 157 Name: "exitwhensynced", 158 Usage: "Exits after block synchronisation completes", 159 } 160 IterativeOutputFlag = cli.BoolTFlag{ 161 Name: "iterative", 162 Usage: "Print streaming JSON iteratively, delimited by newlines", 163 } 164 ExcludeStorageFlag = cli.BoolFlag{ 165 Name: "nostorage", 166 Usage: "Exclude storage entries (save db lookups)", 167 } 168 IncludeIncompletesFlag = cli.BoolFlag{ 169 Name: "incompletes", 170 Usage: "Include accounts for which we don't have the address (missing preimage)", 171 } 172 ExcludeCodeFlag = cli.BoolFlag{ 173 Name: "nocode", 174 Usage: "Exclude contract code (save db lookups)", 175 } 176 StartKeyFlag = cli.StringFlag{ 177 Name: "start", 178 Usage: "Start position. Either a hash or address", 179 Value: "0x0000000000000000000000000000000000000000000000000000000000000000", 180 } 181 DumpLimitFlag = cli.Uint64Flag{ 182 Name: "limit", 183 Usage: "Max number of elements (0 = no limit)", 184 Value: 0, 185 } 186 defaultSyncMode = ethconfig.Defaults.SyncMode 187 SyncModeFlag = TextMarshalerFlag{ 188 Name: "syncmode", 189 Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`, 190 Value: &defaultSyncMode, 191 } 192 GCModeFlag = cli.StringFlag{ 193 Name: "gcmode", 194 Usage: `Blockchain garbage collection mode ("full", "archive")`, 195 Value: "full", 196 } 197 SnapshotFlag = cli.BoolTFlag{ 198 Name: "snapshot", 199 Usage: `Enables snapshot-database mode (default = enable)`, 200 } 201 TxLookupLimitFlag = cli.Uint64Flag{ 202 Name: "txlookuplimit", 203 Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)", 204 Value: ethconfig.Defaults.TxLookupLimit, 205 } 206 LightKDFFlag = cli.BoolFlag{ 207 Name: "lightkdf", 208 Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", 209 } 210 WhitelistFlag = cli.StringFlag{ 211 Name: "whitelist", 212 Usage: "Comma separated block number-to-hash mappings to enforce (<number>=<hash>)", 213 } 214 BloomFilterSizeFlag = cli.Uint64Flag{ 215 Name: "bloomfilter.size", 216 Usage: "Megabytes of memory allocated to bloom-filter for pruning", 217 Value: 2048, 218 } 219 OverrideLondonFlag = cli.Uint64Flag{ 220 Name: "override.london", 221 Usage: "Manually specify London fork-block, overriding the bundled setting", 222 } 223 // Light server and client settings 224 LightServeFlag = cli.IntFlag{ 225 Name: "light.serve", 226 Usage: "Maximum percentage of time allowed for serving LES requests (multi-threaded processing allows values over 100)", 227 Value: ethconfig.Defaults.LightServ, 228 } 229 LightIngressFlag = cli.IntFlag{ 230 Name: "light.ingress", 231 Usage: "Incoming bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)", 232 Value: ethconfig.Defaults.LightIngress, 233 } 234 LightEgressFlag = cli.IntFlag{ 235 Name: "light.egress", 236 Usage: "Outgoing bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)", 237 Value: ethconfig.Defaults.LightEgress, 238 } 239 LightMaxPeersFlag = cli.IntFlag{ 240 Name: "light.maxpeers", 241 Usage: "Maximum number of light clients to serve, or light servers to attach to", 242 Value: ethconfig.Defaults.LightPeers, 243 } 244 UltraLightServersFlag = cli.StringFlag{ 245 Name: "ulc.servers", 246 Usage: "List of trusted ultra-light servers", 247 Value: strings.Join(ethconfig.Defaults.UltraLightServers, ","), 248 } 249 UltraLightFractionFlag = cli.IntFlag{ 250 Name: "ulc.fraction", 251 Usage: "Minimum % of trusted ultra-light servers required to announce a new head", 252 Value: ethconfig.Defaults.UltraLightFraction, 253 } 254 UltraLightOnlyAnnounceFlag = cli.BoolFlag{ 255 Name: "ulc.onlyannounce", 256 Usage: "Ultra light server sends announcements only", 257 } 258 LightNoPruneFlag = cli.BoolFlag{ 259 Name: "light.nopruning", 260 Usage: "Disable ancient light chain data pruning", 261 } 262 LightNoSyncServeFlag = cli.BoolFlag{ 263 Name: "light.nosyncserve", 264 Usage: "Enables serving light clients before syncing", 265 } 266 // Transaction pool settings 267 TxPoolLocalsFlag = cli.StringFlag{ 268 Name: "txpool.locals", 269 Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", 270 } 271 TxPoolNoLocalsFlag = cli.BoolFlag{ 272 Name: "txpool.nolocals", 273 Usage: "Disables price exemptions for locally submitted transactions", 274 } 275 TxPoolJournalFlag = cli.StringFlag{ 276 Name: "txpool.journal", 277 Usage: "Disk journal for local transaction to survive node restarts", 278 Value: core.DefaultTxPoolConfig.Journal, 279 } 280 TxPoolRejournalFlag = cli.DurationFlag{ 281 Name: "txpool.rejournal", 282 Usage: "Time interval to regenerate the local transaction journal", 283 Value: core.DefaultTxPoolConfig.Rejournal, 284 } 285 TxPoolPriceLimitFlag = cli.Uint64Flag{ 286 Name: "txpool.pricelimit", 287 Usage: "Minimum gas price limit to enforce for acceptance into the pool", 288 Value: ethconfig.Defaults.TxPool.PriceLimit, 289 } 290 TxPoolPriceBumpFlag = cli.Uint64Flag{ 291 Name: "txpool.pricebump", 292 Usage: "Price bump percentage to replace an already existing transaction", 293 Value: ethconfig.Defaults.TxPool.PriceBump, 294 } 295 TxPoolAccountSlotsFlag = cli.Uint64Flag{ 296 Name: "txpool.accountslots", 297 Usage: "Minimum number of executable transaction slots guaranteed per account", 298 Value: ethconfig.Defaults.TxPool.AccountSlots, 299 } 300 TxPoolGlobalSlotsFlag = cli.Uint64Flag{ 301 Name: "txpool.globalslots", 302 Usage: "Maximum number of executable transaction slots for all accounts", 303 Value: ethconfig.Defaults.TxPool.GlobalSlots, 304 } 305 TxPoolAccountQueueFlag = cli.Uint64Flag{ 306 Name: "txpool.accountqueue", 307 Usage: "Maximum number of non-executable transaction slots permitted per account", 308 Value: ethconfig.Defaults.TxPool.AccountQueue, 309 } 310 TxPoolGlobalQueueFlag = cli.Uint64Flag{ 311 Name: "txpool.globalqueue", 312 Usage: "Maximum number of non-executable transaction slots for all accounts", 313 Value: ethconfig.Defaults.TxPool.GlobalQueue, 314 } 315 TxPoolLifetimeFlag = cli.DurationFlag{ 316 Name: "txpool.lifetime", 317 Usage: "Maximum amount of time non-executable transaction are queued", 318 Value: ethconfig.Defaults.TxPool.Lifetime, 319 } 320 // Performance tuning settings 321 CacheFlag = cli.IntFlag{ 322 Name: "cache", 323 Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node, 128 light mode)", 324 Value: 1024, 325 } 326 CacheDatabaseFlag = cli.IntFlag{ 327 Name: "cache.database", 328 Usage: "Percentage of cache memory allowance to use for database io", 329 Value: 50, 330 } 331 CacheTrieFlag = cli.IntFlag{ 332 Name: "cache.trie", 333 Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)", 334 Value: 15, 335 } 336 CacheTrieJournalFlag = cli.StringFlag{ 337 Name: "cache.trie.journal", 338 Usage: "Disk journal directory for trie cache to survive node restarts", 339 Value: ethconfig.Defaults.TrieCleanCacheJournal, 340 } 341 CacheTrieRejournalFlag = cli.DurationFlag{ 342 Name: "cache.trie.rejournal", 343 Usage: "Time interval to regenerate the trie cache journal", 344 Value: ethconfig.Defaults.TrieCleanCacheRejournal, 345 } 346 CacheGCFlag = cli.IntFlag{ 347 Name: "cache.gc", 348 Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", 349 Value: 25, 350 } 351 CacheSnapshotFlag = cli.IntFlag{ 352 Name: "cache.snapshot", 353 Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)", 354 Value: 10, 355 } 356 CacheNoPrefetchFlag = cli.BoolFlag{ 357 Name: "cache.noprefetch", 358 Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)", 359 } 360 CachePreimagesFlag = cli.BoolFlag{ 361 Name: "cache.preimages", 362 Usage: "Enable recording the SHA3/keccak preimages of trie keys", 363 } 364 // Account settings 365 UnlockedAccountFlag = cli.StringFlag{ 366 Name: "unlock", 367 Usage: "Comma separated list of accounts to unlock", 368 Value: "", 369 } 370 PasswordFileFlag = cli.StringFlag{ 371 Name: "password", 372 Usage: "Password file to use for non-interactive password input", 373 Value: "", 374 } 375 ExternalSignerFlag = cli.StringFlag{ 376 Name: "signer", 377 Usage: "External signer (url or path to ipc file)", 378 Value: "", 379 } 380 VMEnableDebugFlag = cli.BoolFlag{ 381 Name: "vmdebug", 382 Usage: "Record information useful for VM and contract debugging", 383 } 384 InsecureUnlockAllowedFlag = cli.BoolFlag{ 385 Name: "allow-insecure-unlock", 386 Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http", 387 } 388 RPCGlobalGasCapFlag = cli.Uint64Flag{ 389 Name: "rpc.gascap", 390 Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", 391 Value: ethconfig.Defaults.RPCGasCap, 392 } 393 RPCGlobalTxFeeCapFlag = cli.Float64Flag{ 394 Name: "rpc.txfeecap", 395 Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)", 396 Value: ethconfig.Defaults.RPCTxFeeCap, 397 } 398 // Logging and debug settings 399 FakePoWFlag = cli.BoolFlag{ 400 Name: "fakepow", 401 Usage: "Disables proof-of-work verification", 402 } 403 NoCompactionFlag = cli.BoolFlag{ 404 Name: "nocompaction", 405 Usage: "Disables db compaction after import", 406 } 407 // RPC settings 408 IPCDisabledFlag = cli.BoolFlag{ 409 Name: "ipcdisable", 410 Usage: "Disable the IPC-RPC server", 411 } 412 IPCPathFlag = DirectoryFlag{ 413 Name: "ipcpath", 414 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 415 } 416 HTTPEnabledFlag = cli.BoolFlag{ 417 Name: "http", 418 Usage: "Enable the HTTP-RPC server", 419 } 420 HTTPListenAddrFlag = cli.StringFlag{ 421 Name: "http.addr", 422 Usage: "HTTP-RPC server listening interface", 423 Value: node.DefaultHTTPHost, 424 } 425 HTTPPortFlag = cli.IntFlag{ 426 Name: "http.port", 427 Usage: "HTTP-RPC server listening port", 428 Value: node.DefaultHTTPPort, 429 } 430 HTTPCORSDomainFlag = cli.StringFlag{ 431 Name: "http.corsdomain", 432 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 433 Value: "", 434 } 435 HTTPVirtualHostsFlag = cli.StringFlag{ 436 Name: "http.vhosts", 437 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 438 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 439 } 440 HTTPApiFlag = cli.StringFlag{ 441 Name: "http.api", 442 Usage: "API's offered over the HTTP-RPC interface", 443 Value: "", 444 } 445 HTTPPathPrefixFlag = cli.StringFlag{ 446 Name: "http.rpcprefix", 447 Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", 448 Value: "", 449 } 450 WSEnabledFlag = cli.BoolFlag{ 451 Name: "ws", 452 Usage: "Enable the WS-RPC server", 453 } 454 WSListenAddrFlag = cli.StringFlag{ 455 Name: "ws.addr", 456 Usage: "WS-RPC server listening interface", 457 Value: node.DefaultWSHost, 458 } 459 WSPortFlag = cli.IntFlag{ 460 Name: "ws.port", 461 Usage: "WS-RPC server listening port", 462 Value: node.DefaultWSPort, 463 } 464 WSApiFlag = cli.StringFlag{ 465 Name: "ws.api", 466 Usage: "API's offered over the WS-RPC interface", 467 Value: "", 468 } 469 WSAllowedOriginsFlag = cli.StringFlag{ 470 Name: "ws.origins", 471 Usage: "Origins from which to accept websockets requests", 472 Value: "", 473 } 474 WSPathPrefixFlag = cli.StringFlag{ 475 Name: "ws.rpcprefix", 476 Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.", 477 Value: "", 478 } 479 ExecFlag = cli.StringFlag{ 480 Name: "exec", 481 Usage: "Execute JavaScript statement", 482 } 483 PreloadJSFlag = cli.StringFlag{ 484 Name: "preload", 485 Usage: "Comma separated list of JavaScript files to preload into the console", 486 } 487 AllowUnprotectedTxs = cli.BoolFlag{ 488 Name: "rpc.allow-unprotected-txs", 489 Usage: "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC", 490 } 491 492 // Network Settings 493 MaxPeersFlag = cli.IntFlag{ 494 Name: "maxpeers", 495 Usage: "Maximum number of network peers (network disabled if set to 0)", 496 Value: node.DefaultConfig.P2P.MaxPeers, 497 } 498 MaxPendingPeersFlag = cli.IntFlag{ 499 Name: "maxpendpeers", 500 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 501 Value: node.DefaultConfig.P2P.MaxPendingPeers, 502 } 503 ListenPortFlag = cli.IntFlag{ 504 Name: "port", 505 Usage: "Network listening port", 506 Value: 30303, 507 } 508 BootnodesFlag = cli.StringFlag{ 509 Name: "bootnodes", 510 Usage: "Comma separated enode URLs for P2P discovery bootstrap", 511 Value: "", 512 } 513 NodeKeyFileFlag = cli.StringFlag{ 514 Name: "nodekey", 515 Usage: "P2P node key file", 516 } 517 NodeKeyHexFlag = cli.StringFlag{ 518 Name: "nodekeyhex", 519 Usage: "P2P node key as hex (for testing)", 520 } 521 NATFlag = cli.StringFlag{ 522 Name: "nat", 523 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 524 Value: "any", 525 } 526 NoDiscoverFlag = cli.BoolFlag{ 527 Name: "nodiscover", 528 Usage: "Disables the peer discovery mechanism (manual peer addition)", 529 } 530 DiscoveryV5Flag = cli.BoolFlag{ 531 Name: "v5disc", 532 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 533 } 534 NetrestrictFlag = cli.StringFlag{ 535 Name: "netrestrict", 536 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 537 } 538 IPrestrictFlag = cli.StringFlag{ 539 Name: "iprestrict", 540 Usage: "Restricts network communication to the given IP addresses", 541 } 542 PrivateNodeFlag = cli.StringFlag{ 543 Name: "privatenodes", 544 Usage: "Comma separated enode URLs which must not be advertised as peers to public network", 545 } 546 DNSDiscoveryFlag = cli.StringFlag{ 547 Name: "discovery.dns", 548 Usage: "Sets DNS discovery entry points (use \"\" to disable DNS)", 549 } 550 551 // ATM the url is left to the user and deployment to 552 JSpathFlag = DirectoryFlag{ 553 Name: "jspath", 554 Usage: "JavaScript root path for `loadScript`", 555 Value: DirectoryString("."), 556 } 557 558 // Gas price oracle settings 559 GpoBlocksFlag = cli.IntFlag{ 560 Name: "gpo.blocks", 561 Usage: "Number of recent blocks to check for gas prices", 562 Value: ethconfig.Defaults.GPO.Blocks, 563 } 564 GpoPercentileFlag = cli.IntFlag{ 565 Name: "gpo.percentile", 566 Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", 567 Value: ethconfig.Defaults.GPO.Percentile, 568 } 569 GpoMaxGasPriceFlag = cli.Int64Flag{ 570 Name: "gpo.maxprice", 571 Usage: "Maximum gas price will be recommended by gpo", 572 Value: ethconfig.Defaults.GPO.MaxPrice.Int64(), 573 } 574 GpoIgnoreGasPriceFlag = cli.Int64Flag{ 575 Name: "gpo.ignoreprice", 576 Usage: "Gas price below which gpo will ignore transactions", 577 Value: ethconfig.Defaults.GPO.IgnorePrice.Int64(), 578 } 579 580 // Metrics flags 581 MetricsEnabledFlag = cli.BoolFlag{ 582 Name: "metrics", 583 Usage: "Enable metrics collection and reporting", 584 } 585 MetricsEnabledExpensiveFlag = cli.BoolFlag{ 586 Name: "metrics.expensive", 587 Usage: "Enable expensive metrics collection and reporting", 588 } 589 590 // MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint. 591 // Since the pprof service enables sensitive/vulnerable behavior, this allows a user 592 // to enable a public-OK metrics endpoint without having to worry about ALSO exposing 593 // other profiling behavior or information. 594 MetricsHTTPFlag = cli.StringFlag{ 595 Name: "metrics.addr", 596 Usage: "Enable stand-alone metrics HTTP server listening interface", 597 Value: metrics.DefaultConfig.HTTP, 598 } 599 MetricsPortFlag = cli.IntFlag{ 600 Name: "metrics.port", 601 Usage: "Metrics HTTP server listening port", 602 Value: metrics.DefaultConfig.Port, 603 } 604 MetricsEnableInfluxDBFlag = cli.BoolFlag{ 605 Name: "metrics.influxdb", 606 Usage: "Enable metrics export/push to an external InfluxDB database", 607 } 608 MetricsInfluxDBEndpointFlag = cli.StringFlag{ 609 Name: "metrics.influxdb.endpoint", 610 Usage: "InfluxDB API endpoint to report metrics to", 611 Value: metrics.DefaultConfig.InfluxDBEndpoint, 612 } 613 MetricsInfluxDBDatabaseFlag = cli.StringFlag{ 614 Name: "metrics.influxdb.database", 615 Usage: "InfluxDB database name to push reported metrics to", 616 Value: metrics.DefaultConfig.InfluxDBDatabase, 617 } 618 MetricsInfluxDBUsernameFlag = cli.StringFlag{ 619 Name: "metrics.influxdb.username", 620 Usage: "Username to authorize access to the database", 621 Value: metrics.DefaultConfig.InfluxDBUsername, 622 } 623 MetricsInfluxDBPasswordFlag = cli.StringFlag{ 624 Name: "metrics.influxdb.password", 625 Usage: "Password to authorize access to the database", 626 Value: metrics.DefaultConfig.InfluxDBPassword, 627 } 628 // Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB. 629 // For example `host` tag could be used so that we can group all nodes and average a measurement 630 // across all of them, but also so that we can select a specific node and inspect its measurements. 631 // https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key 632 MetricsInfluxDBTagsFlag = cli.StringFlag{ 633 Name: "metrics.influxdb.tags", 634 Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", 635 Value: metrics.DefaultConfig.InfluxDBTags, 636 } 637 638 MetricsEnableInfluxDBV2Flag = cli.BoolFlag{ 639 Name: "metrics.influxdbv2", 640 Usage: "Enable metrics export/push to an external InfluxDB v2 database", 641 } 642 643 MetricsInfluxDBTokenFlag = cli.StringFlag{ 644 Name: "metrics.influxdb.token", 645 Usage: "Token to authorize access to the database (v2 only)", 646 Value: metrics.DefaultConfig.InfluxDBToken, 647 } 648 649 MetricsInfluxDBBucketFlag = cli.StringFlag{ 650 Name: "metrics.influxdb.bucket", 651 Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", 652 Value: metrics.DefaultConfig.InfluxDBBucket, 653 } 654 655 MetricsInfluxDBOrganizationFlag = cli.StringFlag{ 656 Name: "metrics.influxdb.organization", 657 Usage: "InfluxDB organization name (v2 only)", 658 Value: metrics.DefaultConfig.InfluxDBOrganization, 659 } 660 661 MetricsPrometheusEndpointFlag = cli.StringFlag{ 662 Name: "metrics.prometheus.endpoint", 663 Usage: "Prometheus API endpoint to report metrics to", 664 Value: metrics.DefaultConfig.PrometheusEndpointPort, 665 } 666 667 CatalystFlag = cli.BoolFlag{ 668 Name: "catalyst", 669 Usage: "Catalyst mode (eth2 integration testing)", 670 } 671 ) 672 673 // MakeDataDir retrieves the currently requested data directory, terminating 674 // if none (or the empty string) is specified. If the node is starting a testnet, 675 // then a subdirectory of the specified datadir will be used. 676 func MakeDataDir(ctx *cli.Context) string { 677 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 678 if ctx.GlobalBool(RopstenFlag.Name) { 679 // Maintain compatibility with older Geth configurations storing the 680 // Ropsten database in `testnet` instead of `ropsten`. 681 return filepath.Join(path, "ropsten") 682 } 683 if ctx.GlobalBool(RinkebyFlag.Name) { 684 return filepath.Join(path, "rinkeby") 685 } 686 if ctx.GlobalBool(GoerliFlag.Name) { 687 return filepath.Join(path, "goerli") 688 } 689 return path 690 } 691 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 692 return "" 693 } 694 695 // setNodeKey creates a node key from set command line flags, either loading it 696 // from a file or as a specified hex value. If neither flags were provided, this 697 // method returns nil and an emphemeral key is to be generated. 698 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 699 var ( 700 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 701 file = ctx.GlobalString(NodeKeyFileFlag.Name) 702 key *ecdsa.PrivateKey 703 err error 704 ) 705 switch { 706 case file != "" && hex != "": 707 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 708 case file != "": 709 if key, err = crypto.LoadECDSA(file); err != nil { 710 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 711 } 712 cfg.PrivateKey = key 713 case hex != "": 714 if key, err = crypto.HexToECDSA(hex); err != nil { 715 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 716 } 717 cfg.PrivateKey = key 718 } 719 } 720 721 // setNodeUserIdent creates the user identifier from CLI flags. 722 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 723 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 724 cfg.UserIdent = identity 725 } 726 } 727 728 // setListenAddress creates a TCP listening address string from set command 729 // line flags. 730 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 731 if ctx.GlobalIsSet(ListenPortFlag.Name) { 732 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 733 } 734 } 735 736 // setNAT creates a port mapper from command line flags. 737 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 738 if ctx.GlobalIsSet(NATFlag.Name) { 739 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 740 if err != nil { 741 Fatalf("Option %s: %v", NATFlag.Name, err) 742 } 743 cfg.NAT = natif 744 } 745 } 746 747 // SplitAndTrim splits input separated by a comma 748 // and trims excessive white space from the substrings. 749 func SplitAndTrim(input string) (ret []string) { 750 l := strings.Split(input, ",") 751 for _, r := range l { 752 if r = strings.TrimSpace(r); r != "" { 753 ret = append(ret, r) 754 } 755 } 756 return ret 757 } 758 759 // setHTTP creates the HTTP RPC listener interface string from the set 760 // command line flags, returning empty if the HTTP endpoint is disabled. 761 func setHTTP(ctx *cli.Context, cfg *node.Config) { 762 if ctx.GlobalBool(LegacyRPCEnabledFlag.Name) && cfg.HTTPHost == "" { 763 log.Warn("The flag --rpc is deprecated and will be removed June 2021, please use --http") 764 cfg.HTTPHost = "127.0.0.1" 765 if ctx.GlobalIsSet(LegacyRPCListenAddrFlag.Name) { 766 cfg.HTTPHost = ctx.GlobalString(LegacyRPCListenAddrFlag.Name) 767 log.Warn("The flag --rpcaddr is deprecated and will be removed June 2021, please use --http.addr") 768 } 769 } 770 if ctx.GlobalBool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" { 771 cfg.HTTPHost = "127.0.0.1" 772 if ctx.GlobalIsSet(HTTPListenAddrFlag.Name) { 773 cfg.HTTPHost = ctx.GlobalString(HTTPListenAddrFlag.Name) 774 } 775 } 776 777 if ctx.GlobalIsSet(LegacyRPCPortFlag.Name) { 778 cfg.HTTPPort = ctx.GlobalInt(LegacyRPCPortFlag.Name) 779 log.Warn("The flag --rpcport is deprecated and will be removed June 2021, please use --http.port") 780 } 781 if ctx.GlobalIsSet(HTTPPortFlag.Name) { 782 cfg.HTTPPort = ctx.GlobalInt(HTTPPortFlag.Name) 783 } 784 785 if ctx.GlobalIsSet(LegacyRPCCORSDomainFlag.Name) { 786 cfg.HTTPCors = SplitAndTrim(ctx.GlobalString(LegacyRPCCORSDomainFlag.Name)) 787 log.Warn("The flag --rpccorsdomain is deprecated and will be removed June 2021, please use --http.corsdomain") 788 } 789 if ctx.GlobalIsSet(HTTPCORSDomainFlag.Name) { 790 cfg.HTTPCors = SplitAndTrim(ctx.GlobalString(HTTPCORSDomainFlag.Name)) 791 } 792 793 if ctx.GlobalIsSet(LegacyRPCApiFlag.Name) { 794 cfg.HTTPModules = SplitAndTrim(ctx.GlobalString(LegacyRPCApiFlag.Name)) 795 log.Warn("The flag --rpcapi is deprecated and will be removed June 2021, please use --http.api") 796 } 797 if ctx.GlobalIsSet(HTTPApiFlag.Name) { 798 cfg.HTTPModules = SplitAndTrim(ctx.GlobalString(HTTPApiFlag.Name)) 799 } 800 801 if ctx.GlobalIsSet(LegacyRPCVirtualHostsFlag.Name) { 802 cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(LegacyRPCVirtualHostsFlag.Name)) 803 log.Warn("The flag --rpcvhosts is deprecated and will be removed June 2021, please use --http.vhosts") 804 } 805 if ctx.GlobalIsSet(HTTPVirtualHostsFlag.Name) { 806 cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(HTTPVirtualHostsFlag.Name)) 807 } 808 809 if ctx.GlobalIsSet(HTTPPathPrefixFlag.Name) { 810 cfg.HTTPPathPrefix = ctx.GlobalString(HTTPPathPrefixFlag.Name) 811 } 812 if ctx.GlobalIsSet(AllowUnprotectedTxs.Name) { 813 cfg.AllowUnprotectedTxs = ctx.GlobalBool(AllowUnprotectedTxs.Name) 814 } 815 } 816 817 // setWS creates the WebSocket RPC listener interface string from the set 818 // command line flags, returning empty if the HTTP endpoint is disabled. 819 func setWS(ctx *cli.Context, cfg *node.Config) { 820 if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { 821 cfg.WSHost = "127.0.0.1" 822 if ctx.GlobalIsSet(WSListenAddrFlag.Name) { 823 cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) 824 } 825 } 826 if ctx.GlobalIsSet(WSPortFlag.Name) { 827 cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) 828 } 829 830 if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { 831 cfg.WSOrigins = SplitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) 832 } 833 834 if ctx.GlobalIsSet(WSApiFlag.Name) { 835 cfg.WSModules = SplitAndTrim(ctx.GlobalString(WSApiFlag.Name)) 836 } 837 838 if ctx.GlobalIsSet(WSPathPrefixFlag.Name) { 839 cfg.WSPathPrefix = ctx.GlobalString(WSPathPrefixFlag.Name) 840 } 841 } 842 843 // setIPC creates an IPC path configuration from the set command line flags, 844 // returning an empty string if IPC was explicitly disabled, or the set path. 845 func setIPC(ctx *cli.Context, cfg *node.Config) { 846 CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 847 switch { 848 case ctx.GlobalBool(IPCDisabledFlag.Name): 849 cfg.IPCPath = "" 850 case ctx.GlobalIsSet(IPCPathFlag.Name): 851 cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) 852 } 853 } 854 855 // MakeDatabaseHandles raises out the number of allowed file handles per process 856 // for Geth and returns half of the allowance to assign to the database. 857 func MakeDatabaseHandles() int { 858 limit, err := fdlimit.Maximum() 859 if err != nil { 860 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 861 } 862 raised, err := fdlimit.Raise(uint64(limit)) 863 if err != nil { 864 Fatalf("Failed to raise file descriptor allowance: %v", err) 865 } 866 return int(raised / 2) // Leave half for networking and other stuff 867 } 868 869 // MakeAddress converts an account specified directly as a hex encoded string or 870 // a key index in the key store to an internal account representation. 871 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 872 // If the specified account is a valid address, return it 873 if common.IsHexAddress(account) { 874 return accounts.Account{Address: common.HexToAddress(account)}, nil 875 } 876 // Otherwise try to interpret the account as a keystore index 877 index, err := strconv.Atoi(account) 878 if err != nil || index < 0 { 879 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 880 } 881 log.Warn("-------------------------------------------------------------------") 882 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 883 log.Warn("This functionality is deprecated and will be removed in the future!") 884 log.Warn("Please use explicit addresses! (can search via `geth account list`)") 885 log.Warn("-------------------------------------------------------------------") 886 887 accs := ks.Accounts() 888 if len(accs) <= index { 889 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 890 } 891 return accs[index], nil 892 } 893 894 // MakePasswordList reads password lines from the file specified by the global --password flag. 895 func MakePasswordList(ctx *cli.Context) []string { 896 path := ctx.GlobalString(PasswordFileFlag.Name) 897 if path == "" { 898 return nil 899 } 900 text, err := ioutil.ReadFile(path) 901 if err != nil { 902 Fatalf("Failed to read password file: %v", err) 903 } 904 lines := strings.Split(string(text), "\n") 905 // Sanitise DOS line endings. 906 for i := range lines { 907 lines[i] = strings.TrimRight(lines[i], "\r") 908 } 909 return lines 910 } 911 912 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 913 setNodeKey(ctx, cfg) 914 setNAT(ctx, cfg) 915 setListenAddress(ctx, cfg) 916 // setBootstrapNodes(ctx, cfg) 917 // setBootstrapNodesV5(ctx, cfg) 918 919 lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light" 920 lightServer := (ctx.GlobalInt(LightServeFlag.Name) != 0) 921 922 lightPeers := ctx.GlobalInt(LightMaxPeersFlag.Name) 923 if lightClient && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) { 924 // dynamic default - for clients we use 1/10th of the default for servers 925 lightPeers /= 10 926 } 927 928 if ctx.GlobalIsSet(MaxPeersFlag.Name) { 929 cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) 930 if lightServer && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) { 931 cfg.MaxPeers += lightPeers 932 } 933 } else { 934 if lightServer { 935 cfg.MaxPeers += lightPeers 936 } 937 if lightClient && ctx.GlobalIsSet(LightMaxPeersFlag.Name) && cfg.MaxPeers < lightPeers { 938 cfg.MaxPeers = lightPeers 939 } 940 } 941 if !(lightClient || lightServer) { 942 lightPeers = 0 943 } 944 log.Info("Maximum peer count", "total", cfg.MaxPeers) 945 946 if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { 947 cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) 948 } 949 if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { 950 cfg.NoDiscovery = true 951 } 952 953 // if we're running a light client or server, force enable the v5 peer discovery 954 // unless it is explicitly disabled with --nodiscover note that explicitly specifying 955 // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery 956 forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) 957 if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { 958 cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) 959 } else if forceV5Discovery { 960 cfg.DiscoveryV5 = true 961 } 962 963 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 964 list, err := netutil.ParseNetlist(netrestrict) 965 if err != nil { 966 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 967 } 968 cfg.NetRestrict = list 969 } 970 971 var err error 972 if iprestrict := ctx.GlobalString(IPrestrictFlag.Name); iprestrict != "" { 973 cfg.IPRestrict, err = netutil.ParseIPs(iprestrict) 974 if err != nil { 975 Fatalf("Option %q: %v", IPrestrictFlag.Name, err) 976 } 977 } 978 979 if privatenodes := ctx.GlobalString(PrivateNodeFlag.Name); privatenodes != "" { 980 cfg.PrivateNodes, err = enode.ParseNodes(privatenodes) 981 if err != nil { 982 Fatalf("Option %q: %v", PrivateNodeFlag.Name, err) 983 } 984 } 985 986 if ctx.GlobalBool(DeveloperFlag.Name) || ctx.GlobalBool(CatalystFlag.Name) { 987 // --dev mode can't use p2p networking. 988 cfg.MaxPeers = 0 989 cfg.ListenAddr = "" 990 cfg.NoDial = true 991 cfg.NoDiscovery = true 992 cfg.DiscoveryV5 = false 993 } 994 } 995 996 // SetNodeConfig applies node-related command line flags to the config. 997 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 998 SetP2PConfig(ctx, &cfg.P2P) 999 setIPC(ctx, cfg) 1000 setHTTP(ctx, cfg) 1001 setWS(ctx, cfg) 1002 setNodeUserIdent(ctx, cfg) 1003 setDataDir(ctx, cfg) 1004 setSmartCard(ctx, cfg) 1005 1006 if ctx.GlobalIsSet(ExternalSignerFlag.Name) { 1007 cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name) 1008 } 1009 1010 if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { 1011 cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) 1012 } 1013 if ctx.GlobalIsSet(DeveloperFlag.Name) { 1014 cfg.UseLightweightKDF = true 1015 } 1016 if ctx.GlobalIsSet(LightKDFFlag.Name) { 1017 cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) 1018 } 1019 if ctx.GlobalIsSet(NoUSBFlag.Name) || cfg.NoUSB { 1020 log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable") 1021 } 1022 if ctx.GlobalIsSet(USBFlag.Name) { 1023 cfg.USB = ctx.GlobalBool(USBFlag.Name) 1024 } 1025 if ctx.GlobalIsSet(InsecureUnlockAllowedFlag.Name) { 1026 cfg.InsecureUnlockAllowed = ctx.GlobalBool(InsecureUnlockAllowedFlag.Name) 1027 } 1028 } 1029 1030 func setSmartCard(ctx *cli.Context, cfg *node.Config) { 1031 // Skip enabling smartcards if no path is set 1032 path := ctx.GlobalString(SmartCardDaemonPathFlag.Name) 1033 if path == "" { 1034 return 1035 } 1036 // Sanity check that the smartcard path is valid 1037 fi, err := os.Stat(path) 1038 if err != nil { 1039 log.Info("Smartcard socket not found, disabling", "err", err) 1040 return 1041 } 1042 if fi.Mode()&os.ModeType != os.ModeSocket { 1043 log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String()) 1044 return 1045 } 1046 // Smartcard daemon path exists and is a socket, enable it 1047 cfg.SmartCardDaemonPath = path 1048 } 1049 1050 func setDataDir(ctx *cli.Context, cfg *node.Config) { 1051 switch { 1052 case ctx.GlobalIsSet(DataDirFlag.Name): 1053 cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) 1054 case ctx.GlobalBool(DeveloperFlag.Name): 1055 cfg.DataDir = "" // unless explicitly requested, use memory databases 1056 case ctx.GlobalBool(RopstenFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1057 // Maintain compatibility with older Geth configurations storing the 1058 // Ropsten database in `testnet` instead of `ropsten`. 1059 legacyPath := filepath.Join(node.DefaultDataDir(), "testnet") 1060 if _, err := os.Stat(legacyPath); !os.IsNotExist(err) { 1061 log.Warn("Using the deprecated `testnet` datadir. Future versions will store the Ropsten chain in `ropsten`.") 1062 cfg.DataDir = legacyPath 1063 } else { 1064 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten") 1065 } 1066 1067 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten") 1068 case ctx.GlobalBool(RinkebyFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1069 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby") 1070 case ctx.GlobalBool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1071 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli") 1072 } 1073 } 1074 1075 // CheckExclusive verifies that only a single instance of the provided flags was 1076 // set by the user. Each flag might optionally be followed by a string type to 1077 // specialize it further. 1078 func CheckExclusive(ctx *cli.Context, args ...interface{}) { 1079 set := make([]string, 0, 1) 1080 for i := 0; i < len(args); i++ { 1081 // Make sure the next argument is a flag and skip if not set 1082 flag, ok := args[i].(cli.Flag) 1083 if !ok { 1084 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 1085 } 1086 // Check if next arg extends current and expand its name if so 1087 name := flag.GetName() 1088 1089 if i+1 < len(args) { 1090 switch option := args[i+1].(type) { 1091 case string: 1092 // Extended flag check, make sure value set doesn't conflict with passed in option 1093 if ctx.GlobalString(flag.GetName()) == option { 1094 name += "=" + option 1095 set = append(set, "--"+name) 1096 } 1097 // shift arguments and continue 1098 i++ 1099 continue 1100 1101 case cli.Flag: 1102 default: 1103 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 1104 } 1105 } 1106 // Mark the flag if it's set 1107 if ctx.GlobalIsSet(flag.GetName()) { 1108 set = append(set, "--"+name) 1109 } 1110 } 1111 if len(set) > 1 { 1112 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 1113 } 1114 } 1115 1116 func SetupMetrics(ctx *cli.Context) { 1117 if metrics.Enabled { 1118 log.Info("Enabling metrics collection") 1119 1120 var ( 1121 enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name) 1122 enableExportV2 = ctx.GlobalBool(MetricsEnableInfluxDBV2Flag.Name) 1123 ) 1124 1125 if enableExport || enableExportV2 { 1126 CheckExclusive(ctx, MetricsEnableInfluxDBFlag, MetricsEnableInfluxDBV2Flag) 1127 1128 v1FlagIsSet := ctx.GlobalIsSet(MetricsInfluxDBUsernameFlag.Name) || 1129 ctx.GlobalIsSet(MetricsInfluxDBPasswordFlag.Name) 1130 1131 v2FlagIsSet := ctx.GlobalIsSet(MetricsInfluxDBTokenFlag.Name) || 1132 ctx.GlobalIsSet(MetricsInfluxDBOrganizationFlag.Name) || 1133 ctx.GlobalIsSet(MetricsInfluxDBBucketFlag.Name) 1134 1135 if enableExport && v2FlagIsSet { 1136 Fatalf("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2") 1137 } else if enableExportV2 && v1FlagIsSet { 1138 Fatalf("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1") 1139 } 1140 } 1141 1142 var ( 1143 endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name) 1144 database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name) 1145 username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name) 1146 password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name) 1147 1148 token = ctx.GlobalString(MetricsInfluxDBTokenFlag.Name) 1149 bucket = ctx.GlobalString(MetricsInfluxDBBucketFlag.Name) 1150 organization = ctx.GlobalString(MetricsInfluxDBOrganizationFlag.Name) 1151 ) 1152 1153 if enableExport { 1154 tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name)) 1155 1156 log.Info("Enabling metrics export to InfluxDB") 1157 1158 go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) 1159 } else if enableExportV2 { 1160 tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name)) 1161 1162 log.Info("Enabling metrics export to InfluxDB (v2)") 1163 1164 go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap) 1165 } 1166 1167 if ctx.GlobalIsSet(MetricsHTTPFlag.Name) { 1168 address := fmt.Sprintf("%s:%d", ctx.GlobalString(MetricsHTTPFlag.Name), ctx.GlobalInt(MetricsPortFlag.Name)) 1169 log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address) 1170 exp.Setup(address) 1171 } 1172 } 1173 } 1174 1175 func SplitTagsFlag(tagsFlag string) map[string]string { 1176 tags := strings.Split(tagsFlag, ",") 1177 tagsMap := map[string]string{} 1178 1179 for _, t := range tags { 1180 if t != "" { 1181 kv := strings.Split(t, "=") 1182 1183 if len(kv) == 2 { 1184 tagsMap[kv[0]] = kv[1] 1185 } 1186 } 1187 } 1188 1189 return tagsMap 1190 } 1191 1192 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 1193 // scripts to preload before starting. 1194 func MakeConsolePreloads(ctx *cli.Context) []string { 1195 // Skip preloading if there's nothing to preload 1196 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 1197 return nil 1198 } 1199 // Otherwise resolve absolute paths and return them 1200 var preloads []string 1201 1202 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 1203 preloads = append(preloads, strings.TrimSpace(file)) 1204 } 1205 return preloads 1206 } 1207 1208 // MigrateFlags sets the global flag from a local flag when it's set. 1209 // This is a temporary function used for migrating old command/flags to the 1210 // new format. 1211 // 1212 // e.g. geth account new --keystore /tmp/mykeystore --lightkdf 1213 // 1214 // is equivalent after calling this method with: 1215 // 1216 // geth --keystore /tmp/mykeystore --lightkdf account new 1217 // 1218 // This allows the use of the existing configuration functionality. 1219 // When all flags are migrated this function can be removed and the existing 1220 // configuration functionality must be changed that is uses local flags 1221 func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { 1222 return func(ctx *cli.Context) error { 1223 for _, name := range ctx.FlagNames() { 1224 if ctx.IsSet(name) { 1225 ctx.GlobalSet(name, ctx.String(name)) 1226 } 1227 } 1228 return action(ctx) 1229 } 1230 }