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