github.com/cryptogateway/go-paymex@v0.0.0-20210204174735-96277fb1e602/cmd/utils/flags.go (about)

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