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