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