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