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