github.com/jincm/wesharechain@v0.0.0-20210122032815-1537409ce26a/chain/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 "encoding/json" 23 "fmt" 24 "io/ioutil" 25 "math/big" 26 "os" 27 "path/filepath" 28 "strconv" 29 "strings" 30 "time" 31 32 "github.com/ethereum/go-ethereum/accounts" 33 "github.com/ethereum/go-ethereum/accounts/keystore" 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/common/fdlimit" 36 "github.com/ethereum/go-ethereum/consensus" 37 "github.com/ethereum/go-ethereum/consensus/clique" 38 "github.com/ethereum/go-ethereum/consensus/ethash" 39 "github.com/ethereum/go-ethereum/core" 40 "github.com/ethereum/go-ethereum/core/state" 41 "github.com/ethereum/go-ethereum/core/vm" 42 "github.com/ethereum/go-ethereum/crypto" 43 "github.com/ethereum/go-ethereum/dashboard" 44 "github.com/ethereum/go-ethereum/eth" 45 "github.com/ethereum/go-ethereum/eth/downloader" 46 "github.com/ethereum/go-ethereum/eth/gasprice" 47 "github.com/ethereum/go-ethereum/ethdb" 48 "github.com/ethereum/go-ethereum/ethstats" 49 "github.com/ethereum/go-ethereum/les" 50 "github.com/ethereum/go-ethereum/log" 51 "github.com/ethereum/go-ethereum/metrics" 52 "github.com/ethereum/go-ethereum/metrics/influxdb" 53 "github.com/ethereum/go-ethereum/node" 54 "github.com/ethereum/go-ethereum/p2p" 55 "github.com/ethereum/go-ethereum/p2p/discv5" 56 "github.com/ethereum/go-ethereum/p2p/enode" 57 "github.com/ethereum/go-ethereum/p2p/nat" 58 "github.com/ethereum/go-ethereum/p2p/netutil" 59 "github.com/ethereum/go-ethereum/params" 60 whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" 61 cli "gopkg.in/urfave/cli.v1" 62 ) 63 64 var ( 65 CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...] 66 {{if .cmd.Description}}{{.cmd.Description}} 67 {{end}}{{if .cmd.Subcommands}} 68 SUBCOMMANDS: 69 {{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 70 {{end}}{{end}}{{if .categorizedFlags}} 71 {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS: 72 {{range $categorized.Flags}}{{"\t"}}{{.}} 73 {{end}} 74 {{end}}{{end}}` 75 ) 76 77 func init() { 78 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 79 80 VERSION: 81 {{.Version}} 82 83 COMMANDS: 84 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 85 {{end}}{{if .Flags}} 86 GLOBAL OPTIONS: 87 {{range .Flags}}{{.}} 88 {{end}}{{end}} 89 ` 90 91 cli.CommandHelpTemplate = CommandHelpTemplate 92 } 93 94 // NewApp creates an app with sane defaults. 95 func NewApp(gitCommit, usage string) *cli.App { 96 app := cli.NewApp() 97 app.Name = filepath.Base(os.Args[0]) 98 app.Author = "" 99 //app.Authors = nil 100 app.Email = "" 101 app.Version = params.VersionWithMeta 102 if len(gitCommit) >= 8 { 103 app.Version += "-" + gitCommit[:8] 104 } 105 app.Usage = usage 106 return app 107 } 108 109 // These are all the command line flags we support. 110 // If you add to this list, please remember to include the 111 // flag in the appropriate command definition. 112 // 113 // The flags are defined here so their names and help texts 114 // are the same for all commands. 115 116 var ( 117 // General settings 118 DataDirFlag = DirectoryFlag{ 119 Name: "datadir", 120 Usage: "Data directory for the databases and keystore", 121 Value: DirectoryString{node.DefaultDataDir()}, 122 } 123 KeyStoreDirFlag = DirectoryFlag{ 124 Name: "keystore", 125 Usage: "Directory for the keystore (default = inside the datadir)", 126 } 127 NoUSBFlag = cli.BoolFlag{ 128 Name: "nousb", 129 Usage: "Disables monitoring for and managing USB hardware wallets", 130 } 131 NetworkIdFlag = cli.Uint64Flag{ 132 Name: "networkid", 133 Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)", 134 Value: eth.DefaultConfig.NetworkId, 135 } 136 TestnetFlag = cli.BoolFlag{ 137 Name: "testnet", 138 Usage: "Ropsten network: pre-configured proof-of-work test network", 139 } 140 RinkebyFlag = cli.BoolFlag{ 141 Name: "rinkeby", 142 Usage: "Rinkeby network: pre-configured proof-of-authority test network", 143 } 144 GoerliFlag = cli.BoolFlag{ 145 Name: "goerli", 146 Usage: "Görli network: pre-configured proof-of-authority test network", 147 } 148 ConstantinopleOverrideFlag = cli.Uint64Flag{ 149 Name: "override.constantinople", 150 Usage: "Manually specify constantinople fork-block, overriding the bundled setting", 151 } 152 DeveloperFlag = cli.BoolFlag{ 153 Name: "dev", 154 Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", 155 } 156 DeveloperPeriodFlag = cli.IntFlag{ 157 Name: "dev.period", 158 Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", 159 } 160 IdentityFlag = cli.StringFlag{ 161 Name: "identity", 162 Usage: "Custom node name", 163 } 164 DocRootFlag = DirectoryFlag{ 165 Name: "docroot", 166 Usage: "Document Root for HTTPClient file scheme", 167 Value: DirectoryString{homeDir()}, 168 } 169 ExitWhenSyncedFlag = cli.BoolFlag{ 170 Name: "exitwhensynced", 171 Usage: "Exists syncing after block synchronisation", 172 } 173 ULCModeConfigFlag = cli.StringFlag{ 174 Name: "ulc.config", 175 Usage: "Config file to use for ultra light client mode", 176 } 177 OnlyAnnounceModeFlag = cli.BoolFlag{ 178 Name: "ulc.onlyannounce", 179 Usage: "ULC server sends announcements only", 180 } 181 ULCMinTrustedFractionFlag = cli.IntFlag{ 182 Name: "ulc.fraction", 183 Usage: "Minimum % of trusted ULC servers required to announce a new head", 184 } 185 ULCTrustedNodesFlag = cli.StringFlag{ 186 Name: "ulc.trusted", 187 Usage: "List of trusted ULC servers", 188 } 189 defaultSyncMode = eth.DefaultConfig.SyncMode 190 SyncModeFlag = TextMarshalerFlag{ 191 Name: "syncmode", 192 Usage: `Blockchain sync mode ("fast", "full", or "light")`, 193 Value: &defaultSyncMode, 194 } 195 GCModeFlag = cli.StringFlag{ 196 Name: "gcmode", 197 Usage: `Blockchain garbage collection mode ("full", "archive")`, 198 Value: "full", 199 } 200 LightServFlag = cli.IntFlag{ 201 Name: "lightserv", 202 Usage: "Maximum percentage of time allowed for serving LES requests (multi-threaded processing allows values over 100)", 203 Value: 0, 204 } 205 LightBandwidthInFlag = cli.IntFlag{ 206 Name: "lightbwin", 207 Usage: "Incoming bandwidth limit for light server (1000 bytes/sec, 0 = unlimited)", 208 Value: 1000, 209 } 210 LightBandwidthOutFlag = cli.IntFlag{ 211 Name: "lightbwout", 212 Usage: "Outgoing bandwidth limit for light server (1000 bytes/sec, 0 = unlimited)", 213 Value: 5000, 214 } 215 LightPeersFlag = cli.IntFlag{ 216 Name: "lightpeers", 217 Usage: "Maximum number of LES client peers", 218 Value: eth.DefaultConfig.LightPeers, 219 } 220 LightKDFFlag = cli.BoolFlag{ 221 Name: "lightkdf", 222 Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", 223 } 224 WhitelistFlag = cli.StringFlag{ 225 Name: "whitelist", 226 Usage: "Comma separated block number-to-hash mappings to enforce (<number>=<hash>)", 227 } 228 // Dashboard settings 229 DashboardEnabledFlag = cli.BoolFlag{ 230 Name: metrics.DashboardEnabledFlag, 231 Usage: "Enable the dashboard", 232 } 233 DashboardAddrFlag = cli.StringFlag{ 234 Name: "dashboard.addr", 235 Usage: "Dashboard listening interface", 236 Value: dashboard.DefaultConfig.Host, 237 } 238 DashboardPortFlag = cli.IntFlag{ 239 Name: "dashboard.host", 240 Usage: "Dashboard listening port", 241 Value: dashboard.DefaultConfig.Port, 242 } 243 DashboardRefreshFlag = cli.DurationFlag{ 244 Name: "dashboard.refresh", 245 Usage: "Dashboard metrics collection refresh rate", 246 Value: dashboard.DefaultConfig.Refresh, 247 } 248 // Ethash settings 249 EthashCacheDirFlag = DirectoryFlag{ 250 Name: "ethash.cachedir", 251 Usage: "Directory to store the ethash verification caches (default = inside the datadir)", 252 } 253 EthashCachesInMemoryFlag = cli.IntFlag{ 254 Name: "ethash.cachesinmem", 255 Usage: "Number of recent ethash caches to keep in memory (16MB each)", 256 Value: eth.DefaultConfig.Ethash.CachesInMem, 257 } 258 EthashCachesOnDiskFlag = cli.IntFlag{ 259 Name: "ethash.cachesondisk", 260 Usage: "Number of recent ethash caches to keep on disk (16MB each)", 261 Value: eth.DefaultConfig.Ethash.CachesOnDisk, 262 } 263 EthashDatasetDirFlag = DirectoryFlag{ 264 Name: "ethash.dagdir", 265 Usage: "Directory to store the ethash mining DAGs (default = inside home folder)", 266 Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir}, 267 } 268 EthashDatasetsInMemoryFlag = cli.IntFlag{ 269 Name: "ethash.dagsinmem", 270 Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)", 271 Value: eth.DefaultConfig.Ethash.DatasetsInMem, 272 } 273 EthashDatasetsOnDiskFlag = cli.IntFlag{ 274 Name: "ethash.dagsondisk", 275 Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)", 276 Value: eth.DefaultConfig.Ethash.DatasetsOnDisk, 277 } 278 // Transaction pool settings 279 TxPoolLocalsFlag = cli.StringFlag{ 280 Name: "txpool.locals", 281 Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", 282 } 283 TxPoolNoLocalsFlag = cli.BoolFlag{ 284 Name: "txpool.nolocals", 285 Usage: "Disables price exemptions for locally submitted transactions", 286 } 287 TxPoolJournalFlag = cli.StringFlag{ 288 Name: "txpool.journal", 289 Usage: "Disk journal for local transaction to survive node restarts", 290 Value: core.DefaultTxPoolConfig.Journal, 291 } 292 TxPoolRejournalFlag = cli.DurationFlag{ 293 Name: "txpool.rejournal", 294 Usage: "Time interval to regenerate the local transaction journal", 295 Value: core.DefaultTxPoolConfig.Rejournal, 296 } 297 TxPoolPriceLimitFlag = cli.Uint64Flag{ 298 Name: "txpool.pricelimit", 299 Usage: "Minimum gas price limit to enforce for acceptance into the pool", 300 Value: eth.DefaultConfig.TxPool.PriceLimit, 301 } 302 TxPoolPriceBumpFlag = cli.Uint64Flag{ 303 Name: "txpool.pricebump", 304 Usage: "Price bump percentage to replace an already existing transaction", 305 Value: eth.DefaultConfig.TxPool.PriceBump, 306 } 307 TxPoolAccountSlotsFlag = cli.Uint64Flag{ 308 Name: "txpool.accountslots", 309 Usage: "Minimum number of executable transaction slots guaranteed per account", 310 Value: eth.DefaultConfig.TxPool.AccountSlots, 311 } 312 TxPoolGlobalSlotsFlag = cli.Uint64Flag{ 313 Name: "txpool.globalslots", 314 Usage: "Maximum number of executable transaction slots for all accounts", 315 Value: eth.DefaultConfig.TxPool.GlobalSlots, 316 } 317 TxPoolAccountQueueFlag = cli.Uint64Flag{ 318 Name: "txpool.accountqueue", 319 Usage: "Maximum number of non-executable transaction slots permitted per account", 320 Value: eth.DefaultConfig.TxPool.AccountQueue, 321 } 322 TxPoolGlobalQueueFlag = cli.Uint64Flag{ 323 Name: "txpool.globalqueue", 324 Usage: "Maximum number of non-executable transaction slots for all accounts", 325 Value: eth.DefaultConfig.TxPool.GlobalQueue, 326 } 327 TxPoolLifetimeFlag = cli.DurationFlag{ 328 Name: "txpool.lifetime", 329 Usage: "Maximum amount of time non-executable transaction are queued", 330 Value: eth.DefaultConfig.TxPool.Lifetime, 331 } 332 // Performance tuning settings 333 CacheFlag = cli.IntFlag{ 334 Name: "cache", 335 Usage: "Megabytes of memory allocated to internal caching", 336 Value: 1024, 337 } 338 CacheDatabaseFlag = cli.IntFlag{ 339 Name: "cache.database", 340 Usage: "Percentage of cache memory allowance to use for database io", 341 Value: 50, 342 } 343 CacheTrieFlag = cli.IntFlag{ 344 Name: "cache.trie", 345 Usage: "Percentage of cache memory allowance to use for trie caching (default = 25% full mode, 50% archive mode)", 346 Value: 25, 347 } 348 CacheGCFlag = cli.IntFlag{ 349 Name: "cache.gc", 350 Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)", 351 Value: 25, 352 } 353 TrieCacheGenFlag = cli.IntFlag{ 354 Name: "trie-cache-gens", 355 Usage: "Number of trie node generations to keep in memory", 356 Value: int(state.MaxTrieCacheGen), 357 } 358 // Miner settings 359 MiningEnabledFlag = cli.BoolFlag{ 360 Name: "mine", 361 Usage: "Enable mining", 362 } 363 MinerThreadsFlag = cli.IntFlag{ 364 Name: "miner.threads", 365 Usage: "Number of CPU threads to use for mining", 366 Value: 0, 367 } 368 MinerLegacyThreadsFlag = cli.IntFlag{ 369 Name: "minerthreads", 370 Usage: "Number of CPU threads to use for mining (deprecated, use --miner.threads)", 371 Value: 0, 372 } 373 MinerNotifyFlag = cli.StringFlag{ 374 Name: "miner.notify", 375 Usage: "Comma separated HTTP URL list to notify of new work packages", 376 } 377 MinerGasTargetFlag = cli.Uint64Flag{ 378 Name: "miner.gastarget", 379 Usage: "Target gas floor for mined blocks", 380 Value: eth.DefaultConfig.MinerGasFloor, 381 } 382 MinerLegacyGasTargetFlag = cli.Uint64Flag{ 383 Name: "targetgaslimit", 384 Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)", 385 Value: eth.DefaultConfig.MinerGasFloor, 386 } 387 MinerGasLimitFlag = cli.Uint64Flag{ 388 Name: "miner.gaslimit", 389 Usage: "Target gas ceiling for mined blocks", 390 Value: eth.DefaultConfig.MinerGasCeil, 391 } 392 MinerGasPriceFlag = BigFlag{ 393 Name: "miner.gasprice", 394 Usage: "Minimum gas price for mining a transaction", 395 Value: eth.DefaultConfig.MinerGasPrice, 396 } 397 MinerLegacyGasPriceFlag = BigFlag{ 398 Name: "gasprice", 399 Usage: "Minimum gas price for mining a transaction (deprecated, use --miner.gasprice)", 400 Value: eth.DefaultConfig.MinerGasPrice, 401 } 402 MinerEtherbaseFlag = cli.StringFlag{ 403 Name: "miner.etherbase", 404 Usage: "Public address for block mining rewards (default = first account)", 405 Value: "0", 406 } 407 MinerLegacyEtherbaseFlag = cli.StringFlag{ 408 Name: "etherbase", 409 Usage: "Public address for block mining rewards (default = first account, deprecated, use --miner.etherbase)", 410 Value: "0", 411 } 412 MinerExtraDataFlag = cli.StringFlag{ 413 Name: "miner.extradata", 414 Usage: "Block extra data set by the miner (default = client version)", 415 } 416 MinerLegacyExtraDataFlag = cli.StringFlag{ 417 Name: "extradata", 418 Usage: "Block extra data set by the miner (default = client version, deprecated, use --miner.extradata)", 419 } 420 MinerRecommitIntervalFlag = cli.DurationFlag{ 421 Name: "miner.recommit", 422 Usage: "Time interval to recreate the block being mined", 423 Value: eth.DefaultConfig.MinerRecommit, 424 } 425 MinerNoVerfiyFlag = cli.BoolFlag{ 426 Name: "miner.noverify", 427 Usage: "Disable remote sealing verification", 428 } 429 // Account settings 430 UnlockedAccountFlag = cli.StringFlag{ 431 Name: "unlock", 432 Usage: "Comma separated list of accounts to unlock", 433 Value: "", 434 } 435 PasswordFileFlag = cli.StringFlag{ 436 Name: "password", 437 Usage: "Password file to use for non-interactive password input", 438 Value: "", 439 } 440 ExternalSignerFlag = cli.StringFlag{ 441 Name: "signer", 442 Usage: "External signer (url or path to ipc file)", 443 Value: "", 444 } 445 VMEnableDebugFlag = cli.BoolFlag{ 446 Name: "vmdebug", 447 Usage: "Record information useful for VM and contract debugging", 448 } 449 // Logging and debug settings 450 EthStatsURLFlag = cli.StringFlag{ 451 Name: "ethstats", 452 Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", 453 } 454 FakePoWFlag = cli.BoolFlag{ 455 Name: "fakepow", 456 Usage: "Disables proof-of-work verification", 457 } 458 NoCompactionFlag = cli.BoolFlag{ 459 Name: "nocompaction", 460 Usage: "Disables db compaction after import", 461 } 462 // RPC settings 463 RPCEnabledFlag = cli.BoolFlag{ 464 Name: "rpc", 465 Usage: "Enable the HTTP-RPC server", 466 } 467 RPCListenAddrFlag = cli.StringFlag{ 468 Name: "rpcaddr", 469 Usage: "HTTP-RPC server listening interface", 470 Value: node.DefaultHTTPHost, 471 } 472 RPCPortFlag = cli.IntFlag{ 473 Name: "rpcport", 474 Usage: "HTTP-RPC server listening port", 475 Value: node.DefaultHTTPPort, 476 } 477 GraphQLEnabledFlag = cli.BoolFlag{ 478 Name: "graphql", 479 Usage: "Enable the GraphQL server", 480 } 481 GraphQLListenAddrFlag = cli.StringFlag{ 482 Name: "graphql.addr", 483 Usage: "GraphQL server listening interface", 484 Value: node.DefaultGraphQLHost, 485 } 486 GraphQLPortFlag = cli.IntFlag{ 487 Name: "graphql.port", 488 Usage: "GraphQL server listening port", 489 Value: node.DefaultGraphQLPort, 490 } 491 GraphQLCORSDomainFlag = cli.StringFlag{ 492 Name: "graphql.rpccorsdomain", 493 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 494 Value: "", 495 } 496 GraphQLVirtualHostsFlag = cli.StringFlag{ 497 Name: "graphql.rpcvhosts", 498 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 499 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 500 } 501 RPCCORSDomainFlag = cli.StringFlag{ 502 Name: "rpccorsdomain", 503 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 504 Value: "", 505 } 506 RPCVirtualHostsFlag = cli.StringFlag{ 507 Name: "rpcvhosts", 508 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 509 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 510 } 511 RPCApiFlag = cli.StringFlag{ 512 Name: "rpcapi", 513 Usage: "API's offered over the HTTP-RPC interface", 514 Value: "", 515 } 516 IPCDisabledFlag = cli.BoolFlag{ 517 Name: "ipcdisable", 518 Usage: "Disable the IPC-RPC server", 519 } 520 IPCPathFlag = DirectoryFlag{ 521 Name: "ipcpath", 522 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 523 } 524 WSEnabledFlag = cli.BoolFlag{ 525 Name: "ws", 526 Usage: "Enable the WS-RPC server", 527 } 528 WSListenAddrFlag = cli.StringFlag{ 529 Name: "wsaddr", 530 Usage: "WS-RPC server listening interface", 531 Value: node.DefaultWSHost, 532 } 533 WSPortFlag = cli.IntFlag{ 534 Name: "wsport", 535 Usage: "WS-RPC server listening port", 536 Value: node.DefaultWSPort, 537 } 538 WSApiFlag = cli.StringFlag{ 539 Name: "wsapi", 540 Usage: "API's offered over the WS-RPC interface", 541 Value: "", 542 } 543 WSAllowedOriginsFlag = cli.StringFlag{ 544 Name: "wsorigins", 545 Usage: "Origins from which to accept websockets requests", 546 Value: "", 547 } 548 ExecFlag = cli.StringFlag{ 549 Name: "exec", 550 Usage: "Execute JavaScript statement", 551 } 552 PreloadJSFlag = cli.StringFlag{ 553 Name: "preload", 554 Usage: "Comma separated list of JavaScript files to preload into the console", 555 } 556 557 // Network Settings 558 MaxPeersFlag = cli.IntFlag{ 559 Name: "maxpeers", 560 Usage: "Maximum number of network peers (network disabled if set to 0)", 561 Value: 25, 562 } 563 MaxPendingPeersFlag = cli.IntFlag{ 564 Name: "maxpendpeers", 565 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 566 Value: 0, 567 } 568 ListenPortFlag = cli.IntFlag{ 569 Name: "port", 570 Usage: "Network listening port", 571 Value: 30303, 572 } 573 BootnodesFlag = cli.StringFlag{ 574 Name: "bootnodes", 575 Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)", 576 Value: "", 577 } 578 BootnodesV4Flag = cli.StringFlag{ 579 Name: "bootnodesv4", 580 Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)", 581 Value: "", 582 } 583 BootnodesV5Flag = cli.StringFlag{ 584 Name: "bootnodesv5", 585 Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)", 586 Value: "", 587 } 588 NodeKeyFileFlag = cli.StringFlag{ 589 Name: "nodekey", 590 Usage: "P2P node key file", 591 } 592 NodeKeyHexFlag = cli.StringFlag{ 593 Name: "nodekeyhex", 594 Usage: "P2P node key as hex (for testing)", 595 } 596 NATFlag = cli.StringFlag{ 597 Name: "nat", 598 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 599 Value: "any", 600 } 601 NoDiscoverFlag = cli.BoolFlag{ 602 Name: "nodiscover", 603 Usage: "Disables the peer discovery mechanism (manual peer addition)", 604 } 605 DiscoveryV5Flag = cli.BoolFlag{ 606 Name: "v5disc", 607 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 608 } 609 NetrestrictFlag = cli.StringFlag{ 610 Name: "netrestrict", 611 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 612 } 613 614 // ATM the url is left to the user and deployment to 615 JSpathFlag = cli.StringFlag{ 616 Name: "jspath", 617 Usage: "JavaScript root path for `loadScript`", 618 Value: ".", 619 } 620 621 // Gas price oracle settings 622 GpoBlocksFlag = cli.IntFlag{ 623 Name: "gpoblocks", 624 Usage: "Number of recent blocks to check for gas prices", 625 Value: eth.DefaultConfig.GPO.Blocks, 626 } 627 GpoPercentileFlag = cli.IntFlag{ 628 Name: "gpopercentile", 629 Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", 630 Value: eth.DefaultConfig.GPO.Percentile, 631 } 632 WhisperEnabledFlag = cli.BoolFlag{ 633 Name: "shh", 634 Usage: "Enable Whisper", 635 } 636 WhisperMaxMessageSizeFlag = cli.IntFlag{ 637 Name: "shh.maxmessagesize", 638 Usage: "Max message size accepted", 639 Value: int(whisper.DefaultMaxMessageSize), 640 } 641 WhisperMinPOWFlag = cli.Float64Flag{ 642 Name: "shh.pow", 643 Usage: "Minimum POW accepted", 644 Value: whisper.DefaultMinimumPoW, 645 } 646 WhisperRestrictConnectionBetweenLightClientsFlag = cli.BoolFlag{ 647 Name: "shh.restrict-light", 648 Usage: "Restrict connection between two whisper light clients", 649 } 650 651 // Metrics flags 652 MetricsEnabledFlag = cli.BoolFlag{ 653 Name: metrics.MetricsEnabledFlag, 654 Usage: "Enable metrics collection and reporting", 655 } 656 MetricsEnableInfluxDBFlag = cli.BoolFlag{ 657 Name: "metrics.influxdb", 658 Usage: "Enable metrics export/push to an external InfluxDB database", 659 } 660 MetricsInfluxDBEndpointFlag = cli.StringFlag{ 661 Name: "metrics.influxdb.endpoint", 662 Usage: "InfluxDB API endpoint to report metrics to", 663 Value: "http://localhost:8086", 664 } 665 MetricsInfluxDBDatabaseFlag = cli.StringFlag{ 666 Name: "metrics.influxdb.database", 667 Usage: "InfluxDB database name to push reported metrics to", 668 Value: "geth", 669 } 670 MetricsInfluxDBUsernameFlag = cli.StringFlag{ 671 Name: "metrics.influxdb.username", 672 Usage: "Username to authorize access to the database", 673 Value: "test", 674 } 675 MetricsInfluxDBPasswordFlag = cli.StringFlag{ 676 Name: "metrics.influxdb.password", 677 Usage: "Password to authorize access to the database", 678 Value: "test", 679 } 680 // Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB. 681 // For example `host` tag could be used so that we can group all nodes and average a measurement 682 // across all of them, but also so that we can select a specific node and inspect its measurements. 683 // https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key 684 MetricsInfluxDBTagsFlag = cli.StringFlag{ 685 Name: "metrics.influxdb.tags", 686 Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", 687 Value: "host=localhost", 688 } 689 690 EWASMInterpreterFlag = cli.StringFlag{ 691 Name: "vm.ewasm", 692 Usage: "External ewasm configuration (default = built-in interpreter)", 693 Value: "", 694 } 695 EVMInterpreterFlag = cli.StringFlag{ 696 Name: "vm.evm", 697 Usage: "External EVM configuration (default = built-in interpreter)", 698 Value: "", 699 } 700 ) 701 702 // MakeDataDir retrieves the currently requested data directory, terminating 703 // if none (or the empty string) is specified. If the node is starting a testnet, 704 // the a subdirectory of the specified datadir will be used. 705 func MakeDataDir(ctx *cli.Context) string { 706 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 707 if ctx.GlobalBool(TestnetFlag.Name) { 708 return filepath.Join(path, "testnet") 709 } 710 if ctx.GlobalBool(RinkebyFlag.Name) { 711 return filepath.Join(path, "rinkeby") 712 } 713 if ctx.GlobalBool(GoerliFlag.Name) { 714 return filepath.Join(path, "goerli") 715 } 716 return path 717 } 718 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 719 return "" 720 } 721 722 // setNodeKey creates a node key from set command line flags, either loading it 723 // from a file or as a specified hex value. If neither flags were provided, this 724 // method returns nil and an emphemeral key is to be generated. 725 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 726 var ( 727 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 728 file = ctx.GlobalString(NodeKeyFileFlag.Name) 729 key *ecdsa.PrivateKey 730 err error 731 ) 732 switch { 733 case file != "" && hex != "": 734 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 735 case file != "": 736 if key, err = crypto.LoadECDSA(file); err != nil { 737 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 738 } 739 cfg.PrivateKey = key 740 case hex != "": 741 if key, err = crypto.HexToECDSA(hex); err != nil { 742 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 743 } 744 cfg.PrivateKey = key 745 } 746 } 747 748 // setNodeUserIdent creates the user identifier from CLI flags. 749 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 750 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 751 cfg.UserIdent = identity 752 } 753 } 754 755 // setBootstrapNodes creates a list of bootstrap nodes from the command line 756 // flags, reverting to pre-configured ones if none have been specified. 757 func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { 758 urls := params.MainnetBootnodes 759 switch { 760 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name): 761 if ctx.GlobalIsSet(BootnodesV4Flag.Name) { 762 urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",") 763 } else { 764 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 765 } 766 case ctx.GlobalBool(TestnetFlag.Name): 767 urls = params.TestnetBootnodes 768 case ctx.GlobalBool(RinkebyFlag.Name): 769 urls = params.RinkebyBootnodes 770 case ctx.GlobalBool(GoerliFlag.Name): 771 urls = params.GoerliBootnodes 772 case cfg.BootstrapNodes != nil: 773 return // already set, don't apply defaults. 774 } 775 776 cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls)) 777 for _, url := range urls { 778 if url != "" { 779 node, err := enode.ParseV4(url) 780 if err != nil { 781 log.Crit("Bootstrap URL invalid", "enode", url, "err", err) 782 } 783 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 784 } 785 } 786 } 787 788 // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line 789 // flags, reverting to pre-configured ones if none have been specified. 790 func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { 791 urls := params.DiscoveryV5Bootnodes 792 switch { 793 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name): 794 if ctx.GlobalIsSet(BootnodesV5Flag.Name) { 795 urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",") 796 } else { 797 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 798 } 799 case ctx.GlobalBool(RinkebyFlag.Name): 800 urls = params.RinkebyBootnodes 801 case ctx.GlobalBool(GoerliFlag.Name): 802 urls = params.GoerliBootnodes 803 case cfg.BootstrapNodesV5 != nil: 804 return // already set, don't apply defaults. 805 } 806 807 cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls)) 808 for _, url := range urls { 809 node, err := discv5.ParseNode(url) 810 if err != nil { 811 log.Error("Bootstrap URL invalid", "enode", url, "err", err) 812 continue 813 } 814 cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) 815 } 816 } 817 818 // setListenAddress creates a TCP listening address string from set command 819 // line flags. 820 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 821 if ctx.GlobalIsSet(ListenPortFlag.Name) { 822 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 823 } 824 } 825 826 // setNAT creates a port mapper from command line flags. 827 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 828 if ctx.GlobalIsSet(NATFlag.Name) { 829 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 830 if err != nil { 831 Fatalf("Option %s: %v", NATFlag.Name, err) 832 } 833 cfg.NAT = natif 834 } 835 } 836 837 // splitAndTrim splits input separated by a comma 838 // and trims excessive white space from the substrings. 839 func splitAndTrim(input string) []string { 840 result := strings.Split(input, ",") 841 for i, r := range result { 842 result[i] = strings.TrimSpace(r) 843 } 844 return result 845 } 846 847 // setHTTP creates the HTTP RPC listener interface string from the set 848 // command line flags, returning empty if the HTTP endpoint is disabled. 849 func setHTTP(ctx *cli.Context, cfg *node.Config) { 850 if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { 851 cfg.HTTPHost = "127.0.0.1" 852 if ctx.GlobalIsSet(RPCListenAddrFlag.Name) { 853 cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name) 854 } 855 } 856 857 if ctx.GlobalIsSet(RPCPortFlag.Name) { 858 cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) 859 } 860 if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { 861 cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name)) 862 } 863 if ctx.GlobalIsSet(RPCApiFlag.Name) { 864 cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name)) 865 } 866 if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) { 867 cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name)) 868 } 869 } 870 871 // setGraphQL creates the GraphQL listener interface string from the set 872 // command line flags, returning empty if the GraphQL endpoint is disabled. 873 func setGraphQL(ctx *cli.Context, cfg *node.Config) { 874 if ctx.GlobalBool(GraphQLEnabledFlag.Name) && cfg.GraphQLHost == "" { 875 cfg.GraphQLHost = "127.0.0.1" 876 if ctx.GlobalIsSet(GraphQLListenAddrFlag.Name) { 877 cfg.GraphQLHost = ctx.GlobalString(GraphQLListenAddrFlag.Name) 878 } 879 } 880 cfg.GraphQLPort = ctx.GlobalInt(GraphQLPortFlag.Name) 881 if ctx.GlobalIsSet(GraphQLCORSDomainFlag.Name) { 882 cfg.GraphQLCors = splitAndTrim(ctx.GlobalString(GraphQLCORSDomainFlag.Name)) 883 } 884 if ctx.GlobalIsSet(GraphQLVirtualHostsFlag.Name) { 885 cfg.GraphQLVirtualHosts = splitAndTrim(ctx.GlobalString(GraphQLVirtualHostsFlag.Name)) 886 } 887 } 888 889 // setWS creates the WebSocket RPC listener interface string from the set 890 // command line flags, returning empty if the HTTP endpoint is disabled. 891 func setWS(ctx *cli.Context, cfg *node.Config) { 892 if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { 893 cfg.WSHost = "127.0.0.1" 894 if ctx.GlobalIsSet(WSListenAddrFlag.Name) { 895 cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) 896 } 897 } 898 899 if ctx.GlobalIsSet(WSPortFlag.Name) { 900 cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) 901 } 902 if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { 903 cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) 904 } 905 if ctx.GlobalIsSet(WSApiFlag.Name) { 906 cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name)) 907 } 908 } 909 910 // setIPC creates an IPC path configuration from the set command line flags, 911 // returning an empty string if IPC was explicitly disabled, or the set path. 912 func setIPC(ctx *cli.Context, cfg *node.Config) { 913 checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 914 switch { 915 case ctx.GlobalBool(IPCDisabledFlag.Name): 916 cfg.IPCPath = "" 917 case ctx.GlobalIsSet(IPCPathFlag.Name): 918 cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) 919 } 920 } 921 922 // SetULC setup ULC config from file if given. 923 func SetULC(ctx *cli.Context, cfg *eth.Config) { 924 // ULC config isn't loaded from global config and ULC config and ULC trusted nodes are not defined. 925 if cfg.ULC == nil && !(ctx.GlobalIsSet(ULCModeConfigFlag.Name) || ctx.GlobalIsSet(ULCTrustedNodesFlag.Name)) { 926 return 927 } 928 cfg.ULC = ð.ULCConfig{} 929 930 path := ctx.GlobalString(ULCModeConfigFlag.Name) 931 if path != "" { 932 cfgData, err := ioutil.ReadFile(path) 933 if err != nil { 934 Fatalf("Failed to unmarshal ULC configuration: %v", err) 935 } 936 937 err = json.Unmarshal(cfgData, &cfg.ULC) 938 if err != nil { 939 Fatalf("Failed to unmarshal ULC configuration: %s", err.Error()) 940 } 941 } 942 943 if trustedNodes := ctx.GlobalString(ULCTrustedNodesFlag.Name); trustedNodes != "" { 944 cfg.ULC.TrustedServers = strings.Split(trustedNodes, ",") 945 } 946 947 if trustedFraction := ctx.GlobalInt(ULCMinTrustedFractionFlag.Name); trustedFraction > 0 { 948 cfg.ULC.MinTrustedFraction = trustedFraction 949 } 950 if cfg.ULC.MinTrustedFraction <= 0 && cfg.ULC.MinTrustedFraction > 100 { 951 log.Error("MinTrustedFraction is invalid", "MinTrustedFraction", cfg.ULC.MinTrustedFraction, "Changed to default", eth.DefaultULCMinTrustedFraction) 952 cfg.ULC.MinTrustedFraction = eth.DefaultULCMinTrustedFraction 953 } 954 } 955 956 // makeDatabaseHandles raises out the number of allowed file handles per process 957 // for Geth and returns half of the allowance to assign to the database. 958 func makeDatabaseHandles() int { 959 limit, err := fdlimit.Maximum() 960 if err != nil { 961 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 962 } 963 raised, err := fdlimit.Raise(uint64(limit)) 964 if err != nil { 965 Fatalf("Failed to raise file descriptor allowance: %v", err) 966 } 967 return int(raised / 2) // Leave half for networking and other stuff 968 } 969 970 // MakeAddress converts an account specified directly as a hex encoded string or 971 // a key index in the key store to an internal account representation. 972 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 973 // If the specified account is a valid address, return it 974 if common.IsHexAddress(account) { 975 return accounts.Account{Address: common.HexToAddress(account)}, nil 976 } 977 // Otherwise try to interpret the account as a keystore index 978 index, err := strconv.Atoi(account) 979 if err != nil || index < 0 { 980 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 981 } 982 log.Warn("-------------------------------------------------------------------") 983 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 984 log.Warn("This functionality is deprecated and will be removed in the future!") 985 log.Warn("Please use explicit addresses! (can search via `geth account list`)") 986 log.Warn("-------------------------------------------------------------------") 987 988 accs := ks.Accounts() 989 if len(accs) <= index { 990 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 991 } 992 return accs[index], nil 993 } 994 995 // setEtherbase retrieves the etherbase either from the directly specified 996 // command line flags or from the keystore if CLI indexed. 997 func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) { 998 // Extract the current etherbase, new flag overriding legacy one 999 var etherbase string 1000 if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) { 1001 etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name) 1002 } 1003 if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) { 1004 etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name) 1005 } 1006 // Convert the etherbase into an address and configure it 1007 if etherbase != "" { 1008 if ks != nil { 1009 account, err := MakeAddress(ks, etherbase) 1010 if err != nil { 1011 Fatalf("Invalid miner etherbase: %v", err) 1012 } 1013 cfg.Etherbase = account.Address 1014 } else { 1015 Fatalf("No etherbase configured") 1016 } 1017 } 1018 } 1019 1020 // MakePasswordList reads password lines from the file specified by the global --password flag. 1021 func MakePasswordList(ctx *cli.Context) []string { 1022 path := ctx.GlobalString(PasswordFileFlag.Name) 1023 if path == "" { 1024 return nil 1025 } 1026 text, err := ioutil.ReadFile(path) 1027 if err != nil { 1028 Fatalf("Failed to read password file: %v", err) 1029 } 1030 lines := strings.Split(string(text), "\n") 1031 // Sanitise DOS line endings. 1032 for i := range lines { 1033 lines[i] = strings.TrimRight(lines[i], "\r") 1034 } 1035 return lines 1036 } 1037 1038 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 1039 setNodeKey(ctx, cfg) 1040 setNAT(ctx, cfg) 1041 setListenAddress(ctx, cfg) 1042 setBootstrapNodes(ctx, cfg) 1043 setBootstrapNodesV5(ctx, cfg) 1044 1045 lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light" 1046 lightServer := ctx.GlobalInt(LightServFlag.Name) != 0 1047 lightPeers := ctx.GlobalInt(LightPeersFlag.Name) 1048 1049 if ctx.GlobalIsSet(MaxPeersFlag.Name) { 1050 cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) 1051 if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) { 1052 cfg.MaxPeers += lightPeers 1053 } 1054 } else { 1055 if lightServer { 1056 cfg.MaxPeers += lightPeers 1057 } 1058 if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers { 1059 cfg.MaxPeers = lightPeers 1060 } 1061 } 1062 if !(lightClient || lightServer) { 1063 lightPeers = 0 1064 } 1065 ethPeers := cfg.MaxPeers - lightPeers 1066 if lightClient { 1067 ethPeers = 0 1068 } 1069 log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers) 1070 1071 if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { 1072 cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) 1073 } 1074 if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { 1075 cfg.NoDiscovery = true 1076 } 1077 1078 // if we're running a light client or server, force enable the v5 peer discovery 1079 // unless it is explicitly disabled with --nodiscover note that explicitly specifying 1080 // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery 1081 forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) 1082 if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { 1083 cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) 1084 } else if forceV5Discovery { 1085 cfg.DiscoveryV5 = true 1086 } 1087 1088 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 1089 list, err := netutil.ParseNetlist(netrestrict) 1090 if err != nil { 1091 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 1092 } 1093 cfg.NetRestrict = list 1094 } 1095 1096 if ctx.GlobalBool(DeveloperFlag.Name) { 1097 // --dev mode can't use p2p networking. 1098 cfg.MaxPeers = 0 1099 cfg.ListenAddr = ":0" 1100 cfg.NoDiscovery = true 1101 cfg.DiscoveryV5 = false 1102 } 1103 } 1104 1105 // SetNodeConfig applies node-related command line flags to the config. 1106 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 1107 SetP2PConfig(ctx, &cfg.P2P) 1108 setIPC(ctx, cfg) 1109 setHTTP(ctx, cfg) 1110 setGraphQL(ctx, cfg) 1111 setWS(ctx, cfg) 1112 setNodeUserIdent(ctx, cfg) 1113 setDataDir(ctx, cfg) 1114 1115 if ctx.GlobalIsSet(ExternalSignerFlag.Name) { 1116 cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name) 1117 } 1118 1119 if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { 1120 cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) 1121 } 1122 if ctx.GlobalIsSet(LightKDFFlag.Name) { 1123 cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) 1124 } 1125 if ctx.GlobalIsSet(NoUSBFlag.Name) { 1126 cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name) 1127 } 1128 } 1129 1130 func setDataDir(ctx *cli.Context, cfg *node.Config) { 1131 switch { 1132 case ctx.GlobalIsSet(DataDirFlag.Name): 1133 cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) 1134 case ctx.GlobalBool(DeveloperFlag.Name): 1135 cfg.DataDir = "" // unless explicitly requested, use memory databases 1136 case ctx.GlobalBool(TestnetFlag.Name): 1137 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet") 1138 case ctx.GlobalBool(RinkebyFlag.Name): 1139 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby") 1140 case ctx.GlobalBool(GoerliFlag.Name): 1141 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli") 1142 } 1143 } 1144 1145 func setGPO(ctx *cli.Context, cfg *gasprice.Config) { 1146 if ctx.GlobalIsSet(GpoBlocksFlag.Name) { 1147 cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) 1148 } 1149 if ctx.GlobalIsSet(GpoPercentileFlag.Name) { 1150 cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) 1151 } 1152 } 1153 1154 func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { 1155 if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) { 1156 locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",") 1157 for _, account := range locals { 1158 if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) { 1159 Fatalf("Invalid account in --txpool.locals: %s", trimmed) 1160 } else { 1161 cfg.Locals = append(cfg.Locals, common.HexToAddress(account)) 1162 } 1163 } 1164 } 1165 if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) { 1166 cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name) 1167 } 1168 if ctx.GlobalIsSet(TxPoolJournalFlag.Name) { 1169 cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name) 1170 } 1171 if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) { 1172 cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name) 1173 } 1174 if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) { 1175 cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name) 1176 } 1177 if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) { 1178 cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name) 1179 } 1180 if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) { 1181 cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name) 1182 } 1183 if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) { 1184 cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name) 1185 } 1186 if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) { 1187 cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name) 1188 } 1189 if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) { 1190 cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name) 1191 } 1192 if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) { 1193 cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name) 1194 } 1195 } 1196 1197 func setEthash(ctx *cli.Context, cfg *eth.Config) { 1198 if ctx.GlobalIsSet(EthashCacheDirFlag.Name) { 1199 cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name) 1200 } 1201 if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) { 1202 cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name) 1203 } 1204 if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) { 1205 cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name) 1206 } 1207 if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) { 1208 cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name) 1209 } 1210 if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) { 1211 cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name) 1212 } 1213 if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) { 1214 cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name) 1215 } 1216 } 1217 1218 func setWhitelist(ctx *cli.Context, cfg *eth.Config) { 1219 whitelist := ctx.GlobalString(WhitelistFlag.Name) 1220 if whitelist == "" { 1221 return 1222 } 1223 cfg.Whitelist = make(map[uint64]common.Hash) 1224 for _, entry := range strings.Split(whitelist, ",") { 1225 parts := strings.Split(entry, "=") 1226 if len(parts) != 2 { 1227 Fatalf("Invalid whitelist entry: %s", entry) 1228 } 1229 number, err := strconv.ParseUint(parts[0], 0, 64) 1230 if err != nil { 1231 Fatalf("Invalid whitelist block number %s: %v", parts[0], err) 1232 } 1233 var hash common.Hash 1234 if err = hash.UnmarshalText([]byte(parts[1])); err != nil { 1235 Fatalf("Invalid whitelist hash %s: %v", parts[1], err) 1236 } 1237 cfg.Whitelist[number] = hash 1238 } 1239 } 1240 1241 // checkExclusive verifies that only a single instance of the provided flags was 1242 // set by the user. Each flag might optionally be followed by a string type to 1243 // specialize it further. 1244 func checkExclusive(ctx *cli.Context, args ...interface{}) { 1245 set := make([]string, 0, 1) 1246 for i := 0; i < len(args); i++ { 1247 // Make sure the next argument is a flag and skip if not set 1248 flag, ok := args[i].(cli.Flag) 1249 if !ok { 1250 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 1251 } 1252 // Check if next arg extends current and expand its name if so 1253 name := flag.GetName() 1254 1255 if i+1 < len(args) { 1256 switch option := args[i+1].(type) { 1257 case string: 1258 // Extended flag check, make sure value set doesn't conflict with passed in option 1259 if ctx.GlobalString(flag.GetName()) == option { 1260 name += "=" + option 1261 set = append(set, "--"+name) 1262 } 1263 // shift arguments and continue 1264 i++ 1265 continue 1266 1267 case cli.Flag: 1268 default: 1269 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 1270 } 1271 } 1272 // Mark the flag if it's set 1273 if ctx.GlobalIsSet(flag.GetName()) { 1274 set = append(set, "--"+name) 1275 } 1276 } 1277 if len(set) > 1 { 1278 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 1279 } 1280 } 1281 1282 // SetShhConfig applies shh-related command line flags to the config. 1283 func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) { 1284 if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) { 1285 cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name)) 1286 } 1287 if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) { 1288 cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name) 1289 } 1290 if ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) { 1291 cfg.RestrictConnectionBetweenLightClients = true 1292 } 1293 } 1294 1295 // SetEthConfig applies eth-related command line flags to the config. 1296 func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { 1297 // Avoid conflicting network flags 1298 checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag, GoerliFlag) 1299 checkExclusive(ctx, LightServFlag, SyncModeFlag, "light") 1300 // Can't use both ephemeral unlocked and external signer 1301 checkExclusive(ctx, DeveloperFlag, ExternalSignerFlag) 1302 var ks *keystore.KeyStore 1303 if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { 1304 ks = keystores[0].(*keystore.KeyStore) 1305 } 1306 setEtherbase(ctx, ks, cfg) 1307 setGPO(ctx, &cfg.GPO) 1308 setTxPool(ctx, &cfg.TxPool) 1309 setEthash(ctx, cfg) 1310 setWhitelist(ctx, cfg) 1311 1312 if ctx.GlobalIsSet(SyncModeFlag.Name) { 1313 cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 1314 } 1315 if ctx.GlobalIsSet(LightServFlag.Name) { 1316 cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) 1317 } 1318 cfg.LightBandwidthIn = ctx.GlobalInt(LightBandwidthInFlag.Name) 1319 cfg.LightBandwidthOut = ctx.GlobalInt(LightBandwidthOutFlag.Name) 1320 if ctx.GlobalIsSet(LightPeersFlag.Name) { 1321 cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) 1322 } 1323 if ctx.GlobalIsSet(OnlyAnnounceModeFlag.Name) { 1324 cfg.OnlyAnnounce = ctx.GlobalBool(OnlyAnnounceModeFlag.Name) 1325 } 1326 if ctx.GlobalIsSet(NetworkIdFlag.Name) { 1327 cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) 1328 } 1329 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { 1330 cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1331 } 1332 cfg.DatabaseHandles = makeDatabaseHandles() 1333 1334 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1335 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1336 } 1337 cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" 1338 1339 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { 1340 cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 1341 } 1342 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1343 cfg.TrieDirtyCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1344 } 1345 if ctx.GlobalIsSet(MinerNotifyFlag.Name) { 1346 cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",") 1347 } 1348 if ctx.GlobalIsSet(DocRootFlag.Name) { 1349 cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) 1350 } 1351 if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) { 1352 cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name)) 1353 } 1354 if ctx.GlobalIsSet(MinerExtraDataFlag.Name) { 1355 cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name)) 1356 } 1357 if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) { 1358 cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name) 1359 } 1360 if ctx.GlobalIsSet(MinerGasTargetFlag.Name) { 1361 cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name) 1362 } 1363 if ctx.GlobalIsSet(MinerGasLimitFlag.Name) { 1364 cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name) 1365 } 1366 if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { 1367 cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name) 1368 } 1369 if ctx.GlobalIsSet(MinerGasPriceFlag.Name) { 1370 cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name) 1371 } 1372 if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) { 1373 cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name) 1374 } 1375 if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) { 1376 cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name) 1377 } 1378 if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { 1379 // TODO(fjl): force-enable this in --dev mode 1380 cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) 1381 } 1382 1383 if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) { 1384 cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name) 1385 } 1386 1387 if ctx.GlobalIsSet(EVMInterpreterFlag.Name) { 1388 cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name) 1389 } 1390 1391 // Override any default configs for hard coded networks. 1392 switch { 1393 case ctx.GlobalBool(TestnetFlag.Name): 1394 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1395 cfg.NetworkId = 3 1396 } 1397 cfg.Genesis = core.DefaultTestnetGenesisBlock() 1398 case ctx.GlobalBool(RinkebyFlag.Name): 1399 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1400 cfg.NetworkId = 4 1401 } 1402 cfg.Genesis = core.DefaultRinkebyGenesisBlock() 1403 case ctx.GlobalBool(GoerliFlag.Name): 1404 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1405 cfg.NetworkId = 5 1406 } 1407 cfg.Genesis = core.DefaultGoerliGenesisBlock() 1408 case ctx.GlobalBool(DeveloperFlag.Name): 1409 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1410 cfg.NetworkId = 1337 1411 } 1412 // Create new developer account or reuse existing one 1413 var ( 1414 developer accounts.Account 1415 err error 1416 ) 1417 if accs := ks.Accounts(); len(accs) > 0 { 1418 developer = ks.Accounts()[0] 1419 } else { 1420 developer, err = ks.NewAccount("") 1421 if err != nil { 1422 Fatalf("Failed to create developer account: %v", err) 1423 } 1424 } 1425 if err := ks.Unlock(developer, ""); err != nil { 1426 Fatalf("Failed to unlock developer account: %v", err) 1427 } 1428 log.Info("Using developer account", "address", developer.Address) 1429 1430 cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address) 1431 if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { 1432 cfg.MinerGasPrice = big.NewInt(1) 1433 } 1434 } 1435 // TODO(fjl): move trie cache generations into config 1436 if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 { 1437 state.MaxTrieCacheGen = uint16(gen) 1438 } 1439 } 1440 1441 // SetDashboardConfig applies dashboard related command line flags to the config. 1442 func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) { 1443 cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name) 1444 cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name) 1445 cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name) 1446 } 1447 1448 // RegisterEthService adds an Ethereum client to the stack. 1449 func RegisterEthService(stack *node.Node, cfg *eth.Config) { 1450 var err error 1451 if cfg.SyncMode == downloader.LightSync { 1452 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1453 return les.New(ctx, cfg) 1454 }) 1455 } else { 1456 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1457 fullNode, err := eth.New(ctx, cfg) 1458 if fullNode != nil && cfg.LightServ > 0 { 1459 ls, _ := les.NewLesServer(fullNode, cfg) 1460 fullNode.AddLesServer(ls) 1461 } 1462 return fullNode, err 1463 }) 1464 } 1465 if err != nil { 1466 Fatalf("Failed to register the Ethereum service: %v", err) 1467 } 1468 } 1469 1470 // RegisterDashboardService adds a dashboard to the stack. 1471 func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) { 1472 stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1473 return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil 1474 }) 1475 } 1476 1477 // RegisterShhService configures Whisper and adds it to the given node. 1478 func RegisterShhService(stack *node.Node, cfg *whisper.Config) { 1479 if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) { 1480 return whisper.New(cfg), nil 1481 }); err != nil { 1482 Fatalf("Failed to register the Whisper service: %v", err) 1483 } 1484 } 1485 1486 // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to 1487 // the given node. 1488 func RegisterEthStatsService(stack *node.Node, url string) { 1489 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1490 // Retrieve both eth and les services 1491 var ethServ *eth.Ethereum 1492 ctx.Service(ðServ) 1493 1494 var lesServ *les.LightEthereum 1495 ctx.Service(&lesServ) 1496 1497 return ethstats.New(url, ethServ, lesServ) 1498 }); err != nil { 1499 Fatalf("Failed to register the Ethereum Stats service: %v", err) 1500 } 1501 } 1502 1503 func SetupMetrics(ctx *cli.Context) { 1504 if metrics.Enabled { 1505 log.Info("Enabling metrics collection") 1506 var ( 1507 enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name) 1508 endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name) 1509 database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name) 1510 username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name) 1511 password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name) 1512 ) 1513 1514 if enableExport { 1515 tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name)) 1516 1517 log.Info("Enabling metrics export to InfluxDB") 1518 1519 go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) 1520 } 1521 } 1522 } 1523 1524 func SplitTagsFlag(tagsFlag string) map[string]string { 1525 tags := strings.Split(tagsFlag, ",") 1526 tagsMap := map[string]string{} 1527 1528 for _, t := range tags { 1529 if t != "" { 1530 kv := strings.Split(t, "=") 1531 1532 if len(kv) == 2 { 1533 tagsMap[kv[0]] = kv[1] 1534 } 1535 } 1536 } 1537 1538 return tagsMap 1539 } 1540 1541 // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. 1542 func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { 1543 var ( 1544 cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1545 handles = makeDatabaseHandles() 1546 ) 1547 name := "chaindata" 1548 if ctx.GlobalString(SyncModeFlag.Name) == "light" { 1549 name = "lightchaindata" 1550 } 1551 chainDb, err := stack.OpenDatabase(name, cache, handles) 1552 if err != nil { 1553 Fatalf("Could not open database: %v", err) 1554 } 1555 return chainDb 1556 } 1557 1558 func MakeGenesis(ctx *cli.Context) *core.Genesis { 1559 var genesis *core.Genesis 1560 switch { 1561 case ctx.GlobalBool(TestnetFlag.Name): 1562 genesis = core.DefaultTestnetGenesisBlock() 1563 case ctx.GlobalBool(RinkebyFlag.Name): 1564 genesis = core.DefaultRinkebyGenesisBlock() 1565 case ctx.GlobalBool(GoerliFlag.Name): 1566 genesis = core.DefaultGoerliGenesisBlock() 1567 case ctx.GlobalBool(DeveloperFlag.Name): 1568 Fatalf("Developer chains are ephemeral") 1569 } 1570 return genesis 1571 } 1572 1573 // MakeChain creates a chain manager from set command line flags. 1574 func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { 1575 var err error 1576 chainDb = MakeChainDatabase(ctx, stack) 1577 config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) 1578 if err != nil { 1579 Fatalf("%v", err) 1580 } 1581 var engine consensus.Engine 1582 if config.Clique != nil { 1583 engine = clique.New(config.Clique, chainDb) 1584 } else { 1585 engine = ethash.NewFaker() 1586 if !ctx.GlobalBool(FakePoWFlag.Name) { 1587 engine = ethash.New(ethash.Config{ 1588 CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir), 1589 CachesInMem: eth.DefaultConfig.Ethash.CachesInMem, 1590 CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk, 1591 DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir), 1592 DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem, 1593 DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, 1594 }, nil, false) 1595 } 1596 } 1597 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1598 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1599 } 1600 cache := &core.CacheConfig{ 1601 Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive", 1602 TrieCleanLimit: eth.DefaultConfig.TrieCleanCache, 1603 TrieDirtyLimit: eth.DefaultConfig.TrieDirtyCache, 1604 TrieTimeLimit: eth.DefaultConfig.TrieTimeout, 1605 } 1606 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { 1607 cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 1608 } 1609 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1610 cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1611 } 1612 vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} 1613 chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil) 1614 if err != nil { 1615 Fatalf("Can't create BlockChain: %v", err) 1616 } 1617 return chain, chainDb 1618 } 1619 1620 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 1621 // scripts to preload before starting. 1622 func MakeConsolePreloads(ctx *cli.Context) []string { 1623 // Skip preloading if there's nothing to preload 1624 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 1625 return nil 1626 } 1627 // Otherwise resolve absolute paths and return them 1628 var preloads []string 1629 1630 assets := ctx.GlobalString(JSpathFlag.Name) 1631 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 1632 preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file))) 1633 } 1634 return preloads 1635 } 1636 1637 // MigrateFlags sets the global flag from a local flag when it's set. 1638 // This is a temporary function used for migrating old command/flags to the 1639 // new format. 1640 // 1641 // e.g. geth account new --keystore /tmp/mykeystore --lightkdf 1642 // 1643 // is equivalent after calling this method with: 1644 // 1645 // geth --keystore /tmp/mykeystore --lightkdf account new 1646 // 1647 // This allows the use of the existing configuration functionality. 1648 // When all flags are migrated this function can be removed and the existing 1649 // configuration functionality must be changed that is uses local flags 1650 func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { 1651 return func(ctx *cli.Context) error { 1652 for _, name := range ctx.FlagNames() { 1653 if ctx.IsSet(name) { 1654 ctx.GlobalSet(name, ctx.String(name)) 1655 } 1656 } 1657 return action(ctx) 1658 } 1659 }