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