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