github.com/codingfuture/orig-energi3@v0.8.4/cmd/utils/flags.go (about)

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