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