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