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