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