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