github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/cmd/utils/flags.go (about)

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