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