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