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