github.com/pslzym/go-ethereum@v1.8.17-0.20180926104442-4b6824e07b1b/cmd/utils/flags.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package utils contains internal helper functions for go-ethereum commands.
    18  package utils
    19  
    20  import (
    21  	"crypto/ecdsa"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"os"
    26  	"path/filepath"
    27  	"strconv"
    28  	"strings"
    29  	"time"
    30  
    31  	"github.com/ethereum/go-ethereum/accounts"
    32  	"github.com/ethereum/go-ethereum/accounts/keystore"
    33  	"github.com/ethereum/go-ethereum/common"
    34  	"github.com/ethereum/go-ethereum/common/fdlimit"
    35  	"github.com/ethereum/go-ethereum/consensus"
    36  	"github.com/ethereum/go-ethereum/consensus/clique"
    37  	"github.com/ethereum/go-ethereum/consensus/ethash"
    38  	"github.com/ethereum/go-ethereum/core"
    39  	"github.com/ethereum/go-ethereum/core/state"
    40  	"github.com/ethereum/go-ethereum/core/vm"
    41  	"github.com/ethereum/go-ethereum/crypto"
    42  	"github.com/ethereum/go-ethereum/dashboard"
    43  	"github.com/ethereum/go-ethereum/eth"
    44  	"github.com/ethereum/go-ethereum/eth/downloader"
    45  	"github.com/ethereum/go-ethereum/eth/gasprice"
    46  	"github.com/ethereum/go-ethereum/ethdb"
    47  	"github.com/ethereum/go-ethereum/ethstats"
    48  	"github.com/ethereum/go-ethereum/les"
    49  	"github.com/ethereum/go-ethereum/log"
    50  	"github.com/ethereum/go-ethereum/metrics"
    51  	"github.com/ethereum/go-ethereum/metrics/influxdb"
    52  	"github.com/ethereum/go-ethereum/node"
    53  	"github.com/ethereum/go-ethereum/p2p"
    54  	"github.com/ethereum/go-ethereum/p2p/discv5"
    55  	"github.com/ethereum/go-ethereum/p2p/enode"
    56  	"github.com/ethereum/go-ethereum/p2p/nat"
    57  	"github.com/ethereum/go-ethereum/p2p/netutil"
    58  	"github.com/ethereum/go-ethereum/params"
    59  	whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
    60  	"gopkg.in/urfave/cli.v1"
    61  )
    62  
    63  var (
    64  	CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...]
    65  {{if .cmd.Description}}{{.cmd.Description}}
    66  {{end}}{{if .cmd.Subcommands}}
    67  SUBCOMMANDS:
    68  	{{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    69  	{{end}}{{end}}{{if .categorizedFlags}}
    70  {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
    71  {{range $categorized.Flags}}{{"\t"}}{{.}}
    72  {{end}}
    73  {{end}}{{end}}`
    74  )
    75  
    76  func init() {
    77  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    78  
    79  VERSION:
    80     {{.Version}}
    81  
    82  COMMANDS:
    83     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    84     {{end}}{{if .Flags}}
    85  GLOBAL OPTIONS:
    86     {{range .Flags}}{{.}}
    87     {{end}}{{end}}
    88  `
    89  
    90  	cli.CommandHelpTemplate = CommandHelpTemplate
    91  }
    92  
    93  // NewApp creates an app with sane defaults.
    94  func NewApp(gitCommit, usage string) *cli.App {
    95  	app := cli.NewApp()
    96  	app.Name = filepath.Base(os.Args[0])
    97  	app.Author = ""
    98  	//app.Authors = nil
    99  	app.Email = ""
   100  	app.Version = params.VersionWithMeta
   101  	if len(gitCommit) >= 8 {
   102  		app.Version += "-" + gitCommit[:8]
   103  	}
   104  	app.Usage = usage
   105  	return app
   106  }
   107  
   108  // These are all the command line flags we support.
   109  // If you add to this list, please remember to include the
   110  // flag in the appropriate command definition.
   111  //
   112  // The flags are defined here so their names and help texts
   113  // are the same for all commands.
   114  
   115  var (
   116  	// General settings
   117  	DataDirFlag = DirectoryFlag{
   118  		Name:  "datadir",
   119  		Usage: "Data directory for the databases and keystore",
   120  		Value: DirectoryString{node.DefaultDataDir()},
   121  	}
   122  	KeyStoreDirFlag = DirectoryFlag{
   123  		Name:  "keystore",
   124  		Usage: "Directory for the keystore (default = inside the datadir)",
   125  	}
   126  	NoUSBFlag = cli.BoolFlag{
   127  		Name:  "nousb",
   128  		Usage: "Disables monitoring for and managing USB hardware wallets",
   129  	}
   130  	NetworkIdFlag = cli.Uint64Flag{
   131  		Name:  "networkid",
   132  		Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)",
   133  		Value: eth.DefaultConfig.NetworkId,
   134  	}
   135  	TestnetFlag = cli.BoolFlag{
   136  		Name:  "testnet",
   137  		Usage: "Ropsten network: pre-configured proof-of-work test network",
   138  	}
   139  	RinkebyFlag = cli.BoolFlag{
   140  		Name:  "rinkeby",
   141  		Usage: "Rinkeby network: pre-configured proof-of-authority test network",
   142  	}
   143  	DeveloperFlag = cli.BoolFlag{
   144  		Name:  "dev",
   145  		Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   146  	}
   147  	DeveloperPeriodFlag = cli.IntFlag{
   148  		Name:  "dev.period",
   149  		Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   150  	}
   151  	IdentityFlag = cli.StringFlag{
   152  		Name:  "identity",
   153  		Usage: "Custom node name",
   154  	}
   155  	DocRootFlag = DirectoryFlag{
   156  		Name:  "docroot",
   157  		Usage: "Document Root for HTTPClient file scheme",
   158  		Value: DirectoryString{homeDir()},
   159  	}
   160  	defaultSyncMode = eth.DefaultConfig.SyncMode
   161  	SyncModeFlag    = TextMarshalerFlag{
   162  		Name:  "syncmode",
   163  		Usage: `Blockchain sync mode ("fast", "full", or "light")`,
   164  		Value: &defaultSyncMode,
   165  	}
   166  	GCModeFlag = cli.StringFlag{
   167  		Name:  "gcmode",
   168  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   169  		Value: "full",
   170  	}
   171  	LightServFlag = cli.IntFlag{
   172  		Name:  "lightserv",
   173  		Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
   174  		Value: 0,
   175  	}
   176  	LightPeersFlag = cli.IntFlag{
   177  		Name:  "lightpeers",
   178  		Usage: "Maximum number of LES client peers",
   179  		Value: eth.DefaultConfig.LightPeers,
   180  	}
   181  	LightKDFFlag = cli.BoolFlag{
   182  		Name:  "lightkdf",
   183  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   184  	}
   185  	// Dashboard settings
   186  	DashboardEnabledFlag = cli.BoolFlag{
   187  		Name:  metrics.DashboardEnabledFlag,
   188  		Usage: "Enable the dashboard",
   189  	}
   190  	DashboardAddrFlag = cli.StringFlag{
   191  		Name:  "dashboard.addr",
   192  		Usage: "Dashboard listening interface",
   193  		Value: dashboard.DefaultConfig.Host,
   194  	}
   195  	DashboardPortFlag = cli.IntFlag{
   196  		Name:  "dashboard.host",
   197  		Usage: "Dashboard listening port",
   198  		Value: dashboard.DefaultConfig.Port,
   199  	}
   200  	DashboardRefreshFlag = cli.DurationFlag{
   201  		Name:  "dashboard.refresh",
   202  		Usage: "Dashboard metrics collection refresh rate",
   203  		Value: dashboard.DefaultConfig.Refresh,
   204  	}
   205  	// Ethash settings
   206  	EthashCacheDirFlag = DirectoryFlag{
   207  		Name:  "ethash.cachedir",
   208  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   209  	}
   210  	EthashCachesInMemoryFlag = cli.IntFlag{
   211  		Name:  "ethash.cachesinmem",
   212  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   213  		Value: eth.DefaultConfig.Ethash.CachesInMem,
   214  	}
   215  	EthashCachesOnDiskFlag = cli.IntFlag{
   216  		Name:  "ethash.cachesondisk",
   217  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   218  		Value: eth.DefaultConfig.Ethash.CachesOnDisk,
   219  	}
   220  	EthashDatasetDirFlag = DirectoryFlag{
   221  		Name:  "ethash.dagdir",
   222  		Usage: "Directory to store the ethash mining DAGs (default = inside home folder)",
   223  		Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir},
   224  	}
   225  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   226  		Name:  "ethash.dagsinmem",
   227  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   228  		Value: eth.DefaultConfig.Ethash.DatasetsInMem,
   229  	}
   230  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   231  		Name:  "ethash.dagsondisk",
   232  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   233  		Value: eth.DefaultConfig.Ethash.DatasetsOnDisk,
   234  	}
   235  	// Transaction pool settings
   236  	TxPoolLocalsFlag = cli.StringFlag{
   237  		Name:  "txpool.locals",
   238  		Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
   239  	}
   240  	TxPoolNoLocalsFlag = cli.BoolFlag{
   241  		Name:  "txpool.nolocals",
   242  		Usage: "Disables price exemptions for locally submitted transactions",
   243  	}
   244  	TxPoolJournalFlag = cli.StringFlag{
   245  		Name:  "txpool.journal",
   246  		Usage: "Disk journal for local transaction to survive node restarts",
   247  		Value: core.DefaultTxPoolConfig.Journal,
   248  	}
   249  	TxPoolRejournalFlag = cli.DurationFlag{
   250  		Name:  "txpool.rejournal",
   251  		Usage: "Time interval to regenerate the local transaction journal",
   252  		Value: core.DefaultTxPoolConfig.Rejournal,
   253  	}
   254  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   255  		Name:  "txpool.pricelimit",
   256  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   257  		Value: eth.DefaultConfig.TxPool.PriceLimit,
   258  	}
   259  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   260  		Name:  "txpool.pricebump",
   261  		Usage: "Price bump percentage to replace an already existing transaction",
   262  		Value: eth.DefaultConfig.TxPool.PriceBump,
   263  	}
   264  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   265  		Name:  "txpool.accountslots",
   266  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   267  		Value: eth.DefaultConfig.TxPool.AccountSlots,
   268  	}
   269  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   270  		Name:  "txpool.globalslots",
   271  		Usage: "Maximum number of executable transaction slots for all accounts",
   272  		Value: eth.DefaultConfig.TxPool.GlobalSlots,
   273  	}
   274  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   275  		Name:  "txpool.accountqueue",
   276  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   277  		Value: eth.DefaultConfig.TxPool.AccountQueue,
   278  	}
   279  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   280  		Name:  "txpool.globalqueue",
   281  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   282  		Value: eth.DefaultConfig.TxPool.GlobalQueue,
   283  	}
   284  	TxPoolLifetimeFlag = cli.DurationFlag{
   285  		Name:  "txpool.lifetime",
   286  		Usage: "Maximum amount of time non-executable transaction are queued",
   287  		Value: eth.DefaultConfig.TxPool.Lifetime,
   288  	}
   289  	// Performance tuning settings
   290  	CacheFlag = cli.IntFlag{
   291  		Name:  "cache",
   292  		Usage: "Megabytes of memory allocated to internal caching",
   293  		Value: 1024,
   294  	}
   295  	CacheDatabaseFlag = cli.IntFlag{
   296  		Name:  "cache.database",
   297  		Usage: "Percentage of cache memory allowance to use for database io",
   298  		Value: 75,
   299  	}
   300  	CacheGCFlag = cli.IntFlag{
   301  		Name:  "cache.gc",
   302  		Usage: "Percentage of cache memory allowance to use for trie pruning",
   303  		Value: 25,
   304  	}
   305  	TrieCacheGenFlag = cli.IntFlag{
   306  		Name:  "trie-cache-gens",
   307  		Usage: "Number of trie node generations to keep in memory",
   308  		Value: int(state.MaxTrieCacheGen),
   309  	}
   310  	// Miner settings
   311  	MiningEnabledFlag = cli.BoolFlag{
   312  		Name:  "mine",
   313  		Usage: "Enable mining",
   314  	}
   315  	MinerThreadsFlag = cli.IntFlag{
   316  		Name:  "miner.threads",
   317  		Usage: "Number of CPU threads to use for mining",
   318  		Value: 0,
   319  	}
   320  	MinerLegacyThreadsFlag = cli.IntFlag{
   321  		Name:  "minerthreads",
   322  		Usage: "Number of CPU threads to use for mining (deprecated, use --miner.threads)",
   323  		Value: 0,
   324  	}
   325  	MinerNotifyFlag = cli.StringFlag{
   326  		Name:  "miner.notify",
   327  		Usage: "Comma separated HTTP URL list to notify of new work packages",
   328  	}
   329  	MinerGasTargetFlag = cli.Uint64Flag{
   330  		Name:  "miner.gastarget",
   331  		Usage: "Target gas floor for mined blocks",
   332  		Value: eth.DefaultConfig.MinerGasFloor,
   333  	}
   334  	MinerLegacyGasTargetFlag = cli.Uint64Flag{
   335  		Name:  "targetgaslimit",
   336  		Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)",
   337  		Value: eth.DefaultConfig.MinerGasFloor,
   338  	}
   339  	MinerGasLimitFlag = cli.Uint64Flag{
   340  		Name:  "miner.gaslimit",
   341  		Usage: "Target gas ceiling for mined blocks",
   342  		Value: eth.DefaultConfig.MinerGasCeil,
   343  	}
   344  	MinerGasPriceFlag = BigFlag{
   345  		Name:  "miner.gasprice",
   346  		Usage: "Minimum gas price for mining a transaction",
   347  		Value: eth.DefaultConfig.MinerGasPrice,
   348  	}
   349  	MinerLegacyGasPriceFlag = BigFlag{
   350  		Name:  "gasprice",
   351  		Usage: "Minimum gas price for mining a transaction (deprecated, use --miner.gasprice)",
   352  		Value: eth.DefaultConfig.MinerGasPrice,
   353  	}
   354  	MinerEtherbaseFlag = cli.StringFlag{
   355  		Name:  "miner.etherbase",
   356  		Usage: "Public address for block mining rewards (default = first account)",
   357  		Value: "0",
   358  	}
   359  	MinerLegacyEtherbaseFlag = cli.StringFlag{
   360  		Name:  "etherbase",
   361  		Usage: "Public address for block mining rewards (default = first account, deprecated, use --miner.etherbase)",
   362  		Value: "0",
   363  	}
   364  	MinerExtraDataFlag = cli.StringFlag{
   365  		Name:  "miner.extradata",
   366  		Usage: "Block extra data set by the miner (default = client version)",
   367  	}
   368  	MinerLegacyExtraDataFlag = cli.StringFlag{
   369  		Name:  "extradata",
   370  		Usage: "Block extra data set by the miner (default = client version, deprecated, use --miner.extradata)",
   371  	}
   372  	MinerRecommitIntervalFlag = cli.DurationFlag{
   373  		Name:  "miner.recommit",
   374  		Usage: "Time interval to recreate the block being mined",
   375  		Value: eth.DefaultConfig.MinerRecommit,
   376  	}
   377  	MinerNoVerfiyFlag = cli.BoolFlag{
   378  		Name:  "miner.noverify",
   379  		Usage: "Disable remote sealing verification",
   380  	}
   381  	// Account settings
   382  	UnlockedAccountFlag = cli.StringFlag{
   383  		Name:  "unlock",
   384  		Usage: "Comma separated list of accounts to unlock",
   385  		Value: "",
   386  	}
   387  	PasswordFileFlag = cli.StringFlag{
   388  		Name:  "password",
   389  		Usage: "Password file to use for non-interactive password input",
   390  		Value: "",
   391  	}
   392  
   393  	VMEnableDebugFlag = cli.BoolFlag{
   394  		Name:  "vmdebug",
   395  		Usage: "Record information useful for VM and contract debugging",
   396  	}
   397  	// Logging and debug settings
   398  	EthStatsURLFlag = cli.StringFlag{
   399  		Name:  "ethstats",
   400  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   401  	}
   402  	FakePoWFlag = cli.BoolFlag{
   403  		Name:  "fakepow",
   404  		Usage: "Disables proof-of-work verification",
   405  	}
   406  	NoCompactionFlag = cli.BoolFlag{
   407  		Name:  "nocompaction",
   408  		Usage: "Disables db compaction after import",
   409  	}
   410  	// RPC settings
   411  	RPCEnabledFlag = cli.BoolFlag{
   412  		Name:  "rpc",
   413  		Usage: "Enable the HTTP-RPC server",
   414  	}
   415  	RPCListenAddrFlag = cli.StringFlag{
   416  		Name:  "rpcaddr",
   417  		Usage: "HTTP-RPC server listening interface",
   418  		Value: node.DefaultHTTPHost,
   419  	}
   420  	RPCPortFlag = cli.IntFlag{
   421  		Name:  "rpcport",
   422  		Usage: "HTTP-RPC server listening port",
   423  		Value: node.DefaultHTTPPort,
   424  	}
   425  	RPCCORSDomainFlag = cli.StringFlag{
   426  		Name:  "rpccorsdomain",
   427  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   428  		Value: "",
   429  	}
   430  	RPCVirtualHostsFlag = cli.StringFlag{
   431  		Name:  "rpcvhosts",
   432  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   433  		Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
   434  	}
   435  	RPCApiFlag = cli.StringFlag{
   436  		Name:  "rpcapi",
   437  		Usage: "API's offered over the HTTP-RPC interface",
   438  		Value: "",
   439  	}
   440  	IPCDisabledFlag = cli.BoolFlag{
   441  		Name:  "ipcdisable",
   442  		Usage: "Disable the IPC-RPC server",
   443  	}
   444  	IPCPathFlag = DirectoryFlag{
   445  		Name:  "ipcpath",
   446  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   447  	}
   448  	WSEnabledFlag = cli.BoolFlag{
   449  		Name:  "ws",
   450  		Usage: "Enable the WS-RPC server",
   451  	}
   452  	WSListenAddrFlag = cli.StringFlag{
   453  		Name:  "wsaddr",
   454  		Usage: "WS-RPC server listening interface",
   455  		Value: node.DefaultWSHost,
   456  	}
   457  	WSPortFlag = cli.IntFlag{
   458  		Name:  "wsport",
   459  		Usage: "WS-RPC server listening port",
   460  		Value: node.DefaultWSPort,
   461  	}
   462  	WSApiFlag = cli.StringFlag{
   463  		Name:  "wsapi",
   464  		Usage: "API's offered over the WS-RPC interface",
   465  		Value: "",
   466  	}
   467  	WSAllowedOriginsFlag = cli.StringFlag{
   468  		Name:  "wsorigins",
   469  		Usage: "Origins from which to accept websockets requests",
   470  		Value: "",
   471  	}
   472  	ExecFlag = cli.StringFlag{
   473  		Name:  "exec",
   474  		Usage: "Execute JavaScript statement",
   475  	}
   476  	PreloadJSFlag = cli.StringFlag{
   477  		Name:  "preload",
   478  		Usage: "Comma separated list of JavaScript files to preload into the console",
   479  	}
   480  
   481  	// Network Settings
   482  	MaxPeersFlag = cli.IntFlag{
   483  		Name:  "maxpeers",
   484  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   485  		Value: 25,
   486  	}
   487  	MaxPendingPeersFlag = cli.IntFlag{
   488  		Name:  "maxpendpeers",
   489  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   490  		Value: 0,
   491  	}
   492  	ListenPortFlag = cli.IntFlag{
   493  		Name:  "port",
   494  		Usage: "Network listening port",
   495  		Value: 30303,
   496  	}
   497  	BootnodesFlag = cli.StringFlag{
   498  		Name:  "bootnodes",
   499  		Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
   500  		Value: "",
   501  	}
   502  	BootnodesV4Flag = cli.StringFlag{
   503  		Name:  "bootnodesv4",
   504  		Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
   505  		Value: "",
   506  	}
   507  	BootnodesV5Flag = cli.StringFlag{
   508  		Name:  "bootnodesv5",
   509  		Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
   510  		Value: "",
   511  	}
   512  	NodeKeyFileFlag = cli.StringFlag{
   513  		Name:  "nodekey",
   514  		Usage: "P2P node key file",
   515  	}
   516  	NodeKeyHexFlag = cli.StringFlag{
   517  		Name:  "nodekeyhex",
   518  		Usage: "P2P node key as hex (for testing)",
   519  	}
   520  	NATFlag = cli.StringFlag{
   521  		Name:  "nat",
   522  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   523  		Value: "any",
   524  	}
   525  	NoDiscoverFlag = cli.BoolFlag{
   526  		Name:  "nodiscover",
   527  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   528  	}
   529  	DiscoveryV5Flag = cli.BoolFlag{
   530  		Name:  "v5disc",
   531  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   532  	}
   533  	NetrestrictFlag = cli.StringFlag{
   534  		Name:  "netrestrict",
   535  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   536  	}
   537  
   538  	// ATM the url is left to the user and deployment to
   539  	JSpathFlag = cli.StringFlag{
   540  		Name:  "jspath",
   541  		Usage: "JavaScript root path for `loadScript`",
   542  		Value: ".",
   543  	}
   544  
   545  	// Gas price oracle settings
   546  	GpoBlocksFlag = cli.IntFlag{
   547  		Name:  "gpoblocks",
   548  		Usage: "Number of recent blocks to check for gas prices",
   549  		Value: eth.DefaultConfig.GPO.Blocks,
   550  	}
   551  	GpoPercentileFlag = cli.IntFlag{
   552  		Name:  "gpopercentile",
   553  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   554  		Value: eth.DefaultConfig.GPO.Percentile,
   555  	}
   556  	WhisperEnabledFlag = cli.BoolFlag{
   557  		Name:  "shh",
   558  		Usage: "Enable Whisper",
   559  	}
   560  	WhisperMaxMessageSizeFlag = cli.IntFlag{
   561  		Name:  "shh.maxmessagesize",
   562  		Usage: "Max message size accepted",
   563  		Value: int(whisper.DefaultMaxMessageSize),
   564  	}
   565  	WhisperMinPOWFlag = cli.Float64Flag{
   566  		Name:  "shh.pow",
   567  		Usage: "Minimum POW accepted",
   568  		Value: whisper.DefaultMinimumPoW,
   569  	}
   570  	WhisperRestrictConnectionBetweenLightClientsFlag = cli.BoolFlag{
   571  		Name:  "shh.restrict-light",
   572  		Usage: "Restrict connection between two whisper light clients",
   573  	}
   574  
   575  	// Metrics flags
   576  	MetricsEnabledFlag = cli.BoolFlag{
   577  		Name:  metrics.MetricsEnabledFlag,
   578  		Usage: "Enable metrics collection and reporting",
   579  	}
   580  	MetricsEnableInfluxDBFlag = cli.BoolFlag{
   581  		Name:  "metrics.influxdb",
   582  		Usage: "Enable metrics export/push to an external InfluxDB database",
   583  	}
   584  	MetricsInfluxDBEndpointFlag = cli.StringFlag{
   585  		Name:  "metrics.influxdb.endpoint",
   586  		Usage: "InfluxDB API endpoint to report metrics to",
   587  		Value: "http://localhost:8086",
   588  	}
   589  	MetricsInfluxDBDatabaseFlag = cli.StringFlag{
   590  		Name:  "metrics.influxdb.database",
   591  		Usage: "InfluxDB database name to push reported metrics to",
   592  		Value: "geth",
   593  	}
   594  	MetricsInfluxDBUsernameFlag = cli.StringFlag{
   595  		Name:  "metrics.influxdb.username",
   596  		Usage: "Username to authorize access to the database",
   597  		Value: "test",
   598  	}
   599  	MetricsInfluxDBPasswordFlag = cli.StringFlag{
   600  		Name:  "metrics.influxdb.password",
   601  		Usage: "Password to authorize access to the database",
   602  		Value: "test",
   603  	}
   604  	// The `host` tag is part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB.
   605  	// It is used so that we can group all nodes and average a measurement across all of them, but also so
   606  	// that we can select a specific node and inspect its measurements.
   607  	// https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key
   608  	MetricsInfluxDBHostTagFlag = cli.StringFlag{
   609  		Name:  "metrics.influxdb.host.tag",
   610  		Usage: "InfluxDB `host` tag attached to all measurements",
   611  		Value: "localhost",
   612  	}
   613  
   614  	EWASMInterpreterFlag = cli.StringFlag{
   615  		Name:  "vm.ewasm",
   616  		Usage: "External ewasm configuration (default = built-in interpreter)",
   617  		Value: "",
   618  	}
   619  	EVMInterpreterFlag = cli.StringFlag{
   620  		Name:  "vm.evm",
   621  		Usage: "External EVM configuration (default = built-in interpreter)",
   622  		Value: "",
   623  	}
   624  )
   625  
   626  // MakeDataDir retrieves the currently requested data directory, terminating
   627  // if none (or the empty string) is specified. If the node is starting a testnet,
   628  // the a subdirectory of the specified datadir will be used.
   629  func MakeDataDir(ctx *cli.Context) string {
   630  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   631  		if ctx.GlobalBool(TestnetFlag.Name) {
   632  			return filepath.Join(path, "testnet")
   633  		}
   634  		if ctx.GlobalBool(RinkebyFlag.Name) {
   635  			return filepath.Join(path, "rinkeby")
   636  		}
   637  		return path
   638  	}
   639  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   640  	return ""
   641  }
   642  
   643  // setNodeKey creates a node key from set command line flags, either loading it
   644  // from a file or as a specified hex value. If neither flags were provided, this
   645  // method returns nil and an emphemeral key is to be generated.
   646  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   647  	var (
   648  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   649  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   650  		key  *ecdsa.PrivateKey
   651  		err  error
   652  	)
   653  	switch {
   654  	case file != "" && hex != "":
   655  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   656  	case file != "":
   657  		if key, err = crypto.LoadECDSA(file); err != nil {
   658  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   659  		}
   660  		cfg.PrivateKey = key
   661  	case hex != "":
   662  		if key, err = crypto.HexToECDSA(hex); err != nil {
   663  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   664  		}
   665  		cfg.PrivateKey = key
   666  	}
   667  }
   668  
   669  // setNodeUserIdent creates the user identifier from CLI flags.
   670  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   671  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   672  		cfg.UserIdent = identity
   673  	}
   674  }
   675  
   676  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   677  // flags, reverting to pre-configured ones if none have been specified.
   678  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   679  	urls := params.MainnetBootnodes
   680  	switch {
   681  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   682  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   683  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   684  		} else {
   685  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   686  		}
   687  	case ctx.GlobalBool(TestnetFlag.Name):
   688  		urls = params.TestnetBootnodes
   689  	case ctx.GlobalBool(RinkebyFlag.Name):
   690  		urls = params.RinkebyBootnodes
   691  	case cfg.BootstrapNodes != nil:
   692  		return // already set, don't apply defaults.
   693  	}
   694  
   695  	cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls))
   696  	for _, url := range urls {
   697  		node, err := enode.ParseV4(url)
   698  		if err != nil {
   699  			log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
   700  		}
   701  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   702  	}
   703  }
   704  
   705  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   706  // flags, reverting to pre-configured ones if none have been specified.
   707  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   708  	urls := params.DiscoveryV5Bootnodes
   709  	switch {
   710  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
   711  		if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
   712  			urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",")
   713  		} else {
   714  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   715  		}
   716  	case ctx.GlobalBool(RinkebyFlag.Name):
   717  		urls = params.RinkebyBootnodes
   718  	case cfg.BootstrapNodesV5 != nil:
   719  		return // already set, don't apply defaults.
   720  	}
   721  
   722  	cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
   723  	for _, url := range urls {
   724  		node, err := discv5.ParseNode(url)
   725  		if err != nil {
   726  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   727  			continue
   728  		}
   729  		cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   730  	}
   731  }
   732  
   733  // setListenAddress creates a TCP listening address string from set command
   734  // line flags.
   735  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   736  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   737  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   738  	}
   739  }
   740  
   741  // setNAT creates a port mapper from command line flags.
   742  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   743  	if ctx.GlobalIsSet(NATFlag.Name) {
   744  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   745  		if err != nil {
   746  			Fatalf("Option %s: %v", NATFlag.Name, err)
   747  		}
   748  		cfg.NAT = natif
   749  	}
   750  }
   751  
   752  // splitAndTrim splits input separated by a comma
   753  // and trims excessive white space from the substrings.
   754  func splitAndTrim(input string) []string {
   755  	result := strings.Split(input, ",")
   756  	for i, r := range result {
   757  		result[i] = strings.TrimSpace(r)
   758  	}
   759  	return result
   760  }
   761  
   762  // setHTTP creates the HTTP RPC listener interface string from the set
   763  // command line flags, returning empty if the HTTP endpoint is disabled.
   764  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   765  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   766  		cfg.HTTPHost = "127.0.0.1"
   767  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   768  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   769  		}
   770  	}
   771  
   772  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   773  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   774  	}
   775  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   776  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   777  	}
   778  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   779  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   780  	}
   781  	if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) {
   782  		cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
   783  	}
   784  }
   785  
   786  // setWS creates the WebSocket RPC listener interface string from the set
   787  // command line flags, returning empty if the HTTP endpoint is disabled.
   788  func setWS(ctx *cli.Context, cfg *node.Config) {
   789  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   790  		cfg.WSHost = "127.0.0.1"
   791  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   792  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   793  		}
   794  	}
   795  
   796  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   797  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   798  	}
   799  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   800  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   801  	}
   802  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   803  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   804  	}
   805  }
   806  
   807  // setIPC creates an IPC path configuration from the set command line flags,
   808  // returning an empty string if IPC was explicitly disabled, or the set path.
   809  func setIPC(ctx *cli.Context, cfg *node.Config) {
   810  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   811  	switch {
   812  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   813  		cfg.IPCPath = ""
   814  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   815  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   816  	}
   817  }
   818  
   819  // makeDatabaseHandles raises out the number of allowed file handles per process
   820  // for Geth and returns half of the allowance to assign to the database.
   821  func makeDatabaseHandles() int {
   822  	limit, err := fdlimit.Current()
   823  	if err != nil {
   824  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   825  	}
   826  	if limit < 2048 {
   827  		if err := fdlimit.Raise(2048); err != nil {
   828  			Fatalf("Failed to raise file descriptor allowance: %v", err)
   829  		}
   830  	}
   831  	if limit > 2048 { // cap database file descriptors even if more is available
   832  		limit = 2048
   833  	}
   834  	return limit / 2 // Leave half for networking and other stuff
   835  }
   836  
   837  // MakeAddress converts an account specified directly as a hex encoded string or
   838  // a key index in the key store to an internal account representation.
   839  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   840  	// If the specified account is a valid address, return it
   841  	if common.IsHexAddress(account) {
   842  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   843  	}
   844  	// Otherwise try to interpret the account as a keystore index
   845  	index, err := strconv.Atoi(account)
   846  	if err != nil || index < 0 {
   847  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   848  	}
   849  	log.Warn("-------------------------------------------------------------------")
   850  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   851  	log.Warn("This functionality is deprecated and will be removed in the future!")
   852  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   853  	log.Warn("-------------------------------------------------------------------")
   854  
   855  	accs := ks.Accounts()
   856  	if len(accs) <= index {
   857  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   858  	}
   859  	return accs[index], nil
   860  }
   861  
   862  // setEtherbase retrieves the etherbase either from the directly specified
   863  // command line flags or from the keystore if CLI indexed.
   864  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
   865  	// Extract the current etherbase, new flag overriding legacy one
   866  	var etherbase string
   867  	if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) {
   868  		etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name)
   869  	}
   870  	if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) {
   871  		etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name)
   872  	}
   873  	// Convert the etherbase into an address and configure it
   874  	if etherbase != "" {
   875  		account, err := MakeAddress(ks, etherbase)
   876  		if err != nil {
   877  			Fatalf("Invalid miner etherbase: %v", err)
   878  		}
   879  		cfg.Etherbase = account.Address
   880  	}
   881  }
   882  
   883  // MakePasswordList reads password lines from the file specified by the global --password flag.
   884  func MakePasswordList(ctx *cli.Context) []string {
   885  	path := ctx.GlobalString(PasswordFileFlag.Name)
   886  	if path == "" {
   887  		return nil
   888  	}
   889  	text, err := ioutil.ReadFile(path)
   890  	if err != nil {
   891  		Fatalf("Failed to read password file: %v", err)
   892  	}
   893  	lines := strings.Split(string(text), "\n")
   894  	// Sanitise DOS line endings.
   895  	for i := range lines {
   896  		lines[i] = strings.TrimRight(lines[i], "\r")
   897  	}
   898  	return lines
   899  }
   900  
   901  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   902  	setNodeKey(ctx, cfg)
   903  	setNAT(ctx, cfg)
   904  	setListenAddress(ctx, cfg)
   905  	setBootstrapNodes(ctx, cfg)
   906  	setBootstrapNodesV5(ctx, cfg)
   907  
   908  	lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light"
   909  	lightServer := ctx.GlobalInt(LightServFlag.Name) != 0
   910  	lightPeers := ctx.GlobalInt(LightPeersFlag.Name)
   911  
   912  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   913  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   914  		if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) {
   915  			cfg.MaxPeers += lightPeers
   916  		}
   917  	} else {
   918  		if lightServer {
   919  			cfg.MaxPeers += lightPeers
   920  		}
   921  		if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers {
   922  			cfg.MaxPeers = lightPeers
   923  		}
   924  	}
   925  	if !(lightClient || lightServer) {
   926  		lightPeers = 0
   927  	}
   928  	ethPeers := cfg.MaxPeers - lightPeers
   929  	if lightClient {
   930  		ethPeers = 0
   931  	}
   932  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
   933  
   934  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   935  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   936  	}
   937  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
   938  		cfg.NoDiscovery = true
   939  	}
   940  
   941  	// if we're running a light client or server, force enable the v5 peer discovery
   942  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   943  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   944  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   945  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   946  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   947  	} else if forceV5Discovery {
   948  		cfg.DiscoveryV5 = true
   949  	}
   950  
   951  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   952  		list, err := netutil.ParseNetlist(netrestrict)
   953  		if err != nil {
   954  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   955  		}
   956  		cfg.NetRestrict = list
   957  	}
   958  
   959  	if ctx.GlobalBool(DeveloperFlag.Name) {
   960  		// --dev mode can't use p2p networking.
   961  		cfg.MaxPeers = 0
   962  		cfg.ListenAddr = ":0"
   963  		cfg.NoDiscovery = true
   964  		cfg.DiscoveryV5 = false
   965  	}
   966  }
   967  
   968  // SetNodeConfig applies node-related command line flags to the config.
   969  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   970  	SetP2PConfig(ctx, &cfg.P2P)
   971  	setIPC(ctx, cfg)
   972  	setHTTP(ctx, cfg)
   973  	setWS(ctx, cfg)
   974  	setNodeUserIdent(ctx, cfg)
   975  
   976  	switch {
   977  	case ctx.GlobalIsSet(DataDirFlag.Name):
   978  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
   979  	case ctx.GlobalBool(DeveloperFlag.Name):
   980  		cfg.DataDir = "" // unless explicitly requested, use memory databases
   981  	case ctx.GlobalBool(TestnetFlag.Name):
   982  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
   983  	case ctx.GlobalBool(RinkebyFlag.Name):
   984  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
   985  	}
   986  
   987  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
   988  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
   989  	}
   990  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
   991  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
   992  	}
   993  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
   994  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
   995  	}
   996  }
   997  
   998  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
   999  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
  1000  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
  1001  	}
  1002  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
  1003  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
  1004  	}
  1005  }
  1006  
  1007  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
  1008  	if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) {
  1009  		locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",")
  1010  		for _, account := range locals {
  1011  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
  1012  				Fatalf("Invalid account in --txpool.locals: %s", trimmed)
  1013  			} else {
  1014  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
  1015  			}
  1016  		}
  1017  	}
  1018  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
  1019  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
  1020  	}
  1021  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
  1022  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
  1023  	}
  1024  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
  1025  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
  1026  	}
  1027  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
  1028  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
  1029  	}
  1030  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
  1031  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
  1032  	}
  1033  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
  1034  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
  1035  	}
  1036  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
  1037  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
  1038  	}
  1039  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
  1040  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
  1041  	}
  1042  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
  1043  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
  1044  	}
  1045  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
  1046  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
  1047  	}
  1048  }
  1049  
  1050  func setEthash(ctx *cli.Context, cfg *eth.Config) {
  1051  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
  1052  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
  1053  	}
  1054  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
  1055  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
  1056  	}
  1057  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
  1058  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
  1059  	}
  1060  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
  1061  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
  1062  	}
  1063  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
  1064  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
  1065  	}
  1066  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
  1067  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
  1068  	}
  1069  }
  1070  
  1071  // checkExclusive verifies that only a single instance of the provided flags was
  1072  // set by the user. Each flag might optionally be followed by a string type to
  1073  // specialize it further.
  1074  func checkExclusive(ctx *cli.Context, args ...interface{}) {
  1075  	set := make([]string, 0, 1)
  1076  	for i := 0; i < len(args); i++ {
  1077  		// Make sure the next argument is a flag and skip if not set
  1078  		flag, ok := args[i].(cli.Flag)
  1079  		if !ok {
  1080  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1081  		}
  1082  		// Check if next arg extends current and expand its name if so
  1083  		name := flag.GetName()
  1084  
  1085  		if i+1 < len(args) {
  1086  			switch option := args[i+1].(type) {
  1087  			case string:
  1088  				// Extended flag, expand the name and shift the arguments
  1089  				if ctx.GlobalString(flag.GetName()) == option {
  1090  					name += "=" + option
  1091  				}
  1092  				i++
  1093  
  1094  			case cli.Flag:
  1095  			default:
  1096  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1097  			}
  1098  		}
  1099  		// Mark the flag if it's set
  1100  		if ctx.GlobalIsSet(flag.GetName()) {
  1101  			set = append(set, "--"+name)
  1102  		}
  1103  	}
  1104  	if len(set) > 1 {
  1105  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1106  	}
  1107  }
  1108  
  1109  // SetShhConfig applies shh-related command line flags to the config.
  1110  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
  1111  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
  1112  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
  1113  	}
  1114  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
  1115  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
  1116  	}
  1117  	if ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) {
  1118  		cfg.RestrictConnectionBetweenLightClients = true
  1119  	}
  1120  }
  1121  
  1122  // SetEthConfig applies eth-related command line flags to the config.
  1123  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
  1124  	// Avoid conflicting network flags
  1125  	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
  1126  	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
  1127  
  1128  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
  1129  	setEtherbase(ctx, ks, cfg)
  1130  	setGPO(ctx, &cfg.GPO)
  1131  	setTxPool(ctx, &cfg.TxPool)
  1132  	setEthash(ctx, cfg)
  1133  
  1134  	if ctx.GlobalIsSet(SyncModeFlag.Name) {
  1135  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1136  	}
  1137  	if ctx.GlobalIsSet(LightServFlag.Name) {
  1138  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
  1139  	}
  1140  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
  1141  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
  1142  	}
  1143  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1144  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1145  	}
  1146  
  1147  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
  1148  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1149  	}
  1150  	cfg.DatabaseHandles = makeDatabaseHandles()
  1151  
  1152  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1153  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1154  	}
  1155  	cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
  1156  
  1157  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1158  		cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1159  	}
  1160  	if ctx.GlobalIsSet(MinerNotifyFlag.Name) {
  1161  		cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",")
  1162  	}
  1163  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1164  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1165  	}
  1166  	if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) {
  1167  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name))
  1168  	}
  1169  	if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
  1170  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
  1171  	}
  1172  	if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) {
  1173  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name)
  1174  	}
  1175  	if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
  1176  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
  1177  	}
  1178  	if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
  1179  		cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
  1180  	}
  1181  	if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1182  		cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name)
  1183  	}
  1184  	if ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
  1185  		cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name)
  1186  	}
  1187  	if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) {
  1188  		cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
  1189  	}
  1190  	if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
  1191  		cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name)
  1192  	}
  1193  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1194  		// TODO(fjl): force-enable this in --dev mode
  1195  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1196  	}
  1197  
  1198  	if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) {
  1199  		cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name)
  1200  	}
  1201  
  1202  	if ctx.GlobalIsSet(EVMInterpreterFlag.Name) {
  1203  		cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name)
  1204  	}
  1205  
  1206  	// Override any default configs for hard coded networks.
  1207  	switch {
  1208  	case ctx.GlobalBool(TestnetFlag.Name):
  1209  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1210  			cfg.NetworkId = 3
  1211  		}
  1212  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1213  	case ctx.GlobalBool(RinkebyFlag.Name):
  1214  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1215  			cfg.NetworkId = 4
  1216  		}
  1217  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1218  	case ctx.GlobalBool(DeveloperFlag.Name):
  1219  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1220  			cfg.NetworkId = 1337
  1221  		}
  1222  		// Create new developer account or reuse existing one
  1223  		var (
  1224  			developer accounts.Account
  1225  			err       error
  1226  		)
  1227  		if accs := ks.Accounts(); len(accs) > 0 {
  1228  			developer = ks.Accounts()[0]
  1229  		} else {
  1230  			developer, err = ks.NewAccount("")
  1231  			if err != nil {
  1232  				Fatalf("Failed to create developer account: %v", err)
  1233  			}
  1234  		}
  1235  		if err := ks.Unlock(developer, ""); err != nil {
  1236  			Fatalf("Failed to unlock developer account: %v", err)
  1237  		}
  1238  		log.Info("Using developer account", "address", developer.Address)
  1239  
  1240  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1241  		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1242  			cfg.MinerGasPrice = big.NewInt(1)
  1243  		}
  1244  	}
  1245  	// TODO(fjl): move trie cache generations into config
  1246  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1247  		state.MaxTrieCacheGen = uint16(gen)
  1248  	}
  1249  }
  1250  
  1251  // SetDashboardConfig applies dashboard related command line flags to the config.
  1252  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1253  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1254  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1255  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1256  }
  1257  
  1258  // RegisterEthService adds an Ethereum client to the stack.
  1259  func RegisterEthService(stack *node.Node, cfg *eth.Config) {
  1260  	var err error
  1261  	if cfg.SyncMode == downloader.LightSync {
  1262  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1263  			return les.New(ctx, cfg)
  1264  		})
  1265  	} else {
  1266  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1267  			fullNode, err := eth.New(ctx, cfg)
  1268  			if fullNode != nil && cfg.LightServ > 0 {
  1269  				ls, _ := les.NewLesServer(fullNode, cfg)
  1270  				fullNode.AddLesServer(ls)
  1271  			}
  1272  			return fullNode, err
  1273  		})
  1274  	}
  1275  	if err != nil {
  1276  		Fatalf("Failed to register the Ethereum service: %v", err)
  1277  	}
  1278  }
  1279  
  1280  // RegisterDashboardService adds a dashboard to the stack.
  1281  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
  1282  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1283  		return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil
  1284  	})
  1285  }
  1286  
  1287  // RegisterShhService configures Whisper and adds it to the given node.
  1288  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1289  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1290  		return whisper.New(cfg), nil
  1291  	}); err != nil {
  1292  		Fatalf("Failed to register the Whisper service: %v", err)
  1293  	}
  1294  }
  1295  
  1296  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1297  // the given node.
  1298  func RegisterEthStatsService(stack *node.Node, url string) {
  1299  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1300  		// Retrieve both eth and les services
  1301  		var ethServ *eth.Ethereum
  1302  		ctx.Service(&ethServ)
  1303  
  1304  		var lesServ *les.LightEthereum
  1305  		ctx.Service(&lesServ)
  1306  
  1307  		return ethstats.New(url, ethServ, lesServ)
  1308  	}); err != nil {
  1309  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1310  	}
  1311  }
  1312  
  1313  func SetupMetrics(ctx *cli.Context) {
  1314  	if metrics.Enabled {
  1315  		log.Info("Enabling metrics collection")
  1316  		var (
  1317  			enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
  1318  			endpoint     = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
  1319  			database     = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
  1320  			username     = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
  1321  			password     = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
  1322  			hosttag      = ctx.GlobalString(MetricsInfluxDBHostTagFlag.Name)
  1323  		)
  1324  
  1325  		if enableExport {
  1326  			log.Info("Enabling metrics export to InfluxDB")
  1327  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", map[string]string{
  1328  				"host": hosttag,
  1329  			})
  1330  		}
  1331  	}
  1332  }
  1333  
  1334  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1335  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1336  	var (
  1337  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1338  		handles = makeDatabaseHandles()
  1339  	)
  1340  	name := "chaindata"
  1341  	if ctx.GlobalString(SyncModeFlag.Name) == "light" {
  1342  		name = "lightchaindata"
  1343  	}
  1344  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1345  	if err != nil {
  1346  		Fatalf("Could not open database: %v", err)
  1347  	}
  1348  	return chainDb
  1349  }
  1350  
  1351  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1352  	var genesis *core.Genesis
  1353  	switch {
  1354  	case ctx.GlobalBool(TestnetFlag.Name):
  1355  		genesis = core.DefaultTestnetGenesisBlock()
  1356  	case ctx.GlobalBool(RinkebyFlag.Name):
  1357  		genesis = core.DefaultRinkebyGenesisBlock()
  1358  	case ctx.GlobalBool(DeveloperFlag.Name):
  1359  		Fatalf("Developer chains are ephemeral")
  1360  	}
  1361  	return genesis
  1362  }
  1363  
  1364  // MakeChain creates a chain manager from set command line flags.
  1365  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  1366  	var err error
  1367  	chainDb = MakeChainDatabase(ctx, stack)
  1368  
  1369  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1370  	if err != nil {
  1371  		Fatalf("%v", err)
  1372  	}
  1373  	var engine consensus.Engine
  1374  	if config.Clique != nil {
  1375  		engine = clique.New(config.Clique, chainDb)
  1376  	} else {
  1377  		engine = ethash.NewFaker()
  1378  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1379  			engine = ethash.New(ethash.Config{
  1380  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1381  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1382  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1383  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1384  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1385  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1386  			}, nil, false)
  1387  		}
  1388  	}
  1389  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1390  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1391  	}
  1392  	cache := &core.CacheConfig{
  1393  		Disabled:      ctx.GlobalString(GCModeFlag.Name) == "archive",
  1394  		TrieNodeLimit: eth.DefaultConfig.TrieCache,
  1395  		TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
  1396  	}
  1397  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1398  		cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1399  	}
  1400  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1401  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil)
  1402  	if err != nil {
  1403  		Fatalf("Can't create BlockChain: %v", err)
  1404  	}
  1405  	return chain, chainDb
  1406  }
  1407  
  1408  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1409  // scripts to preload before starting.
  1410  func MakeConsolePreloads(ctx *cli.Context) []string {
  1411  	// Skip preloading if there's nothing to preload
  1412  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1413  		return nil
  1414  	}
  1415  	// Otherwise resolve absolute paths and return them
  1416  	preloads := []string{}
  1417  
  1418  	assets := ctx.GlobalString(JSpathFlag.Name)
  1419  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1420  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1421  	}
  1422  	return preloads
  1423  }
  1424  
  1425  // MigrateFlags sets the global flag from a local flag when it's set.
  1426  // This is a temporary function used for migrating old command/flags to the
  1427  // new format.
  1428  //
  1429  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1430  //
  1431  // is equivalent after calling this method with:
  1432  //
  1433  // geth --keystore /tmp/mykeystore --lightkdf account new
  1434  //
  1435  // This allows the use of the existing configuration functionality.
  1436  // When all flags are migrated this function can be removed and the existing
  1437  // configuration functionality must be changed that is uses local flags
  1438  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1439  	return func(ctx *cli.Context) error {
  1440  		for _, name := range ctx.FlagNames() {
  1441  			if ctx.IsSet(name) {
  1442  				ctx.GlobalSet(name, ctx.String(name))
  1443  			}
  1444  		}
  1445  		return action(ctx)
  1446  	}
  1447  }