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