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