github.com/tmoore22/go-ethereum@v1.10.22-0.20220814113424-76f4d8bc4994/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: "Root directory for ancient data (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 // Metrics flags 879 MetricsEnabledFlag = &cli.BoolFlag{ 880 Name: "metrics", 881 Usage: "Enable metrics collection and reporting", 882 Category: flags.MetricsCategory, 883 } 884 MetricsEnabledExpensiveFlag = &cli.BoolFlag{ 885 Name: "metrics.expensive", 886 Usage: "Enable expensive metrics collection and reporting", 887 Category: flags.MetricsCategory, 888 } 889 890 // MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint. 891 // Since the pprof service enables sensitive/vulnerable behavior, this allows a user 892 // to enable a public-OK metrics endpoint without having to worry about ALSO exposing 893 // other profiling behavior or information. 894 MetricsHTTPFlag = &cli.StringFlag{ 895 Name: "metrics.addr", 896 Usage: "Enable stand-alone metrics HTTP server listening interface", 897 Value: metrics.DefaultConfig.HTTP, 898 Category: flags.MetricsCategory, 899 } 900 MetricsPortFlag = &cli.IntFlag{ 901 Name: "metrics.port", 902 Usage: "Metrics HTTP server listening port", 903 Value: metrics.DefaultConfig.Port, 904 Category: flags.MetricsCategory, 905 } 906 MetricsEnableInfluxDBFlag = &cli.BoolFlag{ 907 Name: "metrics.influxdb", 908 Usage: "Enable metrics export/push to an external InfluxDB database", 909 Category: flags.MetricsCategory, 910 } 911 MetricsInfluxDBEndpointFlag = &cli.StringFlag{ 912 Name: "metrics.influxdb.endpoint", 913 Usage: "InfluxDB API endpoint to report metrics to", 914 Value: metrics.DefaultConfig.InfluxDBEndpoint, 915 Category: flags.MetricsCategory, 916 } 917 MetricsInfluxDBDatabaseFlag = &cli.StringFlag{ 918 Name: "metrics.influxdb.database", 919 Usage: "InfluxDB database name to push reported metrics to", 920 Value: metrics.DefaultConfig.InfluxDBDatabase, 921 Category: flags.MetricsCategory, 922 } 923 MetricsInfluxDBUsernameFlag = &cli.StringFlag{ 924 Name: "metrics.influxdb.username", 925 Usage: "Username to authorize access to the database", 926 Value: metrics.DefaultConfig.InfluxDBUsername, 927 Category: flags.MetricsCategory, 928 } 929 MetricsInfluxDBPasswordFlag = &cli.StringFlag{ 930 Name: "metrics.influxdb.password", 931 Usage: "Password to authorize access to the database", 932 Value: metrics.DefaultConfig.InfluxDBPassword, 933 Category: flags.MetricsCategory, 934 } 935 // Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB. 936 // For example `host` tag could be used so that we can group all nodes and average a measurement 937 // across all of them, but also so that we can select a specific node and inspect its measurements. 938 // https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key 939 MetricsInfluxDBTagsFlag = &cli.StringFlag{ 940 Name: "metrics.influxdb.tags", 941 Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", 942 Value: metrics.DefaultConfig.InfluxDBTags, 943 Category: flags.MetricsCategory, 944 } 945 946 MetricsEnableInfluxDBV2Flag = &cli.BoolFlag{ 947 Name: "metrics.influxdbv2", 948 Usage: "Enable metrics export/push to an external InfluxDB v2 database", 949 Category: flags.MetricsCategory, 950 } 951 952 MetricsInfluxDBTokenFlag = &cli.StringFlag{ 953 Name: "metrics.influxdb.token", 954 Usage: "Token to authorize access to the database (v2 only)", 955 Value: metrics.DefaultConfig.InfluxDBToken, 956 Category: flags.MetricsCategory, 957 } 958 959 MetricsInfluxDBBucketFlag = &cli.StringFlag{ 960 Name: "metrics.influxdb.bucket", 961 Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", 962 Value: metrics.DefaultConfig.InfluxDBBucket, 963 Category: flags.MetricsCategory, 964 } 965 966 MetricsInfluxDBOrganizationFlag = &cli.StringFlag{ 967 Name: "metrics.influxdb.organization", 968 Usage: "InfluxDB organization name (v2 only)", 969 Value: metrics.DefaultConfig.InfluxDBOrganization, 970 Category: flags.MetricsCategory, 971 } 972 ) 973 974 var ( 975 // TestnetFlags is the flag group of all built-in supported testnets. 976 TestnetFlags = []cli.Flag{ 977 RopstenFlag, 978 RinkebyFlag, 979 GoerliFlag, 980 SepoliaFlag, 981 KilnFlag, 982 } 983 // NetworkFlags is the flag group of all built-in supported networks. 984 NetworkFlags = append([]cli.Flag{ 985 MainnetFlag, 986 }, TestnetFlags...) 987 988 // DatabasePathFlags is the flag group of all database path flags. 989 DatabasePathFlags = []cli.Flag{ 990 DataDirFlag, 991 AncientFlag, 992 RemoteDBFlag, 993 } 994 ) 995 996 // MakeDataDir retrieves the currently requested data directory, terminating 997 // if none (or the empty string) is specified. If the node is starting a testnet, 998 // then a subdirectory of the specified datadir will be used. 999 func MakeDataDir(ctx *cli.Context) string { 1000 if path := ctx.String(DataDirFlag.Name); path != "" { 1001 if ctx.Bool(RopstenFlag.Name) { 1002 // Maintain compatibility with older Geth configurations storing the 1003 // Ropsten database in `testnet` instead of `ropsten`. 1004 return filepath.Join(path, "ropsten") 1005 } 1006 if ctx.Bool(RinkebyFlag.Name) { 1007 return filepath.Join(path, "rinkeby") 1008 } 1009 if ctx.Bool(GoerliFlag.Name) { 1010 return filepath.Join(path, "goerli") 1011 } 1012 if ctx.Bool(SepoliaFlag.Name) { 1013 return filepath.Join(path, "sepolia") 1014 } 1015 if ctx.Bool(KilnFlag.Name) { 1016 return filepath.Join(path, "kiln") 1017 } 1018 return path 1019 } 1020 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 1021 return "" 1022 } 1023 1024 // setNodeKey creates a node key from set command line flags, either loading it 1025 // from a file or as a specified hex value. If neither flags were provided, this 1026 // method returns nil and an emphemeral key is to be generated. 1027 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 1028 var ( 1029 hex = ctx.String(NodeKeyHexFlag.Name) 1030 file = ctx.String(NodeKeyFileFlag.Name) 1031 key *ecdsa.PrivateKey 1032 err error 1033 ) 1034 switch { 1035 case file != "" && hex != "": 1036 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 1037 case file != "": 1038 if key, err = crypto.LoadECDSA(file); err != nil { 1039 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 1040 } 1041 cfg.PrivateKey = key 1042 case hex != "": 1043 if key, err = crypto.HexToECDSA(hex); err != nil { 1044 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 1045 } 1046 cfg.PrivateKey = key 1047 } 1048 } 1049 1050 // setNodeUserIdent creates the user identifier from CLI flags. 1051 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 1052 if identity := ctx.String(IdentityFlag.Name); len(identity) > 0 { 1053 cfg.UserIdent = identity 1054 } 1055 } 1056 1057 // setBootstrapNodes creates a list of bootstrap nodes from the command line 1058 // flags, reverting to pre-configured ones if none have been specified. 1059 func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { 1060 urls := params.MainnetBootnodes 1061 switch { 1062 case ctx.IsSet(BootnodesFlag.Name): 1063 urls = SplitAndTrim(ctx.String(BootnodesFlag.Name)) 1064 case ctx.Bool(RopstenFlag.Name): 1065 urls = params.RopstenBootnodes 1066 case ctx.Bool(SepoliaFlag.Name): 1067 urls = params.SepoliaBootnodes 1068 case ctx.Bool(RinkebyFlag.Name): 1069 urls = params.RinkebyBootnodes 1070 case ctx.Bool(GoerliFlag.Name): 1071 urls = params.GoerliBootnodes 1072 case ctx.Bool(KilnFlag.Name): 1073 urls = params.KilnBootnodes 1074 } 1075 1076 // don't apply defaults if BootstrapNodes is already set 1077 if cfg.BootstrapNodes != nil { 1078 return 1079 } 1080 1081 cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls)) 1082 for _, url := range urls { 1083 if url != "" { 1084 node, err := enode.Parse(enode.ValidSchemes, url) 1085 if err != nil { 1086 log.Crit("Bootstrap URL invalid", "enode", url, "err", err) 1087 continue 1088 } 1089 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 1090 } 1091 } 1092 } 1093 1094 // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line 1095 // flags, reverting to pre-configured ones if none have been specified. 1096 func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { 1097 urls := params.V5Bootnodes 1098 switch { 1099 case ctx.IsSet(BootnodesFlag.Name): 1100 urls = SplitAndTrim(ctx.String(BootnodesFlag.Name)) 1101 case cfg.BootstrapNodesV5 != nil: 1102 return // already set, don't apply defaults. 1103 } 1104 1105 cfg.BootstrapNodesV5 = make([]*enode.Node, 0, len(urls)) 1106 for _, url := range urls { 1107 if url != "" { 1108 node, err := enode.Parse(enode.ValidSchemes, url) 1109 if err != nil { 1110 log.Error("Bootstrap URL invalid", "enode", url, "err", err) 1111 continue 1112 } 1113 cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) 1114 } 1115 } 1116 } 1117 1118 // setListenAddress creates TCP/UDP listening address strings from set command 1119 // line flags 1120 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 1121 if ctx.IsSet(ListenPortFlag.Name) { 1122 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.Int(ListenPortFlag.Name)) 1123 } 1124 if ctx.IsSet(DiscoveryPortFlag.Name) { 1125 cfg.DiscAddr = fmt.Sprintf(":%d", ctx.Int(DiscoveryPortFlag.Name)) 1126 } 1127 } 1128 1129 // setNAT creates a port mapper from command line flags. 1130 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 1131 if ctx.IsSet(NATFlag.Name) { 1132 natif, err := nat.Parse(ctx.String(NATFlag.Name)) 1133 if err != nil { 1134 Fatalf("Option %s: %v", NATFlag.Name, err) 1135 } 1136 cfg.NAT = natif 1137 } 1138 } 1139 1140 // SplitAndTrim splits input separated by a comma 1141 // and trims excessive white space from the substrings. 1142 func SplitAndTrim(input string) (ret []string) { 1143 l := strings.Split(input, ",") 1144 for _, r := range l { 1145 if r = strings.TrimSpace(r); r != "" { 1146 ret = append(ret, r) 1147 } 1148 } 1149 return ret 1150 } 1151 1152 // setHTTP creates the HTTP RPC listener interface string from the set 1153 // command line flags, returning empty if the HTTP endpoint is disabled. 1154 func setHTTP(ctx *cli.Context, cfg *node.Config) { 1155 if ctx.Bool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" { 1156 cfg.HTTPHost = "127.0.0.1" 1157 if ctx.IsSet(HTTPListenAddrFlag.Name) { 1158 cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name) 1159 } 1160 } 1161 1162 if ctx.IsSet(HTTPPortFlag.Name) { 1163 cfg.HTTPPort = ctx.Int(HTTPPortFlag.Name) 1164 } 1165 1166 if ctx.IsSet(AuthListenFlag.Name) { 1167 cfg.AuthAddr = ctx.String(AuthListenFlag.Name) 1168 } 1169 1170 if ctx.IsSet(AuthPortFlag.Name) { 1171 cfg.AuthPort = ctx.Int(AuthPortFlag.Name) 1172 } 1173 1174 if ctx.IsSet(AuthVirtualHostsFlag.Name) { 1175 cfg.AuthVirtualHosts = SplitAndTrim(ctx.String(AuthVirtualHostsFlag.Name)) 1176 } 1177 1178 if ctx.IsSet(HTTPCORSDomainFlag.Name) { 1179 cfg.HTTPCors = SplitAndTrim(ctx.String(HTTPCORSDomainFlag.Name)) 1180 } 1181 1182 if ctx.IsSet(HTTPApiFlag.Name) { 1183 cfg.HTTPModules = SplitAndTrim(ctx.String(HTTPApiFlag.Name)) 1184 } 1185 1186 if ctx.IsSet(HTTPVirtualHostsFlag.Name) { 1187 cfg.HTTPVirtualHosts = SplitAndTrim(ctx.String(HTTPVirtualHostsFlag.Name)) 1188 } 1189 1190 if ctx.IsSet(HTTPPathPrefixFlag.Name) { 1191 cfg.HTTPPathPrefix = ctx.String(HTTPPathPrefixFlag.Name) 1192 } 1193 if ctx.IsSet(AllowUnprotectedTxs.Name) { 1194 cfg.AllowUnprotectedTxs = ctx.Bool(AllowUnprotectedTxs.Name) 1195 } 1196 } 1197 1198 // setGraphQL creates the GraphQL listener interface string from the set 1199 // command line flags, returning empty if the GraphQL endpoint is disabled. 1200 func setGraphQL(ctx *cli.Context, cfg *node.Config) { 1201 if ctx.IsSet(GraphQLCORSDomainFlag.Name) { 1202 cfg.GraphQLCors = SplitAndTrim(ctx.String(GraphQLCORSDomainFlag.Name)) 1203 } 1204 if ctx.IsSet(GraphQLVirtualHostsFlag.Name) { 1205 cfg.GraphQLVirtualHosts = SplitAndTrim(ctx.String(GraphQLVirtualHostsFlag.Name)) 1206 } 1207 } 1208 1209 // setWS creates the WebSocket RPC listener interface string from the set 1210 // command line flags, returning empty if the HTTP endpoint is disabled. 1211 func setWS(ctx *cli.Context, cfg *node.Config) { 1212 if ctx.Bool(WSEnabledFlag.Name) && cfg.WSHost == "" { 1213 cfg.WSHost = "127.0.0.1" 1214 if ctx.IsSet(WSListenAddrFlag.Name) { 1215 cfg.WSHost = ctx.String(WSListenAddrFlag.Name) 1216 } 1217 } 1218 if ctx.IsSet(WSPortFlag.Name) { 1219 cfg.WSPort = ctx.Int(WSPortFlag.Name) 1220 } 1221 1222 if ctx.IsSet(WSAllowedOriginsFlag.Name) { 1223 cfg.WSOrigins = SplitAndTrim(ctx.String(WSAllowedOriginsFlag.Name)) 1224 } 1225 1226 if ctx.IsSet(WSApiFlag.Name) { 1227 cfg.WSModules = SplitAndTrim(ctx.String(WSApiFlag.Name)) 1228 } 1229 1230 if ctx.IsSet(WSPathPrefixFlag.Name) { 1231 cfg.WSPathPrefix = ctx.String(WSPathPrefixFlag.Name) 1232 } 1233 } 1234 1235 // setIPC creates an IPC path configuration from the set command line flags, 1236 // returning an empty string if IPC was explicitly disabled, or the set path. 1237 func setIPC(ctx *cli.Context, cfg *node.Config) { 1238 CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 1239 switch { 1240 case ctx.Bool(IPCDisabledFlag.Name): 1241 cfg.IPCPath = "" 1242 case ctx.IsSet(IPCPathFlag.Name): 1243 cfg.IPCPath = ctx.String(IPCPathFlag.Name) 1244 } 1245 } 1246 1247 // setLes configures the les server and ultra light client settings from the command line flags. 1248 func setLes(ctx *cli.Context, cfg *ethconfig.Config) { 1249 if ctx.IsSet(LightServeFlag.Name) { 1250 cfg.LightServ = ctx.Int(LightServeFlag.Name) 1251 } 1252 if ctx.IsSet(LightIngressFlag.Name) { 1253 cfg.LightIngress = ctx.Int(LightIngressFlag.Name) 1254 } 1255 if ctx.IsSet(LightEgressFlag.Name) { 1256 cfg.LightEgress = ctx.Int(LightEgressFlag.Name) 1257 } 1258 if ctx.IsSet(LightMaxPeersFlag.Name) { 1259 cfg.LightPeers = ctx.Int(LightMaxPeersFlag.Name) 1260 } 1261 if ctx.IsSet(UltraLightServersFlag.Name) { 1262 cfg.UltraLightServers = strings.Split(ctx.String(UltraLightServersFlag.Name), ",") 1263 } 1264 if ctx.IsSet(UltraLightFractionFlag.Name) { 1265 cfg.UltraLightFraction = ctx.Int(UltraLightFractionFlag.Name) 1266 } 1267 if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 { 1268 log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", ethconfig.Defaults.UltraLightFraction) 1269 cfg.UltraLightFraction = ethconfig.Defaults.UltraLightFraction 1270 } 1271 if ctx.IsSet(UltraLightOnlyAnnounceFlag.Name) { 1272 cfg.UltraLightOnlyAnnounce = ctx.Bool(UltraLightOnlyAnnounceFlag.Name) 1273 } 1274 if ctx.IsSet(LightNoPruneFlag.Name) { 1275 cfg.LightNoPrune = ctx.Bool(LightNoPruneFlag.Name) 1276 } 1277 if ctx.IsSet(LightNoSyncServeFlag.Name) { 1278 cfg.LightNoSyncServe = ctx.Bool(LightNoSyncServeFlag.Name) 1279 } 1280 } 1281 1282 // MakeDatabaseHandles raises out the number of allowed file handles per process 1283 // for Geth and returns half of the allowance to assign to the database. 1284 func MakeDatabaseHandles(max int) int { 1285 limit, err := fdlimit.Maximum() 1286 if err != nil { 1287 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 1288 } 1289 switch { 1290 case max == 0: 1291 // User didn't specify a meaningful value, use system limits 1292 case max < 128: 1293 // User specified something unhealthy, just use system defaults 1294 log.Error("File descriptor limit invalid (<128)", "had", max, "updated", limit) 1295 case max > limit: 1296 // User requested more than the OS allows, notify that we can't allocate it 1297 log.Warn("Requested file descriptors denied by OS", "req", max, "limit", limit) 1298 default: 1299 // User limit is meaningful and within allowed range, use that 1300 limit = max 1301 } 1302 raised, err := fdlimit.Raise(uint64(limit)) 1303 if err != nil { 1304 Fatalf("Failed to raise file descriptor allowance: %v", err) 1305 } 1306 return int(raised / 2) // Leave half for networking and other stuff 1307 } 1308 1309 // MakeAddress converts an account specified directly as a hex encoded string or 1310 // a key index in the key store to an internal account representation. 1311 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 1312 // If the specified account is a valid address, return it 1313 if common.IsHexAddress(account) { 1314 return accounts.Account{Address: common.HexToAddress(account)}, nil 1315 } 1316 // Otherwise try to interpret the account as a keystore index 1317 index, err := strconv.Atoi(account) 1318 if err != nil || index < 0 { 1319 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 1320 } 1321 log.Warn("-------------------------------------------------------------------") 1322 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 1323 log.Warn("This functionality is deprecated and will be removed in the future!") 1324 log.Warn("Please use explicit addresses! (can search via `geth account list`)") 1325 log.Warn("-------------------------------------------------------------------") 1326 1327 accs := ks.Accounts() 1328 if len(accs) <= index { 1329 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 1330 } 1331 return accs[index], nil 1332 } 1333 1334 // setEtherbase retrieves the etherbase either from the directly specified 1335 // command line flags or from the keystore if CLI indexed. 1336 func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *ethconfig.Config) { 1337 // Extract the current etherbase 1338 var etherbase string 1339 if ctx.IsSet(MinerEtherbaseFlag.Name) { 1340 etherbase = ctx.String(MinerEtherbaseFlag.Name) 1341 } 1342 // Convert the etherbase into an address and configure it 1343 if etherbase != "" { 1344 if ks != nil { 1345 account, err := MakeAddress(ks, etherbase) 1346 if err != nil { 1347 Fatalf("Invalid miner etherbase: %v", err) 1348 } 1349 cfg.Miner.Etherbase = account.Address 1350 } else { 1351 Fatalf("No etherbase configured") 1352 } 1353 } 1354 } 1355 1356 // MakePasswordList reads password lines from the file specified by the global --password flag. 1357 func MakePasswordList(ctx *cli.Context) []string { 1358 path := ctx.Path(PasswordFileFlag.Name) 1359 if path == "" { 1360 return nil 1361 } 1362 text, err := os.ReadFile(path) 1363 if err != nil { 1364 Fatalf("Failed to read password file: %v", err) 1365 } 1366 lines := strings.Split(string(text), "\n") 1367 // Sanitise DOS line endings. 1368 for i := range lines { 1369 lines[i] = strings.TrimRight(lines[i], "\r") 1370 } 1371 return lines 1372 } 1373 1374 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 1375 setNodeKey(ctx, cfg) 1376 setNAT(ctx, cfg) 1377 setListenAddress(ctx, cfg) 1378 setBootstrapNodes(ctx, cfg) 1379 setBootstrapNodesV5(ctx, cfg) 1380 1381 lightClient := ctx.String(SyncModeFlag.Name) == "light" 1382 lightServer := (ctx.Int(LightServeFlag.Name) != 0) 1383 1384 lightPeers := ctx.Int(LightMaxPeersFlag.Name) 1385 if lightClient && !ctx.IsSet(LightMaxPeersFlag.Name) { 1386 // dynamic default - for clients we use 1/10th of the default for servers 1387 lightPeers /= 10 1388 } 1389 1390 if ctx.IsSet(MaxPeersFlag.Name) { 1391 cfg.MaxPeers = ctx.Int(MaxPeersFlag.Name) 1392 if lightServer && !ctx.IsSet(LightMaxPeersFlag.Name) { 1393 cfg.MaxPeers += lightPeers 1394 } 1395 } else { 1396 if lightServer { 1397 cfg.MaxPeers += lightPeers 1398 } 1399 if lightClient && ctx.IsSet(LightMaxPeersFlag.Name) && cfg.MaxPeers < lightPeers { 1400 cfg.MaxPeers = lightPeers 1401 } 1402 } 1403 if !(lightClient || lightServer) { 1404 lightPeers = 0 1405 } 1406 ethPeers := cfg.MaxPeers - lightPeers 1407 if lightClient { 1408 ethPeers = 0 1409 } 1410 log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers) 1411 1412 if ctx.IsSet(MaxPendingPeersFlag.Name) { 1413 cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name) 1414 } 1415 if ctx.IsSet(NoDiscoverFlag.Name) || lightClient { 1416 cfg.NoDiscovery = true 1417 } 1418 1419 // if we're running a light client or server, force enable the v5 peer discovery 1420 // unless it is explicitly disabled with --nodiscover note that explicitly specifying 1421 // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery 1422 forceV5Discovery := (lightClient || lightServer) && !ctx.Bool(NoDiscoverFlag.Name) 1423 if ctx.IsSet(DiscoveryV5Flag.Name) { 1424 cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name) 1425 } else if forceV5Discovery { 1426 cfg.DiscoveryV5 = true 1427 } 1428 1429 if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" { 1430 list, err := netutil.ParseNetlist(netrestrict) 1431 if err != nil { 1432 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 1433 } 1434 cfg.NetRestrict = list 1435 } 1436 1437 if ctx.Bool(DeveloperFlag.Name) { 1438 // --dev mode can't use p2p networking. 1439 cfg.MaxPeers = 0 1440 cfg.ListenAddr = "" 1441 cfg.NoDial = true 1442 cfg.NoDiscovery = true 1443 cfg.DiscoveryV5 = false 1444 } 1445 } 1446 1447 // SetNodeConfig applies node-related command line flags to the config. 1448 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 1449 SetP2PConfig(ctx, &cfg.P2P) 1450 setIPC(ctx, cfg) 1451 setHTTP(ctx, cfg) 1452 setGraphQL(ctx, cfg) 1453 setWS(ctx, cfg) 1454 setNodeUserIdent(ctx, cfg) 1455 SetDataDir(ctx, cfg) 1456 setSmartCard(ctx, cfg) 1457 1458 if ctx.IsSet(JWTSecretFlag.Name) { 1459 cfg.JWTSecret = ctx.String(JWTSecretFlag.Name) 1460 } 1461 1462 if ctx.IsSet(ExternalSignerFlag.Name) { 1463 cfg.ExternalSigner = ctx.String(ExternalSignerFlag.Name) 1464 } 1465 1466 if ctx.IsSet(KeyStoreDirFlag.Name) { 1467 cfg.KeyStoreDir = ctx.String(KeyStoreDirFlag.Name) 1468 } 1469 if ctx.IsSet(DeveloperFlag.Name) { 1470 cfg.UseLightweightKDF = true 1471 } 1472 if ctx.IsSet(LightKDFFlag.Name) { 1473 cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name) 1474 } 1475 if ctx.IsSet(NoUSBFlag.Name) || cfg.NoUSB { 1476 log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable") 1477 } 1478 if ctx.IsSet(USBFlag.Name) { 1479 cfg.USB = ctx.Bool(USBFlag.Name) 1480 } 1481 if ctx.IsSet(InsecureUnlockAllowedFlag.Name) { 1482 cfg.InsecureUnlockAllowed = ctx.Bool(InsecureUnlockAllowedFlag.Name) 1483 } 1484 } 1485 1486 func setSmartCard(ctx *cli.Context, cfg *node.Config) { 1487 // Skip enabling smartcards if no path is set 1488 path := ctx.String(SmartCardDaemonPathFlag.Name) 1489 if path == "" { 1490 return 1491 } 1492 // Sanity check that the smartcard path is valid 1493 fi, err := os.Stat(path) 1494 if err != nil { 1495 log.Info("Smartcard socket not found, disabling", "err", err) 1496 return 1497 } 1498 if fi.Mode()&os.ModeType != os.ModeSocket { 1499 log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String()) 1500 return 1501 } 1502 // Smartcard daemon path exists and is a socket, enable it 1503 cfg.SmartCardDaemonPath = path 1504 } 1505 1506 func SetDataDir(ctx *cli.Context, cfg *node.Config) { 1507 switch { 1508 case ctx.IsSet(DataDirFlag.Name): 1509 cfg.DataDir = ctx.String(DataDirFlag.Name) 1510 case ctx.Bool(DeveloperFlag.Name): 1511 cfg.DataDir = "" // unless explicitly requested, use memory databases 1512 case ctx.Bool(RopstenFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1513 // Maintain compatibility with older Geth configurations storing the 1514 // Ropsten database in `testnet` instead of `ropsten`. 1515 legacyPath := filepath.Join(node.DefaultDataDir(), "testnet") 1516 if common.FileExist(legacyPath) { 1517 log.Warn("Using the deprecated `testnet` datadir. Future versions will store the Ropsten chain in `ropsten`.") 1518 cfg.DataDir = legacyPath 1519 } else { 1520 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten") 1521 } 1522 1523 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten") 1524 case ctx.Bool(RinkebyFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1525 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby") 1526 case ctx.Bool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1527 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli") 1528 case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1529 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia") 1530 case ctx.Bool(KilnFlag.Name) && cfg.DataDir == node.DefaultDataDir(): 1531 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "kiln") 1532 } 1533 } 1534 1535 func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) { 1536 // If we are running the light client, apply another group 1537 // settings for gas oracle. 1538 if light { 1539 *cfg = ethconfig.LightClientGPO 1540 } 1541 if ctx.IsSet(GpoBlocksFlag.Name) { 1542 cfg.Blocks = ctx.Int(GpoBlocksFlag.Name) 1543 } 1544 if ctx.IsSet(GpoPercentileFlag.Name) { 1545 cfg.Percentile = ctx.Int(GpoPercentileFlag.Name) 1546 } 1547 if ctx.IsSet(GpoMaxGasPriceFlag.Name) { 1548 cfg.MaxPrice = big.NewInt(ctx.Int64(GpoMaxGasPriceFlag.Name)) 1549 } 1550 if ctx.IsSet(GpoIgnoreGasPriceFlag.Name) { 1551 cfg.IgnorePrice = big.NewInt(ctx.Int64(GpoIgnoreGasPriceFlag.Name)) 1552 } 1553 } 1554 1555 func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { 1556 if ctx.IsSet(TxPoolLocalsFlag.Name) { 1557 locals := strings.Split(ctx.String(TxPoolLocalsFlag.Name), ",") 1558 for _, account := range locals { 1559 if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) { 1560 Fatalf("Invalid account in --txpool.locals: %s", trimmed) 1561 } else { 1562 cfg.Locals = append(cfg.Locals, common.HexToAddress(account)) 1563 } 1564 } 1565 } 1566 if ctx.IsSet(TxPoolNoLocalsFlag.Name) { 1567 cfg.NoLocals = ctx.Bool(TxPoolNoLocalsFlag.Name) 1568 } 1569 if ctx.IsSet(TxPoolJournalFlag.Name) { 1570 cfg.Journal = ctx.String(TxPoolJournalFlag.Name) 1571 } 1572 if ctx.IsSet(TxPoolRejournalFlag.Name) { 1573 cfg.Rejournal = ctx.Duration(TxPoolRejournalFlag.Name) 1574 } 1575 if ctx.IsSet(TxPoolPriceLimitFlag.Name) { 1576 cfg.PriceLimit = ctx.Uint64(TxPoolPriceLimitFlag.Name) 1577 } 1578 if ctx.IsSet(TxPoolPriceBumpFlag.Name) { 1579 cfg.PriceBump = ctx.Uint64(TxPoolPriceBumpFlag.Name) 1580 } 1581 if ctx.IsSet(TxPoolAccountSlotsFlag.Name) { 1582 cfg.AccountSlots = ctx.Uint64(TxPoolAccountSlotsFlag.Name) 1583 } 1584 if ctx.IsSet(TxPoolGlobalSlotsFlag.Name) { 1585 cfg.GlobalSlots = ctx.Uint64(TxPoolGlobalSlotsFlag.Name) 1586 } 1587 if ctx.IsSet(TxPoolAccountQueueFlag.Name) { 1588 cfg.AccountQueue = ctx.Uint64(TxPoolAccountQueueFlag.Name) 1589 } 1590 if ctx.IsSet(TxPoolGlobalQueueFlag.Name) { 1591 cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name) 1592 } 1593 if ctx.IsSet(TxPoolLifetimeFlag.Name) { 1594 cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name) 1595 } 1596 } 1597 1598 func setEthash(ctx *cli.Context, cfg *ethconfig.Config) { 1599 if ctx.IsSet(EthashCacheDirFlag.Name) { 1600 cfg.Ethash.CacheDir = ctx.String(EthashCacheDirFlag.Name) 1601 } 1602 if ctx.IsSet(EthashDatasetDirFlag.Name) { 1603 cfg.Ethash.DatasetDir = ctx.String(EthashDatasetDirFlag.Name) 1604 } 1605 if ctx.IsSet(EthashCachesInMemoryFlag.Name) { 1606 cfg.Ethash.CachesInMem = ctx.Int(EthashCachesInMemoryFlag.Name) 1607 } 1608 if ctx.IsSet(EthashCachesOnDiskFlag.Name) { 1609 cfg.Ethash.CachesOnDisk = ctx.Int(EthashCachesOnDiskFlag.Name) 1610 } 1611 if ctx.IsSet(EthashCachesLockMmapFlag.Name) { 1612 cfg.Ethash.CachesLockMmap = ctx.Bool(EthashCachesLockMmapFlag.Name) 1613 } 1614 if ctx.IsSet(EthashDatasetsInMemoryFlag.Name) { 1615 cfg.Ethash.DatasetsInMem = ctx.Int(EthashDatasetsInMemoryFlag.Name) 1616 } 1617 if ctx.IsSet(EthashDatasetsOnDiskFlag.Name) { 1618 cfg.Ethash.DatasetsOnDisk = ctx.Int(EthashDatasetsOnDiskFlag.Name) 1619 } 1620 if ctx.IsSet(EthashDatasetsLockMmapFlag.Name) { 1621 cfg.Ethash.DatasetsLockMmap = ctx.Bool(EthashDatasetsLockMmapFlag.Name) 1622 } 1623 } 1624 1625 func setMiner(ctx *cli.Context, cfg *miner.Config) { 1626 if ctx.IsSet(MinerNotifyFlag.Name) { 1627 cfg.Notify = strings.Split(ctx.String(MinerNotifyFlag.Name), ",") 1628 } 1629 cfg.NotifyFull = ctx.Bool(MinerNotifyFullFlag.Name) 1630 if ctx.IsSet(MinerExtraDataFlag.Name) { 1631 cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name)) 1632 } 1633 if ctx.IsSet(MinerGasLimitFlag.Name) { 1634 cfg.GasCeil = ctx.Uint64(MinerGasLimitFlag.Name) 1635 } 1636 if ctx.IsSet(MinerGasPriceFlag.Name) { 1637 cfg.GasPrice = flags.GlobalBig(ctx, MinerGasPriceFlag.Name) 1638 } 1639 if ctx.IsSet(MinerRecommitIntervalFlag.Name) { 1640 cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name) 1641 } 1642 if ctx.IsSet(MinerNoVerifyFlag.Name) { 1643 cfg.Noverify = ctx.Bool(MinerNoVerifyFlag.Name) 1644 } 1645 if ctx.IsSet(LegacyMinerGasTargetFlag.Name) { 1646 log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!") 1647 } 1648 } 1649 1650 func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) { 1651 requiredBlocks := ctx.String(EthRequiredBlocksFlag.Name) 1652 if requiredBlocks == "" { 1653 if ctx.IsSet(LegacyWhitelistFlag.Name) { 1654 log.Warn("The flag --whitelist is deprecated and will be removed, please use --eth.requiredblocks") 1655 requiredBlocks = ctx.String(LegacyWhitelistFlag.Name) 1656 } else { 1657 return 1658 } 1659 } 1660 cfg.RequiredBlocks = make(map[uint64]common.Hash) 1661 for _, entry := range strings.Split(requiredBlocks, ",") { 1662 parts := strings.Split(entry, "=") 1663 if len(parts) != 2 { 1664 Fatalf("Invalid required block entry: %s", entry) 1665 } 1666 number, err := strconv.ParseUint(parts[0], 0, 64) 1667 if err != nil { 1668 Fatalf("Invalid required block number %s: %v", parts[0], err) 1669 } 1670 var hash common.Hash 1671 if err = hash.UnmarshalText([]byte(parts[1])); err != nil { 1672 Fatalf("Invalid required block hash %s: %v", parts[1], err) 1673 } 1674 cfg.RequiredBlocks[number] = hash 1675 } 1676 } 1677 1678 // CheckExclusive verifies that only a single instance of the provided flags was 1679 // set by the user. Each flag might optionally be followed by a string type to 1680 // specialize it further. 1681 func CheckExclusive(ctx *cli.Context, args ...interface{}) { 1682 set := make([]string, 0, 1) 1683 for i := 0; i < len(args); i++ { 1684 // Make sure the next argument is a flag and skip if not set 1685 flag, ok := args[i].(cli.Flag) 1686 if !ok { 1687 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 1688 } 1689 // Check if next arg extends current and expand its name if so 1690 name := flag.Names()[0] 1691 1692 if i+1 < len(args) { 1693 switch option := args[i+1].(type) { 1694 case string: 1695 // Extended flag check, make sure value set doesn't conflict with passed in option 1696 if ctx.String(flag.Names()[0]) == option { 1697 name += "=" + option 1698 set = append(set, "--"+name) 1699 } 1700 // shift arguments and continue 1701 i++ 1702 continue 1703 1704 case cli.Flag: 1705 default: 1706 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 1707 } 1708 } 1709 // Mark the flag if it's set 1710 if ctx.IsSet(flag.Names()[0]) { 1711 set = append(set, "--"+name) 1712 } 1713 } 1714 if len(set) > 1 { 1715 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 1716 } 1717 } 1718 1719 // SetEthConfig applies eth-related command line flags to the config. 1720 func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { 1721 // Avoid conflicting network flags 1722 CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RopstenFlag, RinkebyFlag, GoerliFlag, SepoliaFlag, KilnFlag) 1723 CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light") 1724 CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer 1725 if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { 1726 ctx.Set(TxLookupLimitFlag.Name, "0") 1727 log.Warn("Disable transaction unindexing for archive node") 1728 } 1729 if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { 1730 log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited") 1731 } 1732 var ks *keystore.KeyStore 1733 if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { 1734 ks = keystores[0].(*keystore.KeyStore) 1735 } 1736 setEtherbase(ctx, ks, cfg) 1737 setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light") 1738 setTxPool(ctx, &cfg.TxPool) 1739 setEthash(ctx, cfg) 1740 setMiner(ctx, &cfg.Miner) 1741 setRequiredBlocks(ctx, cfg) 1742 setLes(ctx, cfg) 1743 1744 // Cap the cache allowance and tune the garbage collector 1745 mem, err := gopsutil.VirtualMemory() 1746 if err == nil { 1747 if 32<<(^uintptr(0)>>63) == 32 && mem.Total > 2*1024*1024*1024 { 1748 log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024) 1749 mem.Total = 2 * 1024 * 1024 * 1024 1750 } 1751 allowance := int(mem.Total / 1024 / 1024 / 3) 1752 if cache := ctx.Int(CacheFlag.Name); cache > allowance { 1753 log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) 1754 ctx.Set(CacheFlag.Name, strconv.Itoa(allowance)) 1755 } 1756 } 1757 // Ensure Go's GC ignores the database cache for trigger percentage 1758 cache := ctx.Int(CacheFlag.Name) 1759 gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024))) 1760 1761 log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc)) 1762 godebug.SetGCPercent(int(gogc)) 1763 1764 if ctx.IsSet(SyncModeFlag.Name) { 1765 cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 1766 } 1767 if ctx.IsSet(NetworkIdFlag.Name) { 1768 cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name) 1769 } 1770 if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheDatabaseFlag.Name) { 1771 cfg.DatabaseCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 1772 } 1773 cfg.DatabaseHandles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) 1774 if ctx.IsSet(AncientFlag.Name) { 1775 cfg.DatabaseFreezer = ctx.String(AncientFlag.Name) 1776 } 1777 1778 if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1779 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1780 } 1781 if ctx.IsSet(GCModeFlag.Name) { 1782 cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive" 1783 } 1784 if ctx.IsSet(CacheNoPrefetchFlag.Name) { 1785 cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name) 1786 } 1787 // Read the value from the flag no matter if it's set or not. 1788 cfg.Preimages = ctx.Bool(CachePreimagesFlag.Name) 1789 if cfg.NoPruning && !cfg.Preimages { 1790 cfg.Preimages = true 1791 log.Info("Enabling recording of key preimages since archive mode is used") 1792 } 1793 if ctx.IsSet(TxLookupLimitFlag.Name) { 1794 cfg.TxLookupLimit = ctx.Uint64(TxLookupLimitFlag.Name) 1795 } 1796 if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { 1797 cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 1798 } 1799 if ctx.IsSet(CacheTrieJournalFlag.Name) { 1800 cfg.TrieCleanCacheJournal = ctx.String(CacheTrieJournalFlag.Name) 1801 } 1802 if ctx.IsSet(CacheTrieRejournalFlag.Name) { 1803 cfg.TrieCleanCacheRejournal = ctx.Duration(CacheTrieRejournalFlag.Name) 1804 } 1805 if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { 1806 cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 1807 } 1808 if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) { 1809 cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100 1810 } 1811 if !ctx.Bool(SnapshotFlag.Name) { 1812 // If snap-sync is requested, this flag is also required 1813 if cfg.SyncMode == downloader.SnapSync { 1814 log.Info("Snap sync requested, enabling --snapshot") 1815 } else { 1816 cfg.TrieCleanCache += cfg.SnapshotCache 1817 cfg.SnapshotCache = 0 // Disabled 1818 } 1819 } 1820 if ctx.IsSet(DocRootFlag.Name) { 1821 cfg.DocRoot = ctx.String(DocRootFlag.Name) 1822 } 1823 if ctx.IsSet(VMEnableDebugFlag.Name) { 1824 // TODO(fjl): force-enable this in --dev mode 1825 cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name) 1826 } 1827 1828 if ctx.IsSet(RPCGlobalGasCapFlag.Name) { 1829 cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name) 1830 } 1831 if cfg.RPCGasCap != 0 { 1832 log.Info("Set global gas cap", "cap", cfg.RPCGasCap) 1833 } else { 1834 log.Info("Global gas cap disabled") 1835 } 1836 if ctx.IsSet(RPCGlobalEVMTimeoutFlag.Name) { 1837 cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name) 1838 } 1839 if ctx.IsSet(RPCGlobalTxFeeCapFlag.Name) { 1840 cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalTxFeeCapFlag.Name) 1841 } 1842 if ctx.IsSet(NoDiscoverFlag.Name) { 1843 cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{} 1844 } else if ctx.IsSet(DNSDiscoveryFlag.Name) { 1845 urls := ctx.String(DNSDiscoveryFlag.Name) 1846 if urls == "" { 1847 cfg.EthDiscoveryURLs = []string{} 1848 } else { 1849 cfg.EthDiscoveryURLs = SplitAndTrim(urls) 1850 } 1851 } 1852 // Override any default configs for hard coded networks. 1853 switch { 1854 case ctx.Bool(MainnetFlag.Name): 1855 if !ctx.IsSet(NetworkIdFlag.Name) { 1856 cfg.NetworkId = 1 1857 } 1858 cfg.Genesis = core.DefaultGenesisBlock() 1859 SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) 1860 case ctx.Bool(RopstenFlag.Name): 1861 if !ctx.IsSet(NetworkIdFlag.Name) { 1862 cfg.NetworkId = 3 1863 } 1864 cfg.Genesis = core.DefaultRopstenGenesisBlock() 1865 SetDNSDiscoveryDefaults(cfg, params.RopstenGenesisHash) 1866 case ctx.Bool(SepoliaFlag.Name): 1867 if !ctx.IsSet(NetworkIdFlag.Name) { 1868 cfg.NetworkId = 11155111 1869 } 1870 cfg.Genesis = core.DefaultSepoliaGenesisBlock() 1871 SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash) 1872 case ctx.Bool(RinkebyFlag.Name): 1873 log.Warn("") 1874 log.Warn("--------------------------------------------------------------------------------") 1875 log.Warn("Please note, Rinkeby has been deprecated. It will still work for the time being,") 1876 log.Warn("but there will be no further hard-forks shipped for it. Eventually the network") 1877 log.Warn("will be permanently halted after the other networks transition through the merge") 1878 log.Warn("and prove stable enough. For the most future proof testnet, choose Sepolia as") 1879 log.Warn("your replacement environment (--sepolia instead of --rinkeby).") 1880 log.Warn("--------------------------------------------------------------------------------") 1881 log.Warn("") 1882 1883 if !ctx.IsSet(NetworkIdFlag.Name) { 1884 cfg.NetworkId = 4 1885 } 1886 cfg.Genesis = core.DefaultRinkebyGenesisBlock() 1887 SetDNSDiscoveryDefaults(cfg, params.RinkebyGenesisHash) 1888 case ctx.Bool(GoerliFlag.Name): 1889 if !ctx.IsSet(NetworkIdFlag.Name) { 1890 cfg.NetworkId = 5 1891 } 1892 cfg.Genesis = core.DefaultGoerliGenesisBlock() 1893 SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash) 1894 case ctx.Bool(KilnFlag.Name): 1895 if !ctx.IsSet(NetworkIdFlag.Name) { 1896 cfg.NetworkId = 1337802 1897 } 1898 cfg.Genesis = core.DefaultKilnGenesisBlock() 1899 SetDNSDiscoveryDefaults(cfg, params.KilnGenesisHash) 1900 case ctx.Bool(DeveloperFlag.Name): 1901 if !ctx.IsSet(NetworkIdFlag.Name) { 1902 cfg.NetworkId = 1337 1903 } 1904 cfg.SyncMode = downloader.FullSync 1905 // Create new developer account or reuse existing one 1906 var ( 1907 developer accounts.Account 1908 passphrase string 1909 err error 1910 ) 1911 if list := MakePasswordList(ctx); len(list) > 0 { 1912 // Just take the first value. Although the function returns a possible multiple values and 1913 // some usages iterate through them as attempts, that doesn't make sense in this setting, 1914 // when we're definitely concerned with only one account. 1915 passphrase = list[0] 1916 } 1917 // setEtherbase has been called above, configuring the miner address from command line flags. 1918 if cfg.Miner.Etherbase != (common.Address{}) { 1919 developer = accounts.Account{Address: cfg.Miner.Etherbase} 1920 } else if accs := ks.Accounts(); len(accs) > 0 { 1921 developer = ks.Accounts()[0] 1922 } else { 1923 developer, err = ks.NewAccount(passphrase) 1924 if err != nil { 1925 Fatalf("Failed to create developer account: %v", err) 1926 } 1927 } 1928 if err := ks.Unlock(developer, passphrase); err != nil { 1929 Fatalf("Failed to unlock developer account: %v", err) 1930 } 1931 log.Info("Using developer account", "address", developer.Address) 1932 1933 // Create a new developer genesis block or reuse existing one 1934 cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address) 1935 if ctx.IsSet(DataDirFlag.Name) { 1936 // If datadir doesn't exist we need to open db in write-mode 1937 // so leveldb can create files. 1938 readonly := true 1939 if !common.FileExist(stack.ResolvePath("chaindata")) { 1940 readonly = false 1941 } 1942 // Check if we have an already initialized chain and fall back to 1943 // that if so. Otherwise we need to generate a new genesis spec. 1944 chaindb := MakeChainDatabase(ctx, stack, readonly) 1945 if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) { 1946 cfg.Genesis = nil // fallback to db content 1947 } 1948 chaindb.Close() 1949 } 1950 if !ctx.IsSet(MinerGasPriceFlag.Name) { 1951 cfg.Miner.GasPrice = big.NewInt(1) 1952 } 1953 default: 1954 if cfg.NetworkId == 1 { 1955 SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) 1956 } 1957 } 1958 } 1959 1960 // SetDNSDiscoveryDefaults configures DNS discovery with the given URL if 1961 // no URLs are set. 1962 func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) { 1963 if cfg.EthDiscoveryURLs != nil { 1964 return // already set through flags/config 1965 } 1966 protocol := "all" 1967 if cfg.SyncMode == downloader.LightSync { 1968 protocol = "les" 1969 } 1970 if url := params.KnownDNSNetwork(genesis, protocol); url != "" { 1971 cfg.EthDiscoveryURLs = []string{url} 1972 cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs 1973 } 1974 } 1975 1976 // RegisterEthService adds an Ethereum client to the stack. 1977 // The second return value is the full node instance, which may be nil if the 1978 // node is running as a light client. 1979 func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) { 1980 if cfg.SyncMode == downloader.LightSync { 1981 backend, err := les.New(stack, cfg) 1982 if err != nil { 1983 Fatalf("Failed to register the Ethereum service: %v", err) 1984 } 1985 stack.RegisterAPIs(tracers.APIs(backend.ApiBackend)) 1986 if err := lescatalyst.Register(stack, backend); err != nil { 1987 Fatalf("Failed to register the Engine API service: %v", err) 1988 } 1989 return backend.ApiBackend, nil 1990 } 1991 backend, err := eth.New(stack, cfg) 1992 if err != nil { 1993 Fatalf("Failed to register the Ethereum service: %v", err) 1994 } 1995 if cfg.LightServ > 0 { 1996 _, err := les.NewLesServer(stack, backend, cfg) 1997 if err != nil { 1998 Fatalf("Failed to create the LES server: %v", err) 1999 } 2000 } 2001 if err := ethcatalyst.Register(stack, backend); err != nil { 2002 Fatalf("Failed to register the Engine API service: %v", err) 2003 } 2004 stack.RegisterAPIs(tracers.APIs(backend.APIBackend)) 2005 return backend.APIBackend, backend 2006 } 2007 2008 // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to 2009 // the given node. 2010 func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) { 2011 if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil { 2012 Fatalf("Failed to register the Ethereum Stats service: %v", err) 2013 } 2014 } 2015 2016 // RegisterGraphQLService is a utility function to construct a new service and register it against a node. 2017 func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, cfg node.Config) { 2018 if err := graphql.New(stack, backend, cfg.GraphQLCors, cfg.GraphQLVirtualHosts); err != nil { 2019 Fatalf("Failed to register the GraphQL service: %v", err) 2020 } 2021 } 2022 2023 func SetupMetrics(ctx *cli.Context) { 2024 if metrics.Enabled { 2025 log.Info("Enabling metrics collection") 2026 2027 var ( 2028 enableExport = ctx.Bool(MetricsEnableInfluxDBFlag.Name) 2029 enableExportV2 = ctx.Bool(MetricsEnableInfluxDBV2Flag.Name) 2030 ) 2031 2032 if enableExport || enableExportV2 { 2033 CheckExclusive(ctx, MetricsEnableInfluxDBFlag, MetricsEnableInfluxDBV2Flag) 2034 2035 v1FlagIsSet := ctx.IsSet(MetricsInfluxDBUsernameFlag.Name) || 2036 ctx.IsSet(MetricsInfluxDBPasswordFlag.Name) 2037 2038 v2FlagIsSet := ctx.IsSet(MetricsInfluxDBTokenFlag.Name) || 2039 ctx.IsSet(MetricsInfluxDBOrganizationFlag.Name) || 2040 ctx.IsSet(MetricsInfluxDBBucketFlag.Name) 2041 2042 if enableExport && v2FlagIsSet { 2043 Fatalf("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2") 2044 } else if enableExportV2 && v1FlagIsSet { 2045 Fatalf("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1") 2046 } 2047 } 2048 2049 var ( 2050 endpoint = ctx.String(MetricsInfluxDBEndpointFlag.Name) 2051 database = ctx.String(MetricsInfluxDBDatabaseFlag.Name) 2052 username = ctx.String(MetricsInfluxDBUsernameFlag.Name) 2053 password = ctx.String(MetricsInfluxDBPasswordFlag.Name) 2054 2055 token = ctx.String(MetricsInfluxDBTokenFlag.Name) 2056 bucket = ctx.String(MetricsInfluxDBBucketFlag.Name) 2057 organization = ctx.String(MetricsInfluxDBOrganizationFlag.Name) 2058 ) 2059 2060 if enableExport { 2061 tagsMap := SplitTagsFlag(ctx.String(MetricsInfluxDBTagsFlag.Name)) 2062 2063 log.Info("Enabling metrics export to InfluxDB") 2064 2065 go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) 2066 } else if enableExportV2 { 2067 tagsMap := SplitTagsFlag(ctx.String(MetricsInfluxDBTagsFlag.Name)) 2068 2069 log.Info("Enabling metrics export to InfluxDB (v2)") 2070 2071 go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap) 2072 } 2073 2074 if ctx.IsSet(MetricsHTTPFlag.Name) { 2075 address := fmt.Sprintf("%s:%d", ctx.String(MetricsHTTPFlag.Name), ctx.Int(MetricsPortFlag.Name)) 2076 log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address) 2077 exp.Setup(address) 2078 } 2079 } 2080 } 2081 2082 func SplitTagsFlag(tagsFlag string) map[string]string { 2083 tags := strings.Split(tagsFlag, ",") 2084 tagsMap := map[string]string{} 2085 2086 for _, t := range tags { 2087 if t != "" { 2088 kv := strings.Split(t, "=") 2089 2090 if len(kv) == 2 { 2091 tagsMap[kv[0]] = kv[1] 2092 } 2093 } 2094 } 2095 2096 return tagsMap 2097 } 2098 2099 // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. 2100 func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database { 2101 var ( 2102 cache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 2103 handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) 2104 2105 err error 2106 chainDb ethdb.Database 2107 ) 2108 switch { 2109 case ctx.IsSet(RemoteDBFlag.Name): 2110 log.Info("Using remote db", "url", ctx.String(RemoteDBFlag.Name)) 2111 chainDb, err = remotedb.New(ctx.String(RemoteDBFlag.Name)) 2112 case ctx.String(SyncModeFlag.Name) == "light": 2113 chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly) 2114 default: 2115 chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly) 2116 } 2117 if err != nil { 2118 Fatalf("Could not open database: %v", err) 2119 } 2120 return chainDb 2121 } 2122 2123 func MakeGenesis(ctx *cli.Context) *core.Genesis { 2124 var genesis *core.Genesis 2125 switch { 2126 case ctx.Bool(MainnetFlag.Name): 2127 genesis = core.DefaultGenesisBlock() 2128 case ctx.Bool(RopstenFlag.Name): 2129 genesis = core.DefaultRopstenGenesisBlock() 2130 case ctx.Bool(SepoliaFlag.Name): 2131 genesis = core.DefaultSepoliaGenesisBlock() 2132 case ctx.Bool(RinkebyFlag.Name): 2133 genesis = core.DefaultRinkebyGenesisBlock() 2134 case ctx.Bool(GoerliFlag.Name): 2135 genesis = core.DefaultGoerliGenesisBlock() 2136 case ctx.Bool(KilnFlag.Name): 2137 genesis = core.DefaultKilnGenesisBlock() 2138 case ctx.Bool(DeveloperFlag.Name): 2139 Fatalf("Developer chains are ephemeral") 2140 } 2141 return genesis 2142 } 2143 2144 // MakeChain creates a chain manager from set command line flags. 2145 func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { 2146 var err error 2147 chainDb = MakeChainDatabase(ctx, stack, false) // TODO(rjl493456442) support read-only database 2148 config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) 2149 if err != nil { 2150 Fatalf("%v", err) 2151 } 2152 2153 var engine consensus.Engine 2154 ethashConf := ethconfig.Defaults.Ethash 2155 if ctx.Bool(FakePoWFlag.Name) { 2156 ethashConf.PowMode = ethash.ModeFake 2157 } 2158 engine = ethconfig.CreateConsensusEngine(stack, config, ðashConf, nil, false, chainDb) 2159 if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 2160 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 2161 } 2162 cache := &core.CacheConfig{ 2163 TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, 2164 TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), 2165 TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, 2166 TrieDirtyDisabled: ctx.String(GCModeFlag.Name) == "archive", 2167 TrieTimeLimit: ethconfig.Defaults.TrieTimeout, 2168 SnapshotLimit: ethconfig.Defaults.SnapshotCache, 2169 Preimages: ctx.Bool(CachePreimagesFlag.Name), 2170 } 2171 if cache.TrieDirtyDisabled && !cache.Preimages { 2172 cache.Preimages = true 2173 log.Info("Enabling recording of key preimages since archive mode is used") 2174 } 2175 if !ctx.Bool(SnapshotFlag.Name) { 2176 cache.SnapshotLimit = 0 // Disabled 2177 } 2178 if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { 2179 cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 2180 } 2181 if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { 2182 cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 2183 } 2184 vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)} 2185 2186 // TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only. 2187 // Disable transaction indexing/unindexing by default. 2188 chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil) 2189 if err != nil { 2190 Fatalf("Can't create BlockChain: %v", err) 2191 } 2192 return chain, chainDb 2193 } 2194 2195 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 2196 // scripts to preload before starting. 2197 func MakeConsolePreloads(ctx *cli.Context) []string { 2198 // Skip preloading if there's nothing to preload 2199 if ctx.String(PreloadJSFlag.Name) == "" { 2200 return nil 2201 } 2202 // Otherwise resolve absolute paths and return them 2203 var preloads []string 2204 2205 for _, file := range strings.Split(ctx.String(PreloadJSFlag.Name), ",") { 2206 preloads = append(preloads, strings.TrimSpace(file)) 2207 } 2208 return preloads 2209 }