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