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