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