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