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