github.com/alexdevranger/node-1.8.27@v0.0.0-20221128213301-aa5841e41d2d/cmd/utils/flags.go (about)

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