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