github.com/XinFinOrg/xdcchain@v1.1.0/cmd/utils/flags.go (about)

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