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