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