github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/cmd/utils/flags.go (about)

     1  // Copyright 2015 The Spectrum Authors
     2  // This file is part of Spectrum.
     3  //
     4  // Spectrum 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  // Spectrum 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 Spectrum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package utils contains internal helper functions for Spectrum commands.
    18  package utils
    19  
    20  import (
    21  	"fmt"
    22  	"io/ioutil"
    23  	"math/big"
    24  	"os"
    25  	"path/filepath"
    26  	"runtime"
    27  	"strconv"
    28  	"strings"
    29  
    30  	"github.com/SmartMeshFoundation/Spectrum/accounts"
    31  	"github.com/SmartMeshFoundation/Spectrum/accounts/keystore"
    32  	"github.com/SmartMeshFoundation/Spectrum/common"
    33  	"github.com/SmartMeshFoundation/Spectrum/consensus"
    34  	"github.com/SmartMeshFoundation/Spectrum/consensus/clique"
    35  	"github.com/SmartMeshFoundation/Spectrum/consensus/ethash"
    36  	"github.com/SmartMeshFoundation/Spectrum/core"
    37  	"github.com/SmartMeshFoundation/Spectrum/core/state"
    38  	"github.com/SmartMeshFoundation/Spectrum/core/vm"
    39  	"github.com/SmartMeshFoundation/Spectrum/dashboard"
    40  	"github.com/SmartMeshFoundation/Spectrum/eth"
    41  	"github.com/SmartMeshFoundation/Spectrum/eth/downloader"
    42  	"github.com/SmartMeshFoundation/Spectrum/eth/gasprice"
    43  	"github.com/SmartMeshFoundation/Spectrum/ethdb"
    44  	"github.com/SmartMeshFoundation/Spectrum/ethstats"
    45  	"github.com/SmartMeshFoundation/Spectrum/les"
    46  	"github.com/SmartMeshFoundation/Spectrum/log"
    47  	"github.com/SmartMeshFoundation/Spectrum/metrics"
    48  	"github.com/SmartMeshFoundation/Spectrum/node"
    49  	"github.com/SmartMeshFoundation/Spectrum/p2p"
    50  	"github.com/SmartMeshFoundation/Spectrum/p2p/discover"
    51  	"github.com/SmartMeshFoundation/Spectrum/p2p/discv5"
    52  	"github.com/SmartMeshFoundation/Spectrum/p2p/nat"
    53  	"github.com/SmartMeshFoundation/Spectrum/p2p/netutil"
    54  	"github.com/SmartMeshFoundation/Spectrum/params"
    55  	whisper "github.com/SmartMeshFoundation/Spectrum/whisper/whisperv5"
    56  	"gopkg.in/urfave/cli.v1"
    57  )
    58  
    59  var (
    60  	CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...]
    61  {{if .cmd.Description}}{{.cmd.Description}}
    62  {{end}}{{if .cmd.Subcommands}}
    63  SUBCOMMANDS:
    64  	{{range .cmd.Subcommands}}{{.cmd.Name}}{{with .cmd.ShortName}}, {{.cmd}}{{end}}{{ "\t" }}{{.cmd.Usage}}
    65  	{{end}}{{end}}{{if .categorizedFlags}}
    66  {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
    67  {{range $categorized.Flags}}{{"\t"}}{{.}}
    68  {{end}}
    69  {{end}}{{end}}`
    70  )
    71  
    72  func init() {
    73  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    74  
    75  VERSION:
    76     {{.Version}}
    77  
    78  COMMANDS:
    79     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    80     {{end}}{{if .Flags}}
    81  GLOBAL OPTIONS:
    82     {{range .Flags}}{{.}}
    83     {{end}}{{end}}
    84  `
    85  
    86  	cli.CommandHelpTemplate = CommandHelpTemplate
    87  }
    88  
    89  // NewApp creates an app with sane defaults.
    90  func NewApp(gitCommit, usage string) *cli.App {
    91  	app := cli.NewApp()
    92  	app.Name = filepath.Base(os.Args[0])
    93  	app.Author = ""
    94  	//app.Authors = nil
    95  	app.Email = ""
    96  	app.Version = params.Version
    97  	if gitCommit != "" {
    98  		app.Version += "-" + gitCommit[:8]
    99  	}
   100  	app.Usage = usage
   101  	return app
   102  }
   103  
   104  // These are all the command line flags we support.
   105  // If you add to this list, please remember to include the
   106  // flag in the appropriate command definition.
   107  //
   108  // The flags are defined here so their names and help texts
   109  // are the same for all commands.
   110  
   111  var (
   112  	// General settings
   113  	DataDirFlag = DirectoryFlag{
   114  		Name:  "datadir",
   115  		Usage: "Data directory for the databases and keystore",
   116  		Value: DirectoryString{node.DefaultDataDir()},
   117  	}
   118  	KeyStoreDirFlag = DirectoryFlag{
   119  		Name:  "keystore",
   120  		Usage: "Directory for the keystore (default = inside the datadir)",
   121  	}
   122  	NoUSBFlag = cli.BoolFlag{
   123  		Name:  "nousb",
   124  		Usage: "Disables monitoring for and managing USB hardware wallets",
   125  	}
   126  	NetworkIdFlag = cli.Uint64Flag{
   127  		Name:  "networkid",
   128  		Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)",
   129  		Value: eth.DefaultConfig.NetworkId,
   130  	}
   131  	TestnetFlag = cli.BoolFlag{
   132  		Name:  "testnet",
   133  		Usage: "Ropsten network: pre-configured POC test network",
   134  	}
   135  
   136  	// add by liangc for devnet >>>>>>>>>>>>>>>>>>>>>>>>>
   137  	DevnetFlag = cli.BoolFlag{
   138  		Name:  "devnet",
   139  		Usage: "Ephemeral POC network with a pre-funded developer account, mining enabled",
   140  	}
   141  
   142  	DevnetResetFlag = cli.BoolFlag{
   143  		Name:  "devreset",
   144  		Usage: "clean all devnet data and reset",
   145  	}
   146  
   147  	DevnetMasterFlag = cli.BoolFlag{
   148  		Name:  "devmaster",
   149  		Usage: "one devnet only one master, the master is genesis signer",
   150  	}
   151  	// add by liangc for devnet <<<<<<<<<<<<<<<<<<<<<<<<<
   152  
   153  	DeveloperFlag = cli.BoolFlag{
   154  		Name:  "dev",
   155  		Usage: "Ephemeral POC network with a pre-funded developer account, mining enabled",
   156  	}
   157  
   158  	/*
   159  		DeveloperPeriodFlag = cli.IntFlag{
   160  			Name:  "dev.period",
   161  			Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   162  		}*/
   163  	IdentityFlag = cli.StringFlag{
   164  		Name:  "identity",
   165  		Usage: "Custom node name",
   166  	}
   167  	DocRootFlag = DirectoryFlag{
   168  		Name:  "docroot",
   169  		Usage: "Document Root for HTTPClient file scheme",
   170  		Value: DirectoryString{homeDir()},
   171  	}
   172  	FastSyncFlag = cli.BoolFlag{
   173  		Name:  "fast",
   174  		Usage: "Enable fast syncing through state downloads",
   175  	}
   176  	LightModeFlag = cli.BoolFlag{
   177  		Name:  "light",
   178  		Usage: "Enable light client mode",
   179  	}
   180  	defaultSyncMode = eth.DefaultConfig.SyncMode
   181  	SyncModeFlag    = TextMarshalerFlag{
   182  		Name:  "syncmode",
   183  		Usage: `Blockchain sync mode ("full" or "light(TODO:not yet)")`,
   184  		Value: &defaultSyncMode,
   185  	}
   186  
   187  	LightServFlag = cli.IntFlag{
   188  		Name:  "lightserv",
   189  		Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
   190  		Value: 0,
   191  	}
   192  	LightPeersFlag = cli.IntFlag{
   193  		Name:  "lightpeers",
   194  		Usage: "Maximum number of LES client peers",
   195  		Value: 20,
   196  	}
   197  	LightKDFFlag = cli.BoolFlag{
   198  		Name:  "lightkdf",
   199  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   200  	}
   201  	// Dashboard settings
   202  	DashboardEnabledFlag = cli.BoolFlag{
   203  		Name:  "dashboard",
   204  		Usage: "Enable the dashboard",
   205  	}
   206  	DashboardAddrFlag = cli.StringFlag{
   207  		Name:  "dashboard.addr",
   208  		Usage: "Dashboard listening interface",
   209  		Value: dashboard.DefaultConfig.Host,
   210  	}
   211  	DashboardPortFlag = cli.IntFlag{
   212  		Name:  "dashboard.host",
   213  		Usage: "Dashboard listening port",
   214  		Value: dashboard.DefaultConfig.Port,
   215  	}
   216  	DashboardRefreshFlag = cli.DurationFlag{
   217  		Name:  "dashboard.refresh",
   218  		Usage: "Dashboard metrics collection refresh rate",
   219  		Value: dashboard.DefaultConfig.Refresh,
   220  	}
   221  	DashboardAssetsFlag = cli.StringFlag{
   222  		Name:  "dashboard.assets",
   223  		Usage: "Developer flag to serve the dashboard from the local file system",
   224  		Value: dashboard.DefaultConfig.Assets,
   225  	}
   226  	// Ethash settings
   227  	EthashCacheDirFlag = DirectoryFlag{
   228  		Name:  "ethash.cachedir",
   229  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   230  	}
   231  	EthashCachesInMemoryFlag = cli.IntFlag{
   232  		Name:  "ethash.cachesinmem",
   233  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   234  		Value: eth.DefaultConfig.Ethash.CachesInMem,
   235  	}
   236  	EthashCachesOnDiskFlag = cli.IntFlag{
   237  		Name:  "ethash.cachesondisk",
   238  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   239  		Value: eth.DefaultConfig.Ethash.CachesOnDisk,
   240  	}
   241  	EthashDatasetDirFlag = DirectoryFlag{
   242  		Name:  "ethash.dagdir",
   243  		Usage: "Directory to store the ethash mining DAGs (default = inside home folder)",
   244  		Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir},
   245  	}
   246  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   247  		Name:  "ethash.dagsinmem",
   248  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   249  		Value: eth.DefaultConfig.Ethash.DatasetsInMem,
   250  	}
   251  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   252  		Name:  "ethash.dagsondisk",
   253  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   254  		Value: eth.DefaultConfig.Ethash.DatasetsOnDisk,
   255  	}
   256  	// Transaction pool settings
   257  	TxPoolNoLocalsFlag = cli.BoolFlag{
   258  		Name:  "txpool.nolocals",
   259  		Usage: "Disables price exemptions for locally submitted transactions",
   260  	}
   261  	TxPoolJournalFlag = cli.StringFlag{
   262  		Name:  "txpool.journal",
   263  		Usage: "Disk journal for local transaction to survive node restarts",
   264  		Value: core.DefaultTxPoolConfig.Journal,
   265  	}
   266  	TxPoolRejournalFlag = cli.DurationFlag{
   267  		Name:  "txpool.rejournal",
   268  		Usage: "Time interval to regenerate the local transaction journal",
   269  		Value: core.DefaultTxPoolConfig.Rejournal,
   270  	}
   271  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   272  		Name:  "txpool.pricelimit",
   273  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   274  		Value: eth.DefaultConfig.TxPool.PriceLimit,
   275  	}
   276  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   277  		Name:  "txpool.pricebump",
   278  		Usage: "Price bump percentage to replace an already existing transaction",
   279  		Value: eth.DefaultConfig.TxPool.PriceBump,
   280  	}
   281  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   282  		Name:  "txpool.accountslots",
   283  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   284  		Value: eth.DefaultConfig.TxPool.AccountSlots,
   285  	}
   286  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   287  		Name:  "txpool.globalslots",
   288  		Usage: "Maximum number of executable transaction slots for all accounts",
   289  		Value: eth.DefaultConfig.TxPool.GlobalSlots,
   290  	}
   291  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   292  		Name:  "txpool.accountqueue",
   293  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   294  		Value: eth.DefaultConfig.TxPool.AccountQueue,
   295  	}
   296  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   297  		Name:  "txpool.globalqueue",
   298  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   299  		Value: eth.DefaultConfig.TxPool.GlobalQueue,
   300  	}
   301  	TxPoolLifetimeFlag = cli.DurationFlag{
   302  		Name:  "txpool.lifetime",
   303  		Usage: "Maximum amount of time non-executable transaction are queued",
   304  		Value: eth.DefaultConfig.TxPool.Lifetime,
   305  	}
   306  	// Performance tuning settings
   307  	CacheFlag = cli.IntFlag{
   308  		Name:  "cache",
   309  		Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)",
   310  		Value: 128,
   311  	}
   312  	TrieCacheGenFlag = cli.IntFlag{
   313  		Name:  "trie-cache-gens",
   314  		Usage: "Number of trie node generations to keep in memory",
   315  		Value: int(state.MaxTrieCacheGen),
   316  	}
   317  	// Miner settings
   318  	MiningEnabledFlag = cli.BoolFlag{
   319  		Name:  "mine",
   320  		Usage: "Enable mining",
   321  	}
   322  	MinerThreadsFlag = cli.IntFlag{
   323  		Name:  "minerthreads",
   324  		Usage: "Number of CPU threads to use for mining",
   325  		Value: runtime.NumCPU(),
   326  	}
   327  	TargetGasLimitFlag = cli.Uint64Flag{
   328  		Name:  "targetgaslimit",
   329  		Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
   330  		Value: params.GenesisGasLimit.Uint64(),
   331  	}
   332  	EtherbaseFlag = cli.StringFlag{
   333  		Name:  "etherbase",
   334  		Usage: "Public address for block mining rewards (default = first account created)",
   335  		Value: "0",
   336  	}
   337  	GasPriceFlag = BigFlag{
   338  		Name:  "gasprice",
   339  		Usage: "Minimal gas price to accept for mining a transactions",
   340  		Value: eth.DefaultConfig.GasPrice,
   341  	}
   342  	ExtraDataFlag = cli.StringFlag{
   343  		Name:  "extradata",
   344  		Usage: "Block extra data set by the miner (default = client version)",
   345  	}
   346  	// Account settings
   347  	UnlockedAccountFlag = cli.StringFlag{
   348  		Name:  "unlock",
   349  		Usage: "Comma separated list of accounts to unlock",
   350  		Value: "",
   351  	}
   352  	PasswordFileFlag = cli.StringFlag{
   353  		Name:  "password",
   354  		Usage: "Password file to use for non-interactive password input",
   355  		Value: "",
   356  	}
   357  
   358  	VMEnableDebugFlag = cli.BoolFlag{
   359  		Name:  "vmdebug",
   360  		Usage: "Record information useful for VM and contract debugging",
   361  	}
   362  	// Logging and debug settings
   363  	EthStatsURLFlag = cli.StringFlag{
   364  		Name:  "ethstats",
   365  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   366  	}
   367  	MetricsEnabledFlag = cli.BoolFlag{
   368  		Name:  metrics.MetricsEnabledFlag,
   369  		Usage: "Enable metrics collection and reporting",
   370  	}
   371  	FakePoWFlag = cli.BoolFlag{
   372  		Name:  "fakepow",
   373  		Usage: "Disables proof-of-work verification",
   374  	}
   375  	NoCompactionFlag = cli.BoolFlag{
   376  		Name:  "nocompaction",
   377  		Usage: "Disables db compaction after import",
   378  	}
   379  	// RPC settings
   380  	RPCEnabledFlag = cli.BoolFlag{
   381  		Name:  "rpc",
   382  		Usage: "Enable the HTTP-RPC server",
   383  	}
   384  	RPCListenAddrFlag = cli.StringFlag{
   385  		Name:  "rpcaddr",
   386  		Usage: "HTTP-RPC server listening interface",
   387  		Value: node.DefaultHTTPHost,
   388  	}
   389  	RPCPortFlag = cli.IntFlag{
   390  		Name:  "rpcport",
   391  		Usage: "HTTP-RPC server listening port",
   392  		Value: node.DefaultHTTPPort,
   393  	}
   394  	RPCCORSDomainFlag = cli.StringFlag{
   395  		Name:  "rpccorsdomain",
   396  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   397  		Value: "",
   398  	}
   399  	RPCApiFlag = cli.StringFlag{
   400  		Name:  "rpcapi",
   401  		Usage: "API's offered over the HTTP-RPC interface",
   402  		Value: "",
   403  	}
   404  	IPCDisabledFlag = cli.BoolFlag{
   405  		Name:  "ipcdisable",
   406  		Usage: "Disable the IPC-RPC server",
   407  	}
   408  	IPCPathFlag = DirectoryFlag{
   409  		Name:  "ipcpath",
   410  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   411  	}
   412  	WSEnabledFlag = cli.BoolFlag{
   413  		Name:  "ws",
   414  		Usage: "Enable the WS-RPC server",
   415  	}
   416  	WSListenAddrFlag = cli.StringFlag{
   417  		Name:  "wsaddr",
   418  		Usage: "WS-RPC server listening interface",
   419  		Value: node.DefaultWSHost,
   420  	}
   421  	WSPortFlag = cli.IntFlag{
   422  		Name:  "wsport",
   423  		Usage: "WS-RPC server listening port",
   424  		Value: node.DefaultWSPort,
   425  	}
   426  	WSApiFlag = cli.StringFlag{
   427  		Name:  "wsapi",
   428  		Usage: "API's offered over the WS-RPC interface",
   429  		Value: "",
   430  	}
   431  	WSAllowedOriginsFlag = cli.StringFlag{
   432  		Name:  "wsorigins",
   433  		Usage: "Origins from which to accept websockets requests",
   434  		Value: "",
   435  	}
   436  	ExecFlag = cli.StringFlag{
   437  		Name:  "exec",
   438  		Usage: "Execute JavaScript statement",
   439  	}
   440  	PreloadJSFlag = cli.StringFlag{
   441  		Name:  "preload",
   442  		Usage: "Comma separated list of JavaScript files to preload into the console",
   443  	}
   444  
   445  	// Network Settings
   446  	MaxPeersFlag = cli.IntFlag{
   447  		Name:  "maxpeers",
   448  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   449  		Value: 25,
   450  	}
   451  	MaxPendingPeersFlag = cli.IntFlag{
   452  		Name:  "maxpendpeers",
   453  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   454  		Value: 0,
   455  	}
   456  	ListenPortFlag = cli.IntFlag{
   457  		Name:  "port",
   458  		Usage: "Network listening port",
   459  		Value: 60303,
   460  	}
   461  	BootnodesFlag = cli.StringFlag{
   462  		Name:  "bootnodes",
   463  		Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
   464  		Value: "",
   465  	}
   466  	BootnodesV4Flag = cli.StringFlag{
   467  		Name:  "bootnodesv4",
   468  		Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
   469  		Value: "",
   470  	}
   471  	BootnodesV5Flag = cli.StringFlag{
   472  		Name:  "bootnodesv5",
   473  		Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
   474  		Value: "",
   475  	}
   476  	/*
   477  		NodeKeyFileFlag = cli.StringFlag{
   478  			Name:  "nodekey",
   479  			Usage: "P2P node key file",
   480  		}
   481  		NodeKeyHexFlag = cli.StringFlag{
   482  			Name:  "nodekeyhex",
   483  			Usage: "P2P node key as hex (for testing)",
   484  		}*/
   485  
   486  	NATFlag = cli.StringFlag{
   487  		Name:  "nat",
   488  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   489  		Value: "any",
   490  	}
   491  	NoDiscoverFlag = cli.BoolFlag{
   492  		Name:  "nodiscover",
   493  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   494  	}
   495  	DiscoveryV5Flag = cli.BoolFlag{
   496  		Name:  "v5disc",
   497  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   498  	}
   499  	NetrestrictFlag = cli.StringFlag{
   500  		Name:  "netrestrict",
   501  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   502  	}
   503  
   504  	// ATM the url is left to the user and deployment to
   505  	JSpathFlag = cli.StringFlag{
   506  		Name:  "jspath",
   507  		Usage: "JavaScript root path for `loadScript`",
   508  		Value: ".",
   509  	}
   510  
   511  	// Gas price oracle settings
   512  	GpoBlocksFlag = cli.IntFlag{
   513  		Name:  "gpoblocks",
   514  		Usage: "Number of recent blocks to check for gas prices",
   515  		Value: eth.DefaultConfig.GPO.Blocks,
   516  	}
   517  	GpoPercentileFlag = cli.IntFlag{
   518  		Name:  "gpopercentile",
   519  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   520  		Value: eth.DefaultConfig.GPO.Percentile,
   521  	}
   522  	WhisperEnabledFlag = cli.BoolFlag{
   523  		Name:  "shh",
   524  		Usage: "Enable Whisper",
   525  	}
   526  	WhisperMaxMessageSizeFlag = cli.IntFlag{
   527  		Name:  "shh.maxmessagesize",
   528  		Usage: "Max message size accepted",
   529  		Value: int(whisper.DefaultMaxMessageSize),
   530  	}
   531  	WhisperMinPOWFlag = cli.Float64Flag{
   532  		Name:  "shh.pow",
   533  		Usage: "Minimum POW accepted",
   534  		Value: whisper.DefaultMinimumPoW,
   535  	}
   536  )
   537  
   538  // MakeDataDir retrieves the currently requested data directory, terminating
   539  // if none (or the empty string) is specified. If the node is starting a testnet,
   540  // the a subdirectory of the specified datadir will be used.
   541  func MakeDataDir(ctx *cli.Context) string {
   542  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   543  		if ctx.GlobalBool(TestnetFlag.Name) {
   544  			return filepath.Join(path, "testnet")
   545  		}
   546  		if ctx.GlobalBool(DevnetFlag.Name) {
   547  			return filepath.Join(path, "devnet")
   548  		}
   549  		return path
   550  	}
   551  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   552  	return ""
   553  }
   554  
   555  // setNodeKey creates a node key from set command line flags, either loading it
   556  // from a file or as a specified hex value. If neither flags were provided, this
   557  // method returns nil and an emphemeral key is to be generated.
   558  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   559  	/* add by liangc : disable this method
   560  	var (
   561  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   562  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   563  		key  *ecdsa.PrivateKey
   564  		err  error
   565  	)
   566  	switch {
   567  	case file != "" && hex != "":
   568  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   569  	case file != "":
   570  		if key, err = crypto.LoadECDSA(file); err != nil {
   571  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   572  		}
   573  		cfg.PrivateKey = key
   574  	case hex != "":
   575  		if key, err = crypto.HexToECDSA(hex); err != nil {
   576  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   577  		}
   578  		cfg.PrivateKey = key
   579  	}
   580  	*/
   581  }
   582  
   583  // setNodeUserIdent creates the user identifier from CLI flags.
   584  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   585  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   586  		cfg.UserIdent = identity
   587  	}
   588  }
   589  
   590  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   591  // flags, reverting to pre-configured ones if none have been specified.
   592  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   593  	urls := params.MainnetBootnodes
   594  	switch {
   595  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   596  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   597  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   598  		} else {
   599  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   600  		}
   601  	case ctx.GlobalBool(TestnetFlag.Name):
   602  		urls = params.TestnetBootnodes
   603  	case ctx.GlobalBool(DevnetFlag.Name):
   604  		urls = params.DevnetBootnodes
   605  	case cfg.BootstrapNodes != nil:
   606  		return // already set, don't apply defaults.
   607  	}
   608  
   609  	cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls))
   610  	for _, url := range urls {
   611  		node, err := discover.ParseNode(url)
   612  		if err != nil {
   613  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   614  			continue
   615  		}
   616  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   617  	}
   618  }
   619  
   620  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   621  // flags, reverting to pre-configured ones if none have been specified.
   622  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   623  	urls := params.DiscoveryV5Bootnodes
   624  	switch {
   625  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
   626  		if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
   627  			urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",")
   628  		} else {
   629  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   630  		}
   631  	case cfg.BootstrapNodesV5 != nil:
   632  		return // already set, don't apply defaults.
   633  	}
   634  
   635  	cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
   636  	for _, url := range urls {
   637  		node, err := discv5.ParseNode(url)
   638  		if err != nil {
   639  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   640  			continue
   641  		}
   642  		cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   643  	}
   644  }
   645  
   646  // setListenAddress creates a TCP listening address string from set command
   647  // line flags.
   648  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   649  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   650  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   651  	}
   652  }
   653  
   654  // setDiscoveryV5Address creates a UDP listening address string from set command
   655  // line flags for the V5 discovery protocol.
   656  func setDiscoveryV5Address(ctx *cli.Context, cfg *p2p.Config) {
   657  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   658  		cfg.DiscoveryV5Addr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)+1)
   659  	}
   660  }
   661  
   662  // setNAT creates a port mapper from command line flags.
   663  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   664  	if ctx.GlobalIsSet(NATFlag.Name) {
   665  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   666  		if err != nil {
   667  			Fatalf("Option %s: %v", NATFlag.Name, err)
   668  		}
   669  		cfg.NAT = natif
   670  	}
   671  }
   672  
   673  // splitAndTrim splits input separated by a comma
   674  // and trims excessive white space from the substrings.
   675  func splitAndTrim(input string) []string {
   676  	result := strings.Split(input, ",")
   677  	for i, r := range result {
   678  		result[i] = strings.TrimSpace(r)
   679  	}
   680  	return result
   681  }
   682  
   683  // setHTTP creates the HTTP RPC listener interface string from the set
   684  // command line flags, returning empty if the HTTP endpoint is disabled.
   685  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   686  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   687  		cfg.HTTPHost = "127.0.0.1"
   688  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   689  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   690  		}
   691  	}
   692  
   693  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   694  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   695  	}
   696  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   697  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   698  	}
   699  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   700  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   701  	}
   702  }
   703  
   704  // setWS creates the WebSocket RPC listener interface string from the set
   705  // command line flags, returning empty if the HTTP endpoint is disabled.
   706  func setWS(ctx *cli.Context, cfg *node.Config) {
   707  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   708  		cfg.WSHost = "127.0.0.1"
   709  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   710  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   711  		}
   712  	}
   713  
   714  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   715  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   716  	}
   717  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   718  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   719  	}
   720  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   721  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   722  	}
   723  }
   724  
   725  // setIPC creates an IPC path configuration from the set command line flags,
   726  // returning an empty string if IPC was explicitly disabled, or the set path.
   727  func setIPC(ctx *cli.Context, cfg *node.Config) {
   728  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   729  	switch {
   730  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   731  		cfg.IPCPath = ""
   732  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   733  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   734  	}
   735  }
   736  
   737  // makeDatabaseHandles raises out the number of allowed file handles per process
   738  // for Geth and returns half of the allowance to assign to the database.
   739  func makeDatabaseHandles() int {
   740  	if err := raiseFdLimit(2048); err != nil {
   741  		Fatalf("Failed to raise file descriptor allowance: %v", err)
   742  	}
   743  	limit, err := getFdLimit()
   744  	if err != nil {
   745  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   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 `smc 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  	setDiscoveryV5Address(ctx, cfg)
   813  	setBootstrapNodes(ctx, cfg)
   814  	setBootstrapNodesV5(ctx, cfg)
   815  
   816  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   817  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   818  	}
   819  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   820  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   821  	}
   822  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name) {
   823  		cfg.NoDiscovery = true
   824  	}
   825  
   826  	// if we're running a light client or server, force enable the v5 peer discovery
   827  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   828  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   829  	forceV5Discovery := (ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   830  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   831  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   832  	} else if forceV5Discovery {
   833  		cfg.DiscoveryV5 = true
   834  	}
   835  
   836  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   837  		list, err := netutil.ParseNetlist(netrestrict)
   838  		if err != nil {
   839  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   840  		}
   841  		cfg.NetRestrict = list
   842  	}
   843  
   844  	if ctx.GlobalBool(DeveloperFlag.Name) {
   845  		// --dev mode can't use p2p networking.
   846  		cfg.MaxPeers = 0
   847  		cfg.ListenAddr = ":0"
   848  		cfg.DiscoveryV5Addr = ":0"
   849  		cfg.NoDiscovery = true
   850  		cfg.DiscoveryV5 = false
   851  	}
   852  }
   853  
   854  // SetNodeConfig applies node-related command line flags to the config.
   855  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   856  	SetP2PConfig(ctx, &cfg.P2P)
   857  	setIPC(ctx, cfg)
   858  	setHTTP(ctx, cfg)
   859  	setWS(ctx, cfg)
   860  	setNodeUserIdent(ctx, cfg)
   861  
   862  	switch {
   863  	case ctx.GlobalIsSet(DataDirFlag.Name):
   864  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
   865  	case ctx.GlobalBool(DeveloperFlag.Name):
   866  		cfg.DataDir = "" // unless explicitly requested, use memory databases
   867  	case ctx.GlobalBool(TestnetFlag.Name):
   868  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
   869  	case ctx.GlobalBool(DevnetFlag.Name):
   870  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "devnet")
   871  	}
   872  
   873  	if ctx.GlobalBool(DevnetFlag.Name) {
   874  		cfg.Devnet = ctx.GlobalBool(DevnetFlag.Name)
   875  		cfg.DevReset = ctx.GlobalBool(DevnetResetFlag.Name)
   876  		cfg.DevMaster = ctx.GlobalBool(DevnetMasterFlag.Name)
   877  	}
   878  
   879  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
   880  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
   881  	}
   882  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
   883  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
   884  	}
   885  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
   886  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
   887  	}
   888  }
   889  
   890  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
   891  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
   892  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
   893  	}
   894  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
   895  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
   896  	}
   897  }
   898  
   899  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
   900  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
   901  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
   902  	}
   903  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
   904  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
   905  	}
   906  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
   907  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
   908  	}
   909  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
   910  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
   911  	}
   912  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
   913  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
   914  	}
   915  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
   916  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
   917  	}
   918  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
   919  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
   920  	}
   921  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
   922  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
   923  	}
   924  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
   925  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
   926  	}
   927  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
   928  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
   929  	}
   930  }
   931  
   932  func setEthash(ctx *cli.Context, cfg *eth.Config) {
   933  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
   934  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
   935  	}
   936  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
   937  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
   938  	}
   939  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
   940  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
   941  	}
   942  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
   943  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
   944  	}
   945  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
   946  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
   947  	}
   948  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
   949  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
   950  	}
   951  }
   952  
   953  // checkExclusive verifies that only a single isntance of the provided flags was
   954  // set by the user. Each flag might optionally be followed by a string type to
   955  // specialize it further.
   956  func checkExclusive(ctx *cli.Context, args ...interface{}) {
   957  	set := make([]string, 0, 1)
   958  	for i := 0; i < len(args); i++ {
   959  		// Make sure the next argument is a flag and skip if not set
   960  		flag, ok := args[i].(cli.Flag)
   961  		if !ok {
   962  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
   963  		}
   964  		// Check if next arg extends current and expand its name if so
   965  		name := flag.GetName()
   966  
   967  		if i+1 < len(args) {
   968  			switch option := args[i+1].(type) {
   969  			case string:
   970  				// Extended flag, expand the name and shift the arguments
   971  				if ctx.GlobalString(flag.GetName()) == option {
   972  					name += "=" + option
   973  				}
   974  				i++
   975  
   976  			case cli.Flag:
   977  			default:
   978  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
   979  			}
   980  		}
   981  		// Mark the flag if it's set
   982  		if ctx.GlobalIsSet(flag.GetName()) {
   983  			set = append(set, "--"+name)
   984  		}
   985  	}
   986  	if len(set) > 1 {
   987  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
   988  	}
   989  }
   990  
   991  // SetShhConfig applies shh-related command line flags to the config.
   992  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
   993  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
   994  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
   995  	}
   996  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
   997  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
   998  	}
   999  }
  1000  
  1001  // SetEthConfig applies eth-related command line flags to the config.
  1002  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
  1003  	// Avoid conflicting network flags
  1004  	checkExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag)
  1005  	checkExclusive(ctx, LightServFlag, LightModeFlag)
  1006  	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
  1007  
  1008  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
  1009  	setEtherbase(ctx, ks, cfg)
  1010  	setGPO(ctx, &cfg.GPO)
  1011  	setTxPool(ctx, &cfg.TxPool)
  1012  	setEthash(ctx, cfg)
  1013  
  1014  	switch {
  1015  	case ctx.GlobalIsSet(SyncModeFlag.Name):
  1016  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1017  	case ctx.GlobalBool(FastSyncFlag.Name):
  1018  		cfg.SyncMode = downloader.FastSync
  1019  	case ctx.GlobalBool(LightModeFlag.Name):
  1020  		cfg.SyncMode = downloader.LightSync
  1021  	}
  1022  	if ctx.GlobalIsSet(LightServFlag.Name) {
  1023  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
  1024  	}
  1025  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
  1026  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
  1027  	}
  1028  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1029  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1030  	}
  1031  
  1032  	if ctx.GlobalIsSet(CacheFlag.Name) {
  1033  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name)
  1034  	}
  1035  	cfg.DatabaseHandles = makeDatabaseHandles()
  1036  
  1037  	if ctx.GlobalIsSet(MinerThreadsFlag.Name) {
  1038  		cfg.MinerThreads = ctx.GlobalInt(MinerThreadsFlag.Name)
  1039  	}
  1040  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1041  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1042  	}
  1043  	if ctx.GlobalIsSet(ExtraDataFlag.Name) {
  1044  		cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name))
  1045  	}
  1046  	if ctx.GlobalIsSet(GasPriceFlag.Name) {
  1047  		cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name)
  1048  	}
  1049  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1050  		// TODO(fjl): force-enable this in --dev mode
  1051  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1052  	}
  1053  
  1054  	// Override any default configs for hard coded networks.
  1055  	switch {
  1056  	case ctx.GlobalBool(TestnetFlag.Name):
  1057  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1058  			cfg.NetworkId = 3
  1059  		}
  1060  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1061  	case ctx.GlobalBool(DevnetFlag.Name):
  1062  		/*if !ctx.GlobalIsSet(GasPriceFlag.Name) {
  1063  			cfg.GasPrice = big.NewInt(1)
  1064  		}*/
  1065  		cfg.Genesis = core.DeveloperGenesisBlock()
  1066  	}
  1067  	// TODO(fjl): move trie cache generations into config
  1068  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1069  		state.MaxTrieCacheGen = uint16(gen)
  1070  	}
  1071  }
  1072  
  1073  // SetDashboardConfig applies dashboard related command line flags to the config.
  1074  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1075  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1076  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1077  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1078  	cfg.Assets = ctx.GlobalString(DashboardAssetsFlag.Name)
  1079  }
  1080  
  1081  // RegisterEthService adds an Ethereum client to the stack.
  1082  func RegisterEthService(stack *node.Node, cfg *eth.Config) {
  1083  	var err error
  1084  	if cfg.SyncMode == downloader.LightSync {
  1085  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1086  			return les.New(ctx, cfg)
  1087  		})
  1088  	} else {
  1089  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1090  			fullNode, err := eth.New(ctx, cfg)
  1091  			if fullNode != nil && cfg.LightServ > 0 {
  1092  				ls, _ := les.NewLesServer(fullNode, cfg)
  1093  				fullNode.AddLesServer(ls)
  1094  			}
  1095  			return fullNode, err
  1096  		})
  1097  	}
  1098  	if err != nil {
  1099  		Fatalf("Failed to register the Ethereum service: %v", err)
  1100  	}
  1101  }
  1102  
  1103  // RegisterDashboardService adds a dashboard to the stack.
  1104  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config) {
  1105  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1106  		return dashboard.New(cfg)
  1107  	})
  1108  }
  1109  
  1110  // RegisterShhService configures Whisper and adds it to the given node.
  1111  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1112  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1113  		return whisper.New(cfg), nil
  1114  	}); err != nil {
  1115  		Fatalf("Failed to register the Whisper service: %v", err)
  1116  	}
  1117  }
  1118  
  1119  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1120  // th egiven node.
  1121  func RegisterEthStatsService(stack *node.Node, url string) {
  1122  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1123  		// Retrieve both eth and les services
  1124  		var ethServ *eth.Ethereum
  1125  		ctx.Service(&ethServ)
  1126  
  1127  		var lesServ *les.LightEthereum
  1128  		ctx.Service(&lesServ)
  1129  
  1130  		return ethstats.New(url, ethServ, lesServ)
  1131  	}); err != nil {
  1132  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1133  	}
  1134  }
  1135  
  1136  // SetupNetwork configures the system for either the main net or some test network.
  1137  func SetupNetwork(ctx *cli.Context) {
  1138  	// TODO(fjl): move target gas limit into config
  1139  	params.TargetGasLimit = new(big.Int).SetUint64(ctx.GlobalUint64(TargetGasLimitFlag.Name))
  1140  }
  1141  
  1142  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1143  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1144  	var (
  1145  		cache   = ctx.GlobalInt(CacheFlag.Name)
  1146  		handles = makeDatabaseHandles()
  1147  	)
  1148  	name := "chaindata"
  1149  	if ctx.GlobalBool(LightModeFlag.Name) {
  1150  		name = "lightchaindata"
  1151  	}
  1152  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1153  	if err != nil {
  1154  		Fatalf("Could not open database: %v", err)
  1155  	}
  1156  	return chainDb
  1157  }
  1158  
  1159  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1160  	var genesis *core.Genesis
  1161  	switch {
  1162  	case ctx.GlobalBool(TestnetFlag.Name):
  1163  		genesis = core.DefaultTestnetGenesisBlock()
  1164  	case ctx.GlobalBool(DevnetFlag.Name):
  1165  		genesis = core.DeveloperGenesisBlock()
  1166  	}
  1167  	return genesis
  1168  }
  1169  
  1170  // MakeChain creates a chain manager from set command line flags.
  1171  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  1172  	var err error
  1173  	chainDb = MakeChainDatabase(ctx, stack)
  1174  
  1175  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1176  	if err != nil {
  1177  		Fatalf("%v", err)
  1178  	}
  1179  	var engine consensus.Engine
  1180  	if config.Clique != nil {
  1181  		engine = clique.New(config.Clique, chainDb)
  1182  	} else {
  1183  		engine = ethash.NewFaker()
  1184  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1185  			engine = ethash.New(ethash.Config{
  1186  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1187  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1188  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1189  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1190  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1191  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1192  			})
  1193  		}
  1194  	}
  1195  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1196  	chain, err = core.NewBlockChain(chainDb, config, engine, vmcfg)
  1197  	if err != nil {
  1198  		Fatalf("Can't create BlockChain: %v", err)
  1199  	}
  1200  	return chain, chainDb
  1201  }
  1202  
  1203  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1204  // scripts to preload before starting.
  1205  func MakeConsolePreloads(ctx *cli.Context) []string {
  1206  	// Skip preloading if there's nothing to preload
  1207  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1208  		return nil
  1209  	}
  1210  	// Otherwise resolve absolute paths and return them
  1211  	preloads := []string{}
  1212  
  1213  	assets := ctx.GlobalString(JSpathFlag.Name)
  1214  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1215  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1216  	}
  1217  	return preloads
  1218  }
  1219  
  1220  // MigrateFlags sets the global flag from a local flag when it's set.
  1221  // This is a temporary function used for migrating old command/flags to the
  1222  // new format.
  1223  //
  1224  // e.g. smc account new --keystore /tmp/mykeystore --lightkdf
  1225  //
  1226  // is equivalent after calling this method with:
  1227  //
  1228  // smc --keystore /tmp/mykeystore --lightkdf account new
  1229  //
  1230  // This allows the use of the existing configuration functionality.
  1231  // When all flags are migrated this function can be removed and the existing
  1232  // configuration functionality must be changed that is uses local flags
  1233  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1234  	return func(ctx *cli.Context) error {
  1235  		for _, name := range ctx.FlagNames() {
  1236  			if ctx.IsSet(name) {
  1237  				ctx.GlobalSet(name, ctx.String(name))
  1238  			}
  1239  		}
  1240  		return action(ctx)
  1241  	}
  1242  }