github.com/puffscoin/go-puffscoin@v0.0.0-20190701205704-e48ad5c90fa1/cmd/utils/flags.go (about)

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