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