github.com/zjj1991/quorum@v0.0.0-20190524123704-ae4b0a1e1a19/cmd/utils/flags.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package utils contains internal helper functions for go-ethereum commands.
    18  package utils
    19  
    20  import (
    21  	"crypto/ecdsa"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"os"
    26  	"path/filepath"
    27  	"strconv"
    28  	"strings"
    29  
    30  	"github.com/ethereum/go-ethereum/accounts"
    31  	"github.com/ethereum/go-ethereum/accounts/keystore"
    32  	"github.com/ethereum/go-ethereum/common"
    33  	"github.com/ethereum/go-ethereum/common/fdlimit"
    34  	"github.com/ethereum/go-ethereum/consensus"
    35  	"github.com/ethereum/go-ethereum/consensus/clique"
    36  	"github.com/ethereum/go-ethereum/consensus/ethash"
    37  	"github.com/ethereum/go-ethereum/core"
    38  	"github.com/ethereum/go-ethereum/core/state"
    39  	"github.com/ethereum/go-ethereum/core/vm"
    40  	"github.com/ethereum/go-ethereum/crypto"
    41  	"github.com/ethereum/go-ethereum/dashboard"
    42  	"github.com/ethereum/go-ethereum/eth"
    43  	"github.com/ethereum/go-ethereum/eth/downloader"
    44  	"github.com/ethereum/go-ethereum/eth/gasprice"
    45  	"github.com/ethereum/go-ethereum/ethdb"
    46  	"github.com/ethereum/go-ethereum/ethstats"
    47  	"github.com/ethereum/go-ethereum/les"
    48  	"github.com/ethereum/go-ethereum/log"
    49  	"github.com/ethereum/go-ethereum/metrics"
    50  	"github.com/ethereum/go-ethereum/metrics/influxdb"
    51  	"github.com/ethereum/go-ethereum/node"
    52  	"github.com/ethereum/go-ethereum/p2p"
    53  	"github.com/ethereum/go-ethereum/p2p/discv5"
    54  	"github.com/ethereum/go-ethereum/p2p/enode"
    55  	"github.com/ethereum/go-ethereum/p2p/nat"
    56  	"github.com/ethereum/go-ethereum/p2p/netutil"
    57  	"github.com/ethereum/go-ethereum/params"
    58  	whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
    59  	"gopkg.in/urfave/cli.v1"
    60  	"time"
    61  )
    62  
    63  var (
    64  	CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...]
    65  {{if .cmd.Description}}{{.cmd.Description}}
    66  {{end}}{{if .cmd.Subcommands}}
    67  SUBCOMMANDS:
    68  	{{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    69  	{{end}}{{end}}{{if .categorizedFlags}}
    70  {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
    71  {{range $categorized.Flags}}{{"\t"}}{{.}}
    72  {{end}}
    73  {{end}}{{end}}`
    74  )
    75  
    76  func init() {
    77  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    78  
    79  VERSION:
    80     {{.Version}}
    81  
    82  COMMANDS:
    83     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    84     {{end}}{{if .Flags}}
    85  GLOBAL OPTIONS:
    86     {{range .Flags}}{{.}}
    87     {{end}}{{end}}
    88  `
    89  
    90  	cli.CommandHelpTemplate = CommandHelpTemplate
    91  }
    92  
    93  // NewApp creates an app with sane defaults.
    94  func NewApp(gitCommit, usage string) *cli.App {
    95  	app := cli.NewApp()
    96  	app.Name = filepath.Base(os.Args[0])
    97  	app.Author = ""
    98  	//app.Authors = nil
    99  	app.Email = ""
   100  	app.Version = params.VersionWithMeta
   101  	if len(gitCommit) >= 8 {
   102  		app.Version += "-" + gitCommit[:8]
   103  	}
   104  	app.Usage = usage
   105  	return app
   106  }
   107  
   108  // These are all the command line flags we support.
   109  // If you add to this list, please remember to include the
   110  // flag in the appropriate command definition.
   111  //
   112  // The flags are defined here so their names and help texts
   113  // are the same for all commands.
   114  
   115  var (
   116  	// General settings
   117  	DataDirFlag = DirectoryFlag{
   118  		Name:  "datadir",
   119  		Usage: "Data directory for the databases and keystore",
   120  		Value: DirectoryString{node.DefaultDataDir()},
   121  	}
   122  	KeyStoreDirFlag = DirectoryFlag{
   123  		Name:  "keystore",
   124  		Usage: "Directory for the keystore (default = inside the datadir)",
   125  	}
   126  	NoUSBFlag = cli.BoolFlag{
   127  		Name:  "nousb",
   128  		Usage: "Disables monitoring for and managing USB hardware wallets",
   129  	}
   130  	NetworkIdFlag = cli.Uint64Flag{
   131  		Name:  "networkid",
   132  		Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby, 5=Ottoman)",
   133  		Value: eth.DefaultConfig.NetworkId,
   134  	}
   135  	TestnetFlag = cli.BoolFlag{
   136  		Name:  "testnet",
   137  		Usage: "Ropsten network: pre-configured proof-of-work test network",
   138  	}
   139  	RinkebyFlag = cli.BoolFlag{
   140  		Name:  "rinkeby",
   141  		Usage: "Rinkeby network: pre-configured proof-of-authority test network",
   142  	}
   143  	OttomanFlag = cli.BoolFlag{
   144  		Name:  "ottoman",
   145  		Usage: "Ottoman network: pre-configured istanbul bft test network",
   146  	}
   147  	DeveloperFlag = cli.BoolFlag{
   148  		Name:  "dev",
   149  		Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   150  	}
   151  	DeveloperPeriodFlag = cli.IntFlag{
   152  		Name:  "dev.period",
   153  		Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   154  	}
   155  	IdentityFlag = cli.StringFlag{
   156  		Name:  "identity",
   157  		Usage: "Custom node name",
   158  	}
   159  	DocRootFlag = DirectoryFlag{
   160  		Name:  "docroot",
   161  		Usage: "Document Root for HTTPClient file scheme",
   162  		Value: DirectoryString{homeDir()},
   163  	}
   164  	defaultSyncMode = eth.DefaultConfig.SyncMode
   165  	SyncModeFlag    = TextMarshalerFlag{
   166  		Name:  "syncmode",
   167  		Usage: `Blockchain sync mode ("fast", "full", or "light")`,
   168  		Value: &defaultSyncMode,
   169  	}
   170  	GCModeFlag = cli.StringFlag{
   171  		Name:  "gcmode",
   172  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   173  		Value: "full",
   174  	}
   175  	LightServFlag = cli.IntFlag{
   176  		Name:  "lightserv",
   177  		Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
   178  		Value: 0,
   179  	}
   180  	LightPeersFlag = cli.IntFlag{
   181  		Name:  "lightpeers",
   182  		Usage: "Maximum number of LES client peers",
   183  		Value: eth.DefaultConfig.LightPeers,
   184  	}
   185  	LightKDFFlag = cli.BoolFlag{
   186  		Name:  "lightkdf",
   187  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   188  	}
   189  	// Dashboard settings
   190  	DashboardEnabledFlag = cli.BoolFlag{
   191  		Name:  metrics.DashboardEnabledFlag,
   192  		Usage: "Enable the dashboard",
   193  	}
   194  	DashboardAddrFlag = cli.StringFlag{
   195  		Name:  "dashboard.addr",
   196  		Usage: "Dashboard listening interface",
   197  		Value: dashboard.DefaultConfig.Host,
   198  	}
   199  	DashboardPortFlag = cli.IntFlag{
   200  		Name:  "dashboard.host",
   201  		Usage: "Dashboard listening port",
   202  		Value: dashboard.DefaultConfig.Port,
   203  	}
   204  	DashboardRefreshFlag = cli.DurationFlag{
   205  		Name:  "dashboard.refresh",
   206  		Usage: "Dashboard metrics collection refresh rate",
   207  		Value: dashboard.DefaultConfig.Refresh,
   208  	}
   209  	// Ethash settings
   210  	EthashCacheDirFlag = DirectoryFlag{
   211  		Name:  "ethash.cachedir",
   212  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   213  	}
   214  	EthashCachesInMemoryFlag = cli.IntFlag{
   215  		Name:  "ethash.cachesinmem",
   216  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   217  		Value: eth.DefaultConfig.Ethash.CachesInMem,
   218  	}
   219  	EthashCachesOnDiskFlag = cli.IntFlag{
   220  		Name:  "ethash.cachesondisk",
   221  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   222  		Value: eth.DefaultConfig.Ethash.CachesOnDisk,
   223  	}
   224  	EthashDatasetDirFlag = DirectoryFlag{
   225  		Name:  "ethash.dagdir",
   226  		Usage: "Directory to store the ethash mining DAGs (default = inside home folder)",
   227  		Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir},
   228  	}
   229  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   230  		Name:  "ethash.dagsinmem",
   231  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   232  		Value: eth.DefaultConfig.Ethash.DatasetsInMem,
   233  	}
   234  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   235  		Name:  "ethash.dagsondisk",
   236  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   237  		Value: eth.DefaultConfig.Ethash.DatasetsOnDisk,
   238  	}
   239  	// Transaction pool settings
   240  	TxPoolLocalsFlag = cli.StringFlag{
   241  		Name:  "txpool.locals",
   242  		Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
   243  	}
   244  	TxPoolNoLocalsFlag = cli.BoolFlag{
   245  		Name:  "txpool.nolocals",
   246  		Usage: "Disables price exemptions for locally submitted transactions",
   247  	}
   248  	TxPoolJournalFlag = cli.StringFlag{
   249  		Name:  "txpool.journal",
   250  		Usage: "Disk journal for local transaction to survive node restarts",
   251  		Value: core.DefaultTxPoolConfig.Journal,
   252  	}
   253  	TxPoolRejournalFlag = cli.DurationFlag{
   254  		Name:  "txpool.rejournal",
   255  		Usage: "Time interval to regenerate the local transaction journal",
   256  		Value: core.DefaultTxPoolConfig.Rejournal,
   257  	}
   258  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   259  		Name:  "txpool.pricelimit",
   260  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   261  		Value: eth.DefaultConfig.TxPool.PriceLimit,
   262  	}
   263  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   264  		Name:  "txpool.pricebump",
   265  		Usage: "Price bump percentage to replace an already existing transaction",
   266  		Value: eth.DefaultConfig.TxPool.PriceBump,
   267  	}
   268  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   269  		Name:  "txpool.accountslots",
   270  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   271  		Value: eth.DefaultConfig.TxPool.AccountSlots,
   272  	}
   273  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   274  		Name:  "txpool.globalslots",
   275  		Usage: "Maximum number of executable transaction slots for all accounts",
   276  		Value: eth.DefaultConfig.TxPool.GlobalSlots,
   277  	}
   278  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   279  		Name:  "txpool.accountqueue",
   280  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   281  		Value: eth.DefaultConfig.TxPool.AccountQueue,
   282  	}
   283  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   284  		Name:  "txpool.globalqueue",
   285  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   286  		Value: eth.DefaultConfig.TxPool.GlobalQueue,
   287  	}
   288  	TxPoolLifetimeFlag = cli.DurationFlag{
   289  		Name:  "txpool.lifetime",
   290  		Usage: "Maximum amount of time non-executable transaction are queued",
   291  		Value: eth.DefaultConfig.TxPool.Lifetime,
   292  	}
   293  	// Performance tuning settings
   294  	CacheFlag = cli.IntFlag{
   295  		Name:  "cache",
   296  		Usage: "Megabytes of memory allocated to internal caching",
   297  		Value: 1024,
   298  	}
   299  	CacheDatabaseFlag = cli.IntFlag{
   300  		Name:  "cache.database",
   301  		Usage: "Percentage of cache memory allowance to use for database io",
   302  		Value: 75,
   303  	}
   304  	CacheGCFlag = cli.IntFlag{
   305  		Name:  "cache.gc",
   306  		Usage: "Percentage of cache memory allowance to use for trie pruning",
   307  		Value: 25,
   308  	}
   309  	TrieCacheGenFlag = cli.IntFlag{
   310  		Name:  "trie-cache-gens",
   311  		Usage: "Number of trie node generations to keep in memory",
   312  		Value: int(state.MaxTrieCacheGen),
   313  	}
   314  	// Miner settings
   315  	MiningEnabledFlag = cli.BoolFlag{
   316  		Name:  "mine",
   317  		Usage: "Enable mining",
   318  	}
   319  	MinerThreadsFlag = cli.IntFlag{
   320  		Name:  "miner.threads",
   321  		Usage: "Number of CPU threads to use for mining",
   322  		Value: 0,
   323  	}
   324  	MinerLegacyThreadsFlag = cli.IntFlag{
   325  		Name:  "minerthreads",
   326  		Usage: "Number of CPU threads to use for mining (deprecated, use --miner.threads)",
   327  		Value: 0,
   328  	}
   329  	MinerNotifyFlag = cli.StringFlag{
   330  		Name:  "miner.notify",
   331  		Usage: "Comma separated HTTP URL list to notify of new work packages",
   332  	}
   333  	MinerGasTargetFlag = cli.Uint64Flag{
   334  		Name:  "miner.gastarget",
   335  		Usage: "Target gas floor for mined blocks",
   336  		Value: eth.DefaultConfig.MinerGasFloor,
   337  	}
   338  	MinerLegacyGasTargetFlag = cli.Uint64Flag{
   339  		Name:  "targetgaslimit",
   340  		Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)",
   341  		Value: eth.DefaultConfig.MinerGasFloor,
   342  	}
   343  	MinerGasLimitFlag = cli.Uint64Flag{
   344  		Name:  "miner.gaslimit",
   345  		Usage: "Target gas ceiling for mined blocks",
   346  		Value: eth.DefaultConfig.MinerGasCeil,
   347  	}
   348  	MinerGasPriceFlag = BigFlag{
   349  		Name:  "miner.gasprice",
   350  		Usage: "Minimum gas price for mining a transaction",
   351  		Value: eth.DefaultConfig.MinerGasPrice,
   352  	}
   353  	MinerLegacyGasPriceFlag = BigFlag{
   354  		Name:  "gasprice",
   355  		Usage: "Minimum gas price for mining a transaction (deprecated, use --miner.gasprice)",
   356  		Value: eth.DefaultConfig.MinerGasPrice,
   357  	}
   358  	MinerEtherbaseFlag = cli.StringFlag{
   359  		Name:  "miner.etherbase",
   360  		Usage: "Public address for block mining rewards (default = first account)",
   361  		Value: "0",
   362  	}
   363  	MinerLegacyEtherbaseFlag = cli.StringFlag{
   364  		Name:  "etherbase",
   365  		Usage: "Public address for block mining rewards (default = first account, deprecated, use --miner.etherbase)",
   366  		Value: "0",
   367  	}
   368  	MinerExtraDataFlag = cli.StringFlag{
   369  		Name:  "miner.extradata",
   370  		Usage: "Block extra data set by the miner (default = client version)",
   371  	}
   372  	MinerLegacyExtraDataFlag = cli.StringFlag{
   373  		Name:  "extradata",
   374  		Usage: "Block extra data set by the miner (default = client version, deprecated, use --miner.extradata)",
   375  	}
   376  	MinerRecommitIntervalFlag = cli.DurationFlag{
   377  		Name:  "miner.recommit",
   378  		Usage: "Time interval to recreate the block being mined",
   379  		Value: eth.DefaultConfig.MinerRecommit,
   380  	}
   381  	MinerNoVerfiyFlag = cli.BoolFlag{
   382  		Name:  "miner.noverify",
   383  		Usage: "Disable remote sealing verification",
   384  	}
   385  	// Account settings
   386  	UnlockedAccountFlag = cli.StringFlag{
   387  		Name:  "unlock",
   388  		Usage: "Comma separated list of accounts to unlock",
   389  		Value: "",
   390  	}
   391  	PasswordFileFlag = cli.StringFlag{
   392  		Name:  "password",
   393  		Usage: "Password file to use for non-interactive password input",
   394  		Value: "",
   395  	}
   396  
   397  	VMEnableDebugFlag = cli.BoolFlag{
   398  		Name:  "vmdebug",
   399  		Usage: "Record information useful for VM and contract debugging",
   400  	}
   401  	// Logging and debug settings
   402  	EthStatsURLFlag = cli.StringFlag{
   403  		Name:  "ethstats",
   404  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   405  	}
   406  	FakePoWFlag = cli.BoolFlag{
   407  		Name:  "fakepow",
   408  		Usage: "Disables proof-of-work verification",
   409  	}
   410  	NoCompactionFlag = cli.BoolFlag{
   411  		Name:  "nocompaction",
   412  		Usage: "Disables db compaction after import",
   413  	}
   414  	// RPC settings
   415  	RPCEnabledFlag = cli.BoolFlag{
   416  		Name:  "rpc",
   417  		Usage: "Enable the HTTP-RPC server",
   418  	}
   419  	RPCListenAddrFlag = cli.StringFlag{
   420  		Name:  "rpcaddr",
   421  		Usage: "HTTP-RPC server listening interface",
   422  		Value: node.DefaultHTTPHost,
   423  	}
   424  	RPCPortFlag = cli.IntFlag{
   425  		Name:  "rpcport",
   426  		Usage: "HTTP-RPC server listening port",
   427  		Value: node.DefaultHTTPPort,
   428  	}
   429  	RPCCORSDomainFlag = cli.StringFlag{
   430  		Name:  "rpccorsdomain",
   431  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   432  		Value: "",
   433  	}
   434  	RPCVirtualHostsFlag = cli.StringFlag{
   435  		Name:  "rpcvhosts",
   436  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   437  		Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
   438  	}
   439  	RPCApiFlag = cli.StringFlag{
   440  		Name:  "rpcapi",
   441  		Usage: "API's offered over the HTTP-RPC interface",
   442  		Value: "",
   443  	}
   444  	IPCDisabledFlag = cli.BoolFlag{
   445  		Name:  "ipcdisable",
   446  		Usage: "Disable the IPC-RPC server",
   447  	}
   448  	IPCPathFlag = DirectoryFlag{
   449  		Name:  "ipcpath",
   450  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   451  	}
   452  	WSEnabledFlag = cli.BoolFlag{
   453  		Name:  "ws",
   454  		Usage: "Enable the WS-RPC server",
   455  	}
   456  	WSListenAddrFlag = cli.StringFlag{
   457  		Name:  "wsaddr",
   458  		Usage: "WS-RPC server listening interface",
   459  		Value: node.DefaultWSHost,
   460  	}
   461  	WSPortFlag = cli.IntFlag{
   462  		Name:  "wsport",
   463  		Usage: "WS-RPC server listening port",
   464  		Value: node.DefaultWSPort,
   465  	}
   466  	WSApiFlag = cli.StringFlag{
   467  		Name:  "wsapi",
   468  		Usage: "API's offered over the WS-RPC interface",
   469  		Value: "",
   470  	}
   471  	WSAllowedOriginsFlag = cli.StringFlag{
   472  		Name:  "wsorigins",
   473  		Usage: "Origins from which to accept websockets requests",
   474  		Value: "",
   475  	}
   476  	ExecFlag = cli.StringFlag{
   477  		Name:  "exec",
   478  		Usage: "Execute JavaScript statement",
   479  	}
   480  	PreloadJSFlag = cli.StringFlag{
   481  		Name:  "preload",
   482  		Usage: "Comma separated list of JavaScript files to preload into the console",
   483  	}
   484  
   485  	// Network Settings
   486  	MaxPeersFlag = cli.IntFlag{
   487  		Name:  "maxpeers",
   488  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   489  		Value: 25,
   490  	}
   491  	MaxPendingPeersFlag = cli.IntFlag{
   492  		Name:  "maxpendpeers",
   493  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   494  		Value: 0,
   495  	}
   496  	ListenPortFlag = cli.IntFlag{
   497  		Name:  "port",
   498  		Usage: "Network listening port",
   499  		Value: 30303,
   500  	}
   501  	BootnodesFlag = cli.StringFlag{
   502  		Name:  "bootnodes",
   503  		Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
   504  		Value: "",
   505  	}
   506  	BootnodesV4Flag = cli.StringFlag{
   507  		Name:  "bootnodesv4",
   508  		Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
   509  		Value: "",
   510  	}
   511  	BootnodesV5Flag = cli.StringFlag{
   512  		Name:  "bootnodesv5",
   513  		Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
   514  		Value: "",
   515  	}
   516  	NodeKeyFileFlag = cli.StringFlag{
   517  		Name:  "nodekey",
   518  		Usage: "P2P node key file",
   519  	}
   520  	NodeKeyHexFlag = cli.StringFlag{
   521  		Name:  "nodekeyhex",
   522  		Usage: "P2P node key as hex (for testing)",
   523  	}
   524  	NATFlag = cli.StringFlag{
   525  		Name:  "nat",
   526  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   527  		Value: "any",
   528  	}
   529  	NoDiscoverFlag = cli.BoolFlag{
   530  		Name:  "nodiscover",
   531  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   532  	}
   533  	DiscoveryV5Flag = cli.BoolFlag{
   534  		Name:  "v5disc",
   535  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   536  	}
   537  	NetrestrictFlag = cli.StringFlag{
   538  		Name:  "netrestrict",
   539  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   540  	}
   541  
   542  	// ATM the url is left to the user and deployment to
   543  	JSpathFlag = cli.StringFlag{
   544  		Name:  "jspath",
   545  		Usage: "JavaScript root path for `loadScript`",
   546  		Value: ".",
   547  	}
   548  
   549  	// Gas price oracle settings
   550  	GpoBlocksFlag = cli.IntFlag{
   551  		Name:  "gpoblocks",
   552  		Usage: "Number of recent blocks to check for gas prices",
   553  		Value: eth.DefaultConfig.GPO.Blocks,
   554  	}
   555  	GpoPercentileFlag = cli.IntFlag{
   556  		Name:  "gpopercentile",
   557  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   558  		Value: eth.DefaultConfig.GPO.Percentile,
   559  	}
   560  	WhisperEnabledFlag = cli.BoolFlag{
   561  		Name:  "shh",
   562  		Usage: "Enable Whisper",
   563  	}
   564  	WhisperMaxMessageSizeFlag = cli.IntFlag{
   565  		Name:  "shh.maxmessagesize",
   566  		Usage: "Max message size accepted",
   567  		Value: int(whisper.DefaultMaxMessageSize),
   568  	}
   569  	WhisperMinPOWFlag = cli.Float64Flag{
   570  		Name:  "shh.pow",
   571  		Usage: "Minimum POW accepted",
   572  		Value: whisper.DefaultMinimumPoW,
   573  	}
   574  	WhisperRestrictConnectionBetweenLightClientsFlag = cli.BoolFlag{
   575  		Name:  "shh.restrict-light",
   576  		Usage: "Restrict connection between two whisper light clients",
   577  	}
   578  
   579  	// Raft flags
   580  	RaftModeFlag = cli.BoolFlag{
   581  		Name:  "raft",
   582  		Usage: "If enabled, uses Raft instead of Quorum Chain for consensus",
   583  	}
   584  	RaftBlockTimeFlag = cli.IntFlag{
   585  		Name:  "raftblocktime",
   586  		Usage: "Amount of time between raft block creations in milliseconds",
   587  		Value: 50,
   588  	}
   589  	RaftJoinExistingFlag = cli.IntFlag{
   590  		Name:  "raftjoinexisting",
   591  		Usage: "The raft ID to assume when joining an pre-existing cluster",
   592  		Value: 0,
   593  	}
   594  	EmitCheckpointsFlag = cli.BoolFlag{
   595  		Name:  "emitcheckpoints",
   596  		Usage: "If enabled, emit specially formatted logging checkpoints",
   597  	}
   598  	RaftPortFlag = cli.IntFlag{
   599  		Name:  "raftport",
   600  		Usage: "The port to bind for the raft transport",
   601  		Value: 50400,
   602  	}
   603  
   604  	// Quorum
   605  	EnableNodePermissionFlag = cli.BoolFlag{
   606  		Name:  "permissioned",
   607  		Usage: "If enabled, the node will allow only a defined list of nodes to connect",
   608  	}
   609  
   610  	// Istanbul settings
   611  	IstanbulRequestTimeoutFlag = cli.Uint64Flag{
   612  		Name:  "istanbul.requesttimeout",
   613  		Usage: "Timeout for each Istanbul round in milliseconds",
   614  		Value: eth.DefaultConfig.Istanbul.RequestTimeout,
   615  	}
   616  	IstanbulBlockPeriodFlag = cli.Uint64Flag{
   617  		Name:  "istanbul.blockperiod",
   618  		Usage: "Default minimum difference between two consecutive block's timestamps in seconds",
   619  		Value: eth.DefaultConfig.Istanbul.BlockPeriod,
   620  	}
   621  
   622  	// Metrics flags
   623  	MetricsEnabledFlag = cli.BoolFlag{
   624  		Name:  metrics.MetricsEnabledFlag,
   625  		Usage: "Enable metrics collection and reporting",
   626  	}
   627  	MetricsEnableInfluxDBFlag = cli.BoolFlag{
   628  		Name:  "metrics.influxdb",
   629  		Usage: "Enable metrics export/push to an external InfluxDB database",
   630  	}
   631  	MetricsInfluxDBEndpointFlag = cli.StringFlag{
   632  		Name:  "metrics.influxdb.endpoint",
   633  		Usage: "InfluxDB API endpoint to report metrics to",
   634  		Value: "http://localhost:8086",
   635  	}
   636  	MetricsInfluxDBDatabaseFlag = cli.StringFlag{
   637  		Name:  "metrics.influxdb.database",
   638  		Usage: "InfluxDB database name to push reported metrics to",
   639  		Value: "geth",
   640  	}
   641  	MetricsInfluxDBUsernameFlag = cli.StringFlag{
   642  		Name:  "metrics.influxdb.username",
   643  		Usage: "Username to authorize access to the database",
   644  		Value: "test",
   645  	}
   646  	MetricsInfluxDBPasswordFlag = cli.StringFlag{
   647  		Name:  "metrics.influxdb.password",
   648  		Usage: "Password to authorize access to the database",
   649  		Value: "test",
   650  	}
   651  	// The `host` tag is part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB.
   652  	// It is used so that we can group all nodes and average a measurement across all of them, but also so
   653  	// that we can select a specific node and inspect its measurements.
   654  	// https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key
   655  	MetricsInfluxDBHostTagFlag = cli.StringFlag{
   656  		Name:  "metrics.influxdb.host.tag",
   657  		Usage: "InfluxDB `host` tag attached to all measurements",
   658  		Value: "localhost",
   659  	}
   660  
   661  	EWASMInterpreterFlag = cli.StringFlag{
   662  		Name:  "vm.ewasm",
   663  		Usage: "External ewasm configuration (default = built-in interpreter)",
   664  		Value: "",
   665  	}
   666  	EVMInterpreterFlag = cli.StringFlag{
   667  		Name:  "vm.evm",
   668  		Usage: "External EVM configuration (default = built-in interpreter)",
   669  		Value: "",
   670  	}
   671  )
   672  
   673  // MakeDataDir retrieves the currently requested data directory, terminating
   674  // if none (or the empty string) is specified. If the node is starting a testnet,
   675  // the a subdirectory of the specified datadir will be used.
   676  func MakeDataDir(ctx *cli.Context) string {
   677  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   678  		if ctx.GlobalBool(TestnetFlag.Name) {
   679  			return filepath.Join(path, "testnet")
   680  		}
   681  		if ctx.GlobalBool(RinkebyFlag.Name) {
   682  			return filepath.Join(path, "rinkeby")
   683  		}
   684  		if ctx.GlobalBool(OttomanFlag.Name) {
   685  			return filepath.Join(path, "ottoman")
   686  		}
   687  		return path
   688  	}
   689  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   690  	return ""
   691  }
   692  
   693  // setNodeKey creates a node key from set command line flags, either loading it
   694  // from a file or as a specified hex value. If neither flags were provided, this
   695  // method returns nil and an emphemeral key is to be generated.
   696  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   697  	var (
   698  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   699  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   700  		key  *ecdsa.PrivateKey
   701  		err  error
   702  	)
   703  	switch {
   704  	case file != "" && hex != "":
   705  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   706  	case file != "":
   707  		if key, err = crypto.LoadECDSA(file); err != nil {
   708  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   709  		}
   710  		cfg.PrivateKey = key
   711  	case hex != "":
   712  		if key, err = crypto.HexToECDSA(hex); err != nil {
   713  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   714  		}
   715  		cfg.PrivateKey = key
   716  	}
   717  }
   718  
   719  // setNodeUserIdent creates the user identifier from CLI flags.
   720  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   721  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   722  		cfg.UserIdent = identity
   723  	}
   724  }
   725  
   726  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   727  // flags, reverting to pre-configured ones if none have been specified.
   728  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   729  	urls := params.MainnetBootnodes
   730  	switch {
   731  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   732  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   733  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   734  		} else {
   735  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   736  		}
   737  	case ctx.GlobalBool(TestnetFlag.Name):
   738  		urls = params.TestnetBootnodes
   739  	case ctx.GlobalBool(RinkebyFlag.Name):
   740  		urls = params.RinkebyBootnodes
   741  	case ctx.GlobalBool(OttomanFlag.Name):
   742  		urls = params.OttomanBootnodes
   743  	case cfg.BootstrapNodes != nil:
   744  		return // already set, don't apply defaults.
   745  	}
   746  
   747  	cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls))
   748  	for _, url := range urls {
   749  		node, err := enode.ParseV4(url)
   750  		if err != nil {
   751  			log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
   752  		}
   753  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   754  	}
   755  }
   756  
   757  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   758  // flags, reverting to pre-configured ones if none have been specified.
   759  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   760  	urls := params.DiscoveryV5Bootnodes
   761  	switch {
   762  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
   763  		if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
   764  			urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",")
   765  		} else {
   766  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   767  		}
   768  	case ctx.GlobalBool(RinkebyFlag.Name):
   769  		urls = params.RinkebyBootnodes
   770  	case cfg.BootstrapNodesV5 != nil:
   771  		return // already set, don't apply defaults.
   772  	}
   773  
   774  	cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
   775  	for _, url := range urls {
   776  		node, err := discv5.ParseNode(url)
   777  		if err != nil {
   778  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   779  			continue
   780  		}
   781  		cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   782  	}
   783  }
   784  
   785  // setListenAddress creates a TCP listening address string from set command
   786  // line flags.
   787  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   788  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   789  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   790  	}
   791  }
   792  
   793  // setNAT creates a port mapper from command line flags.
   794  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   795  	if ctx.GlobalIsSet(NATFlag.Name) {
   796  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   797  		if err != nil {
   798  			Fatalf("Option %s: %v", NATFlag.Name, err)
   799  		}
   800  		cfg.NAT = natif
   801  	}
   802  }
   803  
   804  // splitAndTrim splits input separated by a comma
   805  // and trims excessive white space from the substrings.
   806  func splitAndTrim(input string) []string {
   807  	result := strings.Split(input, ",")
   808  	for i, r := range result {
   809  		result[i] = strings.TrimSpace(r)
   810  	}
   811  	return result
   812  }
   813  
   814  // setHTTP creates the HTTP RPC listener interface string from the set
   815  // command line flags, returning empty if the HTTP endpoint is disabled.
   816  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   817  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   818  		cfg.HTTPHost = "127.0.0.1"
   819  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   820  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   821  		}
   822  	}
   823  
   824  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   825  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   826  	}
   827  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   828  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   829  	}
   830  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   831  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   832  	}
   833  	if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) {
   834  		cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
   835  	}
   836  }
   837  
   838  // setWS creates the WebSocket RPC listener interface string from the set
   839  // command line flags, returning empty if the HTTP endpoint is disabled.
   840  func setWS(ctx *cli.Context, cfg *node.Config) {
   841  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   842  		cfg.WSHost = "127.0.0.1"
   843  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   844  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   845  		}
   846  	}
   847  
   848  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   849  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   850  	}
   851  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   852  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   853  	}
   854  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   855  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   856  	}
   857  }
   858  
   859  // setIPC creates an IPC path configuration from the set command line flags,
   860  // returning an empty string if IPC was explicitly disabled, or the set path.
   861  func setIPC(ctx *cli.Context, cfg *node.Config) {
   862  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   863  	switch {
   864  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   865  		cfg.IPCPath = ""
   866  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   867  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   868  	}
   869  }
   870  
   871  // makeDatabaseHandles raises out the number of allowed file handles per process
   872  // for Geth and returns half of the allowance to assign to the database.
   873  func makeDatabaseHandles() int {
   874  	limit, err := fdlimit.Maximum()
   875  	if err != nil {
   876  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   877  	}
   878  	if err := fdlimit.Raise(uint64(limit)); err != nil {
   879  		Fatalf("Failed to raise file descriptor allowance: %v", err)
   880  	}
   881  	return limit / 2 // Leave half for networking and other stuff
   882  }
   883  
   884  // MakeAddress converts an account specified directly as a hex encoded string or
   885  // a key index in the key store to an internal account representation.
   886  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   887  	// If the specified account is a valid address, return it
   888  	if common.IsHexAddress(account) {
   889  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   890  	}
   891  	// Otherwise try to interpret the account as a keystore index
   892  	index, err := strconv.Atoi(account)
   893  	if err != nil || index < 0 {
   894  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   895  	}
   896  	log.Warn("-------------------------------------------------------------------")
   897  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   898  	log.Warn("This functionality is deprecated and will be removed in the future!")
   899  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   900  	log.Warn("-------------------------------------------------------------------")
   901  
   902  	accs := ks.Accounts()
   903  	if len(accs) <= index {
   904  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   905  	}
   906  	return accs[index], nil
   907  }
   908  
   909  // setEtherbase retrieves the etherbase either from the directly specified
   910  // command line flags or from the keystore if CLI indexed.
   911  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
   912  	// Extract the current etherbase, new flag overriding legacy one
   913  	var etherbase string
   914  	if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) {
   915  		etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name)
   916  	}
   917  	if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) {
   918  		etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name)
   919  	}
   920  	// Convert the etherbase into an address and configure it
   921  	if etherbase != "" {
   922  		account, err := MakeAddress(ks, etherbase)
   923  		if err != nil {
   924  			Fatalf("Invalid miner etherbase: %v", err)
   925  		}
   926  		cfg.Etherbase = account.Address
   927  	}
   928  }
   929  
   930  // MakePasswordList reads password lines from the file specified by the global --password flag.
   931  func MakePasswordList(ctx *cli.Context) []string {
   932  	path := ctx.GlobalString(PasswordFileFlag.Name)
   933  	if path == "" {
   934  		return nil
   935  	}
   936  	text, err := ioutil.ReadFile(path)
   937  	if err != nil {
   938  		Fatalf("Failed to read password file: %v", err)
   939  	}
   940  	lines := strings.Split(string(text), "\n")
   941  	// Sanitise DOS line endings.
   942  	for i := range lines {
   943  		lines[i] = strings.TrimRight(lines[i], "\r")
   944  	}
   945  	return lines
   946  }
   947  
   948  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   949  	setNodeKey(ctx, cfg)
   950  	setNAT(ctx, cfg)
   951  	setListenAddress(ctx, cfg)
   952  	setBootstrapNodes(ctx, cfg)
   953  	setBootstrapNodesV5(ctx, cfg)
   954  
   955  	lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light"
   956  	lightServer := ctx.GlobalInt(LightServFlag.Name) != 0
   957  	lightPeers := ctx.GlobalInt(LightPeersFlag.Name)
   958  
   959  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   960  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   961  		if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) {
   962  			cfg.MaxPeers += lightPeers
   963  		}
   964  	} else {
   965  		if lightServer {
   966  			cfg.MaxPeers += lightPeers
   967  		}
   968  		if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers {
   969  			cfg.MaxPeers = lightPeers
   970  		}
   971  	}
   972  	if !(lightClient || lightServer) {
   973  		lightPeers = 0
   974  	}
   975  	ethPeers := cfg.MaxPeers - lightPeers
   976  	if lightClient {
   977  		ethPeers = 0
   978  	}
   979  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
   980  
   981  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   982  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   983  	}
   984  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
   985  		cfg.NoDiscovery = true
   986  	}
   987  
   988  	// if we're running a light client or server, force enable the v5 peer discovery
   989  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   990  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   991  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   992  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   993  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   994  	} else if forceV5Discovery {
   995  		cfg.DiscoveryV5 = true
   996  	}
   997  
   998  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   999  		list, err := netutil.ParseNetlist(netrestrict)
  1000  		if err != nil {
  1001  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
  1002  		}
  1003  		cfg.NetRestrict = list
  1004  	}
  1005  
  1006  	if ctx.GlobalBool(DeveloperFlag.Name) {
  1007  		// --dev mode can't use p2p networking.
  1008  		cfg.MaxPeers = 0
  1009  		cfg.ListenAddr = ":0"
  1010  		cfg.NoDiscovery = true
  1011  		cfg.DiscoveryV5 = false
  1012  	}
  1013  }
  1014  
  1015  // SetNodeConfig applies node-related command line flags to the config.
  1016  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
  1017  	SetP2PConfig(ctx, &cfg.P2P)
  1018  	setIPC(ctx, cfg)
  1019  	setHTTP(ctx, cfg)
  1020  	setWS(ctx, cfg)
  1021  	setNodeUserIdent(ctx, cfg)
  1022  
  1023  	cfg.EnableNodePermission = ctx.GlobalBool(EnableNodePermissionFlag.Name)
  1024  
  1025  	switch {
  1026  	case ctx.GlobalIsSet(DataDirFlag.Name):
  1027  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
  1028  	case ctx.GlobalBool(DeveloperFlag.Name):
  1029  		cfg.DataDir = "" // unless explicitly requested, use memory databases
  1030  	case ctx.GlobalBool(TestnetFlag.Name):
  1031  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
  1032  	case ctx.GlobalBool(RinkebyFlag.Name):
  1033  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
  1034  	case ctx.GlobalBool(OttomanFlag.Name):
  1035  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ottoman")
  1036  	}
  1037  
  1038  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
  1039  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
  1040  	}
  1041  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
  1042  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
  1043  	}
  1044  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
  1045  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
  1046  	}
  1047  }
  1048  
  1049  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
  1050  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
  1051  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
  1052  	}
  1053  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
  1054  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
  1055  	}
  1056  }
  1057  
  1058  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
  1059  	if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) {
  1060  		locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",")
  1061  		for _, account := range locals {
  1062  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
  1063  				Fatalf("Invalid account in --txpool.locals: %s", trimmed)
  1064  			} else {
  1065  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
  1066  			}
  1067  		}
  1068  	}
  1069  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
  1070  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
  1071  	}
  1072  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
  1073  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
  1074  	}
  1075  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
  1076  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
  1077  	}
  1078  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
  1079  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
  1080  	}
  1081  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
  1082  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
  1083  	}
  1084  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
  1085  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
  1086  	}
  1087  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
  1088  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
  1089  	}
  1090  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
  1091  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
  1092  	}
  1093  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
  1094  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
  1095  	}
  1096  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
  1097  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
  1098  	}
  1099  }
  1100  
  1101  func setEthash(ctx *cli.Context, cfg *eth.Config) {
  1102  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
  1103  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
  1104  	}
  1105  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
  1106  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
  1107  	}
  1108  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
  1109  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
  1110  	}
  1111  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
  1112  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
  1113  	}
  1114  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
  1115  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
  1116  	}
  1117  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
  1118  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
  1119  	}
  1120  }
  1121  
  1122  func setIstanbul(ctx *cli.Context, cfg *eth.Config) {
  1123  	if ctx.GlobalIsSet(IstanbulRequestTimeoutFlag.Name) {
  1124  		cfg.Istanbul.RequestTimeout = ctx.GlobalUint64(IstanbulRequestTimeoutFlag.Name)
  1125  	}
  1126  	if ctx.GlobalIsSet(IstanbulBlockPeriodFlag.Name) {
  1127  		cfg.Istanbul.BlockPeriod = ctx.GlobalUint64(IstanbulBlockPeriodFlag.Name)
  1128  	}
  1129  }
  1130  
  1131  // checkExclusive verifies that only a single instance of the provided flags was
  1132  // set by the user. Each flag might optionally be followed by a string type to
  1133  // specialize it further.
  1134  func checkExclusive(ctx *cli.Context, args ...interface{}) {
  1135  	set := make([]string, 0, 1)
  1136  	for i := 0; i < len(args); i++ {
  1137  		// Make sure the next argument is a flag and skip if not set
  1138  		flag, ok := args[i].(cli.Flag)
  1139  		if !ok {
  1140  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1141  		}
  1142  		// Check if next arg extends current and expand its name if so
  1143  		name := flag.GetName()
  1144  
  1145  		if i+1 < len(args) {
  1146  			switch option := args[i+1].(type) {
  1147  			case string:
  1148  				// Extended flag check, make sure value set doesn't conflict with passed in option
  1149  				if ctx.GlobalString(flag.GetName()) == option {
  1150  					name += "=" + option
  1151  					set = append(set, "--"+name)
  1152  				}
  1153  				// shift arguments and continue
  1154  				i++
  1155  				continue
  1156  
  1157  			case cli.Flag:
  1158  			default:
  1159  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1160  			}
  1161  		}
  1162  		// Mark the flag if it's set
  1163  		if ctx.GlobalIsSet(flag.GetName()) {
  1164  			set = append(set, "--"+name)
  1165  		}
  1166  	}
  1167  	if len(set) > 1 {
  1168  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1169  	}
  1170  }
  1171  
  1172  // SetShhConfig applies shh-related command line flags to the config.
  1173  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
  1174  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
  1175  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
  1176  	}
  1177  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
  1178  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
  1179  	}
  1180  	if ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) {
  1181  		cfg.RestrictConnectionBetweenLightClients = true
  1182  	}
  1183  }
  1184  
  1185  // SetEthConfig applies eth-related command line flags to the config.
  1186  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
  1187  	// Avoid conflicting network flags
  1188  	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
  1189  	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
  1190  
  1191  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
  1192  	setEtherbase(ctx, ks, cfg)
  1193  	setGPO(ctx, &cfg.GPO)
  1194  	setTxPool(ctx, &cfg.TxPool)
  1195  	setEthash(ctx, cfg)
  1196  	setIstanbul(ctx, cfg)
  1197  
  1198  	if ctx.GlobalIsSet(SyncModeFlag.Name) {
  1199  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1200  	}
  1201  	if ctx.GlobalIsSet(LightServFlag.Name) {
  1202  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
  1203  	}
  1204  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
  1205  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
  1206  	}
  1207  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1208  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1209  	}
  1210  
  1211  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
  1212  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1213  	}
  1214  	cfg.DatabaseHandles = makeDatabaseHandles()
  1215  
  1216  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1217  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1218  	}
  1219  	cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
  1220  
  1221  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1222  		cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1223  	}
  1224  	if ctx.GlobalIsSet(MinerNotifyFlag.Name) {
  1225  		cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",")
  1226  	}
  1227  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1228  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1229  	}
  1230  	if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) {
  1231  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name))
  1232  	}
  1233  	if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
  1234  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
  1235  	}
  1236  	if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) {
  1237  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name)
  1238  	}
  1239  	if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
  1240  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
  1241  	}
  1242  	if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
  1243  		cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
  1244  	}
  1245  	if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1246  		cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name)
  1247  	}
  1248  	if ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
  1249  		cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name)
  1250  	}
  1251  	if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) {
  1252  		cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
  1253  	}
  1254  	if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
  1255  		cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name)
  1256  	}
  1257  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1258  		// TODO(fjl): force-enable this in --dev mode
  1259  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1260  	}
  1261  
  1262  	if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) {
  1263  		cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name)
  1264  	}
  1265  
  1266  	if ctx.GlobalIsSet(EVMInterpreterFlag.Name) {
  1267  		cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name)
  1268  	}
  1269  
  1270  	// Override any default configs for hard coded networks.
  1271  	switch {
  1272  	case ctx.GlobalBool(TestnetFlag.Name):
  1273  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1274  			cfg.NetworkId = 3
  1275  		}
  1276  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1277  	case ctx.GlobalBool(RinkebyFlag.Name):
  1278  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1279  			cfg.NetworkId = 4
  1280  		}
  1281  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1282  	case ctx.GlobalBool(OttomanFlag.Name):
  1283  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1284  			cfg.NetworkId = 5
  1285  		}
  1286  		cfg.Genesis = core.DefaultOttomanGenesisBlock()
  1287  	case ctx.GlobalBool(DeveloperFlag.Name):
  1288  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1289  			cfg.NetworkId = 1337
  1290  		}
  1291  		// Create new developer account or reuse existing one
  1292  		var (
  1293  			developer accounts.Account
  1294  			err       error
  1295  		)
  1296  		if accs := ks.Accounts(); len(accs) > 0 {
  1297  			developer = ks.Accounts()[0]
  1298  		} else {
  1299  			developer, err = ks.NewAccount("")
  1300  			if err != nil {
  1301  				Fatalf("Failed to create developer account: %v", err)
  1302  			}
  1303  		}
  1304  		if err := ks.Unlock(developer, ""); err != nil {
  1305  			Fatalf("Failed to unlock developer account: %v", err)
  1306  		}
  1307  		log.Info("Using developer account", "address", developer.Address)
  1308  
  1309  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1310  		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1311  			cfg.MinerGasPrice = big.NewInt(1)
  1312  		}
  1313  	}
  1314  	// TODO(fjl): move trie cache generations into config
  1315  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1316  		state.MaxTrieCacheGen = uint16(gen)
  1317  	}
  1318  }
  1319  
  1320  // SetDashboardConfig applies dashboard related command line flags to the config.
  1321  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1322  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1323  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1324  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1325  }
  1326  
  1327  // RegisterEthService adds an Ethereum client to the stack.
  1328  func RegisterEthService(stack *node.Node, cfg *eth.Config) <-chan *eth.Ethereum {
  1329  	nodeChan := make(chan *eth.Ethereum, 1)
  1330  	var err error
  1331  	if cfg.SyncMode == downloader.LightSync {
  1332  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1333  			return les.New(ctx, cfg)
  1334  		})
  1335  	} else {
  1336  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1337  			fullNode, err := eth.New(ctx, cfg)
  1338  			if fullNode != nil && cfg.LightServ > 0 {
  1339  				ls, _ := les.NewLesServer(fullNode, cfg)
  1340  				fullNode.AddLesServer(ls)
  1341  			}
  1342  			nodeChan <- fullNode
  1343  			return fullNode, err
  1344  		})
  1345  	}
  1346  	if err != nil {
  1347  		Fatalf("Failed to register the Ethereum service: %v", err)
  1348  	}
  1349  
  1350  	return nodeChan
  1351  }
  1352  
  1353  // RegisterDashboardService adds a dashboard to the stack.
  1354  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
  1355  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1356  		return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil
  1357  	})
  1358  }
  1359  
  1360  // RegisterShhService configures Whisper and adds it to the given node.
  1361  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1362  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1363  		return whisper.New(cfg), nil
  1364  	}); err != nil {
  1365  		Fatalf("Failed to register the Whisper service: %v", err)
  1366  	}
  1367  }
  1368  
  1369  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1370  // the given node.
  1371  func RegisterEthStatsService(stack *node.Node, url string) {
  1372  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1373  		// Retrieve both eth and les services
  1374  		var ethServ *eth.Ethereum
  1375  		ctx.Service(&ethServ)
  1376  
  1377  		var lesServ *les.LightEthereum
  1378  		ctx.Service(&lesServ)
  1379  
  1380  		return ethstats.New(url, ethServ, lesServ)
  1381  	}); err != nil {
  1382  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1383  	}
  1384  }
  1385  
  1386  func SetupMetrics(ctx *cli.Context) {
  1387  	if metrics.Enabled {
  1388  		log.Info("Enabling metrics collection")
  1389  		var (
  1390  			enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
  1391  			endpoint     = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
  1392  			database     = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
  1393  			username     = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
  1394  			password     = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
  1395  			hosttag      = ctx.GlobalString(MetricsInfluxDBHostTagFlag.Name)
  1396  		)
  1397  
  1398  		if enableExport {
  1399  			log.Info("Enabling metrics export to InfluxDB")
  1400  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", map[string]string{
  1401  				"host": hosttag,
  1402  			})
  1403  		}
  1404  	}
  1405  }
  1406  
  1407  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1408  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1409  	var (
  1410  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1411  		handles = makeDatabaseHandles()
  1412  	)
  1413  	name := "chaindata"
  1414  	if ctx.GlobalString(SyncModeFlag.Name) == "light" {
  1415  		name = "lightchaindata"
  1416  	}
  1417  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1418  	if err != nil {
  1419  		Fatalf("Could not open database: %v", err)
  1420  	}
  1421  	return chainDb
  1422  }
  1423  
  1424  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1425  	var genesis *core.Genesis
  1426  	switch {
  1427  	case ctx.GlobalBool(TestnetFlag.Name):
  1428  		genesis = core.DefaultTestnetGenesisBlock()
  1429  	case ctx.GlobalBool(RinkebyFlag.Name):
  1430  		genesis = core.DefaultRinkebyGenesisBlock()
  1431  	case ctx.GlobalBool(OttomanFlag.Name):
  1432  		genesis = core.DefaultOttomanGenesisBlock()
  1433  	case ctx.GlobalBool(DeveloperFlag.Name):
  1434  		Fatalf("Developer chains are ephemeral")
  1435  	}
  1436  	return genesis
  1437  }
  1438  
  1439  // MakeChain creates a chain manager from set command line flags.
  1440  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  1441  	var err error
  1442  	chainDb = MakeChainDatabase(ctx, stack)
  1443  
  1444  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1445  	if err != nil {
  1446  		Fatalf("%v", err)
  1447  	}
  1448  	var engine consensus.Engine
  1449  	if config.Clique != nil {
  1450  		engine = clique.New(config.Clique, chainDb)
  1451  	} else {
  1452  		engine = ethash.NewFaker()
  1453  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1454  			engine = ethash.New(ethash.Config{
  1455  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1456  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1457  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1458  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1459  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1460  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1461  			}, nil, false)
  1462  		}
  1463  	}
  1464  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1465  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1466  	}
  1467  	cache := &core.CacheConfig{
  1468  		Disabled:      ctx.GlobalString(GCModeFlag.Name) == "archive",
  1469  		TrieNodeLimit: eth.DefaultConfig.TrieCache,
  1470  		TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
  1471  	}
  1472  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1473  		cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1474  	}
  1475  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1476  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil)
  1477  	if err != nil {
  1478  		Fatalf("Can't create BlockChain: %v", err)
  1479  	}
  1480  	return chain, chainDb
  1481  }
  1482  
  1483  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1484  // scripts to preload before starting.
  1485  func MakeConsolePreloads(ctx *cli.Context) []string {
  1486  	// Skip preloading if there's nothing to preload
  1487  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1488  		return nil
  1489  	}
  1490  	// Otherwise resolve absolute paths and return them
  1491  	preloads := []string{}
  1492  
  1493  	assets := ctx.GlobalString(JSpathFlag.Name)
  1494  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1495  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1496  	}
  1497  	return preloads
  1498  }
  1499  
  1500  // MigrateFlags sets the global flag from a local flag when it's set.
  1501  // This is a temporary function used for migrating old command/flags to the
  1502  // new format.
  1503  //
  1504  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1505  //
  1506  // is equivalent after calling this method with:
  1507  //
  1508  // geth --keystore /tmp/mykeystore --lightkdf account new
  1509  //
  1510  // This allows the use of the existing configuration functionality.
  1511  // When all flags are migrated this function can be removed and the existing
  1512  // configuration functionality must be changed that is uses local flags
  1513  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1514  	return func(ctx *cli.Context) error {
  1515  		for _, name := range ctx.FlagNames() {
  1516  			if ctx.IsSet(name) {
  1517  				ctx.GlobalSet(name, ctx.String(name))
  1518  			}
  1519  		}
  1520  		return action(ctx)
  1521  	}
  1522  }