github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/utils/flags.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:32</date> 10 //</624342607064993792> 11 12 13 //package utils包含用于go-ethereum命令的内部助手函数。 14 package utils 15 16 import ( 17 "crypto/ecdsa" 18 "fmt" 19 "io/ioutil" 20 "math/big" 21 "os" 22 "path/filepath" 23 "strconv" 24 "strings" 25 "time" 26 27 "github.com/ethereum/go-ethereum/accounts" 28 "github.com/ethereum/go-ethereum/accounts/keystore" 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/common/fdlimit" 31 //“github.com/ethereum/go-ethereum/consension”网站 32 //“github.com/ethereum/go-ethereum/consension/clique” 33 //“github.com/ethereum/go-ethereum/consultance/ethash” 34 "github.com/ethereum/go-ethereum/consensus/dpos" 35 "github.com/ethereum/go-ethereum/core" 36 "github.com/ethereum/go-ethereum/core/state" 37 "github.com/ethereum/go-ethereum/core/vm" 38 "github.com/ethereum/go-ethereum/crypto" 39 "github.com/ethereum/go-ethereum/dashboard" 40 "github.com/ethereum/go-ethereum/eth" 41 "github.com/ethereum/go-ethereum/eth/downloader" 42 "github.com/ethereum/go-ethereum/eth/gasprice" 43 "github.com/ethereum/go-ethereum/ethdb" 44 "github.com/ethereum/go-ethereum/ethstats" 45 "github.com/ethereum/go-ethereum/les" 46 "github.com/ethereum/go-ethereum/log" 47 "github.com/ethereum/go-ethereum/metrics" 48 "github.com/ethereum/go-ethereum/metrics/influxdb" 49 "github.com/ethereum/go-ethereum/node" 50 "github.com/ethereum/go-ethereum/p2p" 51 "github.com/ethereum/go-ethereum/p2p/discover" 52 "github.com/ethereum/go-ethereum/p2p/discv5" 53 "github.com/ethereum/go-ethereum/p2p/nat" 54 "github.com/ethereum/go-ethereum/p2p/netutil" 55 "github.com/ethereum/go-ethereum/params" 56 whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" 57 "gopkg.in/urfave/cli.v1" 58 ) 59 60 61 62 var ( 63 CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...] 64 {{if .cmd.Description}}{{.cmd.Description}} 65 {{end}}{{if .cmd.Subcommands}} 66 SUBCOMMANDS: 67 {{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 68 {{end}}{{end}}{{if .categorizedFlags}} 69 {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS: 70 {{range $categorized.Flags}}{{"\t"}}{{.}} 71 {{end}} 72 {{end}}{{end}}` 73 ) 74 75 func init() { 76 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 77 78 VERSION: 79 {{.Version}} 80 81 COMMANDS: 82 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 83 {{end}}{{if .Flags}} 84 GLOBAL OPTIONS: 85 {{range .Flags}}{{.}} 86 {{end}}{{end}} 87 ` 88 89 cli.CommandHelpTemplate = CommandHelpTemplate 90 } 91 92 //newapp创建具有健全默认值的应用程序。 93 func NewApp(gitCommit, usage string) *cli.App { 94 app := cli.NewApp() 95 app.Name = filepath.Base(os.Args[0]) 96 app.Author = "" 97 // 98 app.Email = "" 99 app.Version = params.VersionWithMeta 100 if len(gitCommit) >= 8 { 101 app.Version += "-" + gitCommit[:8] 102 } 103 app.Usage = usage 104 return app 105 } 106 107 //这些都是我们支持的命令行标志。 108 // 109 //在适当的命令定义中标记。 110 // 111 // 112 //所有命令都相同。 113 114 var ( 115 //常规设置 116 DataDirFlag = DirectoryFlag{ 117 Name: "datadir", 118 Usage: "Data directory for the databases and keystore", 119 Value: DirectoryString{node.DefaultDataDir()}, 120 } 121 KeyStoreDirFlag = DirectoryFlag{ 122 Name: "keystore", 123 Usage: "Directory for the keystore (default = inside the datadir)", 124 } 125 NoUSBFlag = cli.BoolFlag{ 126 Name: "nousb", 127 Usage: "Disables monitoring for and managing USB hardware wallets", 128 } 129 NetworkIdFlag = cli.Uint64Flag{ 130 Name: "networkid", 131 Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)", 132 Value: eth.DefaultConfig.NetworkId, 133 } 134 TestnetFlag = cli.BoolFlag{ 135 Name: "testnet", 136 Usage: "Ropsten network: pre-configured proof-of-work test network", 137 } 138 RinkebyFlag = cli.BoolFlag{ 139 Name: "rinkeby", 140 Usage: "Rinkeby network: pre-configured proof-of-authority test network", 141 } 142 DeveloperFlag = cli.BoolFlag{ 143 Name: "dev", 144 Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled", 145 } 146 DeveloperPeriodFlag = cli.IntFlag{ 147 Name: "dev.period", 148 Usage: "Block period to use in developer mode (0 = mine only if transaction pending)", 149 } 150 IdentityFlag = cli.StringFlag{ 151 Name: "identity", 152 Usage: "Custom node name", 153 } 154 DocRootFlag = DirectoryFlag{ 155 Name: "docroot", 156 Usage: "Document Root for HTTPClient file scheme", 157 Value: DirectoryString{homeDir()}, 158 } 159 defaultSyncMode = eth.DefaultConfig.SyncMode 160 SyncModeFlag = TextMarshalerFlag{ 161 Name: "syncmode", 162 Usage: `Blockchain sync mode ("fast", "full", or "light")`, 163 Value: &defaultSyncMode, 164 } 165 GCModeFlag = cli.StringFlag{ 166 Name: "gcmode", 167 Usage: `Blockchain garbage collection mode ("full", "archive")`, 168 Value: "full", 169 } 170 LightServFlag = cli.IntFlag{ 171 Name: "lightserv", 172 Usage: "Maximum percentage of time allowed for serving LES requests (0-90)", 173 Value: 0, 174 } 175 LightPeersFlag = cli.IntFlag{ 176 Name: "lightpeers", 177 Usage: "Maximum number of LES client peers", 178 Value: eth.DefaultConfig.LightPeers, 179 } 180 LightKDFFlag = cli.BoolFlag{ 181 Name: "lightkdf", 182 Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength", 183 } 184 //仪表板设置 185 DashboardEnabledFlag = cli.BoolFlag{ 186 Name: metrics.DashboardEnabledFlag, 187 Usage: "Enable the dashboard", 188 } 189 DashboardAddrFlag = cli.StringFlag{ 190 Name: "dashboard.addr", 191 Usage: "Dashboard listening interface", 192 Value: dashboard.DefaultConfig.Host, 193 } 194 DashboardPortFlag = cli.IntFlag{ 195 Name: "dashboard.host", 196 Usage: "Dashboard listening port", 197 Value: dashboard.DefaultConfig.Port, 198 } 199 DashboardRefreshFlag = cli.DurationFlag{ 200 Name: "dashboard.refresh", 201 Usage: "Dashboard metrics collection refresh rate", 202 Value: dashboard.DefaultConfig.Refresh, 203 } 204 //乙烯利设置 205 EthashCacheDirFlag = DirectoryFlag{ 206 Name: "ethash.cachedir", 207 Usage: "Directory to store the ethash verification caches (default = inside the datadir)", 208 } 209 EthashCachesInMemoryFlag = cli.IntFlag{ 210 Name: "ethash.cachesinmem", 211 Usage: "Number of recent ethash caches to keep in memory (16MB each)", 212 Value: eth.DefaultConfig.Ethash.CachesInMem, 213 } 214 EthashCachesOnDiskFlag = cli.IntFlag{ 215 Name: "ethash.cachesondisk", 216 Usage: "Number of recent ethash caches to keep on disk (16MB each)", 217 Value: eth.DefaultConfig.Ethash.CachesOnDisk, 218 } 219 EthashDatasetDirFlag = DirectoryFlag{ 220 Name: "ethash.dagdir", 221 Usage: "Directory to store the ethash mining DAGs (default = inside home folder)", 222 Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir}, 223 } 224 EthashDatasetsInMemoryFlag = cli.IntFlag{ 225 Name: "ethash.dagsinmem", 226 Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)", 227 Value: eth.DefaultConfig.Ethash.DatasetsInMem, 228 } 229 EthashDatasetsOnDiskFlag = cli.IntFlag{ 230 Name: "ethash.dagsondisk", 231 Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)", 232 Value: eth.DefaultConfig.Ethash.DatasetsOnDisk, 233 } 234 // 235 TxPoolLocalsFlag = cli.StringFlag{ 236 Name: "txpool.locals", 237 Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)", 238 } 239 TxPoolNoLocalsFlag = cli.BoolFlag{ 240 Name: "txpool.nolocals", 241 Usage: "Disables price exemptions for locally submitted transactions", 242 } 243 TxPoolJournalFlag = cli.StringFlag{ 244 Name: "txpool.journal", 245 Usage: "Disk journal for local transaction to survive node restarts", 246 Value: core.DefaultTxPoolConfig.Journal, 247 } 248 TxPoolRejournalFlag = cli.DurationFlag{ 249 Name: "txpool.rejournal", 250 Usage: "Time interval to regenerate the local transaction journal", 251 Value: core.DefaultTxPoolConfig.Rejournal, 252 } 253 TxPoolPriceLimitFlag = cli.Uint64Flag{ 254 Name: "txpool.pricelimit", 255 Usage: "Minimum gas price limit to enforce for acceptance into the pool", 256 Value: eth.DefaultConfig.TxPool.PriceLimit, 257 } 258 TxPoolPriceBumpFlag = cli.Uint64Flag{ 259 Name: "txpool.pricebump", 260 Usage: "Price bump percentage to replace an already existing transaction", 261 Value: eth.DefaultConfig.TxPool.PriceBump, 262 } 263 TxPoolAccountSlotsFlag = cli.Uint64Flag{ 264 Name: "txpool.accountslots", 265 Usage: "Minimum number of executable transaction slots guaranteed per account", 266 Value: eth.DefaultConfig.TxPool.AccountSlots, 267 } 268 TxPoolGlobalSlotsFlag = cli.Uint64Flag{ 269 Name: "txpool.globalslots", 270 Usage: "Maximum number of executable transaction slots for all accounts", 271 Value: eth.DefaultConfig.TxPool.GlobalSlots, 272 } 273 TxPoolAccountQueueFlag = cli.Uint64Flag{ 274 Name: "txpool.accountqueue", 275 Usage: "Maximum number of non-executable transaction slots permitted per account", 276 Value: eth.DefaultConfig.TxPool.AccountQueue, 277 } 278 TxPoolGlobalQueueFlag = cli.Uint64Flag{ 279 Name: "txpool.globalqueue", 280 Usage: "Maximum number of non-executable transaction slots for all accounts", 281 Value: eth.DefaultConfig.TxPool.GlobalQueue, 282 } 283 TxPoolLifetimeFlag = cli.DurationFlag{ 284 Name: "txpool.lifetime", 285 Usage: "Maximum amount of time non-executable transaction are queued", 286 Value: eth.DefaultConfig.TxPool.Lifetime, 287 } 288 //性能调整设置 289 CacheFlag = cli.IntFlag{ 290 Name: "cache", 291 Usage: "Megabytes of memory allocated to internal caching", 292 Value: 1024, 293 } 294 CacheDatabaseFlag = cli.IntFlag{ 295 Name: "cache.database", 296 Usage: "Percentage of cache memory allowance to use for database io", 297 Value: 75, 298 } 299 CacheGCFlag = cli.IntFlag{ 300 Name: "cache.gc", 301 Usage: "Percentage of cache memory allowance to use for trie pruning", 302 Value: 25, 303 } 304 TrieCacheGenFlag = cli.IntFlag{ 305 Name: "trie-cache-gens", 306 Usage: "Number of trie node generations to keep in memory", 307 Value: int(state.MaxTrieCacheGen), 308 } 309 //矿工设置 310 MiningEnabledFlag = cli.BoolFlag{ 311 Name: "mine", 312 Usage: "Enable mining", 313 } 314 MinerThreadsFlag = cli.IntFlag{ 315 Name: "miner.threads", 316 Usage: "Number of CPU threads to use for mining", 317 Value: 0, 318 } 319 MinerLegacyThreadsFlag = cli.IntFlag{ 320 Name: "minerthreads", 321 Usage: "Number of CPU threads to use for mining (deprecated, use --miner.threads)", 322 Value: 0, 323 } 324 MinerNotifyFlag = cli.StringFlag{ 325 Name: "miner.notify", 326 Usage: "Comma separated HTTP URL list to notify of new work packages", 327 } 328 MinerGasTargetFlag = cli.Uint64Flag{ 329 Name: "miner.gastarget", 330 Usage: "Target gas floor for mined blocks", 331 Value: params.GenesisGasLimit, 332 } 333 MinerLegacyGasTargetFlag = cli.Uint64Flag{ 334 Name: "targetgaslimit", 335 Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)", 336 Value: params.GenesisGasLimit, 337 } 338 MinerGasPriceFlag = BigFlag{ 339 Name: "miner.gasprice", 340 Usage: "Minimal gas price for mining a transactions", 341 Value: eth.DefaultConfig.MinerGasPrice, 342 } 343 MinerLegacyGasPriceFlag = BigFlag{ 344 Name: "gasprice", 345 Usage: "Minimal gas price for mining a transactions (deprecated, use --miner.gasprice)", 346 Value: eth.DefaultConfig.MinerGasPrice, 347 } 348 ValidatorFlag = cli.StringFlag{ 349 Name: "validator", 350 Usage: "Public address for block mining signer (default = first account created)", 351 Value: "0", 352 } 353 CoinbaseFlag = cli.StringFlag{ 354 Name: "coinbase", 355 Usage: "Public address for block mining rewards (default = first account created)", 356 Value: "0", 357 } 358 MinerLegacyEtherbaseFlag = cli.StringFlag{ 359 Name: "etherbase", 360 Usage: "Public address for block mining rewards (default = first account, deprecated, use --miner.etherbase)", 361 Value: "0", 362 } 363 MinerExtraDataFlag = cli.StringFlag{ 364 Name: "miner.extradata", 365 Usage: "Block extra data set by the miner (default = client version)", 366 } 367 MinerLegacyExtraDataFlag = cli.StringFlag{ 368 Name: "extradata", 369 Usage: "Block extra data set by the miner (default = client version, deprecated, use --miner.extradata)", 370 } 371 MinerRecommitIntervalFlag = cli.DurationFlag{ 372 Name: "miner.recommit", 373 Usage: "Time interval to recreate the block being mined.", 374 Value: eth.DefaultConfig.MinerRecommit, 375 } 376 //帐户设置 377 UnlockedAccountFlag = cli.StringFlag{ 378 Name: "unlock", 379 Usage: "Comma separated list of accounts to unlock", 380 Value: "", 381 } 382 PasswordFileFlag = cli.StringFlag{ 383 Name: "password", 384 Usage: "Password file to use for non-interactive password input", 385 Value: "", 386 } 387 388 VMEnableDebugFlag = cli.BoolFlag{ 389 Name: "vmdebug", 390 Usage: "Record information useful for VM and contract debugging", 391 } 392 //日志记录和调试设置 393 EthStatsURLFlag = cli.StringFlag{ 394 Name: "ethstats", 395 Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", 396 } 397 FakePoWFlag = cli.BoolFlag{ 398 Name: "fakepow", 399 Usage: "Disables proof-of-work verification", 400 } 401 NoCompactionFlag = cli.BoolFlag{ 402 Name: "nocompaction", 403 Usage: "Disables db compaction after import", 404 } 405 //RPC设置 406 RPCEnabledFlag = cli.BoolFlag{ 407 Name: "rpc", 408 Usage: "Enable the HTTP-RPC server", 409 } 410 RPCListenAddrFlag = cli.StringFlag{ 411 Name: "rpcaddr", 412 Usage: "HTTP-RPC server listening interface", 413 Value: node.DefaultHTTPHost, 414 } 415 RPCPortFlag = cli.IntFlag{ 416 Name: "rpcport", 417 Usage: "HTTP-RPC server listening port", 418 Value: node.DefaultHTTPPort, 419 } 420 RPCCORSDomainFlag = cli.StringFlag{ 421 Name: "rpccorsdomain", 422 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 423 Value: "", 424 } 425 RPCVirtualHostsFlag = cli.StringFlag{ 426 Name: "rpcvhosts", 427 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 428 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 429 } 430 RPCApiFlag = cli.StringFlag{ 431 Name: "rpcapi", 432 Usage: "API's offered over the HTTP-RPC interface", 433 Value: "", 434 } 435 IPCDisabledFlag = cli.BoolFlag{ 436 Name: "ipcdisable", 437 Usage: "Disable the IPC-RPC server", 438 } 439 IPCPathFlag = DirectoryFlag{ 440 Name: "ipcpath", 441 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 442 } 443 WSEnabledFlag = cli.BoolFlag{ 444 Name: "ws", 445 Usage: "Enable the WS-RPC server", 446 } 447 WSListenAddrFlag = cli.StringFlag{ 448 Name: "wsaddr", 449 Usage: "WS-RPC server listening interface", 450 Value: node.DefaultWSHost, 451 } 452 WSPortFlag = cli.IntFlag{ 453 Name: "wsport", 454 Usage: "WS-RPC server listening port", 455 Value: node.DefaultWSPort, 456 } 457 WSApiFlag = cli.StringFlag{ 458 Name: "wsapi", 459 Usage: "API's offered over the WS-RPC interface", 460 Value: "", 461 } 462 WSAllowedOriginsFlag = cli.StringFlag{ 463 Name: "wsorigins", 464 Usage: "Origins from which to accept websockets requests", 465 Value: "", 466 } 467 ExecFlag = cli.StringFlag{ 468 Name: "exec", 469 Usage: "Execute JavaScript statement", 470 } 471 PreloadJSFlag = cli.StringFlag{ 472 Name: "preload", 473 Usage: "Comma separated list of JavaScript files to preload into the console", 474 } 475 476 //网络设置 477 MaxPeersFlag = cli.IntFlag{ 478 Name: "maxpeers", 479 Usage: "Maximum number of network peers (network disabled if set to 0)", 480 Value: 25, 481 } 482 MaxPendingPeersFlag = cli.IntFlag{ 483 Name: "maxpendpeers", 484 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 485 Value: 0, 486 } 487 ListenPortFlag = cli.IntFlag{ 488 Name: "port", 489 Usage: "Network listening port", 490 Value: 30303, 491 } 492 BootnodesFlag = cli.StringFlag{ 493 Name: "bootnodes", 494 Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)", 495 Value: "", 496 } 497 BootnodesV4Flag = cli.StringFlag{ 498 Name: "bootnodesv4", 499 Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)", 500 Value: "", 501 } 502 BootnodesV5Flag = cli.StringFlag{ 503 Name: "bootnodesv5", 504 Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)", 505 Value: "", 506 } 507 NodeKeyFileFlag = cli.StringFlag{ 508 Name: "nodekey", 509 Usage: "P2P node key file", 510 } 511 NodeKeyHexFlag = cli.StringFlag{ 512 Name: "nodekeyhex", 513 Usage: "P2P node key as hex (for testing)", 514 } 515 NATFlag = cli.StringFlag{ 516 Name: "nat", 517 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 518 Value: "any", 519 } 520 NoDiscoverFlag = cli.BoolFlag{ 521 Name: "nodiscover", 522 Usage: "Disables the peer discovery mechanism (manual peer addition)", 523 } 524 DiscoveryV5Flag = cli.BoolFlag{ 525 Name: "v5disc", 526 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 527 } 528 NetrestrictFlag = cli.StringFlag{ 529 Name: "netrestrict", 530 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 531 } 532 533 //将URL留给用户并部署到的ATM 534 JSpathFlag = cli.StringFlag{ 535 Name: "jspath", 536 Usage: "JavaScript root path for `loadScript`", 537 Value: ".", 538 } 539 540 //天然气价格Oracle设置 541 GpoBlocksFlag = cli.IntFlag{ 542 Name: "gpoblocks", 543 Usage: "Number of recent blocks to check for gas prices", 544 Value: eth.DefaultConfig.GPO.Blocks, 545 } 546 GpoPercentileFlag = cli.IntFlag{ 547 Name: "gpopercentile", 548 Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", 549 Value: eth.DefaultConfig.GPO.Percentile, 550 } 551 WhisperEnabledFlag = cli.BoolFlag{ 552 Name: "shh", 553 Usage: "Enable Whisper", 554 } 555 WhisperMaxMessageSizeFlag = cli.IntFlag{ 556 Name: "shh.maxmessagesize", 557 Usage: "Max message size accepted", 558 Value: int(whisper.DefaultMaxMessageSize), 559 } 560 WhisperMinPOWFlag = cli.Float64Flag{ 561 Name: "shh.pow", 562 Usage: "Minimum POW accepted", 563 Value: whisper.DefaultMinimumPoW, 564 } 565 566 //度量标志 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://本地主机:8086“, 579 } 580 MetricsInfluxDBDatabaseFlag = cli.StringFlag{ 581 Name: "metrics.influxdb.database", 582 Usage: "InfluxDB database name to push reported metrics to", 583 Value: "geth", 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 //“host”标记是发送到influxdb的每个度量的一部分。在influxdb中,对标签的查询更快。 596 //它的使用是为了让我们可以对所有节点进行分组,并对所有节点的测量值进行平均,但也同样如此 597 //我们可以选择一个特定的节点并检查它的测量值。 598 //https://docs.influxdata.com/influxdb/v1.4/concepts/key_-concepts/标记密钥 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 606 //makedatadir检索当前请求的数据目录,终止 607 //如果没有指定(或空字符串)。如果节点正在启动一个测试网, 608 // 609 func MakeDataDir(ctx *cli.Context) string { 610 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 611 if ctx.GlobalBool(TestnetFlag.Name) { 612 return filepath.Join(path, "testnet") 613 } 614 if ctx.GlobalBool(RinkebyFlag.Name) { 615 return filepath.Join(path, "rinkeby") 616 } 617 return path 618 } 619 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 620 return "" 621 } 622 623 //set node key从set命令行标志创建一个节点键,或者加载它 624 //从文件或作为指定的十六进制值。如果没有提供任何标志,则 625 //方法返回nil,将生成一个临时键。 626 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 627 var ( 628 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 629 file = ctx.GlobalString(NodeKeyFileFlag.Name) 630 key *ecdsa.PrivateKey 631 err error 632 ) 633 switch { 634 case file != "" && hex != "": 635 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 636 case file != "": 637 if key, err = crypto.LoadECDSA(file); err != nil { 638 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 639 } 640 cfg.PrivateKey = key 641 case hex != "": 642 if key, err = crypto.HexToECDSA(hex); err != nil { 643 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 644 } 645 cfg.PrivateKey = key 646 } 647 } 648 649 //setnodeuserident从cli标志创建用户标识符。 650 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 651 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 652 cfg.UserIdent = identity 653 } 654 } 655 656 // 657 //标记,如果未指定,则恢复为预配置的标记。 658 func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { 659 urls := params.MainnetBootnodes 660 switch { 661 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name): 662 if ctx.GlobalIsSet(BootnodesV4Flag.Name) { 663 urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",") 664 } else { 665 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 666 } 667 case ctx.GlobalBool(TestnetFlag.Name): 668 urls = params.TestnetBootnodes 669 case ctx.GlobalBool(RinkebyFlag.Name): 670 urls = params.RinkebyBootnodes 671 case cfg.BootstrapNodes != nil: 672 return //已设置,不应用默认值。 673 } 674 675 cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls)) 676 for _, url := range urls { 677 node, err := discover.ParseNode(url) 678 if err != nil { 679 log.Crit("Bootstrap URL invalid", "enode", url, "err", err) 680 } 681 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 682 } 683 } 684 685 //setbootstrapnodesv5从命令行创建引导节点列表 686 //标记,如果未指定,则恢复为预配置的标记。 687 func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { 688 urls := params.DiscoveryV5Bootnodes 689 switch { 690 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name): 691 if ctx.GlobalIsSet(BootnodesV5Flag.Name) { 692 urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",") 693 } else { 694 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 695 } 696 case ctx.GlobalBool(RinkebyFlag.Name): 697 urls = params.RinkebyBootnodes 698 case cfg.BootstrapNodesV5 != nil: 699 return //已设置,不应用默认值。 700 } 701 702 cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls)) 703 for _, url := range urls { 704 node, err := discv5.ParseNode(url) 705 if err != nil { 706 log.Error("Bootstrap URL invalid", "enode", url, "err", err) 707 continue 708 } 709 cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) 710 } 711 } 712 713 //setlistenaddress从set命令创建TCP侦听地址字符串 714 //行标志。 715 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 716 if ctx.GlobalIsSet(ListenPortFlag.Name) { 717 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 718 } 719 } 720 721 // 722 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 723 if ctx.GlobalIsSet(NATFlag.Name) { 724 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 725 if err != nil { 726 Fatalf("Option %s: %v", NATFlag.Name, err) 727 } 728 cfg.NAT = natif 729 } 730 } 731 732 //splitandtrim拆分由逗号分隔的输入 733 //并修剪子字符串中多余的空白。 734 func splitAndTrim(input string) []string { 735 result := strings.Split(input, ",") 736 for i, r := range result { 737 result[i] = strings.TrimSpace(r) 738 } 739 return result 740 } 741 742 //set http从集合创建HTTP RPC侦听器接口字符串 743 // 744 func setHTTP(ctx *cli.Context, cfg *node.Config) { 745 if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { 746 cfg.HTTPHost = "127.0.0.1" 747 if ctx.GlobalIsSet(RPCListenAddrFlag.Name) { 748 cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name) 749 } 750 } 751 752 if ctx.GlobalIsSet(RPCPortFlag.Name) { 753 cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) 754 } 755 if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { 756 cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name)) 757 } 758 if ctx.GlobalIsSet(RPCApiFlag.Name) { 759 cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name)) 760 } 761 if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) { 762 cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name)) 763 } 764 } 765 766 //setws从集合创建websocket rpc侦听器接口字符串 767 //命令行标志,如果禁用HTTP端点,则返回空。 768 func setWS(ctx *cli.Context, cfg *node.Config) { 769 if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { 770 cfg.WSHost = "127.0.0.1" 771 if ctx.GlobalIsSet(WSListenAddrFlag.Name) { 772 cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) 773 } 774 } 775 776 if ctx.GlobalIsSet(WSPortFlag.Name) { 777 cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) 778 } 779 if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { 780 cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) 781 } 782 if ctx.GlobalIsSet(WSApiFlag.Name) { 783 cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name)) 784 } 785 } 786 787 // 788 //如果显式禁用了IPC或设置的路径,则返回空字符串。 789 func setIPC(ctx *cli.Context, cfg *node.Config) { 790 checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 791 switch { 792 case ctx.GlobalBool(IPCDisabledFlag.Name): 793 cfg.IPCPath = "" 794 case ctx.GlobalIsSet(IPCPathFlag.Name): 795 cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) 796 } 797 } 798 799 //makedatabasehandles引发每个进程允许的文件句柄数 800 //并返回要分配给数据库的津贴的一半。 801 func makeDatabaseHandles() int { 802 limit, err := fdlimit.Current() 803 if err != nil { 804 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 805 } 806 if limit < 2048 { 807 if err := fdlimit.Raise(2048); err != nil { 808 Fatalf("Failed to raise file descriptor allowance: %v", err) 809 } 810 } 811 if limit > 2048 { // 812 limit = 2048 813 } 814 return limit / 2 //留下一半用于网络和其他东西 815 } 816 817 //makeaddress转换直接指定为十六进制编码字符串或 818 //内部帐户表示形式的密钥存储中的密钥索引。 819 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 820 //如果指定的帐户是有效地址,请将其返回 821 if common.IsHexAddress(account) { 822 return accounts.Account{Address: common.HexToAddress(account)}, nil 823 } 824 //否则,尝试将帐户解释为密钥存储索引 825 index, err := strconv.Atoi(account) 826 if err != nil || index < 0 { 827 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 828 } 829 log.Warn("-------------------------------------------------------------------") 830 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 831 log.Warn("This functionality is deprecated and will be removed in the future!") 832 log.Warn("Please use explicit addresses! (can search via `geth account list`)") 833 log.Warn("-------------------------------------------------------------------") 834 835 accs := ks.Accounts() 836 if len(accs) <= index { 837 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 838 } 839 return accs[index], nil 840 } 841 842 //setvalidator从直接指定的 843 //命令行标志或来自keystore(如果为cli编制了索引)。 844 func setValidator(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) { 845 if ctx.GlobalIsSet(ValidatorFlag.Name) { 846 account, err := MakeAddress(ks, ctx.GlobalString(ValidatorFlag.Name)) 847 if err != nil { 848 Fatalf("Option %q: %v", ValidatorFlag.Name, err) 849 } 850 cfg.Validator = account.Address 851 return 852 } 853 accounts := ks.Accounts() 854 if (cfg.Validator == common.Address{}) { 855 if len(accounts) > 0 { 856 cfg.Validator = accounts[0].Address 857 } else { 858 log.Warn("No validator set and no accounts found as default") 859 } 860 } 861 } 862 863 //setCoinBase从直接指定的 864 //命令行标志或来自keystore(如果为cli编制了索引)。 865 func setCoinbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) { 866 if ctx.GlobalIsSet(CoinbaseFlag.Name) { 867 account, err := MakeAddress(ks, ctx.GlobalString(CoinbaseFlag.Name)) 868 if err != nil { 869 Fatalf("Option %q: %v", CoinbaseFlag.Name, err) 870 } 871 cfg.Coinbase = account.Address 872 return 873 } 874 accounts := ks.Accounts() 875 if (cfg.Coinbase == common.Address{}) { 876 if len(accounts) > 0 { 877 cfg.Coinbase = accounts[0].Address 878 } else { 879 log.Warn("No coinbase set and no accounts found as default") 880 } 881 } 882 } 883 884 //makepasswordlist从global--password标志指定的文件中读取密码行。 885 func MakePasswordList(ctx *cli.Context) []string { 886 path := ctx.GlobalString(PasswordFileFlag.Name) 887 if path == "" { 888 return nil 889 } 890 text, err := ioutil.ReadFile(path) 891 if err != nil { 892 Fatalf("Failed to read password file: %v", err) 893 } 894 lines := strings.Split(string(text), "\n") 895 //对DOS行结尾进行消毒。 896 for i := range lines { 897 lines[i] = strings.TrimRight(lines[i], "\r") 898 } 899 return lines 900 } 901 902 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 903 setNodeKey(ctx, cfg) 904 setNAT(ctx, cfg) 905 setListenAddress(ctx, cfg) 906 setBootstrapNodes(ctx, cfg) 907 setBootstrapNodesV5(ctx, cfg) 908 909 lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light" 910 lightServer := ctx.GlobalInt(LightServFlag.Name) != 0 911 lightPeers := ctx.GlobalInt(LightPeersFlag.Name) 912 913 if ctx.GlobalIsSet(MaxPeersFlag.Name) { 914 cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) 915 if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) { 916 cfg.MaxPeers += lightPeers 917 } 918 } else { 919 if lightServer { 920 cfg.MaxPeers += lightPeers 921 } 922 if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers { 923 cfg.MaxPeers = lightPeers 924 } 925 } 926 if !(lightClient || lightServer) { 927 lightPeers = 0 928 } 929 ethPeers := cfg.MaxPeers - lightPeers 930 if lightClient { 931 ethPeers = 0 932 } 933 log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers) 934 935 if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { 936 cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) 937 } 938 if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { 939 cfg.NoDiscovery = true 940 } 941 942 // 943 //除非使用--nodiscover显式禁用它,否则请注意显式指定 944 //--v5disc overrides--nodiscover,在这种情况下,后者只禁用v4发现 945 forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) 946 if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { 947 cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) 948 } else if forceV5Discovery { 949 cfg.DiscoveryV5 = true 950 } 951 952 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 953 list, err := netutil.ParseNetlist(netrestrict) 954 if err != nil { 955 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 956 } 957 cfg.NetRestrict = list 958 } 959 960 if ctx.GlobalBool(DeveloperFlag.Name) { 961 //--dev模式不能使用p2p网络。 962 cfg.MaxPeers = 0 963 cfg.ListenAddr = ":0" 964 cfg.NoDiscovery = true 965 cfg.DiscoveryV5 = false 966 } 967 } 968 969 //setnodeconfig将与节点相关的命令行标志应用于配置。 970 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 971 SetP2PConfig(ctx, &cfg.P2P) 972 setIPC(ctx, cfg) 973 setHTTP(ctx, cfg) 974 setWS(ctx, cfg) 975 setNodeUserIdent(ctx, cfg) 976 977 switch { 978 case ctx.GlobalIsSet(DataDirFlag.Name): 979 cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) 980 case ctx.GlobalBool(DeveloperFlag.Name): 981 cfg.DataDir = "" //除非明确要求,否则使用内存数据库 982 case ctx.GlobalBool(TestnetFlag.Name): 983 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet") 984 case ctx.GlobalBool(RinkebyFlag.Name): 985 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby") 986 } 987 988 if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { 989 cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) 990 } 991 if ctx.GlobalIsSet(LightKDFFlag.Name) { 992 cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) 993 } 994 if ctx.GlobalIsSet(NoUSBFlag.Name) { 995 cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name) 996 } 997 } 998 999 func setGPO(ctx *cli.Context, cfg *gasprice.Config) { 1000 if ctx.GlobalIsSet(GpoBlocksFlag.Name) { 1001 cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) 1002 } 1003 if ctx.GlobalIsSet(GpoPercentileFlag.Name) { 1004 cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) 1005 } 1006 } 1007 1008 func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { 1009 if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) { 1010 locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",") 1011 for _, account := range locals { 1012 if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) { 1013 Fatalf("Invalid account in --txpool.locals: %s", trimmed) 1014 } else { 1015 cfg.Locals = append(cfg.Locals, common.HexToAddress(account)) 1016 } 1017 } 1018 } 1019 if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) { 1020 cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name) 1021 } 1022 if ctx.GlobalIsSet(TxPoolJournalFlag.Name) { 1023 cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name) 1024 } 1025 if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) { 1026 cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name) 1027 } 1028 if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) { 1029 cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name) 1030 } 1031 if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) { 1032 cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name) 1033 } 1034 if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) { 1035 cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name) 1036 } 1037 if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) { 1038 cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name) 1039 } 1040 if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) { 1041 cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name) 1042 } 1043 if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) { 1044 cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name) 1045 } 1046 if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) { 1047 cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name) 1048 } 1049 } 1050 1051 func setEthash(ctx *cli.Context, cfg *eth.Config) { 1052 if ctx.GlobalIsSet(EthashCacheDirFlag.Name) { 1053 cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name) 1054 } 1055 if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) { 1056 cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name) 1057 } 1058 if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) { 1059 cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name) 1060 } 1061 if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) { 1062 cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name) 1063 } 1064 if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) { 1065 cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name) 1066 } 1067 if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) { 1068 cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name) 1069 } 1070 } 1071 1072 //checkExclusive验证提供的标志只有一个实例 1073 // 1074 //进一步专业化。 1075 func checkExclusive(ctx *cli.Context, args ...interface{}) { 1076 set := make([]string, 0, 1) 1077 for i := 0; i < len(args); i++ { 1078 //确保下一个参数是标志,如果未设置,则跳过。 1079 flag, ok := args[i].(cli.Flag) 1080 if !ok { 1081 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 1082 } 1083 //检查next参数是否扩展当前参数,如果扩展,则扩展其名称 1084 name := flag.GetName() 1085 1086 if i+1 < len(args) { 1087 switch option := args[i+1].(type) { 1088 case string: 1089 //扩展标志,扩展名称并移动参数 1090 if ctx.GlobalString(flag.GetName()) == option { 1091 name += "=" + option 1092 } 1093 i++ 1094 1095 case cli.Flag: 1096 default: 1097 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 1098 } 1099 } 1100 // 1101 if ctx.GlobalIsSet(flag.GetName()) { 1102 set = append(set, "--"+name) 1103 } 1104 } 1105 if len(set) > 1 { 1106 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 1107 } 1108 } 1109 1110 //setshhconfig将与shh相关的命令行标志应用于配置。 1111 func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) { 1112 if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) { 1113 cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name)) 1114 } 1115 if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) { 1116 cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name) 1117 } 1118 } 1119 1120 //setethconfig将与eth相关的命令行标志应用于配置。 1121 func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { 1122 // 1123 checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag) 1124 checkExclusive(ctx, LightServFlag, SyncModeFlag, "light") 1125 1126 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 1127 setValidator(ctx, ks, cfg) 1128 setCoinbase(ctx, ks, cfg) 1129 setGPO(ctx, &cfg.GPO) 1130 setTxPool(ctx, &cfg.TxPool) 1131 setEthash(ctx, cfg) 1132 1133 if ctx.GlobalIsSet(SyncModeFlag.Name) { 1134 cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 1135 } 1136 if ctx.GlobalIsSet(LightServFlag.Name) { 1137 cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) 1138 } 1139 if ctx.GlobalIsSet(LightPeersFlag.Name) { 1140 cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) 1141 } 1142 if ctx.GlobalIsSet(NetworkIdFlag.Name) { 1143 cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) 1144 } 1145 1146 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { 1147 cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1148 } 1149 cfg.DatabaseHandles = makeDatabaseHandles() 1150 1151 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1152 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1153 } 1154 cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" 1155 1156 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1157 cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1158 } 1159 if ctx.GlobalIsSet(MinerLegacyThreadsFlag.Name) { 1160 cfg.MinerThreads = ctx.GlobalInt(MinerLegacyThreadsFlag.Name) 1161 } 1162 if ctx.GlobalIsSet(MinerThreadsFlag.Name) { 1163 cfg.MinerThreads = ctx.GlobalInt(MinerThreadsFlag.Name) 1164 } 1165 if ctx.GlobalIsSet(MinerNotifyFlag.Name) { 1166 cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",") 1167 } 1168 if ctx.GlobalIsSet(DocRootFlag.Name) { 1169 cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) 1170 } 1171 if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) { 1172 cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name)) 1173 } 1174 if ctx.GlobalIsSet(MinerExtraDataFlag.Name) { 1175 cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name)) 1176 } 1177 if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { 1178 cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name) 1179 } 1180 if ctx.GlobalIsSet(MinerGasPriceFlag.Name) { 1181 cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name) 1182 } 1183 if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) { 1184 cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name) 1185 } 1186 if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { 1187 //TODO(FJL):强制启用--dev模式 1188 cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) 1189 } 1190 1191 //覆盖硬编码网络的任何默认配置。 1192 switch { 1193 case ctx.GlobalBool(TestnetFlag.Name): 1194 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1195 cfg.NetworkId = 3 1196 } 1197 cfg.Genesis = core.DefaultTestnetGenesisBlock() 1198 case ctx.GlobalBool(RinkebyFlag.Name): 1199 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1200 cfg.NetworkId = 4 1201 } 1202 cfg.Genesis = core.DefaultRinkebyGenesisBlock() 1203 case ctx.GlobalBool(DeveloperFlag.Name): 1204 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1205 cfg.NetworkId = 1337 1206 } 1207 //创建新的开发人员帐户或重用现有帐户 1208 var ( 1209 developer accounts.Account 1210 err error 1211 ) 1212 if accs := ks.Accounts(); len(accs) > 0 { 1213 developer = ks.Accounts()[0] 1214 } else { 1215 developer, err = ks.NewAccount("") 1216 if err != nil { 1217 Fatalf("Failed to create developer account: %v", err) 1218 } 1219 } 1220 if err := ks.Unlock(developer, ""); err != nil { 1221 Fatalf("Failed to unlock developer account: %v", err) 1222 } 1223 log.Info("Using developer account", "address", developer.Address) 1224 1225 cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address) 1226 if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { 1227 cfg.MinerGasPrice = big.NewInt(1) 1228 } 1229 } 1230 //TODO(FJL):将trie缓存生成移动到配置中 1231 if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 { 1232 state.MaxTrieCacheGen = uint16(gen) 1233 } 1234 } 1235 1236 //setdashboardconfig将与仪表板相关的命令行标志应用于配置。 1237 func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) { 1238 cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name) 1239 cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name) 1240 cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name) 1241 } 1242 1243 //registerethservice将以太坊客户端添加到堆栈中。 1244 func RegisterEthService(stack *node.Node, cfg *eth.Config) { 1245 var err error 1246 if cfg.SyncMode == downloader.LightSync { 1247 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1248 return les.New(ctx, cfg) 1249 }) 1250 } else { 1251 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1252 fullNode, err := eth.New(ctx, cfg) 1253 if fullNode != nil && cfg.LightServ > 0 { 1254 ls, _ := les.NewLesServer(fullNode, cfg) 1255 fullNode.AddLesServer(ls) 1256 } 1257 return fullNode, err 1258 }) 1259 } 1260 if err != nil { 1261 Fatalf("Failed to register the Ethereum service: %v", err) 1262 } 1263 } 1264 1265 //RegisterDashboardService将仪表板添加到堆栈中。 1266 func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) { 1267 stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1268 return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil 1269 }) 1270 } 1271 1272 //registershhservice配置whisper并将其添加到给定节点。 1273 func RegisterShhService(stack *node.Node, cfg *whisper.Config) { 1274 if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) { 1275 return whisper.New(cfg), nil 1276 }); err != nil { 1277 Fatalf("Failed to register the Whisper service: %v", err) 1278 } 1279 } 1280 1281 // 1282 //给定节点。 1283 func RegisterEthStatsService(stack *node.Node, url string) { 1284 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1285 //检索ETH和LES服务 1286 var ethServ *eth.Ethereum 1287 ctx.Service(ðServ) 1288 1289 var lesServ *les.LightEthereum 1290 ctx.Service(&lesServ) 1291 1292 return ethstats.New(url, ethServ, lesServ) 1293 }); err != nil { 1294 Fatalf("Failed to register the Ethereum Stats service: %v", err) 1295 } 1296 } 1297 1298 //SetupNetwork为主网络或某些测试网络配置系统。 1299 func SetupNetwork(ctx *cli.Context) { 1300 //TODO(FJL):将目标气体限制移动到配置中 1301 params.TargetGasLimit = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name) 1302 if ctx.GlobalIsSet(MinerGasTargetFlag.Name) { 1303 params.TargetGasLimit = ctx.GlobalUint64(MinerGasTargetFlag.Name) 1304 } 1305 } 1306 1307 func SetupMetrics(ctx *cli.Context) { 1308 if metrics.Enabled { 1309 log.Info("Enabling metrics collection") 1310 var ( 1311 enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name) 1312 endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name) 1313 database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name) 1314 username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name) 1315 password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name) 1316 hosttag = ctx.GlobalString(MetricsInfluxDBHostTagFlag.Name) 1317 ) 1318 1319 if enableExport { 1320 log.Info("Enabling metrics export to InfluxDB") 1321 go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", map[string]string{ 1322 "host": hosttag, 1323 }) 1324 } 1325 } 1326 } 1327 1328 //makechaindatabase使用传递给客户机的标志打开一个leveldb,如果失败,它将很难崩溃。 1329 func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { 1330 var ( 1331 cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1332 handles = makeDatabaseHandles() 1333 ) 1334 name := "chaindata" 1335 if ctx.GlobalString(SyncModeFlag.Name) == "light" { 1336 name = "lightchaindata" 1337 } 1338 chainDb, err := stack.OpenDatabase(name, cache, handles) 1339 if err != nil { 1340 Fatalf("Could not open database: %v", err) 1341 } 1342 return chainDb 1343 } 1344 1345 func MakeGenesis(ctx *cli.Context) *core.Genesis { 1346 var genesis *core.Genesis 1347 switch { 1348 case ctx.GlobalBool(TestnetFlag.Name): 1349 genesis = core.DefaultTestnetGenesisBlock() 1350 case ctx.GlobalBool(RinkebyFlag.Name): 1351 genesis = core.DefaultRinkebyGenesisBlock() 1352 case ctx.GlobalBool(DeveloperFlag.Name): 1353 Fatalf("Developer chains are ephemeral") 1354 } 1355 return genesis 1356 } 1357 1358 // 1359 func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { 1360 var err error 1361 chainDb = MakeChainDatabase(ctx, stack) 1362 1363 config, _, err := core.SetupGenesisBlock(chainDb, nil) 1364 if err != nil { 1365 Fatalf("%v", err) 1366 } 1367 engine := dpos.New(config.Dpos, chainDb) 1368 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1369 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1370 } 1371 cache := &core.CacheConfig{ 1372 Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive", 1373 TrieNodeLimit: eth.DefaultConfig.TrieCache, 1374 TrieTimeLimit: eth.DefaultConfig.TrieTimeout, 1375 } 1376 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1377 cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1378 } 1379 vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} 1380 chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg) 1381 if err != nil { 1382 Fatalf("Can't create BlockChain: %v", err) 1383 } 1384 return chain, chainDb 1385 } 1386 1387 //makeconsolepreloads检索控制台javascript的绝对路径 1388 //启动前要预加载的脚本。 1389 func MakeConsolePreloads(ctx *cli.Context) []string { 1390 //如果没有要预加载的内容,则跳过预加载 1391 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 1392 return nil 1393 } 1394 //否则,解析绝对路径并返回它们 1395 preloads := []string{} 1396 1397 assets := ctx.GlobalString(JSpathFlag.Name) 1398 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 1399 preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file))) 1400 } 1401 return preloads 1402 } 1403 1404 //migrateflags在设置本地标志时从该标志设置全局标志。 1405 //这是一个临时函数,用于将旧命令/标志迁移到 1406 //新格式。 1407 // 1408 //例如,geth account new--keystore/tmp/mykeystore--lightkdf 1409 // 1410 //在用以下方法调用此方法后等效: 1411 // 1412 //geth--keystore/tmp/mykeystore--lightkdf新帐户 1413 // 1414 //这允许使用现有的配置功能。 1415 //当迁移所有标志时,可以删除此函数,并且 1416 //必须更改使用本地标志的配置功能 1417 func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { 1418 return func(ctx *cli.Context) error { 1419 for _, name := range ctx.FlagNames() { 1420 if ctx.IsSet(name) { 1421 ctx.GlobalSet(name, ctx.String(name)) 1422 } 1423 } 1424 return action(ctx) 1425 } 1426 } 1427 1428