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