github.com/Evanesco-Labs/go-evanesco@v1.0.1/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  	"github.com/Evanesco-Labs/go-evanesco/zkpminer"
    24  	zkpkeypair "github.com/Evanesco-Labs/go-evanesco/zkpminer/keypair"
    25  	"io"
    26  	"io/ioutil"
    27  	"math"
    28  	"math/big"
    29  	"os"
    30  	"path/filepath"
    31  	godebug "runtime/debug"
    32  	"strconv"
    33  	"strings"
    34  	"text/tabwriter"
    35  	"text/template"
    36  	"time"
    37  
    38  	"github.com/Evanesco-Labs/go-evanesco/accounts"
    39  	"github.com/Evanesco-Labs/go-evanesco/accounts/keystore"
    40  	"github.com/Evanesco-Labs/go-evanesco/common"
    41  	"github.com/Evanesco-Labs/go-evanesco/common/fdlimit"
    42  	"github.com/Evanesco-Labs/go-evanesco/consensus"
    43  	"github.com/Evanesco-Labs/go-evanesco/consensus/clique"
    44  	"github.com/Evanesco-Labs/go-evanesco/consensus/ethash"
    45  	"github.com/Evanesco-Labs/go-evanesco/core"
    46  	"github.com/Evanesco-Labs/go-evanesco/core/rawdb"
    47  	"github.com/Evanesco-Labs/go-evanesco/core/vm"
    48  	"github.com/Evanesco-Labs/go-evanesco/crypto"
    49  	"github.com/Evanesco-Labs/go-evanesco/eth"
    50  	"github.com/Evanesco-Labs/go-evanesco/eth/downloader"
    51  	"github.com/Evanesco-Labs/go-evanesco/eth/ethconfig"
    52  	"github.com/Evanesco-Labs/go-evanesco/eth/gasprice"
    53  	"github.com/Evanesco-Labs/go-evanesco/eth/tracers"
    54  	"github.com/Evanesco-Labs/go-evanesco/ethdb"
    55  	"github.com/Evanesco-Labs/go-evanesco/ethstats"
    56  	"github.com/Evanesco-Labs/go-evanesco/graphql"
    57  	"github.com/Evanesco-Labs/go-evanesco/internal/ethapi"
    58  	"github.com/Evanesco-Labs/go-evanesco/internal/flags"
    59  	"github.com/Evanesco-Labs/go-evanesco/les"
    60  	"github.com/Evanesco-Labs/go-evanesco/log"
    61  	"github.com/Evanesco-Labs/go-evanesco/metrics"
    62  	"github.com/Evanesco-Labs/go-evanesco/metrics/exp"
    63  	"github.com/Evanesco-Labs/go-evanesco/metrics/influxdb"
    64  	"github.com/Evanesco-Labs/go-evanesco/miner"
    65  	"github.com/Evanesco-Labs/go-evanesco/node"
    66  	"github.com/Evanesco-Labs/go-evanesco/p2p"
    67  	"github.com/Evanesco-Labs/go-evanesco/p2p/enode"
    68  	"github.com/Evanesco-Labs/go-evanesco/p2p/nat"
    69  	"github.com/Evanesco-Labs/go-evanesco/p2p/netutil"
    70  	"github.com/Evanesco-Labs/go-evanesco/params"
    71  	pcsclite "github.com/gballet/go-libpcsclite"
    72  	gopsutil "github.com/shirou/gopsutil/mem"
    73  	"gopkg.in/urfave/cli.v1"
    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  	cli.CommandHelpTemplate = flags.CommandHelpTemplate
    90  	cli.HelpPrinter = printHelp
    91  }
    92  
    93  func printHelp(out io.Writer, templ string, data interface{}) {
    94  	funcMap := template.FuncMap{"join": strings.Join}
    95  	t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
    96  	w := tabwriter.NewWriter(out, 38, 8, 2, ' ', 0)
    97  	err := t.Execute(w, data)
    98  	if err != nil {
    99  		panic(err)
   100  	}
   101  	w.Flush()
   102  }
   103  
   104  // These are all the command line flags we support.
   105  // If you add to this list, please remember to include the
   106  // flag in the appropriate command definition.
   107  //
   108  // The flags are defined here so their names and help texts
   109  // are the same for all commands.
   110  
   111  var (
   112  	// General settings
   113  	DataDirFlag = DirectoryFlag{
   114  		Name:  "datadir",
   115  		Usage: "Data directory for the databases and keystore",
   116  		Value: DirectoryString(node.DefaultDataDir()),
   117  	}
   118  	AncientFlag = DirectoryFlag{
   119  		Name:  "datadir.ancient",
   120  		Usage: "Data directory for ancient chain segments (default = inside chaindata)",
   121  	}
   122  	MinFreeDiskSpaceFlag = DirectoryFlag{
   123  		Name:  "datadir.minfreedisk",
   124  		Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)",
   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 (deprecated)",
   133  	}
   134  	USBFlag = cli.BoolFlag{
   135  		Name:  "usb",
   136  		Usage: "Enable monitoring and management of USB hardware wallets",
   137  	}
   138  	SmartCardDaemonPathFlag = cli.StringFlag{
   139  		Name:  "pcscdpath",
   140  		Usage: "Path to the smartcard daemon (pcscd) socket file",
   141  		Value: pcsclite.PCSCDSockName,
   142  	}
   143  	NetworkIdFlag = cli.Uint64Flag{
   144  		Name:  "networkid",
   145  		Usage: "Explicitly set network id (integer)(For testnets: use --ropsten, --rinkeby, --goerli instead)",
   146  		Value: ethconfig.Defaults.NetworkId,
   147  	}
   148  	MainnetFlag = cli.BoolFlag{
   149  		Name:  "mainnet",
   150  		Usage: "Ethereum mainnet",
   151  	}
   152  	GoerliFlag = cli.BoolFlag{
   153  		Name:  "goerli",
   154  		Usage: "Görli network: pre-configured proof-of-authority test network",
   155  	}
   156  	CalaverasFlag = cli.BoolFlag{
   157  		Name:  "calaveras",
   158  		Usage: "Calaveras network: pre-configured proof-of-authority shortlived test network.",
   159  	}
   160  	RinkebyFlag = cli.BoolFlag{
   161  		Name:  "rinkeby",
   162  		Usage: "Rinkeby network: pre-configured proof-of-authority test network",
   163  	}
   164  	RopstenFlag = cli.BoolFlag{
   165  		Name:  "ropsten",
   166  		Usage: "Ropsten network: pre-configured proof-of-work test network",
   167  	}
   168  	DeveloperFlag = cli.BoolFlag{
   169  		Name:  "dev",
   170  		Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   171  	}
   172  	DeveloperPeriodFlag = cli.IntFlag{
   173  		Name:  "dev.period",
   174  		Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   175  	}
   176  	IdentityFlag = cli.StringFlag{
   177  		Name:  "identity",
   178  		Usage: "Custom node name",
   179  	}
   180  	DocRootFlag = DirectoryFlag{
   181  		Name:  "docroot",
   182  		Usage: "Document Root for HTTPClient file scheme",
   183  		Value: DirectoryString(HomeDir()),
   184  	}
   185  	ExitWhenSyncedFlag = cli.BoolFlag{
   186  		Name:  "exitwhensynced",
   187  		Usage: "Exits after block synchronisation completes",
   188  	}
   189  	IterativeOutputFlag = cli.BoolTFlag{
   190  		Name:  "iterative",
   191  		Usage: "Print streaming JSON iteratively, delimited by newlines",
   192  	}
   193  	ExcludeStorageFlag = cli.BoolFlag{
   194  		Name:  "nostorage",
   195  		Usage: "Exclude storage entries (save db lookups)",
   196  	}
   197  	IncludeIncompletesFlag = cli.BoolFlag{
   198  		Name:  "incompletes",
   199  		Usage: "Include accounts for which we don't have the address (missing preimage)",
   200  	}
   201  	ExcludeCodeFlag = cli.BoolFlag{
   202  		Name:  "nocode",
   203  		Usage: "Exclude contract code (save db lookups)",
   204  	}
   205  	StartKeyFlag = cli.StringFlag{
   206  		Name:  "start",
   207  		Usage: "Start position. Either a hash or address",
   208  		Value: "0x0000000000000000000000000000000000000000000000000000000000000000",
   209  	}
   210  	DumpLimitFlag = cli.Uint64Flag{
   211  		Name:  "limit",
   212  		Usage: "Max number of elements (0 = no limit)",
   213  		Value: 0,
   214  	}
   215  	defaultSyncMode = ethconfig.Defaults.SyncMode
   216  	SyncModeFlag    = TextMarshalerFlag{
   217  		Name:  "syncmode",
   218  		Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`,
   219  		Value: &defaultSyncMode,
   220  	}
   221  	GCModeFlag = cli.StringFlag{
   222  		Name:  "gcmode",
   223  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   224  		Value: "full",
   225  	}
   226  	SnapshotFlag = cli.BoolTFlag{
   227  		Name:  "snapshot",
   228  		Usage: `Enables snapshot-database mode (default = enable)`,
   229  	}
   230  	TxLookupLimitFlag = cli.Uint64Flag{
   231  		Name:  "txlookuplimit",
   232  		Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)",
   233  		Value: ethconfig.Defaults.TxLookupLimit,
   234  	}
   235  	LightKDFFlag = cli.BoolFlag{
   236  		Name:  "lightkdf",
   237  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   238  	}
   239  	WhitelistFlag = cli.StringFlag{
   240  		Name:  "whitelist",
   241  		Usage: "Comma separated block number-to-hash mappings to enforce (<number>=<hash>)",
   242  	}
   243  	BloomFilterSizeFlag = cli.Uint64Flag{
   244  		Name:  "bloomfilter.size",
   245  		Usage: "Megabytes of memory allocated to bloom-filter for pruning",
   246  		Value: 2048,
   247  	}
   248  	OverrideLondonFlag = cli.Uint64Flag{
   249  		Name:  "override.london",
   250  		Usage: "Manually specify London fork-block, overriding the bundled setting",
   251  	}
   252  	// Light server and client settings
   253  	LightServeFlag = cli.IntFlag{
   254  		Name:  "light.serve",
   255  		Usage: "Maximum percentage of time allowed for serving LES requests (multi-threaded processing allows values over 100)",
   256  		Value: ethconfig.Defaults.LightServ,
   257  	}
   258  	LightIngressFlag = cli.IntFlag{
   259  		Name:  "light.ingress",
   260  		Usage: "Incoming bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
   261  		Value: ethconfig.Defaults.LightIngress,
   262  	}
   263  	LightEgressFlag = cli.IntFlag{
   264  		Name:  "light.egress",
   265  		Usage: "Outgoing bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
   266  		Value: ethconfig.Defaults.LightEgress,
   267  	}
   268  	LightMaxPeersFlag = cli.IntFlag{
   269  		Name:  "light.maxpeers",
   270  		Usage: "Maximum number of light clients to serve, or light servers to attach to",
   271  		Value: ethconfig.Defaults.LightPeers,
   272  	}
   273  	UltraLightServersFlag = cli.StringFlag{
   274  		Name:  "ulc.servers",
   275  		Usage: "List of trusted ultra-light servers",
   276  		Value: strings.Join(ethconfig.Defaults.UltraLightServers, ","),
   277  	}
   278  	UltraLightFractionFlag = cli.IntFlag{
   279  		Name:  "ulc.fraction",
   280  		Usage: "Minimum % of trusted ultra-light servers required to announce a new head",
   281  		Value: ethconfig.Defaults.UltraLightFraction,
   282  	}
   283  	UltraLightOnlyAnnounceFlag = cli.BoolFlag{
   284  		Name:  "ulc.onlyannounce",
   285  		Usage: "Ultra light server sends announcements only",
   286  	}
   287  	LightNoPruneFlag = cli.BoolFlag{
   288  		Name:  "light.nopruning",
   289  		Usage: "Disable ancient light chain data pruning",
   290  	}
   291  	LightNoSyncServeFlag = cli.BoolFlag{
   292  		Name:  "light.nosyncserve",
   293  		Usage: "Enables serving light clients before syncing",
   294  	}
   295  	// Ethash settings
   296  	EthashCacheDirFlag = DirectoryFlag{
   297  		Name:  "ethash.cachedir",
   298  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   299  	}
   300  	EthashCachesInMemoryFlag = cli.IntFlag{
   301  		Name:  "ethash.cachesinmem",
   302  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   303  		Value: ethconfig.Defaults.Ethash.CachesInMem,
   304  	}
   305  	EthashCachesOnDiskFlag = cli.IntFlag{
   306  		Name:  "ethash.cachesondisk",
   307  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   308  		Value: ethconfig.Defaults.Ethash.CachesOnDisk,
   309  	}
   310  	EthashCachesLockMmapFlag = cli.BoolFlag{
   311  		Name:  "ethash.cacheslockmmap",
   312  		Usage: "Lock memory maps of recent ethash caches",
   313  	}
   314  	EthashDatasetDirFlag = DirectoryFlag{
   315  		Name:  "ethash.dagdir",
   316  		Usage: "Directory to store the ethash mining DAGs",
   317  		Value: DirectoryString(ethconfig.Defaults.Ethash.DatasetDir),
   318  	}
   319  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   320  		Name:  "ethash.dagsinmem",
   321  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   322  		Value: ethconfig.Defaults.Ethash.DatasetsInMem,
   323  	}
   324  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   325  		Name:  "ethash.dagsondisk",
   326  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   327  		Value: ethconfig.Defaults.Ethash.DatasetsOnDisk,
   328  	}
   329  	EthashDatasetsLockMmapFlag = cli.BoolFlag{
   330  		Name:  "ethash.dagslockmmap",
   331  		Usage: "Lock memory maps for recent ethash mining DAGs",
   332  	}
   333  	// Transaction pool settings
   334  	TxPoolLocalsFlag = cli.StringFlag{
   335  		Name:  "txpool.locals",
   336  		Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
   337  	}
   338  	TxPoolNoLocalsFlag = cli.BoolFlag{
   339  		Name:  "txpool.nolocals",
   340  		Usage: "Disables price exemptions for locally submitted transactions",
   341  	}
   342  	TxPoolJournalFlag = cli.StringFlag{
   343  		Name:  "txpool.journal",
   344  		Usage: "Disk journal for local transaction to survive node restarts",
   345  		Value: core.DefaultTxPoolConfig.Journal,
   346  	}
   347  	TxPoolRejournalFlag = cli.DurationFlag{
   348  		Name:  "txpool.rejournal",
   349  		Usage: "Time interval to regenerate the local transaction journal",
   350  		Value: core.DefaultTxPoolConfig.Rejournal,
   351  	}
   352  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   353  		Name:  "txpool.pricelimit",
   354  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   355  		Value: ethconfig.Defaults.TxPool.PriceLimit,
   356  	}
   357  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   358  		Name:  "txpool.pricebump",
   359  		Usage: "Price bump percentage to replace an already existing transaction",
   360  		Value: ethconfig.Defaults.TxPool.PriceBump,
   361  	}
   362  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   363  		Name:  "txpool.accountslots",
   364  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   365  		Value: ethconfig.Defaults.TxPool.AccountSlots,
   366  	}
   367  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   368  		Name:  "txpool.globalslots",
   369  		Usage: "Maximum number of executable transaction slots for all accounts",
   370  		Value: ethconfig.Defaults.TxPool.GlobalSlots,
   371  	}
   372  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   373  		Name:  "txpool.accountqueue",
   374  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   375  		Value: ethconfig.Defaults.TxPool.AccountQueue,
   376  	}
   377  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   378  		Name:  "txpool.globalqueue",
   379  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   380  		Value: ethconfig.Defaults.TxPool.GlobalQueue,
   381  	}
   382  	TxPoolLifetimeFlag = cli.DurationFlag{
   383  		Name:  "txpool.lifetime",
   384  		Usage: "Maximum amount of time non-executable transaction are queued",
   385  		Value: ethconfig.Defaults.TxPool.Lifetime,
   386  	}
   387  	// Performance tuning settings
   388  	CacheFlag = cli.IntFlag{
   389  		Name:  "cache",
   390  		Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node, 128 light mode)",
   391  		Value: 1024,
   392  	}
   393  	CacheDatabaseFlag = cli.IntFlag{
   394  		Name:  "cache.database",
   395  		Usage: "Percentage of cache memory allowance to use for database io",
   396  		Value: 50,
   397  	}
   398  	CacheTrieFlag = cli.IntFlag{
   399  		Name:  "cache.trie",
   400  		Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)",
   401  		Value: 15,
   402  	}
   403  	CacheTrieJournalFlag = cli.StringFlag{
   404  		Name:  "cache.trie.journal",
   405  		Usage: "Disk journal directory for trie cache to survive node restarts",
   406  		Value: ethconfig.Defaults.TrieCleanCacheJournal,
   407  	}
   408  	CacheTrieRejournalFlag = cli.DurationFlag{
   409  		Name:  "cache.trie.rejournal",
   410  		Usage: "Time interval to regenerate the trie cache journal",
   411  		Value: ethconfig.Defaults.TrieCleanCacheRejournal,
   412  	}
   413  	CacheGCFlag = cli.IntFlag{
   414  		Name:  "cache.gc",
   415  		Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
   416  		Value: 25,
   417  	}
   418  	CacheSnapshotFlag = cli.IntFlag{
   419  		Name:  "cache.snapshot",
   420  		Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)",
   421  		Value: 10,
   422  	}
   423  	CacheNoPrefetchFlag = cli.BoolFlag{
   424  		Name:  "cache.noprefetch",
   425  		Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
   426  	}
   427  	CachePreimagesFlag = cli.BoolFlag{
   428  		Name:  "cache.preimages",
   429  		Usage: "Enable recording the SHA3/keccak preimages of trie keys",
   430  	}
   431  	// Miner settings
   432  	MiningEnabledFlag = cli.BoolFlag{
   433  		Name:  "mine",
   434  		Usage: "Enable mining",
   435  	}
   436  	MinerThreadsFlag = cli.IntFlag{
   437  		Name:  "miner.threads",
   438  		Usage: "Number of CPU threads to use for mining",
   439  		Value: 0,
   440  	}
   441  	MinerNotifyFlag = cli.StringFlag{
   442  		Name:  "miner.notify",
   443  		Usage: "Comma separated HTTP URL list to notify of new work packages",
   444  	}
   445  	MinerNotifyFullFlag = cli.BoolFlag{
   446  		Name:  "miner.notify.full",
   447  		Usage: "Notify with pending block headers instead of work packages",
   448  	}
   449  	MinerGasTargetFlag = cli.Uint64Flag{
   450  		Name:  "miner.gastarget",
   451  		Usage: "Target gas floor for mined blocks",
   452  		Value: ethconfig.Defaults.Miner.GasFloor,
   453  	}
   454  	MinerGasLimitFlag = cli.Uint64Flag{
   455  		Name:  "miner.gaslimit",
   456  		Usage: "Target gas ceiling for mined blocks",
   457  		Value: ethconfig.Defaults.Miner.GasCeil,
   458  	}
   459  	MinerGasPriceFlag = BigFlag{
   460  		Name:  "miner.gasprice",
   461  		Usage: "Minimum gas price for mining a transaction",
   462  		Value: ethconfig.Defaults.Miner.GasPrice,
   463  	}
   464  	MinerEtherbaseFlag = cli.StringFlag{
   465  		Name:  "miner.etherbase",
   466  		Usage: "Public address for block mining rewards (default = first account)",
   467  		Value: "0",
   468  	}
   469  	MinerExtraDataFlag = cli.StringFlag{
   470  		Name:  "miner.extradata",
   471  		Usage: "Block extra data set by the miner (default = client version)",
   472  	}
   473  	MinerRecommitIntervalFlag = cli.DurationFlag{
   474  		Name:  "miner.recommit",
   475  		Usage: "Time interval to recreate the block being mined",
   476  		Value: ethconfig.Defaults.Miner.Recommit,
   477  	}
   478  	MinerNoVerfiyFlag = cli.BoolFlag{
   479  		Name:  "miner.noverify",
   480  		Usage: "Disable remote sealing verification",
   481  	}
   482  	// Account settings
   483  	UnlockedAccountFlag = cli.StringFlag{
   484  		Name:  "unlock",
   485  		Usage: "Comma separated list of accounts to unlock",
   486  		Value: "",
   487  	}
   488  	PasswordFileFlag = cli.StringFlag{
   489  		Name:  "password",
   490  		Usage: "Password file to use for non-interactive password input",
   491  		Value: "",
   492  	}
   493  	ExternalSignerFlag = cli.StringFlag{
   494  		Name:  "signer",
   495  		Usage: "External signer (url or path to ipc file)",
   496  		Value: "",
   497  	}
   498  	VMEnableDebugFlag = cli.BoolFlag{
   499  		Name:  "vmdebug",
   500  		Usage: "Record information useful for VM and contract debugging",
   501  	}
   502  	InsecureUnlockAllowedFlag = cli.BoolFlag{
   503  		Name:  "allow-insecure-unlock",
   504  		Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http",
   505  	}
   506  	RPCGlobalGasCapFlag = cli.Uint64Flag{
   507  		Name:  "rpc.gascap",
   508  		Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)",
   509  		Value: ethconfig.Defaults.RPCGasCap,
   510  	}
   511  	RPCGlobalTxFeeCapFlag = cli.Float64Flag{
   512  		Name:  "rpc.txfeecap",
   513  		Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)",
   514  		Value: ethconfig.Defaults.RPCTxFeeCap,
   515  	}
   516  	// Logging and debug settings
   517  	EthStatsURLFlag = cli.StringFlag{
   518  		Name:  "ethstats",
   519  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   520  	}
   521  	FakePoWFlag = cli.BoolFlag{
   522  		Name:  "fakepow",
   523  		Usage: "Disables proof-of-work verification",
   524  	}
   525  	NoCompactionFlag = cli.BoolFlag{
   526  		Name:  "nocompaction",
   527  		Usage: "Disables db compaction after import",
   528  	}
   529  	// RPC settings
   530  	IPCDisabledFlag = cli.BoolFlag{
   531  		Name:  "ipcdisable",
   532  		Usage: "Disable the IPC-RPC server",
   533  	}
   534  	IPCPathFlag = DirectoryFlag{
   535  		Name:  "ipcpath",
   536  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   537  	}
   538  	HTTPEnabledFlag = cli.BoolFlag{
   539  		Name:  "http",
   540  		Usage: "Enable the HTTP-RPC server",
   541  	}
   542  	HTTPListenAddrFlag = cli.StringFlag{
   543  		Name:  "http.addr",
   544  		Usage: "HTTP-RPC server listening interface",
   545  		Value: node.DefaultHTTPHost,
   546  	}
   547  	HTTPPortFlag = cli.IntFlag{
   548  		Name:  "http.port",
   549  		Usage: "HTTP-RPC server listening port",
   550  		Value: node.DefaultHTTPPort,
   551  	}
   552  	HTTPCORSDomainFlag = cli.StringFlag{
   553  		Name:  "http.corsdomain",
   554  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   555  		Value: "",
   556  	}
   557  	HTTPVirtualHostsFlag = cli.StringFlag{
   558  		Name:  "http.vhosts",
   559  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   560  		Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
   561  	}
   562  	HTTPApiFlag = cli.StringFlag{
   563  		Name:  "http.api",
   564  		Usage: "API's offered over the HTTP-RPC interface",
   565  		Value: "",
   566  	}
   567  	HTTPPathPrefixFlag = cli.StringFlag{
   568  		Name:  "http.rpcprefix",
   569  		Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
   570  		Value: "",
   571  	}
   572  	GraphQLEnabledFlag = cli.BoolFlag{
   573  		Name:  "graphql",
   574  		Usage: "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.",
   575  	}
   576  	GraphQLCORSDomainFlag = cli.StringFlag{
   577  		Name:  "graphql.corsdomain",
   578  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   579  		Value: "",
   580  	}
   581  	GraphQLVirtualHostsFlag = cli.StringFlag{
   582  		Name:  "graphql.vhosts",
   583  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   584  		Value: strings.Join(node.DefaultConfig.GraphQLVirtualHosts, ","),
   585  	}
   586  	WSEnabledFlag = cli.BoolFlag{
   587  		Name:  "ws",
   588  		Usage: "Enable the WS-RPC server",
   589  	}
   590  	WSListenAddrFlag = cli.StringFlag{
   591  		Name:  "ws.addr",
   592  		Usage: "WS-RPC server listening interface",
   593  		Value: node.DefaultWSHost,
   594  	}
   595  	WSPortFlag = cli.IntFlag{
   596  		Name:  "ws.port",
   597  		Usage: "WS-RPC server listening port",
   598  		Value: node.DefaultWSPort,
   599  	}
   600  	WSApiFlag = cli.StringFlag{
   601  		Name:  "ws.api",
   602  		Usage: "API's offered over the WS-RPC interface",
   603  		Value: "",
   604  	}
   605  	WSAllowedOriginsFlag = cli.StringFlag{
   606  		Name:  "ws.origins",
   607  		Usage: "Origins from which to accept websockets requests",
   608  		Value: "",
   609  	}
   610  	WSPathPrefixFlag = cli.StringFlag{
   611  		Name:  "ws.rpcprefix",
   612  		Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
   613  		Value: "",
   614  	}
   615  	ExecFlag = cli.StringFlag{
   616  		Name:  "exec",
   617  		Usage: "Execute JavaScript statement",
   618  	}
   619  	PreloadJSFlag = cli.StringFlag{
   620  		Name:  "preload",
   621  		Usage: "Comma separated list of JavaScript files to preload into the console",
   622  	}
   623  	AllowUnprotectedTxs = cli.BoolFlag{
   624  		Name:  "rpc.allow-unprotected-txs",
   625  		Usage: "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC",
   626  	}
   627  
   628  	// Network Settings
   629  	MaxPeersFlag = cli.IntFlag{
   630  		Name:  "maxpeers",
   631  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   632  		Value: node.DefaultConfig.P2P.MaxPeers,
   633  	}
   634  	MaxPendingPeersFlag = cli.IntFlag{
   635  		Name:  "maxpendpeers",
   636  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   637  		Value: node.DefaultConfig.P2P.MaxPendingPeers,
   638  	}
   639  	ListenPortFlag = cli.IntFlag{
   640  		Name:  "port",
   641  		Usage: "Network listening port",
   642  		Value: 30303,
   643  	}
   644  	BootnodesFlag = cli.StringFlag{
   645  		Name:  "bootnodes",
   646  		Usage: "Comma separated enode URLs for P2P discovery bootstrap",
   647  		Value: "",
   648  	}
   649  	NodeKeyFileFlag = cli.StringFlag{
   650  		Name:  "nodekey",
   651  		Usage: "P2P node key file",
   652  	}
   653  	NodeKeyHexFlag = cli.StringFlag{
   654  		Name:  "nodekeyhex",
   655  		Usage: "P2P node key as hex (for testing)",
   656  	}
   657  	NATFlag = cli.StringFlag{
   658  		Name:  "nat",
   659  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   660  		Value: "any",
   661  	}
   662  	NoDiscoverFlag = cli.BoolFlag{
   663  		Name:  "nodiscover",
   664  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   665  	}
   666  	DiscoveryV5Flag = cli.BoolFlag{
   667  		Name:  "v5disc",
   668  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   669  	}
   670  	NetrestrictFlag = cli.StringFlag{
   671  		Name:  "netrestrict",
   672  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   673  	}
   674  	DNSDiscoveryFlag = cli.StringFlag{
   675  		Name:  "discovery.dns",
   676  		Usage: "Sets DNS discovery entry points (use \"\" to disable DNS)",
   677  	}
   678  
   679  	// ATM the url is left to the user and deployment to
   680  	JSpathFlag = DirectoryFlag{
   681  		Name:  "jspath",
   682  		Usage: "JavaScript root path for `loadScript`",
   683  		Value: DirectoryString("."),
   684  	}
   685  
   686  	// Gas price oracle settings
   687  	GpoBlocksFlag = cli.IntFlag{
   688  		Name:  "gpo.blocks",
   689  		Usage: "Number of recent blocks to check for gas prices",
   690  		Value: ethconfig.Defaults.GPO.Blocks,
   691  	}
   692  	GpoPercentileFlag = cli.IntFlag{
   693  		Name:  "gpo.percentile",
   694  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   695  		Value: ethconfig.Defaults.GPO.Percentile,
   696  	}
   697  	GpoMaxGasPriceFlag = cli.Int64Flag{
   698  		Name:  "gpo.maxprice",
   699  		Usage: "Maximum gas price will be recommended by gpo",
   700  		Value: ethconfig.Defaults.GPO.MaxPrice.Int64(),
   701  	}
   702  	GpoIgnoreGasPriceFlag = cli.Int64Flag{
   703  		Name:  "gpo.ignoreprice",
   704  		Usage: "Gas price below which gpo will ignore transactions",
   705  		Value: ethconfig.Defaults.GPO.IgnorePrice.Int64(),
   706  	}
   707  
   708  	// Metrics flags
   709  	MetricsEnabledFlag = cli.BoolFlag{
   710  		Name:  "metrics",
   711  		Usage: "Enable metrics collection and reporting",
   712  	}
   713  	MetricsEnabledExpensiveFlag = cli.BoolFlag{
   714  		Name:  "metrics.expensive",
   715  		Usage: "Enable expensive metrics collection and reporting",
   716  	}
   717  
   718  	// MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint.
   719  	// Since the pprof service enables sensitive/vulnerable behavior, this allows a user
   720  	// to enable a public-OK metrics endpoint without having to worry about ALSO exposing
   721  	// other profiling behavior or information.
   722  	MetricsHTTPFlag = cli.StringFlag{
   723  		Name:  "metrics.addr",
   724  		Usage: "Enable stand-alone metrics HTTP server listening interface",
   725  		Value: metrics.DefaultConfig.HTTP,
   726  	}
   727  	MetricsPortFlag = cli.IntFlag{
   728  		Name:  "metrics.port",
   729  		Usage: "Metrics HTTP server listening port",
   730  		Value: metrics.DefaultConfig.Port,
   731  	}
   732  	MetricsEnableInfluxDBFlag = cli.BoolFlag{
   733  		Name:  "metrics.influxdb",
   734  		Usage: "Enable metrics export/push to an external InfluxDB database",
   735  	}
   736  	MetricsInfluxDBEndpointFlag = cli.StringFlag{
   737  		Name:  "metrics.influxdb.endpoint",
   738  		Usage: "InfluxDB API endpoint to report metrics to",
   739  		Value: metrics.DefaultConfig.InfluxDBEndpoint,
   740  	}
   741  	MetricsInfluxDBDatabaseFlag = cli.StringFlag{
   742  		Name:  "metrics.influxdb.database",
   743  		Usage: "InfluxDB database name to push reported metrics to",
   744  		Value: metrics.DefaultConfig.InfluxDBDatabase,
   745  	}
   746  	MetricsInfluxDBUsernameFlag = cli.StringFlag{
   747  		Name:  "metrics.influxdb.username",
   748  		Usage: "Username to authorize access to the database",
   749  		Value: metrics.DefaultConfig.InfluxDBUsername,
   750  	}
   751  	MetricsInfluxDBPasswordFlag = cli.StringFlag{
   752  		Name:  "metrics.influxdb.password",
   753  		Usage: "Password to authorize access to the database",
   754  		Value: metrics.DefaultConfig.InfluxDBPassword,
   755  	}
   756  	// Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB.
   757  	// For example `host` tag could be used so that we can group all nodes and average a measurement
   758  	// across all of them, but also so that we can select a specific node and inspect its measurements.
   759  	// https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key
   760  	MetricsInfluxDBTagsFlag = cli.StringFlag{
   761  		Name:  "metrics.influxdb.tags",
   762  		Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements",
   763  		Value: metrics.DefaultConfig.InfluxDBTags,
   764  	}
   765  	EWASMInterpreterFlag = cli.StringFlag{
   766  		Name:  "vm.ewasm",
   767  		Usage: "External ewasm configuration (default = built-in interpreter)",
   768  		Value: "",
   769  	}
   770  	EVMInterpreterFlag = cli.StringFlag{
   771  		Name:  "vm.evm",
   772  		Usage: "External EVM configuration (default = built-in interpreter)",
   773  		Value: "",
   774  	}
   775  
   776  	CatalystFlag = cli.BoolFlag{
   777  		Name:  "catalyst",
   778  		Usage: "Catalyst mode (eth2 integration testing)",
   779  	}
   780  
   781  	//WhiteNoise RPC Server configs
   782  	WhiteNoiseEnabledFlag = cli.BoolFlag{
   783  		Name:  "wn",
   784  		Usage: "Enable WhiteNoise-RPC server for full node",
   785  	}
   786  
   787  	WhiteNoiseBootstrapFlag = cli.StringFlag{
   788  		Name:  "wn-bootstrap",
   789  		Usage: "Bootstrap node Multiaddress of the WhiteNoise network to access",
   790  	}
   791  
   792  	//zkp verifier configs
   793  	ZKPVkPath = cli.StringFlag{
   794  		Name:  "zkpvkpath",
   795  		Usage: "file path of ZKP verify key",
   796  	}
   797  
   798  	//ZKP miner configs
   799  	ZKPMinerEnableFlag = cli.BoolFlag{
   800  		Name:  "zkpminer",
   801  		Usage: "Enable ZKP miner server for full node",
   802  	}
   803  	ZKPMinerPkPath = cli.StringFlag{
   804  		Name:  "zkppkpath",
   805  		Usage: "file path of ZKP prove key for ZKP miner",
   806  	}
   807  	ZKPMinerKeyPath = cli.StringFlag{
   808  		Name:  "zkpkeypath",
   809  		Usage: "keyfile path of ZKP miner address",
   810  	}
   811  	ZKPMinerPassword = cli.StringFlag{
   812  		Name:  "zkppassword",
   813  		Usage: "password of zkp miner keyfile",
   814  	}
   815  	ZKPMinerCoinbaseAddress = cli.StringFlag{
   816  		Name:  "zkpcoinbase",
   817  		Usage: "coinbase address to get miner rewards",
   818  	}
   819  )
   820  
   821  // MakeDataDir retrieves the currently requested data directory, terminating
   822  // if none (or the empty string) is specified. If the node is starting a testnet,
   823  // then a subdirectory of the specified datadir will be used.
   824  func MakeDataDir(ctx *cli.Context) string {
   825  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   826  		if ctx.GlobalBool(RopstenFlag.Name) {
   827  			// Maintain compatibility with older Geth configurations storing the
   828  			// Ropsten database in `testnet` instead of `ropsten`.
   829  			return filepath.Join(path, "ropsten")
   830  		}
   831  		if ctx.GlobalBool(RinkebyFlag.Name) {
   832  			return filepath.Join(path, "rinkeby")
   833  		}
   834  		if ctx.GlobalBool(GoerliFlag.Name) {
   835  			return filepath.Join(path, "goerli")
   836  		}
   837  		if ctx.GlobalBool(CalaverasFlag.Name) {
   838  			return filepath.Join(path, "calaveras")
   839  		}
   840  		return path
   841  	}
   842  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   843  	return ""
   844  }
   845  
   846  // setNodeKey creates a node key from set command line flags, either loading it
   847  // from a file or as a specified hex value. If neither flags were provided, this
   848  // method returns nil and an emphemeral key is to be generated.
   849  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   850  	var (
   851  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   852  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   853  		key  *ecdsa.PrivateKey
   854  		err  error
   855  	)
   856  	switch {
   857  	case file != "" && hex != "":
   858  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   859  	case file != "":
   860  		if key, err = crypto.LoadECDSA(file); err != nil {
   861  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   862  		}
   863  		cfg.PrivateKey = key
   864  	case hex != "":
   865  		if key, err = crypto.HexToECDSA(hex); err != nil {
   866  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   867  		}
   868  		cfg.PrivateKey = key
   869  	}
   870  }
   871  
   872  // setNodeUserIdent creates the user identifier from CLI flags.
   873  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   874  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   875  		cfg.UserIdent = identity
   876  	}
   877  }
   878  
   879  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   880  // flags, reverting to pre-configured ones if none have been specified.
   881  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   882  	urls := params.MainnetBootnodes
   883  	switch {
   884  	case ctx.GlobalIsSet(BootnodesFlag.Name):
   885  		urls = SplitAndTrim(ctx.GlobalString(BootnodesFlag.Name))
   886  	case ctx.GlobalBool(RopstenFlag.Name):
   887  		urls = params.RopstenBootnodes
   888  	case ctx.GlobalBool(RinkebyFlag.Name):
   889  		urls = params.RinkebyBootnodes
   890  	case ctx.GlobalBool(GoerliFlag.Name):
   891  		urls = params.GoerliBootnodes
   892  	case ctx.GlobalBool(CalaverasFlag.Name):
   893  		urls = params.CalaverasBootnodes
   894  	case cfg.BootstrapNodes != nil:
   895  		return // already set, don't apply defaults.
   896  	}
   897  
   898  	cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls))
   899  	for _, url := range urls {
   900  		if url != "" {
   901  			node, err := enode.Parse(enode.ValidSchemes, url)
   902  			if err != nil {
   903  				log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
   904  				continue
   905  			}
   906  			cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   907  		}
   908  	}
   909  }
   910  
   911  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   912  // flags, reverting to pre-configured ones if none have been specified.
   913  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   914  	urls := params.V5Bootnodes
   915  	switch {
   916  	case ctx.GlobalIsSet(BootnodesFlag.Name):
   917  		urls = SplitAndTrim(ctx.GlobalString(BootnodesFlag.Name))
   918  	case cfg.BootstrapNodesV5 != nil:
   919  		return // already set, don't apply defaults.
   920  	}
   921  
   922  	cfg.BootstrapNodesV5 = make([]*enode.Node, 0, len(urls))
   923  	for _, url := range urls {
   924  		if url != "" {
   925  			node, err := enode.Parse(enode.ValidSchemes, url)
   926  			if err != nil {
   927  				log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   928  				continue
   929  			}
   930  			cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   931  		}
   932  	}
   933  }
   934  
   935  // setListenAddress creates a TCP listening address string from set command
   936  // line flags.
   937  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   938  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   939  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   940  	}
   941  }
   942  
   943  // setNAT creates a port mapper from command line flags.
   944  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   945  	if ctx.GlobalIsSet(NATFlag.Name) {
   946  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   947  		if err != nil {
   948  			Fatalf("Option %s: %v", NATFlag.Name, err)
   949  		}
   950  		cfg.NAT = natif
   951  	}
   952  }
   953  
   954  // SplitAndTrim splits input separated by a comma
   955  // and trims excessive white space from the substrings.
   956  func SplitAndTrim(input string) (ret []string) {
   957  	l := strings.Split(input, ",")
   958  	for _, r := range l {
   959  		if r = strings.TrimSpace(r); r != "" {
   960  			ret = append(ret, r)
   961  		}
   962  	}
   963  	return ret
   964  }
   965  
   966  // setHTTP creates the HTTP RPC listener interface string from the set
   967  // command line flags, returning empty if the HTTP endpoint is disabled.
   968  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   969  	if ctx.GlobalBool(LegacyRPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   970  		log.Warn("The flag --rpc is deprecated and will be removed June 2021, please use --http")
   971  		cfg.HTTPHost = "127.0.0.1"
   972  		if ctx.GlobalIsSet(LegacyRPCListenAddrFlag.Name) {
   973  			cfg.HTTPHost = ctx.GlobalString(LegacyRPCListenAddrFlag.Name)
   974  			log.Warn("The flag --rpcaddr is deprecated and will be removed June 2021, please use --http.addr")
   975  		}
   976  	}
   977  	if ctx.GlobalBool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" {
   978  		cfg.HTTPHost = "127.0.0.1"
   979  		if ctx.GlobalIsSet(HTTPListenAddrFlag.Name) {
   980  			cfg.HTTPHost = ctx.GlobalString(HTTPListenAddrFlag.Name)
   981  		}
   982  	}
   983  
   984  	if ctx.GlobalIsSet(LegacyRPCPortFlag.Name) {
   985  		cfg.HTTPPort = ctx.GlobalInt(LegacyRPCPortFlag.Name)
   986  		log.Warn("The flag --rpcport is deprecated and will be removed June 2021, please use --http.port")
   987  	}
   988  	if ctx.GlobalIsSet(HTTPPortFlag.Name) {
   989  		cfg.HTTPPort = ctx.GlobalInt(HTTPPortFlag.Name)
   990  	}
   991  
   992  	if ctx.GlobalIsSet(LegacyRPCCORSDomainFlag.Name) {
   993  		cfg.HTTPCors = SplitAndTrim(ctx.GlobalString(LegacyRPCCORSDomainFlag.Name))
   994  		log.Warn("The flag --rpccorsdomain is deprecated and will be removed June 2021, please use --http.corsdomain")
   995  	}
   996  	if ctx.GlobalIsSet(HTTPCORSDomainFlag.Name) {
   997  		cfg.HTTPCors = SplitAndTrim(ctx.GlobalString(HTTPCORSDomainFlag.Name))
   998  	}
   999  
  1000  	if ctx.GlobalIsSet(LegacyRPCApiFlag.Name) {
  1001  		cfg.HTTPModules = SplitAndTrim(ctx.GlobalString(LegacyRPCApiFlag.Name))
  1002  		log.Warn("The flag --rpcapi is deprecated and will be removed June 2021, please use --http.api")
  1003  	}
  1004  	if ctx.GlobalIsSet(HTTPApiFlag.Name) {
  1005  		cfg.HTTPModules = SplitAndTrim(ctx.GlobalString(HTTPApiFlag.Name))
  1006  	}
  1007  
  1008  	if ctx.GlobalIsSet(LegacyRPCVirtualHostsFlag.Name) {
  1009  		cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(LegacyRPCVirtualHostsFlag.Name))
  1010  		log.Warn("The flag --rpcvhosts is deprecated and will be removed June 2021, please use --http.vhosts")
  1011  	}
  1012  	if ctx.GlobalIsSet(HTTPVirtualHostsFlag.Name) {
  1013  		cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(HTTPVirtualHostsFlag.Name))
  1014  	}
  1015  
  1016  	if ctx.GlobalIsSet(HTTPPathPrefixFlag.Name) {
  1017  		cfg.HTTPPathPrefix = ctx.GlobalString(HTTPPathPrefixFlag.Name)
  1018  	}
  1019  	if ctx.GlobalIsSet(AllowUnprotectedTxs.Name) {
  1020  		cfg.AllowUnprotectedTxs = ctx.GlobalBool(AllowUnprotectedTxs.Name)
  1021  	}
  1022  }
  1023  
  1024  func setWhiteNoise(ctx *cli.Context, cfg *node.Config) {
  1025  	if ctx.GlobalIsSet(WhiteNoiseEnabledFlag.Name) {
  1026  		cfg.EnableWhiteNoise = ctx.GlobalBool(WhiteNoiseEnabledFlag.Name)
  1027  	}
  1028  	if ctx.GlobalIsSet(WhiteNoiseBootstrapFlag.Name) && cfg.EnableWhiteNoise {
  1029  		cfg.BootstrapAddress = ctx.GlobalString(WhiteNoiseBootstrapFlag.Name)
  1030  	}
  1031  }
  1032  
  1033  // setGraphQL creates the GraphQL listener interface string from the set
  1034  // command line flags, returning empty if the GraphQL endpoint is disabled.
  1035  func setGraphQL(ctx *cli.Context, cfg *node.Config) {
  1036  	if ctx.GlobalIsSet(GraphQLCORSDomainFlag.Name) {
  1037  		cfg.GraphQLCors = SplitAndTrim(ctx.GlobalString(GraphQLCORSDomainFlag.Name))
  1038  	}
  1039  	if ctx.GlobalIsSet(GraphQLVirtualHostsFlag.Name) {
  1040  		cfg.GraphQLVirtualHosts = SplitAndTrim(ctx.GlobalString(GraphQLVirtualHostsFlag.Name))
  1041  	}
  1042  }
  1043  
  1044  // setWS creates the WebSocket RPC listener interface string from the set
  1045  // command line flags, returning empty if the HTTP endpoint is disabled.
  1046  func setWS(ctx *cli.Context, cfg *node.Config) {
  1047  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
  1048  		cfg.WSHost = "127.0.0.1"
  1049  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
  1050  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
  1051  		}
  1052  	}
  1053  	if ctx.GlobalIsSet(WSPortFlag.Name) {
  1054  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
  1055  	}
  1056  
  1057  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
  1058  		cfg.WSOrigins = SplitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
  1059  	}
  1060  
  1061  	if ctx.GlobalIsSet(WSApiFlag.Name) {
  1062  		cfg.WSModules = SplitAndTrim(ctx.GlobalString(WSApiFlag.Name))
  1063  	}
  1064  
  1065  	if ctx.GlobalIsSet(WSPathPrefixFlag.Name) {
  1066  		cfg.WSPathPrefix = ctx.GlobalString(WSPathPrefixFlag.Name)
  1067  	}
  1068  }
  1069  
  1070  // setIPC creates an IPC path configuration from the set command line flags,
  1071  // returning an empty string if IPC was explicitly disabled, or the set path.
  1072  func setIPC(ctx *cli.Context, cfg *node.Config) {
  1073  	CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
  1074  	switch {
  1075  	case ctx.GlobalBool(IPCDisabledFlag.Name):
  1076  		cfg.IPCPath = ""
  1077  	case ctx.GlobalIsSet(IPCPathFlag.Name):
  1078  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
  1079  	}
  1080  }
  1081  
  1082  // setLes configures the les server and ultra light client settings from the command line flags.
  1083  func setLes(ctx *cli.Context, cfg *ethconfig.Config) {
  1084  	if ctx.GlobalIsSet(LightServeFlag.Name) {
  1085  		cfg.LightServ = ctx.GlobalInt(LightServeFlag.Name)
  1086  	}
  1087  	if ctx.GlobalIsSet(LightIngressFlag.Name) {
  1088  		cfg.LightIngress = ctx.GlobalInt(LightIngressFlag.Name)
  1089  	}
  1090  	if ctx.GlobalIsSet(LightEgressFlag.Name) {
  1091  		cfg.LightEgress = ctx.GlobalInt(LightEgressFlag.Name)
  1092  	}
  1093  	if ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
  1094  		cfg.LightPeers = ctx.GlobalInt(LightMaxPeersFlag.Name)
  1095  	}
  1096  	if ctx.GlobalIsSet(UltraLightServersFlag.Name) {
  1097  		cfg.UltraLightServers = strings.Split(ctx.GlobalString(UltraLightServersFlag.Name), ",")
  1098  	}
  1099  	if ctx.GlobalIsSet(UltraLightFractionFlag.Name) {
  1100  		cfg.UltraLightFraction = ctx.GlobalInt(UltraLightFractionFlag.Name)
  1101  	}
  1102  	if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 {
  1103  		log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", ethconfig.Defaults.UltraLightFraction)
  1104  		cfg.UltraLightFraction = ethconfig.Defaults.UltraLightFraction
  1105  	}
  1106  	if ctx.GlobalIsSet(UltraLightOnlyAnnounceFlag.Name) {
  1107  		cfg.UltraLightOnlyAnnounce = ctx.GlobalBool(UltraLightOnlyAnnounceFlag.Name)
  1108  	}
  1109  	if ctx.GlobalIsSet(LightNoPruneFlag.Name) {
  1110  		cfg.LightNoPrune = ctx.GlobalBool(LightNoPruneFlag.Name)
  1111  	}
  1112  	if ctx.GlobalIsSet(LightNoSyncServeFlag.Name) {
  1113  		cfg.LightNoSyncServe = ctx.GlobalBool(LightNoSyncServeFlag.Name)
  1114  	}
  1115  }
  1116  
  1117  // MakeDatabaseHandles raises out the number of allowed file handles per process
  1118  // for Geth and returns half of the allowance to assign to the database.
  1119  func MakeDatabaseHandles() int {
  1120  	limit, err := fdlimit.Maximum()
  1121  	if err != nil {
  1122  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
  1123  	}
  1124  	raised, err := fdlimit.Raise(uint64(limit))
  1125  	if err != nil {
  1126  		Fatalf("Failed to raise file descriptor allowance: %v", err)
  1127  	}
  1128  	return int(raised / 2) // Leave half for networking and other stuff
  1129  }
  1130  
  1131  // MakeAddress converts an account specified directly as a hex encoded string or
  1132  // a key index in the key store to an internal account representation.
  1133  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
  1134  	// If the specified account is a valid address, return it
  1135  	if common.IsHexAddress(account) {
  1136  		return accounts.Account{Address: common.HexToAddress(account)}, nil
  1137  	}
  1138  	// Otherwise try to interpret the account as a keystore index
  1139  	index, err := strconv.Atoi(account)
  1140  	if err != nil || index < 0 {
  1141  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
  1142  	}
  1143  	log.Warn("-------------------------------------------------------------------")
  1144  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
  1145  	log.Warn("This functionality is deprecated and will be removed in the future!")
  1146  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
  1147  	log.Warn("-------------------------------------------------------------------")
  1148  
  1149  	accs := ks.Accounts()
  1150  	if len(accs) <= index {
  1151  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
  1152  	}
  1153  	return accs[index], nil
  1154  }
  1155  
  1156  // setEtherbase retrieves the etherbase either from the directly specified
  1157  // command line flags or from the keystore if CLI indexed.
  1158  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *ethconfig.Config) {
  1159  	// Extract the current etherbase
  1160  	var etherbase string
  1161  	if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) {
  1162  		etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name)
  1163  	}
  1164  	// Convert the etherbase into an address and configure it
  1165  	if etherbase != "" {
  1166  		if ks != nil {
  1167  			account, err := MakeAddress(ks, etherbase)
  1168  			if err != nil {
  1169  				Fatalf("Invalid miner etherbase: %v", err)
  1170  			}
  1171  			cfg.Miner.Etherbase = account.Address
  1172  		} else {
  1173  			Fatalf("No etherbase configured")
  1174  		}
  1175  	}
  1176  }
  1177  
  1178  // MakePasswordList reads password lines from the file specified by the global --password flag.
  1179  func MakePasswordList(ctx *cli.Context) []string {
  1180  	path := ctx.GlobalString(PasswordFileFlag.Name)
  1181  	if path == "" {
  1182  		return nil
  1183  	}
  1184  	text, err := ioutil.ReadFile(path)
  1185  	if err != nil {
  1186  		Fatalf("Failed to read password file: %v", err)
  1187  	}
  1188  	lines := strings.Split(string(text), "\n")
  1189  	// Sanitise DOS line endings.
  1190  	for i := range lines {
  1191  		lines[i] = strings.TrimRight(lines[i], "\r")
  1192  	}
  1193  	return lines
  1194  }
  1195  
  1196  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
  1197  	setNodeKey(ctx, cfg)
  1198  	setNAT(ctx, cfg)
  1199  	setListenAddress(ctx, cfg)
  1200  	setBootstrapNodes(ctx, cfg)
  1201  	setBootstrapNodesV5(ctx, cfg)
  1202  
  1203  	lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light"
  1204  	lightServer := (ctx.GlobalInt(LightServeFlag.Name) != 0)
  1205  
  1206  	lightPeers := ctx.GlobalInt(LightMaxPeersFlag.Name)
  1207  	if lightClient && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
  1208  		// dynamic default - for clients we use 1/10th of the default for servers
  1209  		lightPeers /= 10
  1210  	}
  1211  
  1212  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
  1213  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
  1214  		if lightServer && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
  1215  			cfg.MaxPeers += lightPeers
  1216  		}
  1217  	} else {
  1218  		if lightServer {
  1219  			cfg.MaxPeers += lightPeers
  1220  		}
  1221  		if lightClient && ctx.GlobalIsSet(LightMaxPeersFlag.Name) && cfg.MaxPeers < lightPeers {
  1222  			cfg.MaxPeers = lightPeers
  1223  		}
  1224  	}
  1225  	if !(lightClient || lightServer) {
  1226  		lightPeers = 0
  1227  	}
  1228  	ethPeers := cfg.MaxPeers - lightPeers
  1229  	if lightClient {
  1230  		ethPeers = 0
  1231  	}
  1232  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
  1233  
  1234  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
  1235  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
  1236  	}
  1237  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
  1238  		cfg.NoDiscovery = true
  1239  	}
  1240  
  1241  	// if we're running a light client or server, force enable the v5 peer discovery
  1242  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
  1243  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
  1244  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
  1245  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
  1246  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
  1247  	} else if forceV5Discovery {
  1248  		cfg.DiscoveryV5 = true
  1249  	}
  1250  
  1251  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
  1252  		list, err := netutil.ParseNetlist(netrestrict)
  1253  		if err != nil {
  1254  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
  1255  		}
  1256  		cfg.NetRestrict = list
  1257  	}
  1258  
  1259  	if ctx.GlobalBool(DeveloperFlag.Name) || ctx.GlobalBool(CatalystFlag.Name) {
  1260  		// --dev mode can't use p2p networking.
  1261  		cfg.MaxPeers = 0
  1262  		cfg.ListenAddr = ""
  1263  		cfg.NoDial = true
  1264  		cfg.NoDiscovery = true
  1265  		cfg.DiscoveryV5 = false
  1266  	}
  1267  }
  1268  
  1269  // SetNodeConfig applies node-related command line flags to the config.
  1270  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
  1271  	SetP2PConfig(ctx, &cfg.P2P)
  1272  	setIPC(ctx, cfg)
  1273  	setHTTP(ctx, cfg)
  1274  	setGraphQL(ctx, cfg)
  1275  	setWS(ctx, cfg)
  1276  	setNodeUserIdent(ctx, cfg)
  1277  	setDataDir(ctx, cfg)
  1278  	setSmartCard(ctx, cfg)
  1279  	setWhiteNoise(ctx, cfg)
  1280  
  1281  	if ctx.GlobalIsSet(ExternalSignerFlag.Name) {
  1282  		cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name)
  1283  	}
  1284  
  1285  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
  1286  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
  1287  	}
  1288  	if ctx.GlobalIsSet(DeveloperFlag.Name) {
  1289  		cfg.UseLightweightKDF = true
  1290  	}
  1291  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
  1292  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
  1293  	}
  1294  	if ctx.GlobalIsSet(NoUSBFlag.Name) || cfg.NoUSB {
  1295  		log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable")
  1296  	}
  1297  	if ctx.GlobalIsSet(USBFlag.Name) {
  1298  		cfg.USB = ctx.GlobalBool(USBFlag.Name)
  1299  	}
  1300  	if ctx.GlobalIsSet(InsecureUnlockAllowedFlag.Name) {
  1301  		cfg.InsecureUnlockAllowed = ctx.GlobalBool(InsecureUnlockAllowedFlag.Name)
  1302  	}
  1303  }
  1304  
  1305  func setSmartCard(ctx *cli.Context, cfg *node.Config) {
  1306  	// Skip enabling smartcards if no path is set
  1307  	path := ctx.GlobalString(SmartCardDaemonPathFlag.Name)
  1308  	if path == "" {
  1309  		return
  1310  	}
  1311  	// Sanity check that the smartcard path is valid
  1312  	fi, err := os.Stat(path)
  1313  	if err != nil {
  1314  		log.Info("Smartcard socket not found, disabling", "err", err)
  1315  		return
  1316  	}
  1317  	if fi.Mode()&os.ModeType != os.ModeSocket {
  1318  		log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String())
  1319  		return
  1320  	}
  1321  	// Smartcard daemon path exists and is a socket, enable it
  1322  	cfg.SmartCardDaemonPath = path
  1323  }
  1324  
  1325  func setDataDir(ctx *cli.Context, cfg *node.Config) {
  1326  	switch {
  1327  	case ctx.GlobalIsSet(DataDirFlag.Name):
  1328  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
  1329  	case ctx.GlobalBool(DeveloperFlag.Name):
  1330  		cfg.DataDir = "" // unless explicitly requested, use memory databases
  1331  	case ctx.GlobalBool(RopstenFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1332  		// Maintain compatibility with older Geth configurations storing the
  1333  		// Ropsten database in `testnet` instead of `ropsten`.
  1334  		legacyPath := filepath.Join(node.DefaultDataDir(), "testnet")
  1335  		if _, err := os.Stat(legacyPath); !os.IsNotExist(err) {
  1336  			log.Warn("Using the deprecated `testnet` datadir. Future versions will store the Ropsten chain in `ropsten`.")
  1337  			cfg.DataDir = legacyPath
  1338  		} else {
  1339  			cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten")
  1340  		}
  1341  
  1342  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten")
  1343  	case ctx.GlobalBool(RinkebyFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1344  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
  1345  	case ctx.GlobalBool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1346  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
  1347  	case ctx.GlobalBool(CalaverasFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1348  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "calaveras")
  1349  	}
  1350  }
  1351  
  1352  func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
  1353  	// If we are running the light client, apply another group
  1354  	// settings for gas oracle.
  1355  	if light {
  1356  		*cfg = ethconfig.LightClientGPO
  1357  	}
  1358  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
  1359  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
  1360  	}
  1361  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
  1362  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
  1363  	}
  1364  	if ctx.GlobalIsSet(GpoMaxGasPriceFlag.Name) {
  1365  		cfg.MaxPrice = big.NewInt(ctx.GlobalInt64(GpoMaxGasPriceFlag.Name))
  1366  	}
  1367  	if ctx.GlobalIsSet(GpoIgnoreGasPriceFlag.Name) {
  1368  		cfg.IgnorePrice = big.NewInt(ctx.GlobalInt64(GpoIgnoreGasPriceFlag.Name))
  1369  	}
  1370  }
  1371  
  1372  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
  1373  	if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) {
  1374  		locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",")
  1375  		for _, account := range locals {
  1376  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
  1377  				Fatalf("Invalid account in --txpool.locals: %s", trimmed)
  1378  			} else {
  1379  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
  1380  			}
  1381  		}
  1382  	}
  1383  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
  1384  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
  1385  	}
  1386  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
  1387  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
  1388  	}
  1389  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
  1390  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
  1391  	}
  1392  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
  1393  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
  1394  	}
  1395  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
  1396  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
  1397  	}
  1398  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
  1399  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
  1400  	}
  1401  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
  1402  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
  1403  	}
  1404  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
  1405  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
  1406  	}
  1407  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
  1408  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
  1409  	}
  1410  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
  1411  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
  1412  	}
  1413  }
  1414  
  1415  func setEthash(ctx *cli.Context, cfg *ethconfig.Config) {
  1416  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
  1417  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
  1418  	}
  1419  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
  1420  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
  1421  	}
  1422  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
  1423  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
  1424  	}
  1425  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
  1426  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
  1427  	}
  1428  	if ctx.GlobalIsSet(EthashCachesLockMmapFlag.Name) {
  1429  		cfg.Ethash.CachesLockMmap = ctx.GlobalBool(EthashCachesLockMmapFlag.Name)
  1430  	}
  1431  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
  1432  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
  1433  	}
  1434  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
  1435  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
  1436  	}
  1437  	if ctx.GlobalIsSet(EthashDatasetsLockMmapFlag.Name) {
  1438  		cfg.Ethash.DatasetsLockMmap = ctx.GlobalBool(EthashDatasetsLockMmapFlag.Name)
  1439  	}
  1440  }
  1441  
  1442  func setMiner(ctx *cli.Context, cfg *miner.Config) {
  1443  	if ctx.GlobalIsSet(MinerNotifyFlag.Name) {
  1444  		cfg.Notify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",")
  1445  	}
  1446  	cfg.NotifyFull = ctx.GlobalBool(MinerNotifyFullFlag.Name)
  1447  	if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
  1448  		cfg.ExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
  1449  	}
  1450  	if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
  1451  		cfg.GasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
  1452  	}
  1453  	if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
  1454  		cfg.GasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
  1455  	}
  1456  	if ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
  1457  		cfg.GasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name)
  1458  	}
  1459  	if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) {
  1460  		cfg.Recommit = ctx.GlobalDuration(MinerRecommitIntervalFlag.Name)
  1461  	}
  1462  	if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
  1463  		cfg.Noverify = ctx.GlobalBool(MinerNoVerfiyFlag.Name)
  1464  	}
  1465  }
  1466  
  1467  func setZKPMiner(ctx *cli.Context, cfg *zkpminer.Config) {
  1468  	minerList := make([]zkpkeypair.Key, 0)
  1469  	if !ctx.GlobalBool(ZKPMinerEnableFlag.Name) {
  1470  		return
  1471  	}
  1472  
  1473  	keyPath := ""
  1474  	if ctx.GlobalIsSet(ZKPMinerKeyPath.Name) {
  1475  		keyPath = ctx.GlobalString(ZKPMinerKeyPath.Name)
  1476  	} else {
  1477  		keystoreDir := ctx.GlobalString(DataDirFlag.Name) + "/keystore/"
  1478  		files, err := ioutil.ReadDir(keystoreDir)
  1479  		if len(files) == 0 || err != nil {
  1480  			Fatalf("ZKP miner key path not exist")
  1481  		}
  1482  		keyPath = keystoreDir + files[0].Name()
  1483  	}
  1484  
  1485  	key, err := GetKeyFromFile(ctx, keyPath)
  1486  	if err != nil {
  1487  		Fatalf("load ZKP miner key from file error %v", err)
  1488  	}
  1489  	minerList = append(minerList, key)
  1490  
  1491  	var coinbaseAddr common.Address
  1492  	if ctx.GlobalIsSet(ZKPMinerCoinbaseAddress.Name) {
  1493  		coinbaseAddr = common.HexToAddress(ctx.GlobalString(ZKPMinerCoinbaseAddress.Name))
  1494  	}
  1495  
  1496  	pkPath := "./QmQL4k1hKYiW3SDtMREjnrah1PBsak1VE3VgEqTyoDckz9"
  1497  	if ctx.GlobalIsSet(ZKPMinerPkPath.Name) {
  1498  		pkPath = ctx.GlobalString(ZKPMinerPkPath.Name)
  1499  	}
  1500  
  1501  	cfg.Customize(minerList, coinbaseAddr, []string{}, pkPath)
  1502  }
  1503  
  1504  func GetKeyFromFile(ctx *cli.Context, keypath string) (zkpkeypair.Key, error) {
  1505  	// Read key from file.
  1506  	keyJson, err := ioutil.ReadFile(keypath)
  1507  	if err != nil {
  1508  		return zkpkeypair.Key{}, fmt.Errorf("failed to read the keyfile at '%s': %v", keypath, err)
  1509  	}
  1510  
  1511  	// Decrypt key with passphrase.
  1512  	password := ""
  1513  	if ctx.GlobalIsSet(ZKPMinerPassword.Name) {
  1514  		password = ctx.GlobalString(ZKPMinerPassword.Name)
  1515  	} else {
  1516  		password = GetPassPhrase("", false)
  1517  	}
  1518  
  1519  	rawKey, err := keystore.DecryptKey(keyJson, password)
  1520  	if err != nil {
  1521  		return zkpkeypair.Key{}, fmt.Errorf("error decrypting key: %v", err)
  1522  	}
  1523  
  1524  	minerKey, err := zkpkeypair.NewKey(rawKey.PrivateKey)
  1525  	if err != nil {
  1526  		return zkpkeypair.Key{}, fmt.Errorf("error loading miner key : %v", err)
  1527  	}
  1528  	return minerKey, nil
  1529  }
  1530  
  1531  func setWhitelist(ctx *cli.Context, cfg *ethconfig.Config) {
  1532  	whitelist := ctx.GlobalString(WhitelistFlag.Name)
  1533  	if whitelist == "" {
  1534  		return
  1535  	}
  1536  	cfg.Whitelist = make(map[uint64]common.Hash)
  1537  	for _, entry := range strings.Split(whitelist, ",") {
  1538  		parts := strings.Split(entry, "=")
  1539  		if len(parts) != 2 {
  1540  			Fatalf("Invalid whitelist entry: %s", entry)
  1541  		}
  1542  		number, err := strconv.ParseUint(parts[0], 0, 64)
  1543  		if err != nil {
  1544  			Fatalf("Invalid whitelist block number %s: %v", parts[0], err)
  1545  		}
  1546  		var hash common.Hash
  1547  		if err = hash.UnmarshalText([]byte(parts[1])); err != nil {
  1548  			Fatalf("Invalid whitelist hash %s: %v", parts[1], err)
  1549  		}
  1550  		cfg.Whitelist[number] = hash
  1551  	}
  1552  }
  1553  
  1554  // CheckExclusive verifies that only a single instance of the provided flags was
  1555  // set by the user. Each flag might optionally be followed by a string type to
  1556  // specialize it further.
  1557  func CheckExclusive(ctx *cli.Context, args ...interface{}) {
  1558  	set := make([]string, 0, 1)
  1559  	for i := 0; i < len(args); i++ {
  1560  		// Make sure the next argument is a flag and skip if not set
  1561  		flag, ok := args[i].(cli.Flag)
  1562  		if !ok {
  1563  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1564  		}
  1565  		// Check if next arg extends current and expand its name if so
  1566  		name := flag.GetName()
  1567  
  1568  		if i+1 < len(args) {
  1569  			switch option := args[i+1].(type) {
  1570  			case string:
  1571  				// Extended flag check, make sure value set doesn't conflict with passed in option
  1572  				if ctx.GlobalString(flag.GetName()) == option {
  1573  					name += "=" + option
  1574  					set = append(set, "--"+name)
  1575  				}
  1576  				// shift arguments and continue
  1577  				i++
  1578  				continue
  1579  
  1580  			case cli.Flag:
  1581  			default:
  1582  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1583  			}
  1584  		}
  1585  		// Mark the flag if it's set
  1586  		if ctx.GlobalIsSet(flag.GetName()) {
  1587  			set = append(set, "--"+name)
  1588  		}
  1589  	}
  1590  	if len(set) > 1 {
  1591  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1592  	}
  1593  }
  1594  
  1595  // SetEthConfig applies eth-related command line flags to the config.
  1596  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
  1597  	// Avoid conflicting network flags
  1598  	CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RopstenFlag, RinkebyFlag, GoerliFlag, CalaverasFlag)
  1599  	CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
  1600  	CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
  1601  	if ctx.GlobalString(GCModeFlag.Name) == "archive" && ctx.GlobalUint64(TxLookupLimitFlag.Name) != 0 {
  1602  		ctx.GlobalSet(TxLookupLimitFlag.Name, "0")
  1603  		log.Warn("Disable transaction unindexing for archive node")
  1604  	}
  1605  	if ctx.GlobalIsSet(LightServeFlag.Name) && ctx.GlobalUint64(TxLookupLimitFlag.Name) != 0 {
  1606  		log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
  1607  	}
  1608  	var ks *keystore.KeyStore
  1609  	if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
  1610  		ks = keystores[0].(*keystore.KeyStore)
  1611  	}
  1612  	setEtherbase(ctx, ks, cfg)
  1613  	setGPO(ctx, &cfg.GPO, ctx.GlobalString(SyncModeFlag.Name) == "light")
  1614  	setTxPool(ctx, &cfg.TxPool)
  1615  	setEthash(ctx, cfg)
  1616  	setMiner(ctx, &cfg.Miner)
  1617  	setZKPMiner(ctx, &cfg.ZKPminer)
  1618  	setWhitelist(ctx, cfg)
  1619  	setLes(ctx, cfg)
  1620  
  1621  	//set vkpath
  1622  	if ctx.GlobalIsSet(ZKPVkPath.Name) {
  1623  		cfg.ZKPVkPath = ctx.GlobalString(ZKPVkPath.Name)
  1624  	}
  1625  
  1626  	// Cap the cache allowance and tune the garbage collector
  1627  	mem, err := gopsutil.VirtualMemory()
  1628  	if err == nil {
  1629  		if 32<<(^uintptr(0)>>63) == 32 && mem.Total > 2*1024*1024*1024 {
  1630  			log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024)
  1631  			mem.Total = 2 * 1024 * 1024 * 1024
  1632  		}
  1633  		allowance := int(mem.Total / 1024 / 1024 / 3)
  1634  		if cache := ctx.GlobalInt(CacheFlag.Name); cache > allowance {
  1635  			log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
  1636  			ctx.GlobalSet(CacheFlag.Name, strconv.Itoa(allowance))
  1637  		}
  1638  	}
  1639  	// Ensure Go's GC ignores the database cache for trigger percentage
  1640  	cache := ctx.GlobalInt(CacheFlag.Name)
  1641  	gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))
  1642  
  1643  	log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
  1644  	godebug.SetGCPercent(int(gogc))
  1645  
  1646  	if ctx.GlobalIsSet(SyncModeFlag.Name) {
  1647  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1648  	}
  1649  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1650  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1651  	}
  1652  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
  1653  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1654  	}
  1655  	cfg.DatabaseHandles = MakeDatabaseHandles()
  1656  	if ctx.GlobalIsSet(AncientFlag.Name) {
  1657  		cfg.DatabaseFreezer = ctx.GlobalString(AncientFlag.Name)
  1658  	}
  1659  
  1660  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1661  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1662  	}
  1663  	if ctx.GlobalIsSet(GCModeFlag.Name) {
  1664  		cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
  1665  	}
  1666  	if ctx.GlobalIsSet(CacheNoPrefetchFlag.Name) {
  1667  		cfg.NoPrefetch = ctx.GlobalBool(CacheNoPrefetchFlag.Name)
  1668  	}
  1669  	// Read the value from the flag no matter if it's set or not.
  1670  	cfg.Preimages = ctx.GlobalBool(CachePreimagesFlag.Name)
  1671  	if cfg.NoPruning && !cfg.Preimages {
  1672  		cfg.Preimages = true
  1673  		log.Info("Enabling recording of key preimages since archive mode is used")
  1674  	}
  1675  	if ctx.GlobalIsSet(TxLookupLimitFlag.Name) {
  1676  		cfg.TxLookupLimit = ctx.GlobalUint64(TxLookupLimitFlag.Name)
  1677  	}
  1678  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
  1679  		cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
  1680  	}
  1681  	if ctx.GlobalIsSet(CacheTrieJournalFlag.Name) {
  1682  		cfg.TrieCleanCacheJournal = ctx.GlobalString(CacheTrieJournalFlag.Name)
  1683  	}
  1684  	if ctx.GlobalIsSet(CacheTrieRejournalFlag.Name) {
  1685  		cfg.TrieCleanCacheRejournal = ctx.GlobalDuration(CacheTrieRejournalFlag.Name)
  1686  	}
  1687  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1688  		cfg.TrieDirtyCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1689  	}
  1690  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheSnapshotFlag.Name) {
  1691  		cfg.SnapshotCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheSnapshotFlag.Name) / 100
  1692  	}
  1693  	if !ctx.GlobalBool(SnapshotFlag.Name) {
  1694  		// If snap-sync is requested, this flag is also required
  1695  		if cfg.SyncMode == downloader.SnapSync {
  1696  			log.Info("Snap sync requested, enabling --snapshot")
  1697  		} else {
  1698  			cfg.TrieCleanCache += cfg.SnapshotCache
  1699  			cfg.SnapshotCache = 0 // Disabled
  1700  		}
  1701  	}
  1702  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1703  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1704  	}
  1705  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1706  		// TODO(fjl): force-enable this in --dev mode
  1707  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1708  	}
  1709  
  1710  	if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) {
  1711  		cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name)
  1712  	}
  1713  
  1714  	if ctx.GlobalIsSet(EVMInterpreterFlag.Name) {
  1715  		cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name)
  1716  	}
  1717  	if ctx.GlobalIsSet(RPCGlobalGasCapFlag.Name) {
  1718  		cfg.RPCGasCap = ctx.GlobalUint64(RPCGlobalGasCapFlag.Name)
  1719  	}
  1720  	if cfg.RPCGasCap != 0 {
  1721  		log.Info("Set global gas cap", "cap", cfg.RPCGasCap)
  1722  	} else {
  1723  		log.Info("Global gas cap disabled")
  1724  	}
  1725  	if ctx.GlobalIsSet(RPCGlobalTxFeeCapFlag.Name) {
  1726  		cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCapFlag.Name)
  1727  	}
  1728  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) {
  1729  		cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{}
  1730  	} else if ctx.GlobalIsSet(DNSDiscoveryFlag.Name) {
  1731  		urls := ctx.GlobalString(DNSDiscoveryFlag.Name)
  1732  		if urls == "" {
  1733  			cfg.EthDiscoveryURLs = []string{}
  1734  		} else {
  1735  			cfg.EthDiscoveryURLs = SplitAndTrim(urls)
  1736  		}
  1737  	}
  1738  	// Override any default configs for hard coded networks.
  1739  	switch {
  1740  	case ctx.GlobalBool(MainnetFlag.Name):
  1741  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1742  			cfg.NetworkId = 1
  1743  		}
  1744  		cfg.Genesis = core.DefaultGenesisBlock()
  1745  		SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
  1746  	case ctx.GlobalBool(RopstenFlag.Name):
  1747  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1748  			cfg.NetworkId = 3
  1749  		}
  1750  		cfg.Genesis = core.DefaultRopstenGenesisBlock()
  1751  		SetDNSDiscoveryDefaults(cfg, params.RopstenGenesisHash)
  1752  	case ctx.GlobalBool(RinkebyFlag.Name):
  1753  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1754  			cfg.NetworkId = 4
  1755  		}
  1756  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1757  		SetDNSDiscoveryDefaults(cfg, params.RinkebyGenesisHash)
  1758  	case ctx.GlobalBool(GoerliFlag.Name):
  1759  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1760  			cfg.NetworkId = 5
  1761  		}
  1762  		cfg.Genesis = core.DefaultGoerliGenesisBlock()
  1763  		SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash)
  1764  	case ctx.GlobalBool(CalaverasFlag.Name):
  1765  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1766  			cfg.NetworkId = 123 // https://gist.github.com/holiman/c5697b041b3dc18c50a5cdd382cbdd16
  1767  		}
  1768  		cfg.Genesis = core.DefaultCalaverasGenesisBlock()
  1769  	case ctx.GlobalBool(DeveloperFlag.Name):
  1770  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1771  			cfg.NetworkId = 1337
  1772  		}
  1773  		cfg.SyncMode = downloader.FullSync
  1774  		// Create new developer account or reuse existing one
  1775  		var (
  1776  			developer  accounts.Account
  1777  			passphrase string
  1778  			err        error
  1779  		)
  1780  		if list := MakePasswordList(ctx); len(list) > 0 {
  1781  			// Just take the first value. Although the function returns a possible multiple values and
  1782  			// some usages iterate through them as attempts, that doesn't make sense in this setting,
  1783  			// when we're definitely concerned with only one account.
  1784  			passphrase = list[0]
  1785  		}
  1786  		// setEtherbase has been called above, configuring the miner address from command line flags.
  1787  		if cfg.Miner.Etherbase != (common.Address{}) {
  1788  			developer = accounts.Account{Address: cfg.Miner.Etherbase}
  1789  		} else if accs := ks.Accounts(); len(accs) > 0 {
  1790  			developer = ks.Accounts()[0]
  1791  		} else {
  1792  			developer, err = ks.NewAccount(passphrase)
  1793  			if err != nil {
  1794  				Fatalf("Failed to create developer account: %v", err)
  1795  			}
  1796  		}
  1797  		if err := ks.Unlock(developer, passphrase); err != nil {
  1798  			Fatalf("Failed to unlock developer account: %v", err)
  1799  		}
  1800  		log.Info("Using developer account", "address", developer.Address)
  1801  
  1802  		// Create a new developer genesis block or reuse existing one
  1803  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1804  		if ctx.GlobalIsSet(DataDirFlag.Name) {
  1805  			// Check if we have an already initialized chain and fall back to
  1806  			// that if so. Otherwise we need to generate a new genesis spec.
  1807  			chaindb := MakeChainDatabase(ctx, stack, false) // TODO (MariusVanDerWijden) make this read only
  1808  			if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
  1809  				cfg.Genesis = nil // fallback to db content
  1810  			}
  1811  			chaindb.Close()
  1812  		}
  1813  		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
  1814  			cfg.Miner.GasPrice = big.NewInt(1)
  1815  		}
  1816  	default:
  1817  		if cfg.NetworkId == 1 {
  1818  			SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
  1819  		}
  1820  	}
  1821  }
  1822  
  1823  // SetDNSDiscoveryDefaults configures DNS discovery with the given URL if
  1824  // no URLs are set.
  1825  func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
  1826  	if cfg.EthDiscoveryURLs != nil {
  1827  		return // already set through flags/config
  1828  	}
  1829  	protocol := "all"
  1830  	if cfg.SyncMode == downloader.LightSync {
  1831  		protocol = "les"
  1832  	}
  1833  	if url := params.KnownDNSNetwork(genesis, protocol); url != "" {
  1834  		cfg.EthDiscoveryURLs = []string{url}
  1835  		cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs
  1836  	}
  1837  }
  1838  
  1839  // RegisterEthService adds an Ethereum client to the stack.
  1840  // The second return value is the full node instance, which may be nil if the
  1841  // node is running as a light client.
  1842  func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) {
  1843  	if cfg.SyncMode == downloader.LightSync {
  1844  		backend, err := les.New(stack, cfg)
  1845  		if err != nil {
  1846  			Fatalf("Failed to register the Ethereum service: %v", err)
  1847  		}
  1848  		stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
  1849  		return backend.ApiBackend, nil
  1850  	}
  1851  	backend, err := eth.New(stack, cfg)
  1852  	if err != nil {
  1853  		Fatalf("Failed to register the Ethereum service: %v", err)
  1854  	}
  1855  	if cfg.LightServ > 0 {
  1856  		_, err := les.NewLesServer(stack, backend, cfg)
  1857  		if err != nil {
  1858  			Fatalf("Failed to create the LES server: %v", err)
  1859  		}
  1860  	}
  1861  	stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
  1862  	return backend.APIBackend, backend
  1863  }
  1864  
  1865  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1866  // the given node.
  1867  func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) {
  1868  	if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil {
  1869  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1870  	}
  1871  }
  1872  
  1873  // RegisterGraphQLService is a utility function to construct a new service and register it against a node.
  1874  func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, cfg node.Config) {
  1875  	if err := graphql.New(stack, backend, cfg.GraphQLCors, cfg.GraphQLVirtualHosts); err != nil {
  1876  		Fatalf("Failed to register the GraphQL service: %v", err)
  1877  	}
  1878  }
  1879  
  1880  func SetupMetrics(ctx *cli.Context) {
  1881  	if metrics.Enabled {
  1882  		log.Info("Enabling metrics collection")
  1883  
  1884  		var (
  1885  			enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
  1886  			endpoint     = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
  1887  			database     = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
  1888  			username     = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
  1889  			password     = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
  1890  		)
  1891  
  1892  		if enableExport {
  1893  			tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name))
  1894  
  1895  			log.Info("Enabling metrics export to InfluxDB")
  1896  
  1897  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
  1898  		}
  1899  
  1900  		if ctx.GlobalIsSet(MetricsHTTPFlag.Name) {
  1901  			address := fmt.Sprintf("%s:%d", ctx.GlobalString(MetricsHTTPFlag.Name), ctx.GlobalInt(MetricsPortFlag.Name))
  1902  			log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address)
  1903  			exp.Setup(address)
  1904  		}
  1905  	}
  1906  }
  1907  
  1908  func SplitTagsFlag(tagsFlag string) map[string]string {
  1909  	tags := strings.Split(tagsFlag, ",")
  1910  	tagsMap := map[string]string{}
  1911  
  1912  	for _, t := range tags {
  1913  		if t != "" {
  1914  			kv := strings.Split(t, "=")
  1915  
  1916  			if len(kv) == 2 {
  1917  				tagsMap[kv[0]] = kv[1]
  1918  			}
  1919  		}
  1920  	}
  1921  
  1922  	return tagsMap
  1923  }
  1924  
  1925  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1926  func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database {
  1927  	var (
  1928  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1929  		handles = MakeDatabaseHandles()
  1930  
  1931  		err     error
  1932  		chainDb ethdb.Database
  1933  	)
  1934  	if ctx.GlobalString(SyncModeFlag.Name) == "light" {
  1935  		name := "lightchaindata"
  1936  		chainDb, err = stack.OpenDatabase(name, cache, handles, "", readonly)
  1937  	} else {
  1938  		name := "chaindata"
  1939  		chainDb, err = stack.OpenDatabaseWithFreezer(name, cache, handles, ctx.GlobalString(AncientFlag.Name), "", readonly)
  1940  	}
  1941  	if err != nil {
  1942  		Fatalf("Could not open database: %v", err)
  1943  	}
  1944  	return chainDb
  1945  }
  1946  
  1947  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1948  	var genesis *core.Genesis
  1949  	switch {
  1950  	case ctx.GlobalBool(MainnetFlag.Name):
  1951  		genesis = core.DefaultGenesisBlock()
  1952  	case ctx.GlobalBool(RopstenFlag.Name):
  1953  		genesis = core.DefaultRopstenGenesisBlock()
  1954  	case ctx.GlobalBool(RinkebyFlag.Name):
  1955  		genesis = core.DefaultRinkebyGenesisBlock()
  1956  	case ctx.GlobalBool(GoerliFlag.Name):
  1957  		genesis = core.DefaultGoerliGenesisBlock()
  1958  	case ctx.GlobalBool(CalaverasFlag.Name):
  1959  		genesis = core.DefaultCalaverasGenesisBlock()
  1960  	case ctx.GlobalBool(DeveloperFlag.Name):
  1961  		Fatalf("Developer chains are ephemeral")
  1962  	}
  1963  	return genesis
  1964  }
  1965  
  1966  // MakeChain creates a chain manager from set command line flags.
  1967  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  1968  	var err error
  1969  	chainDb = MakeChainDatabase(ctx, stack, false) // TODO(rjl493456442) support read-only database
  1970  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1971  	if err != nil {
  1972  		Fatalf("%v", err)
  1973  	}
  1974  	var engine consensus.Engine
  1975  	if config.Clique != nil {
  1976  		engine = clique.New(config.Clique, chainDb)
  1977  	} else {
  1978  		engine = ethash.NewFaker()
  1979  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1980  			engine = ethash.New(ethash.Config{
  1981  				CacheDir:         stack.ResolvePath(ethconfig.Defaults.Ethash.CacheDir),
  1982  				CachesInMem:      ethconfig.Defaults.Ethash.CachesInMem,
  1983  				CachesOnDisk:     ethconfig.Defaults.Ethash.CachesOnDisk,
  1984  				CachesLockMmap:   ethconfig.Defaults.Ethash.CachesLockMmap,
  1985  				DatasetDir:       stack.ResolvePath(ethconfig.Defaults.Ethash.DatasetDir),
  1986  				DatasetsInMem:    ethconfig.Defaults.Ethash.DatasetsInMem,
  1987  				DatasetsOnDisk:   ethconfig.Defaults.Ethash.DatasetsOnDisk,
  1988  				DatasetsLockMmap: ethconfig.Defaults.Ethash.DatasetsLockMmap,
  1989  			}, nil, false)
  1990  		}
  1991  	}
  1992  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1993  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1994  	}
  1995  	cache := &core.CacheConfig{
  1996  		TrieCleanLimit:      ethconfig.Defaults.TrieCleanCache,
  1997  		TrieCleanNoPrefetch: ctx.GlobalBool(CacheNoPrefetchFlag.Name),
  1998  		TrieDirtyLimit:      ethconfig.Defaults.TrieDirtyCache,
  1999  		TrieDirtyDisabled:   ctx.GlobalString(GCModeFlag.Name) == "archive",
  2000  		TrieTimeLimit:       ethconfig.Defaults.TrieTimeout,
  2001  		SnapshotLimit:       ethconfig.Defaults.SnapshotCache,
  2002  		Preimages:           ctx.GlobalBool(CachePreimagesFlag.Name),
  2003  	}
  2004  	if cache.TrieDirtyDisabled && !cache.Preimages {
  2005  		cache.Preimages = true
  2006  		log.Info("Enabling recording of key preimages since archive mode is used")
  2007  	}
  2008  	if !ctx.GlobalBool(SnapshotFlag.Name) {
  2009  		cache.SnapshotLimit = 0 // Disabled
  2010  	}
  2011  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
  2012  		cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
  2013  	}
  2014  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  2015  		cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  2016  	}
  2017  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  2018  
  2019  	// TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only.
  2020  	// Disable transaction indexing/unindexing by default.
  2021  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil, nil)
  2022  	if err != nil {
  2023  		Fatalf("Can't create BlockChain: %v", err)
  2024  	}
  2025  	return chain, chainDb
  2026  }
  2027  
  2028  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  2029  // scripts to preload before starting.
  2030  func MakeConsolePreloads(ctx *cli.Context) []string {
  2031  	// Skip preloading if there's nothing to preload
  2032  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  2033  		return nil
  2034  	}
  2035  	// Otherwise resolve absolute paths and return them
  2036  	var preloads []string
  2037  
  2038  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  2039  		preloads = append(preloads, strings.TrimSpace(file))
  2040  	}
  2041  	return preloads
  2042  }
  2043  
  2044  // MigrateFlags sets the global flag from a local flag when it's set.
  2045  // This is a temporary function used for migrating old command/flags to the
  2046  // new format.
  2047  //
  2048  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  2049  //
  2050  // is equivalent after calling this method with:
  2051  //
  2052  // geth --keystore /tmp/mykeystore --lightkdf account new
  2053  //
  2054  // This allows the use of the existing configuration functionality.
  2055  // When all flags are migrated this function can be removed and the existing
  2056  // configuration functionality must be changed that is uses local flags
  2057  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  2058  	return func(ctx *cli.Context) error {
  2059  		for _, name := range ctx.FlagNames() {
  2060  			if ctx.IsSet(name) {
  2061  				ctx.GlobalSet(name, ctx.String(name))
  2062  			}
  2063  		}
  2064  		return action(ctx)
  2065  	}
  2066  }