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