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