github.com/edxfund/validator@v1.8.16-0.20181020093046-c1def72855da/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/EDXFund/Validator/accounts"
    32  	"github.com/EDXFund/Validator/accounts/keystore"
    33  	"github.com/EDXFund/Validator/common"
    34  	"github.com/EDXFund/Validator/common/fdlimit"
    35  	"github.com/EDXFund/Validator/consensus"
    36  	"github.com/EDXFund/Validator/consensus/clique"
    37  	"github.com/EDXFund/Validator/consensus/ethash"
    38  	"github.com/EDXFund/Validator/core"
    39  	"github.com/EDXFund/Validator/core/state"
    40  	"github.com/EDXFund/Validator/core/vm"
    41  	"github.com/EDXFund/Validator/crypto"
    42  	"github.com/EDXFund/Validator/dashboard"
    43  	"github.com/EDXFund/Validator/eth"
    44  	"github.com/EDXFund/Validator/eth/downloader"
    45  	"github.com/EDXFund/Validator/eth/gasprice"
    46  	"github.com/EDXFund/Validator/ethdb"
    47  	"github.com/EDXFund/Validator/ethstats"
    48  	//"github.com/EDXFund/Validator/les"
    49  	"github.com/EDXFund/Validator/log"
    50  	"github.com/EDXFund/Validator/metrics"
    51  	"github.com/EDXFund/Validator/metrics/influxdb"
    52  	"github.com/EDXFund/Validator/node"
    53  	"github.com/EDXFund/Validator/p2p"
    54  	"github.com/EDXFund/Validator/p2p/discover"
    55  	"github.com/EDXFund/Validator/p2p/discv5"
    56  	"github.com/EDXFund/Validator/p2p/nat"
    57  	"github.com/EDXFund/Validator/p2p/netutil"
    58  	"github.com/EDXFund/Validator/params"
    59  	//whisper "github.com/EDXFund/Validator/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  
   615  // MakeDataDir retrieves the currently requested data directory, terminating
   616  // if none (or the empty string) is specified. If the node is starting a testnet,
   617  // the a subdirectory of the specified datadir will be used.
   618  func MakeDataDir(ctx *cli.Context) string {
   619  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   620  		if ctx.GlobalBool(TestnetFlag.Name) {
   621  			return filepath.Join(path, "testnet")
   622  		}
   623  		if ctx.GlobalBool(RinkebyFlag.Name) {
   624  			return filepath.Join(path, "rinkeby")
   625  		}
   626  		return path
   627  	}
   628  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   629  	return ""
   630  }
   631  
   632  // setNodeKey creates a node key from set command line flags, either loading it
   633  // from a file or as a specified hex value. If neither flags were provided, this
   634  // method returns nil and an emphemeral key is to be generated.
   635  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   636  	var (
   637  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   638  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   639  		key  *ecdsa.PrivateKey
   640  		err  error
   641  	)
   642  	switch {
   643  	case file != "" && hex != "":
   644  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   645  	case file != "":
   646  		if key, err = crypto.LoadECDSA(file); err != nil {
   647  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   648  		}
   649  		cfg.PrivateKey = key
   650  	case hex != "":
   651  		if key, err = crypto.HexToECDSA(hex); err != nil {
   652  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   653  		}
   654  		cfg.PrivateKey = key
   655  	}
   656  }
   657  
   658  // setNodeUserIdent creates the user identifier from CLI flags.
   659  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   660  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   661  		cfg.UserIdent = identity
   662  	}
   663  }
   664  
   665  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   666  // flags, reverting to pre-configured ones if none have been specified.
   667  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   668  	urls := params.MainnetBootnodes
   669  	switch {
   670  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   671  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   672  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   673  		} else {
   674  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   675  		}
   676  	case ctx.GlobalBool(TestnetFlag.Name):
   677  		urls = params.TestnetBootnodes
   678  	case ctx.GlobalBool(RinkebyFlag.Name):
   679  		urls = params.RinkebyBootnodes
   680  	case cfg.BootstrapNodes != nil:
   681  		return // already set, don't apply defaults.
   682  	}
   683  
   684  	cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls))
   685  	for _, url := range urls {
   686  		node, err := discover.ParseNode(url)
   687  		if err != nil {
   688  			log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
   689  		}
   690  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   691  	}
   692  }
   693  
   694  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   695  // flags, reverting to pre-configured ones if none have been specified.
   696  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   697  	urls := params.DiscoveryV5Bootnodes
   698  	switch {
   699  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
   700  		if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
   701  			urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",")
   702  		} else {
   703  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   704  		}
   705  	case ctx.GlobalBool(RinkebyFlag.Name):
   706  		urls = params.RinkebyBootnodes
   707  	case cfg.BootstrapNodesV5 != nil:
   708  		return // already set, don't apply defaults.
   709  	}
   710  
   711  	cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
   712  	for _, url := range urls {
   713  		node, err := discv5.ParseNode(url)
   714  		if err != nil {
   715  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   716  			continue
   717  		}
   718  		cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   719  	}
   720  }
   721  
   722  // setListenAddress creates a TCP listening address string from set command
   723  // line flags.
   724  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   725  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   726  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   727  	}
   728  }
   729  
   730  // setNAT creates a port mapper from command line flags.
   731  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   732  	if ctx.GlobalIsSet(NATFlag.Name) {
   733  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   734  		if err != nil {
   735  			Fatalf("Option %s: %v", NATFlag.Name, err)
   736  		}
   737  		cfg.NAT = natif
   738  	}
   739  }
   740  
   741  // splitAndTrim splits input separated by a comma
   742  // and trims excessive white space from the substrings.
   743  func splitAndTrim(input string) []string {
   744  	result := strings.Split(input, ",")
   745  	for i, r := range result {
   746  		result[i] = strings.TrimSpace(r)
   747  	}
   748  	return result
   749  }
   750  
   751  // setHTTP creates the HTTP RPC listener interface string from the set
   752  // command line flags, returning empty if the HTTP endpoint is disabled.
   753  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   754  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   755  		cfg.HTTPHost = "127.0.0.1"
   756  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   757  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   758  		}
   759  	}
   760  
   761  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   762  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   763  	}
   764  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   765  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   766  	}
   767  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   768  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   769  	}
   770  	if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) {
   771  		cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
   772  	}
   773  }
   774  
   775  // setWS creates the WebSocket RPC listener interface string from the set
   776  // command line flags, returning empty if the HTTP endpoint is disabled.
   777  func setWS(ctx *cli.Context, cfg *node.Config) {
   778  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   779  		cfg.WSHost = "127.0.0.1"
   780  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   781  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   782  		}
   783  	}
   784  
   785  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   786  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   787  	}
   788  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   789  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   790  	}
   791  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   792  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   793  	}
   794  }
   795  
   796  // setIPC creates an IPC path configuration from the set command line flags,
   797  // returning an empty string if IPC was explicitly disabled, or the set path.
   798  func setIPC(ctx *cli.Context, cfg *node.Config) {
   799  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   800  	switch {
   801  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   802  		cfg.IPCPath = ""
   803  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   804  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   805  	}
   806  }
   807  
   808  // makeDatabaseHandles raises out the number of allowed file handles per process
   809  // for Geth and returns half of the allowance to assign to the database.
   810  func makeDatabaseHandles() int {
   811  	limit, err := fdlimit.Current()
   812  	if err != nil {
   813  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   814  	}
   815  	if limit < 2048 {
   816  		if err := fdlimit.Raise(2048); err != nil {
   817  			Fatalf("Failed to raise file descriptor allowance: %v", err)
   818  		}
   819  	}
   820  	if limit > 2048 { // cap database file descriptors even if more is available
   821  		limit = 2048
   822  	}
   823  	return limit / 2 // Leave half for networking and other stuff
   824  }
   825  
   826  // MakeAddress converts an account specified directly as a hex encoded string or
   827  // a key index in the key store to an internal account representation.
   828  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   829  	// If the specified account is a valid address, return it
   830  	if common.IsHexAddress(account) {
   831  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   832  	}
   833  	// Otherwise try to interpret the account as a keystore index
   834  	index, err := strconv.Atoi(account)
   835  	if err != nil || index < 0 {
   836  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   837  	}
   838  	log.Warn("-------------------------------------------------------------------")
   839  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   840  	log.Warn("This functionality is deprecated and will be removed in the future!")
   841  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   842  	log.Warn("-------------------------------------------------------------------")
   843  
   844  	accs := ks.Accounts()
   845  	if len(accs) <= index {
   846  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   847  	}
   848  	return accs[index], nil
   849  }
   850  
   851  // setEtherbase retrieves the etherbase either from the directly specified
   852  // command line flags or from the keystore if CLI indexed.
   853  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
   854  	// Extract the current etherbase, new flag overriding legacy one
   855  	var etherbase string
   856  	if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) {
   857  		etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name)
   858  	}
   859  	if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) {
   860  		etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name)
   861  	}
   862  	// Convert the etherbase into an address and configure it
   863  	if etherbase != "" {
   864  		account, err := MakeAddress(ks, etherbase)
   865  		if err != nil {
   866  			Fatalf("Invalid miner etherbase: %v", err)
   867  		}
   868  		cfg.Etherbase = account.Address
   869  	}
   870  }
   871  
   872  // MakePasswordList reads password lines from the file specified by the global --password flag.
   873  func MakePasswordList(ctx *cli.Context) []string {
   874  	path := ctx.GlobalString(PasswordFileFlag.Name)
   875  	if path == "" {
   876  		return nil
   877  	}
   878  	text, err := ioutil.ReadFile(path)
   879  	if err != nil {
   880  		Fatalf("Failed to read password file: %v", err)
   881  	}
   882  	lines := strings.Split(string(text), "\n")
   883  	// Sanitise DOS line endings.
   884  	for i := range lines {
   885  		lines[i] = strings.TrimRight(lines[i], "\r")
   886  	}
   887  	return lines
   888  }
   889  
   890  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   891  	setNodeKey(ctx, cfg)
   892  	setNAT(ctx, cfg)
   893  	setListenAddress(ctx, cfg)
   894  	setBootstrapNodes(ctx, cfg)
   895  	setBootstrapNodesV5(ctx, cfg)
   896  
   897  	lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light"
   898  	lightServer := ctx.GlobalInt(LightServFlag.Name) != 0
   899  	lightPeers := ctx.GlobalInt(LightPeersFlag.Name)
   900  
   901  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   902  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   903  		if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) {
   904  			cfg.MaxPeers += lightPeers
   905  		}
   906  	} else {
   907  		if lightServer {
   908  			cfg.MaxPeers += lightPeers
   909  		}
   910  		if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers {
   911  			cfg.MaxPeers = lightPeers
   912  		}
   913  	}
   914  	if !(lightClient || lightServer) {
   915  		lightPeers = 0
   916  	}
   917  	ethPeers := cfg.MaxPeers - lightPeers
   918  	if lightClient {
   919  		ethPeers = 0
   920  	}
   921  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
   922  
   923  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   924  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   925  	}
   926  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
   927  		cfg.NoDiscovery = true
   928  	}
   929  
   930  	// if we're running a light client or server, force enable the v5 peer discovery
   931  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   932  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   933  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   934  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   935  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   936  	} else if forceV5Discovery {
   937  		cfg.DiscoveryV5 = true
   938  	}
   939  
   940  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   941  		list, err := netutil.ParseNetlist(netrestrict)
   942  		if err != nil {
   943  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   944  		}
   945  		cfg.NetRestrict = list
   946  	}
   947  
   948  	if ctx.GlobalBool(DeveloperFlag.Name) {
   949  		// --dev mode can't use p2p networking.
   950  		cfg.MaxPeers = 0
   951  		cfg.ListenAddr = ":0"
   952  		cfg.NoDiscovery = true
   953  		cfg.DiscoveryV5 = false
   954  	}
   955  }
   956  
   957  // SetNodeConfig applies node-related command line flags to the config.
   958  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   959  	SetP2PConfig(ctx, &cfg.P2P)
   960  	setIPC(ctx, cfg)
   961  	setHTTP(ctx, cfg)
   962  	setWS(ctx, cfg)
   963  	setNodeUserIdent(ctx, cfg)
   964  
   965  	switch {
   966  	case ctx.GlobalIsSet(DataDirFlag.Name):
   967  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
   968  	case ctx.GlobalBool(DeveloperFlag.Name):
   969  		cfg.DataDir = "" // unless explicitly requested, use memory databases
   970  	case ctx.GlobalBool(TestnetFlag.Name):
   971  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
   972  	case ctx.GlobalBool(RinkebyFlag.Name):
   973  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
   974  	}
   975  
   976  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
   977  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
   978  	}
   979  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
   980  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
   981  	}
   982  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
   983  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
   984  	}
   985  }
   986  
   987  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
   988  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
   989  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
   990  	}
   991  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
   992  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
   993  	}
   994  }
   995  
   996  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
   997  	if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) {
   998  		locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",")
   999  		for _, account := range locals {
  1000  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
  1001  				Fatalf("Invalid account in --txpool.locals: %s", trimmed)
  1002  			} else {
  1003  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
  1004  			}
  1005  		}
  1006  	}
  1007  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
  1008  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
  1009  	}
  1010  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
  1011  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
  1012  	}
  1013  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
  1014  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
  1015  	}
  1016  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
  1017  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
  1018  	}
  1019  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
  1020  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
  1021  	}
  1022  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
  1023  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
  1024  	}
  1025  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
  1026  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
  1027  	}
  1028  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
  1029  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
  1030  	}
  1031  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
  1032  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
  1033  	}
  1034  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
  1035  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
  1036  	}
  1037  }
  1038  
  1039  func setEthash(ctx *cli.Context, cfg *eth.Config) {
  1040  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
  1041  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
  1042  	}
  1043  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
  1044  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
  1045  	}
  1046  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
  1047  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
  1048  	}
  1049  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
  1050  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
  1051  	}
  1052  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
  1053  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
  1054  	}
  1055  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
  1056  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
  1057  	}
  1058  }
  1059  
  1060  // checkExclusive verifies that only a single instance of the provided flags was
  1061  // set by the user. Each flag might optionally be followed by a string type to
  1062  // specialize it further.
  1063  func checkExclusive(ctx *cli.Context, args ...interface{}) {
  1064  	set := make([]string, 0, 1)
  1065  	for i := 0; i < len(args); i++ {
  1066  		// Make sure the next argument is a flag and skip if not set
  1067  		flag, ok := args[i].(cli.Flag)
  1068  		if !ok {
  1069  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1070  		}
  1071  		// Check if next arg extends current and expand its name if so
  1072  		name := flag.GetName()
  1073  
  1074  		if i+1 < len(args) {
  1075  			switch option := args[i+1].(type) {
  1076  			case string:
  1077  				// Extended flag, expand the name and shift the arguments
  1078  				if ctx.GlobalString(flag.GetName()) == option {
  1079  					name += "=" + option
  1080  				}
  1081  				i++
  1082  
  1083  			case cli.Flag:
  1084  			default:
  1085  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1086  			}
  1087  		}
  1088  		// Mark the flag if it's set
  1089  		if ctx.GlobalIsSet(flag.GetName()) {
  1090  			set = append(set, "--"+name)
  1091  		}
  1092  	}
  1093  	if len(set) > 1 {
  1094  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1095  	}
  1096  }
  1097  /*
  1098  // SetShhConfig applies shh-related command line flags to the config.
  1099  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
  1100  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
  1101  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
  1102  	}
  1103  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
  1104  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
  1105  	}
  1106  	if ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) {
  1107  		cfg.RestrictConnectionBetweenLightClients = true
  1108  	}
  1109  }
  1110  */
  1111  // SetEthConfig applies eth-related command line flags to the config.
  1112  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
  1113  	// Avoid conflicting network flags
  1114  	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
  1115  	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
  1116  
  1117  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
  1118  	setEtherbase(ctx, ks, cfg)
  1119  	setGPO(ctx, &cfg.GPO)
  1120  	setTxPool(ctx, &cfg.TxPool)
  1121  	setEthash(ctx, cfg)
  1122  
  1123  	if ctx.GlobalIsSet(SyncModeFlag.Name) {
  1124  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1125  	}
  1126  	if ctx.GlobalIsSet(LightServFlag.Name) {
  1127  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
  1128  	}
  1129  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
  1130  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
  1131  	}
  1132  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1133  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1134  	}
  1135  
  1136  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
  1137  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1138  	}
  1139  	cfg.DatabaseHandles = makeDatabaseHandles()
  1140  
  1141  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1142  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1143  	}
  1144  	cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
  1145  
  1146  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1147  		cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1148  	}
  1149  	if ctx.GlobalIsSet(MinerNotifyFlag.Name) {
  1150  		cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",")
  1151  	}
  1152  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1153  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1154  	}
  1155  	if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) {
  1156  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name))
  1157  	}
  1158  	if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
  1159  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
  1160  	}
  1161  	if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) {
  1162  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name)
  1163  	}
  1164  	if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
  1165  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
  1166  	}
  1167  	if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
  1168  		cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
  1169  	}
  1170  	if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1171  		cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name)
  1172  	}
  1173  	if ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
  1174  		cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name)
  1175  	}
  1176  	if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) {
  1177  		cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
  1178  	}
  1179  	if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
  1180  		cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name)
  1181  	}
  1182  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1183  		// TODO(fjl): force-enable this in --dev mode
  1184  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1185  	}
  1186  
  1187  	// Override any default configs for hard coded networks.
  1188  	switch {
  1189  	case ctx.GlobalBool(TestnetFlag.Name):
  1190  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1191  			cfg.NetworkId = 3
  1192  		}
  1193  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1194  	case ctx.GlobalBool(RinkebyFlag.Name):
  1195  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1196  			cfg.NetworkId = 4
  1197  		}
  1198  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1199  	case ctx.GlobalBool(DeveloperFlag.Name):
  1200  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1201  			cfg.NetworkId = 1337
  1202  		}
  1203  		// Create new developer account or reuse existing one
  1204  		var (
  1205  			developer accounts.Account
  1206  			err       error
  1207  		)
  1208  		if accs := ks.Accounts(); len(accs) > 0 {
  1209  			developer = ks.Accounts()[0]
  1210  		} else {
  1211  			developer, err = ks.NewAccount("")
  1212  			if err != nil {
  1213  				Fatalf("Failed to create developer account: %v", err)
  1214  			}
  1215  		}
  1216  		if err := ks.Unlock(developer, ""); err != nil {
  1217  			Fatalf("Failed to unlock developer account: %v", err)
  1218  		}
  1219  		log.Info("Using developer account", "address", developer.Address)
  1220  
  1221  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1222  		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1223  			cfg.MinerGasPrice = big.NewInt(1)
  1224  		}
  1225  	}
  1226  	// TODO(fjl): move trie cache generations into config
  1227  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1228  		state.MaxTrieCacheGen = uint16(gen)
  1229  	}
  1230  }
  1231  
  1232  // SetDashboardConfig applies dashboard related command line flags to the config.
  1233  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1234  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1235  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1236  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1237  }
  1238  
  1239  // RegisterEthService adds an Ethereum client to the stack.
  1240  func RegisterEthService(stack *node.Node, cfg *eth.Config,shardId uint16) {
  1241  	var err error
  1242  	/*if cfg.SyncMode == downloader.LightSync {
  1243  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1244  			return les.New(ctx, cfg)
  1245  		})
  1246  	} else {*/
  1247  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1248  			fullNode, err := eth.New(ctx, cfg,shardId)
  1249  			/*if fullNode != nil && cfg.LightServ > 0 {
  1250  				ls, _ := les.NewLesServer(fullNode, cfg)
  1251  				fullNode.AddLesServer(ls)
  1252  			}*/
  1253  			return fullNode, err
  1254  		})
  1255  	//}
  1256  	if err != nil {
  1257  		Fatalf("Failed to register the Ethereum service: %v", err)
  1258  	}
  1259  }
  1260  
  1261  // RegisterDashboardService adds a dashboard to the stack.
  1262  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
  1263  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1264  		return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil
  1265  	})
  1266  }
  1267  /*
  1268  // RegisterShhService configures Whisper and adds it to the given node.
  1269  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1270  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1271  		return whisper.New(cfg), nil
  1272  	}); err != nil {
  1273  		Fatalf("Failed to register the Whisper service: %v", err)
  1274  	}
  1275  }*/
  1276  
  1277  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1278  // the given node.
  1279  func RegisterEthStatsService(stack *node.Node, url string) {
  1280  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1281  		// Retrieve both eth and les services
  1282  		var ethServ *eth.Ethereum
  1283  		ctx.Service(&ethServ)
  1284  
  1285  		//var lesServ *les.LightEthereum
  1286  		//ctx.Service(&lesServ)
  1287  
  1288  		return ethstats.New(url, ethServ)
  1289  	}); err != nil {
  1290  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1291  	}
  1292  }
  1293  
  1294  func SetupMetrics(ctx *cli.Context) {
  1295  	if metrics.Enabled {
  1296  		log.Info("Enabling metrics collection")
  1297  		var (
  1298  			enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
  1299  			endpoint     = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
  1300  			database     = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
  1301  			username     = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
  1302  			password     = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
  1303  			hosttag      = ctx.GlobalString(MetricsInfluxDBHostTagFlag.Name)
  1304  		)
  1305  
  1306  		if enableExport {
  1307  			log.Info("Enabling metrics export to InfluxDB")
  1308  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", map[string]string{
  1309  				"host": hosttag,
  1310  			})
  1311  		}
  1312  	}
  1313  }
  1314  
  1315  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1316  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1317  	var (
  1318  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1319  		handles = makeDatabaseHandles()
  1320  	)
  1321  	name := "chaindata"
  1322  	if ctx.GlobalString(SyncModeFlag.Name) == "light" {
  1323  		name = "lightchaindata"
  1324  	}
  1325  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1326  	if err != nil {
  1327  		Fatalf("Could not open database: %v", err)
  1328  	}
  1329  	return chainDb
  1330  }
  1331  
  1332  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1333  	var genesis *core.Genesis
  1334  	switch {
  1335  	case ctx.GlobalBool(TestnetFlag.Name):
  1336  		genesis = core.DefaultTestnetGenesisBlock()
  1337  	case ctx.GlobalBool(RinkebyFlag.Name):
  1338  		genesis = core.DefaultRinkebyGenesisBlock()
  1339  	case ctx.GlobalBool(DeveloperFlag.Name):
  1340  		Fatalf("Developer chains are ephemeral")
  1341  	}
  1342  	return genesis
  1343  }
  1344  
  1345  // MakeChain creates a chain manager from set command line flags.
  1346  func MakeChain(ctx *cli.Context, stack *node.Node,shardId uint16) (chain *core.BlockChain, chainDb ethdb.Database) {
  1347  	var err error
  1348  	chainDb = MakeChainDatabase(ctx, stack)
  1349  
  1350  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx),shardId)
  1351  	if err != nil {
  1352  		Fatalf("%v", err)
  1353  	}
  1354  	var engine consensus.Engine
  1355  	if config.Clique != nil {
  1356  		engine = clique.New(config.Clique, chainDb)
  1357  	} else {
  1358  		engine = ethash.NewFaker()
  1359  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1360  			engine = ethash.New(ethash.Config{
  1361  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1362  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1363  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1364  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1365  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1366  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1367  			}, nil, false)
  1368  		}
  1369  	}
  1370  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1371  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1372  	}
  1373  	cache := &core.CacheConfig{
  1374  		Disabled:      ctx.GlobalString(GCModeFlag.Name) == "archive",
  1375  		TrieNodeLimit: eth.DefaultConfig.TrieCache,
  1376  		TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
  1377  	}
  1378  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1379  		cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1380  	}
  1381  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1382  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg,shardId)
  1383  	if err != nil {
  1384  		Fatalf("Can't create BlockChain: %v", err)
  1385  	}
  1386  	return chain, chainDb
  1387  }
  1388  
  1389  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1390  // scripts to preload before starting.
  1391  func MakeConsolePreloads(ctx *cli.Context) []string {
  1392  	// Skip preloading if there's nothing to preload
  1393  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1394  		return nil
  1395  	}
  1396  	// Otherwise resolve absolute paths and return them
  1397  	preloads := []string{}
  1398  
  1399  	assets := ctx.GlobalString(JSpathFlag.Name)
  1400  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1401  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1402  	}
  1403  	return preloads
  1404  }
  1405  
  1406  // MigrateFlags sets the global flag from a local flag when it's set.
  1407  // This is a temporary function used for migrating old command/flags to the
  1408  // new format.
  1409  //
  1410  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1411  //
  1412  // is equivalent after calling this method with:
  1413  //
  1414  // geth --keystore /tmp/mykeystore --lightkdf account new
  1415  //
  1416  // This allows the use of the existing configuration functionality.
  1417  // When all flags are migrated this function can be removed and the existing
  1418  // configuration functionality must be changed that is uses local flags
  1419  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1420  	return func(ctx *cli.Context) error {
  1421  		for _, name := range ctx.FlagNames() {
  1422  			if ctx.IsSet(name) {
  1423  				ctx.GlobalSet(name, ctx.String(name))
  1424  			}
  1425  		}
  1426  		return action(ctx)
  1427  	}
  1428  }