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