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(&ethServ)
  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