github.com/samgwo/go-ethereum@v1.8.2-0.20180302101319-49bcb5fbd55e/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  	"runtime"
    28  	"strconv"
    29  	"strings"
    30  
    31  	"github.com/ethereum/go-ethereum/accounts"
    32  	"github.com/ethereum/go-ethereum/accounts/keystore"
    33  	"github.com/ethereum/go-ethereum/common"
    34  	"github.com/ethereum/go-ethereum/common/fdlimit"
    35  	"github.com/ethereum/go-ethereum/consensus"
    36  	"github.com/ethereum/go-ethereum/consensus/clique"
    37  	"github.com/ethereum/go-ethereum/consensus/ethash"
    38  	"github.com/ethereum/go-ethereum/core"
    39  	"github.com/ethereum/go-ethereum/core/state"
    40  	"github.com/ethereum/go-ethereum/core/vm"
    41  	"github.com/ethereum/go-ethereum/crypto"
    42  	"github.com/ethereum/go-ethereum/dashboard"
    43  	"github.com/ethereum/go-ethereum/eth"
    44  	"github.com/ethereum/go-ethereum/eth/downloader"
    45  	"github.com/ethereum/go-ethereum/eth/gasprice"
    46  	"github.com/ethereum/go-ethereum/ethdb"
    47  	"github.com/ethereum/go-ethereum/ethstats"
    48  	"github.com/ethereum/go-ethereum/les"
    49  	"github.com/ethereum/go-ethereum/log"
    50  	"github.com/ethereum/go-ethereum/metrics"
    51  	"github.com/ethereum/go-ethereum/node"
    52  	"github.com/ethereum/go-ethereum/p2p"
    53  	"github.com/ethereum/go-ethereum/p2p/discover"
    54  	"github.com/ethereum/go-ethereum/p2p/discv5"
    55  	"github.com/ethereum/go-ethereum/p2p/nat"
    56  	"github.com/ethereum/go-ethereum/p2p/netutil"
    57  	"github.com/ethereum/go-ethereum/params"
    58  	whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
    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}}{{.cmd.Name}}{{with .cmd.ShortName}}, {{.cmd}}{{end}}{{ "\t" }}{{.cmd.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.Version
   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  	FastSyncFlag = cli.BoolFlag{
   160  		Name:  "fast",
   161  		Usage: "Enable fast syncing through state downloads",
   162  	}
   163  	LightModeFlag = cli.BoolFlag{
   164  		Name:  "light",
   165  		Usage: "Enable light client mode",
   166  	}
   167  	defaultSyncMode = eth.DefaultConfig.SyncMode
   168  	SyncModeFlag    = TextMarshalerFlag{
   169  		Name:  "syncmode",
   170  		Usage: `Blockchain sync mode ("fast", "full", or "light")`,
   171  		Value: &defaultSyncMode,
   172  	}
   173  	GCModeFlag = cli.StringFlag{
   174  		Name:  "gcmode",
   175  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   176  		Value: "full",
   177  	}
   178  	LightServFlag = cli.IntFlag{
   179  		Name:  "lightserv",
   180  		Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
   181  		Value: 0,
   182  	}
   183  	LightPeersFlag = cli.IntFlag{
   184  		Name:  "lightpeers",
   185  		Usage: "Maximum number of LES client peers",
   186  		Value: eth.DefaultConfig.LightPeers,
   187  	}
   188  	LightKDFFlag = cli.BoolFlag{
   189  		Name:  "lightkdf",
   190  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   191  	}
   192  	// Dashboard settings
   193  	DashboardEnabledFlag = cli.BoolFlag{
   194  		Name:  "dashboard",
   195  		Usage: "Enable the dashboard",
   196  	}
   197  	DashboardAddrFlag = cli.StringFlag{
   198  		Name:  "dashboard.addr",
   199  		Usage: "Dashboard listening interface",
   200  		Value: dashboard.DefaultConfig.Host,
   201  	}
   202  	DashboardPortFlag = cli.IntFlag{
   203  		Name:  "dashboard.host",
   204  		Usage: "Dashboard listening port",
   205  		Value: dashboard.DefaultConfig.Port,
   206  	}
   207  	DashboardRefreshFlag = cli.DurationFlag{
   208  		Name:  "dashboard.refresh",
   209  		Usage: "Dashboard metrics collection refresh rate",
   210  		Value: dashboard.DefaultConfig.Refresh,
   211  	}
   212  	DashboardAssetsFlag = cli.StringFlag{
   213  		Name:  "dashboard.assets",
   214  		Usage: "Developer flag to serve the dashboard from the local file system",
   215  		Value: dashboard.DefaultConfig.Assets,
   216  	}
   217  	// Ethash settings
   218  	EthashCacheDirFlag = DirectoryFlag{
   219  		Name:  "ethash.cachedir",
   220  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   221  	}
   222  	EthashCachesInMemoryFlag = cli.IntFlag{
   223  		Name:  "ethash.cachesinmem",
   224  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   225  		Value: eth.DefaultConfig.Ethash.CachesInMem,
   226  	}
   227  	EthashCachesOnDiskFlag = cli.IntFlag{
   228  		Name:  "ethash.cachesondisk",
   229  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   230  		Value: eth.DefaultConfig.Ethash.CachesOnDisk,
   231  	}
   232  	EthashDatasetDirFlag = DirectoryFlag{
   233  		Name:  "ethash.dagdir",
   234  		Usage: "Directory to store the ethash mining DAGs (default = inside home folder)",
   235  		Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir},
   236  	}
   237  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   238  		Name:  "ethash.dagsinmem",
   239  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   240  		Value: eth.DefaultConfig.Ethash.DatasetsInMem,
   241  	}
   242  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   243  		Name:  "ethash.dagsondisk",
   244  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   245  		Value: eth.DefaultConfig.Ethash.DatasetsOnDisk,
   246  	}
   247  	// Transaction pool settings
   248  	TxPoolNoLocalsFlag = cli.BoolFlag{
   249  		Name:  "txpool.nolocals",
   250  		Usage: "Disables price exemptions for locally submitted transactions",
   251  	}
   252  	TxPoolJournalFlag = cli.StringFlag{
   253  		Name:  "txpool.journal",
   254  		Usage: "Disk journal for local transaction to survive node restarts",
   255  		Value: core.DefaultTxPoolConfig.Journal,
   256  	}
   257  	TxPoolRejournalFlag = cli.DurationFlag{
   258  		Name:  "txpool.rejournal",
   259  		Usage: "Time interval to regenerate the local transaction journal",
   260  		Value: core.DefaultTxPoolConfig.Rejournal,
   261  	}
   262  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   263  		Name:  "txpool.pricelimit",
   264  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   265  		Value: eth.DefaultConfig.TxPool.PriceLimit,
   266  	}
   267  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   268  		Name:  "txpool.pricebump",
   269  		Usage: "Price bump percentage to replace an already existing transaction",
   270  		Value: eth.DefaultConfig.TxPool.PriceBump,
   271  	}
   272  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   273  		Name:  "txpool.accountslots",
   274  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   275  		Value: eth.DefaultConfig.TxPool.AccountSlots,
   276  	}
   277  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   278  		Name:  "txpool.globalslots",
   279  		Usage: "Maximum number of executable transaction slots for all accounts",
   280  		Value: eth.DefaultConfig.TxPool.GlobalSlots,
   281  	}
   282  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   283  		Name:  "txpool.accountqueue",
   284  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   285  		Value: eth.DefaultConfig.TxPool.AccountQueue,
   286  	}
   287  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   288  		Name:  "txpool.globalqueue",
   289  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   290  		Value: eth.DefaultConfig.TxPool.GlobalQueue,
   291  	}
   292  	TxPoolLifetimeFlag = cli.DurationFlag{
   293  		Name:  "txpool.lifetime",
   294  		Usage: "Maximum amount of time non-executable transaction are queued",
   295  		Value: eth.DefaultConfig.TxPool.Lifetime,
   296  	}
   297  	// Performance tuning settings
   298  	CacheFlag = cli.IntFlag{
   299  		Name:  "cache",
   300  		Usage: "Megabytes of memory allocated to internal caching",
   301  		Value: 1024,
   302  	}
   303  	CacheDatabaseFlag = cli.IntFlag{
   304  		Name:  "cache.database",
   305  		Usage: "Percentage of cache memory allowance to use for database io",
   306  		Value: 75,
   307  	}
   308  	CacheGCFlag = cli.IntFlag{
   309  		Name:  "cache.gc",
   310  		Usage: "Percentage of cache memory allowance to use for trie pruning",
   311  		Value: 25,
   312  	}
   313  	TrieCacheGenFlag = cli.IntFlag{
   314  		Name:  "trie-cache-gens",
   315  		Usage: "Number of trie node generations to keep in memory",
   316  		Value: int(state.MaxTrieCacheGen),
   317  	}
   318  	// Miner settings
   319  	MiningEnabledFlag = cli.BoolFlag{
   320  		Name:  "mine",
   321  		Usage: "Enable mining",
   322  	}
   323  	MinerThreadsFlag = cli.IntFlag{
   324  		Name:  "minerthreads",
   325  		Usage: "Number of CPU threads to use for mining",
   326  		Value: runtime.NumCPU(),
   327  	}
   328  	TargetGasLimitFlag = cli.Uint64Flag{
   329  		Name:  "targetgaslimit",
   330  		Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
   331  		Value: params.GenesisGasLimit,
   332  	}
   333  	EtherbaseFlag = cli.StringFlag{
   334  		Name:  "etherbase",
   335  		Usage: "Public address for block mining rewards (default = first account created)",
   336  		Value: "0",
   337  	}
   338  	GasPriceFlag = BigFlag{
   339  		Name:  "gasprice",
   340  		Usage: "Minimal gas price to accept for mining a transactions",
   341  		Value: eth.DefaultConfig.GasPrice,
   342  	}
   343  	ExtraDataFlag = cli.StringFlag{
   344  		Name:  "extradata",
   345  		Usage: "Block extra data set by the miner (default = client version)",
   346  	}
   347  	// Account settings
   348  	UnlockedAccountFlag = cli.StringFlag{
   349  		Name:  "unlock",
   350  		Usage: "Comma separated list of accounts to unlock",
   351  		Value: "",
   352  	}
   353  	PasswordFileFlag = cli.StringFlag{
   354  		Name:  "password",
   355  		Usage: "Password file to use for non-interactive password input",
   356  		Value: "",
   357  	}
   358  
   359  	VMEnableDebugFlag = cli.BoolFlag{
   360  		Name:  "vmdebug",
   361  		Usage: "Record information useful for VM and contract debugging",
   362  	}
   363  	// Logging and debug settings
   364  	EthStatsURLFlag = cli.StringFlag{
   365  		Name:  "ethstats",
   366  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   367  	}
   368  	MetricsEnabledFlag = cli.BoolFlag{
   369  		Name:  metrics.MetricsEnabledFlag,
   370  		Usage: "Enable metrics collection and reporting",
   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: "localhost",
   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  
   542  // MakeDataDir retrieves the currently requested data directory, terminating
   543  // if none (or the empty string) is specified. If the node is starting a testnet,
   544  // the a subdirectory of the specified datadir will be used.
   545  func MakeDataDir(ctx *cli.Context) string {
   546  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   547  		if ctx.GlobalBool(TestnetFlag.Name) {
   548  			return filepath.Join(path, "testnet")
   549  		}
   550  		if ctx.GlobalBool(RinkebyFlag.Name) {
   551  			return filepath.Join(path, "rinkeby")
   552  		}
   553  		return path
   554  	}
   555  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   556  	return ""
   557  }
   558  
   559  // setNodeKey creates a node key from set command line flags, either loading it
   560  // from a file or as a specified hex value. If neither flags were provided, this
   561  // method returns nil and an emphemeral key is to be generated.
   562  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   563  	var (
   564  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   565  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   566  		key  *ecdsa.PrivateKey
   567  		err  error
   568  	)
   569  	switch {
   570  	case file != "" && hex != "":
   571  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   572  	case file != "":
   573  		if key, err = crypto.LoadECDSA(file); err != nil {
   574  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   575  		}
   576  		cfg.PrivateKey = key
   577  	case hex != "":
   578  		if key, err = crypto.HexToECDSA(hex); err != nil {
   579  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   580  		}
   581  		cfg.PrivateKey = key
   582  	}
   583  }
   584  
   585  // setNodeUserIdent creates the user identifier from CLI flags.
   586  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   587  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   588  		cfg.UserIdent = identity
   589  	}
   590  }
   591  
   592  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   593  // flags, reverting to pre-configured ones if none have been specified.
   594  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   595  	urls := params.MainnetBootnodes
   596  	switch {
   597  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   598  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   599  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   600  		} else {
   601  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   602  		}
   603  	case ctx.GlobalBool(TestnetFlag.Name):
   604  		urls = params.TestnetBootnodes
   605  	case ctx.GlobalBool(RinkebyFlag.Name):
   606  		urls = params.RinkebyBootnodes
   607  	case cfg.BootstrapNodes != nil:
   608  		return // already set, don't apply defaults.
   609  	}
   610  
   611  	cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls))
   612  	for _, url := range urls {
   613  		node, err := discover.ParseNode(url)
   614  		if err != nil {
   615  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   616  			continue
   617  		}
   618  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   619  	}
   620  }
   621  
   622  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   623  // flags, reverting to pre-configured ones if none have been specified.
   624  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   625  	urls := params.DiscoveryV5Bootnodes
   626  	switch {
   627  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
   628  		if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
   629  			urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",")
   630  		} else {
   631  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   632  		}
   633  	case ctx.GlobalBool(RinkebyFlag.Name):
   634  		urls = params.RinkebyBootnodes
   635  	case cfg.BootstrapNodesV5 != nil:
   636  		return // already set, don't apply defaults.
   637  	}
   638  
   639  	cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
   640  	for _, url := range urls {
   641  		node, err := discv5.ParseNode(url)
   642  		if err != nil {
   643  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   644  			continue
   645  		}
   646  		cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   647  	}
   648  }
   649  
   650  // setListenAddress creates a TCP listening address string from set command
   651  // line flags.
   652  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   653  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   654  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   655  	}
   656  }
   657  
   658  // setNAT creates a port mapper from command line flags.
   659  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   660  	if ctx.GlobalIsSet(NATFlag.Name) {
   661  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   662  		if err != nil {
   663  			Fatalf("Option %s: %v", NATFlag.Name, err)
   664  		}
   665  		cfg.NAT = natif
   666  	}
   667  }
   668  
   669  // splitAndTrim splits input separated by a comma
   670  // and trims excessive white space from the substrings.
   671  func splitAndTrim(input string) []string {
   672  	result := strings.Split(input, ",")
   673  	for i, r := range result {
   674  		result[i] = strings.TrimSpace(r)
   675  	}
   676  	return result
   677  }
   678  
   679  // setHTTP creates the HTTP RPC listener interface string from the set
   680  // command line flags, returning empty if the HTTP endpoint is disabled.
   681  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   682  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   683  		cfg.HTTPHost = "127.0.0.1"
   684  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   685  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   686  		}
   687  	}
   688  
   689  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   690  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   691  	}
   692  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   693  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   694  	}
   695  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   696  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   697  	}
   698  
   699  	cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
   700  }
   701  
   702  // setWS creates the WebSocket RPC listener interface string from the set
   703  // command line flags, returning empty if the HTTP endpoint is disabled.
   704  func setWS(ctx *cli.Context, cfg *node.Config) {
   705  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   706  		cfg.WSHost = "127.0.0.1"
   707  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   708  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   709  		}
   710  	}
   711  
   712  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   713  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   714  	}
   715  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   716  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   717  	}
   718  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   719  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   720  	}
   721  }
   722  
   723  // setIPC creates an IPC path configuration from the set command line flags,
   724  // returning an empty string if IPC was explicitly disabled, or the set path.
   725  func setIPC(ctx *cli.Context, cfg *node.Config) {
   726  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   727  	switch {
   728  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   729  		cfg.IPCPath = ""
   730  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   731  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   732  	}
   733  }
   734  
   735  // makeDatabaseHandles raises out the number of allowed file handles per process
   736  // for Geth and returns half of the allowance to assign to the database.
   737  func makeDatabaseHandles() int {
   738  	limit, err := fdlimit.Current()
   739  	if err != nil {
   740  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   741  	}
   742  	if limit < 2048 {
   743  		if err := fdlimit.Raise(2048); err != nil {
   744  			Fatalf("Failed to raise file descriptor allowance: %v", err)
   745  		}
   746  	}
   747  	if limit > 2048 { // cap database file descriptors even if more is available
   748  		limit = 2048
   749  	}
   750  	return limit / 2 // Leave half for networking and other stuff
   751  }
   752  
   753  // MakeAddress converts an account specified directly as a hex encoded string or
   754  // a key index in the key store to an internal account representation.
   755  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   756  	// If the specified account is a valid address, return it
   757  	if common.IsHexAddress(account) {
   758  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   759  	}
   760  	// Otherwise try to interpret the account as a keystore index
   761  	index, err := strconv.Atoi(account)
   762  	if err != nil || index < 0 {
   763  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   764  	}
   765  	log.Warn("-------------------------------------------------------------------")
   766  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   767  	log.Warn("This functionality is deprecated and will be removed in the future!")
   768  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   769  	log.Warn("-------------------------------------------------------------------")
   770  
   771  	accs := ks.Accounts()
   772  	if len(accs) <= index {
   773  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   774  	}
   775  	return accs[index], nil
   776  }
   777  
   778  // setEtherbase retrieves the etherbase either from the directly specified
   779  // command line flags or from the keystore if CLI indexed.
   780  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
   781  	if ctx.GlobalIsSet(EtherbaseFlag.Name) {
   782  		account, err := MakeAddress(ks, ctx.GlobalString(EtherbaseFlag.Name))
   783  		if err != nil {
   784  			Fatalf("Option %q: %v", EtherbaseFlag.Name, err)
   785  		}
   786  		cfg.Etherbase = account.Address
   787  	}
   788  }
   789  
   790  // MakePasswordList reads password lines from the file specified by the global --password flag.
   791  func MakePasswordList(ctx *cli.Context) []string {
   792  	path := ctx.GlobalString(PasswordFileFlag.Name)
   793  	if path == "" {
   794  		return nil
   795  	}
   796  	text, err := ioutil.ReadFile(path)
   797  	if err != nil {
   798  		Fatalf("Failed to read password file: %v", err)
   799  	}
   800  	lines := strings.Split(string(text), "\n")
   801  	// Sanitise DOS line endings.
   802  	for i := range lines {
   803  		lines[i] = strings.TrimRight(lines[i], "\r")
   804  	}
   805  	return lines
   806  }
   807  
   808  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   809  	setNodeKey(ctx, cfg)
   810  	setNAT(ctx, cfg)
   811  	setListenAddress(ctx, cfg)
   812  	setBootstrapNodes(ctx, cfg)
   813  	setBootstrapNodesV5(ctx, cfg)
   814  
   815  	lightClient := ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalString(SyncModeFlag.Name) == "light"
   816  	lightServer := ctx.GlobalInt(LightServFlag.Name) != 0
   817  	lightPeers := ctx.GlobalInt(LightPeersFlag.Name)
   818  
   819  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   820  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   821  	} else {
   822  		if lightServer {
   823  			cfg.MaxPeers += lightPeers
   824  		}
   825  		if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers {
   826  			cfg.MaxPeers = lightPeers
   827  		}
   828  	}
   829  	if !(lightClient || lightServer) {
   830  		lightPeers = 0
   831  	}
   832  	ethPeers := cfg.MaxPeers - lightPeers
   833  	if lightClient {
   834  		ethPeers = 0
   835  	}
   836  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
   837  
   838  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   839  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   840  	}
   841  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
   842  		cfg.NoDiscovery = true
   843  	}
   844  
   845  	// if we're running a light client or server, force enable the v5 peer discovery
   846  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   847  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   848  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   849  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   850  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   851  	} else if forceV5Discovery {
   852  		cfg.DiscoveryV5 = true
   853  	}
   854  
   855  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   856  		list, err := netutil.ParseNetlist(netrestrict)
   857  		if err != nil {
   858  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   859  		}
   860  		cfg.NetRestrict = list
   861  	}
   862  
   863  	if ctx.GlobalBool(DeveloperFlag.Name) {
   864  		// --dev mode can't use p2p networking.
   865  		cfg.MaxPeers = 0
   866  		cfg.ListenAddr = ":0"
   867  		cfg.NoDiscovery = true
   868  		cfg.DiscoveryV5 = false
   869  	}
   870  }
   871  
   872  // SetNodeConfig applies node-related command line flags to the config.
   873  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   874  	SetP2PConfig(ctx, &cfg.P2P)
   875  	setIPC(ctx, cfg)
   876  	setHTTP(ctx, cfg)
   877  	setWS(ctx, cfg)
   878  	setNodeUserIdent(ctx, cfg)
   879  
   880  	switch {
   881  	case ctx.GlobalIsSet(DataDirFlag.Name):
   882  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
   883  	case ctx.GlobalBool(DeveloperFlag.Name):
   884  		cfg.DataDir = "" // unless explicitly requested, use memory databases
   885  	case ctx.GlobalBool(TestnetFlag.Name):
   886  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
   887  	case ctx.GlobalBool(RinkebyFlag.Name):
   888  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
   889  	}
   890  
   891  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
   892  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
   893  	}
   894  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
   895  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
   896  	}
   897  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
   898  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
   899  	}
   900  }
   901  
   902  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
   903  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
   904  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
   905  	}
   906  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
   907  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
   908  	}
   909  }
   910  
   911  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
   912  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
   913  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
   914  	}
   915  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
   916  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
   917  	}
   918  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
   919  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
   920  	}
   921  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
   922  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
   923  	}
   924  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
   925  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
   926  	}
   927  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
   928  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
   929  	}
   930  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
   931  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
   932  	}
   933  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
   934  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
   935  	}
   936  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
   937  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
   938  	}
   939  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
   940  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
   941  	}
   942  }
   943  
   944  func setEthash(ctx *cli.Context, cfg *eth.Config) {
   945  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
   946  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
   947  	}
   948  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
   949  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
   950  	}
   951  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
   952  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
   953  	}
   954  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
   955  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
   956  	}
   957  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
   958  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
   959  	}
   960  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
   961  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
   962  	}
   963  }
   964  
   965  // checkExclusive verifies that only a single isntance of the provided flags was
   966  // set by the user. Each flag might optionally be followed by a string type to
   967  // specialize it further.
   968  func checkExclusive(ctx *cli.Context, args ...interface{}) {
   969  	set := make([]string, 0, 1)
   970  	for i := 0; i < len(args); i++ {
   971  		// Make sure the next argument is a flag and skip if not set
   972  		flag, ok := args[i].(cli.Flag)
   973  		if !ok {
   974  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
   975  		}
   976  		// Check if next arg extends current and expand its name if so
   977  		name := flag.GetName()
   978  
   979  		if i+1 < len(args) {
   980  			switch option := args[i+1].(type) {
   981  			case string:
   982  				// Extended flag, expand the name and shift the arguments
   983  				if ctx.GlobalString(flag.GetName()) == option {
   984  					name += "=" + option
   985  				}
   986  				i++
   987  
   988  			case cli.Flag:
   989  			default:
   990  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
   991  			}
   992  		}
   993  		// Mark the flag if it's set
   994  		if ctx.GlobalIsSet(flag.GetName()) {
   995  			set = append(set, "--"+name)
   996  		}
   997  	}
   998  	if len(set) > 1 {
   999  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1000  	}
  1001  }
  1002  
  1003  // SetShhConfig applies shh-related command line flags to the config.
  1004  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
  1005  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
  1006  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
  1007  	}
  1008  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
  1009  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
  1010  	}
  1011  }
  1012  
  1013  // SetEthConfig applies eth-related command line flags to the config.
  1014  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
  1015  	// Avoid conflicting network flags
  1016  	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
  1017  	checkExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag)
  1018  	checkExclusive(ctx, LightServFlag, LightModeFlag)
  1019  	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
  1020  
  1021  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
  1022  	setEtherbase(ctx, ks, cfg)
  1023  	setGPO(ctx, &cfg.GPO)
  1024  	setTxPool(ctx, &cfg.TxPool)
  1025  	setEthash(ctx, cfg)
  1026  
  1027  	switch {
  1028  	case ctx.GlobalIsSet(SyncModeFlag.Name):
  1029  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1030  	case ctx.GlobalBool(FastSyncFlag.Name):
  1031  		cfg.SyncMode = downloader.FastSync
  1032  	case ctx.GlobalBool(LightModeFlag.Name):
  1033  		cfg.SyncMode = downloader.LightSync
  1034  	}
  1035  	if ctx.GlobalIsSet(LightServFlag.Name) {
  1036  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
  1037  	}
  1038  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
  1039  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
  1040  	}
  1041  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1042  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1043  	}
  1044  
  1045  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
  1046  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1047  	}
  1048  	cfg.DatabaseHandles = makeDatabaseHandles()
  1049  
  1050  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1051  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1052  	}
  1053  	cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
  1054  
  1055  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1056  		cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1057  	}
  1058  	if ctx.GlobalIsSet(MinerThreadsFlag.Name) {
  1059  		cfg.MinerThreads = ctx.GlobalInt(MinerThreadsFlag.Name)
  1060  	}
  1061  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1062  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1063  	}
  1064  	if ctx.GlobalIsSet(ExtraDataFlag.Name) {
  1065  		cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name))
  1066  	}
  1067  	if ctx.GlobalIsSet(GasPriceFlag.Name) {
  1068  		cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name)
  1069  	}
  1070  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1071  		// TODO(fjl): force-enable this in --dev mode
  1072  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1073  	}
  1074  
  1075  	// Override any default configs for hard coded networks.
  1076  	switch {
  1077  	case ctx.GlobalBool(TestnetFlag.Name):
  1078  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1079  			cfg.NetworkId = 3
  1080  		}
  1081  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1082  	case ctx.GlobalBool(RinkebyFlag.Name):
  1083  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1084  			cfg.NetworkId = 4
  1085  		}
  1086  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1087  	case ctx.GlobalBool(DeveloperFlag.Name):
  1088  		// Create new developer account or reuse existing one
  1089  		var (
  1090  			developer accounts.Account
  1091  			err       error
  1092  		)
  1093  		if accs := ks.Accounts(); len(accs) > 0 {
  1094  			developer = ks.Accounts()[0]
  1095  		} else {
  1096  			developer, err = ks.NewAccount("")
  1097  			if err != nil {
  1098  				Fatalf("Failed to create developer account: %v", err)
  1099  			}
  1100  		}
  1101  		if err := ks.Unlock(developer, ""); err != nil {
  1102  			Fatalf("Failed to unlock developer account: %v", err)
  1103  		}
  1104  		log.Info("Using developer account", "address", developer.Address)
  1105  
  1106  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1107  		if !ctx.GlobalIsSet(GasPriceFlag.Name) {
  1108  			cfg.GasPrice = big.NewInt(1)
  1109  		}
  1110  	}
  1111  	// TODO(fjl): move trie cache generations into config
  1112  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1113  		state.MaxTrieCacheGen = uint16(gen)
  1114  	}
  1115  }
  1116  
  1117  // SetDashboardConfig applies dashboard related command line flags to the config.
  1118  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1119  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1120  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1121  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1122  	cfg.Assets = ctx.GlobalString(DashboardAssetsFlag.Name)
  1123  }
  1124  
  1125  // RegisterEthService adds an Ethereum client to the stack.
  1126  func RegisterEthService(stack *node.Node, cfg *eth.Config) {
  1127  	var err error
  1128  	if cfg.SyncMode == downloader.LightSync {
  1129  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1130  			return les.New(ctx, cfg)
  1131  		})
  1132  	} else {
  1133  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1134  			fullNode, err := eth.New(ctx, cfg)
  1135  			if fullNode != nil && cfg.LightServ > 0 {
  1136  				ls, _ := les.NewLesServer(fullNode, cfg)
  1137  				fullNode.AddLesServer(ls)
  1138  			}
  1139  			return fullNode, err
  1140  		})
  1141  	}
  1142  	if err != nil {
  1143  		Fatalf("Failed to register the Ethereum service: %v", err)
  1144  	}
  1145  }
  1146  
  1147  // RegisterDashboardService adds a dashboard to the stack.
  1148  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
  1149  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1150  		return dashboard.New(cfg, commit)
  1151  	})
  1152  }
  1153  
  1154  // RegisterShhService configures Whisper and adds it to the given node.
  1155  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1156  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1157  		return whisper.New(cfg), nil
  1158  	}); err != nil {
  1159  		Fatalf("Failed to register the Whisper service: %v", err)
  1160  	}
  1161  }
  1162  
  1163  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1164  // th egiven node.
  1165  func RegisterEthStatsService(stack *node.Node, url string) {
  1166  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1167  		// Retrieve both eth and les services
  1168  		var ethServ *eth.Ethereum
  1169  		ctx.Service(&ethServ)
  1170  
  1171  		var lesServ *les.LightEthereum
  1172  		ctx.Service(&lesServ)
  1173  
  1174  		return ethstats.New(url, ethServ, lesServ)
  1175  	}); err != nil {
  1176  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1177  	}
  1178  }
  1179  
  1180  // SetupNetwork configures the system for either the main net or some test network.
  1181  func SetupNetwork(ctx *cli.Context) {
  1182  	// TODO(fjl): move target gas limit into config
  1183  	params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name)
  1184  }
  1185  
  1186  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1187  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1188  	var (
  1189  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1190  		handles = makeDatabaseHandles()
  1191  	)
  1192  	name := "chaindata"
  1193  	if ctx.GlobalBool(LightModeFlag.Name) {
  1194  		name = "lightchaindata"
  1195  	}
  1196  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1197  	if err != nil {
  1198  		Fatalf("Could not open database: %v", err)
  1199  	}
  1200  	return chainDb
  1201  }
  1202  
  1203  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1204  	var genesis *core.Genesis
  1205  	switch {
  1206  	case ctx.GlobalBool(TestnetFlag.Name):
  1207  		genesis = core.DefaultTestnetGenesisBlock()
  1208  	case ctx.GlobalBool(RinkebyFlag.Name):
  1209  		genesis = core.DefaultRinkebyGenesisBlock()
  1210  	case ctx.GlobalBool(DeveloperFlag.Name):
  1211  		Fatalf("Developer chains are ephemeral")
  1212  	}
  1213  	return genesis
  1214  }
  1215  
  1216  // MakeChain creates a chain manager from set command line flags.
  1217  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  1218  	var err error
  1219  	chainDb = MakeChainDatabase(ctx, stack)
  1220  
  1221  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1222  	if err != nil {
  1223  		Fatalf("%v", err)
  1224  	}
  1225  	var engine consensus.Engine
  1226  	if config.Clique != nil {
  1227  		engine = clique.New(config.Clique, chainDb)
  1228  	} else {
  1229  		engine = ethash.NewFaker()
  1230  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1231  			engine = ethash.New(ethash.Config{
  1232  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1233  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1234  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1235  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1236  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1237  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1238  			})
  1239  		}
  1240  	}
  1241  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1242  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1243  	}
  1244  	cache := &core.CacheConfig{
  1245  		Disabled:      ctx.GlobalString(GCModeFlag.Name) == "archive",
  1246  		TrieNodeLimit: eth.DefaultConfig.TrieCache,
  1247  		TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
  1248  	}
  1249  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1250  		cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1251  	}
  1252  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1253  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg)
  1254  	if err != nil {
  1255  		Fatalf("Can't create BlockChain: %v", err)
  1256  	}
  1257  	return chain, chainDb
  1258  }
  1259  
  1260  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1261  // scripts to preload before starting.
  1262  func MakeConsolePreloads(ctx *cli.Context) []string {
  1263  	// Skip preloading if there's nothing to preload
  1264  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1265  		return nil
  1266  	}
  1267  	// Otherwise resolve absolute paths and return them
  1268  	preloads := []string{}
  1269  
  1270  	assets := ctx.GlobalString(JSpathFlag.Name)
  1271  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1272  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1273  	}
  1274  	return preloads
  1275  }
  1276  
  1277  // MigrateFlags sets the global flag from a local flag when it's set.
  1278  // This is a temporary function used for migrating old command/flags to the
  1279  // new format.
  1280  //
  1281  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1282  //
  1283  // is equivalent after calling this method with:
  1284  //
  1285  // geth --keystore /tmp/mykeystore --lightkdf account new
  1286  //
  1287  // This allows the use of the existing configuration functionality.
  1288  // When all flags are migrated this function can be removed and the existing
  1289  // configuration functionality must be changed that is uses local flags
  1290  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1291  	return func(ctx *cli.Context) error {
  1292  		for _, name := range ctx.FlagNames() {
  1293  			if ctx.IsSet(name) {
  1294  				ctx.GlobalSet(name, ctx.String(name))
  1295  			}
  1296  		}
  1297  		return action(ctx)
  1298  	}
  1299  }