github.com/xfers/quorum@v21.1.0+incompatible/cmd/utils/flags.go (about)

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