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