github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/utils/flags.go (about)

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