github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/cmd/utils/flags.go (about)

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