github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/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  	"os"
    26  	"path/filepath"
    27  	"strconv"
    28  	"strings"
    29  	"text/tabwriter"
    30  	"text/template"
    31  	"time"
    32  
    33  	pcsclite "github.com/gballet/go-libpcsclite"
    34  	"gopkg.in/urfave/cli.v1"
    35  
    36  	"github.com/unicornultrafoundation/go-u2u/accounts"
    37  	"github.com/unicornultrafoundation/go-u2u/accounts/keystore"
    38  	"github.com/unicornultrafoundation/go-u2u/common"
    39  	"github.com/unicornultrafoundation/go-u2u/common/fdlimit"
    40  	"github.com/unicornultrafoundation/go-u2u/crypto"
    41  	"github.com/unicornultrafoundation/go-u2u/eth/ethconfig"
    42  	core "github.com/unicornultrafoundation/go-u2u/evmcore"
    43  	"github.com/unicornultrafoundation/go-u2u/flags"
    44  	"github.com/unicornultrafoundation/go-u2u/log"
    45  	"github.com/unicornultrafoundation/go-u2u/metrics"
    46  	"github.com/unicornultrafoundation/go-u2u/metrics/exp"
    47  	"github.com/unicornultrafoundation/go-u2u/metrics/influxdb"
    48  	"github.com/unicornultrafoundation/go-u2u/node"
    49  	"github.com/unicornultrafoundation/go-u2u/p2p"
    50  	"github.com/unicornultrafoundation/go-u2u/p2p/enode"
    51  	"github.com/unicornultrafoundation/go-u2u/p2p/nat"
    52  	"github.com/unicornultrafoundation/go-u2u/p2p/netutil"
    53  )
    54  
    55  func init() {
    56  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    57  
    58  VERSION:
    59     {{.Version}}
    60  
    61  COMMANDS:
    62     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    63     {{end}}{{if .Flags}}
    64  GLOBAL OPTIONS:
    65     {{range .Flags}}{{.}}
    66     {{end}}{{end}}
    67  `
    68  	cli.CommandHelpTemplate = flags.CommandHelpTemplate
    69  	cli.HelpPrinter = printHelp
    70  }
    71  
    72  func printHelp(out io.Writer, templ string, data interface{}) {
    73  	funcMap := template.FuncMap{"join": strings.Join}
    74  	t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
    75  	w := tabwriter.NewWriter(out, 38, 8, 2, ' ', 0)
    76  	err := t.Execute(w, data)
    77  	if err != nil {
    78  		panic(err)
    79  	}
    80  	w.Flush()
    81  }
    82  
    83  // These are all the command line flags we support.
    84  // If you add to this list, please remember to include the
    85  // flag in the appropriate command definition.
    86  //
    87  // The flags are defined here so their names and help texts
    88  // are the same for all commands.
    89  
    90  var (
    91  	// General settings
    92  	DataDirFlag = DirectoryFlag{
    93  		Name:  "datadir",
    94  		Usage: "Data directory for the databases and keystore",
    95  		Value: DirectoryString(node.DefaultDataDir()),
    96  	}
    97  	AncientFlag = DirectoryFlag{
    98  		Name:  "datadir.ancient",
    99  		Usage: "Data directory for ancient chain segments (default = inside chaindata)",
   100  	}
   101  	MinFreeDiskSpaceFlag = DirectoryFlag{
   102  		Name:  "datadir.minfreedisk",
   103  		Usage: "Minimum free disk space in MB, once reached triggers auto shut down (default = 8192 MB, 0 = disabled)",
   104  	}
   105  	KeyStoreDirFlag = DirectoryFlag{
   106  		Name:  "keystore",
   107  		Usage: "Directory for the keystore (default = inside the datadir)",
   108  	}
   109  	USBFlag = cli.BoolFlag{
   110  		Name:  "usb",
   111  		Usage: "Enable monitoring and management of USB hardware wallets",
   112  	}
   113  	SmartCardDaemonPathFlag = cli.StringFlag{
   114  		Name:  "pcscdpath",
   115  		Usage: "Path to the smartcard daemon (pcscd) socket file",
   116  		Value: pcsclite.PCSCDSockName,
   117  	}
   118  	NetworkIdFlag = cli.Uint64Flag{
   119  		Name:  "networkid",
   120  		Usage: "Explicitly set network id (integer)(For testnets: use --ropsten, --rinkeby, --goerli instead)",
   121  		Value: ethconfig.Defaults.NetworkId,
   122  	}
   123  	MainnetFlag = cli.BoolFlag{
   124  		Name:  "mainnet",
   125  		Usage: "Ethereum mainnet",
   126  	}
   127  	GoerliFlag = cli.BoolFlag{
   128  		Name:  "goerli",
   129  		Usage: "Görli network: pre-configured proof-of-authority test network",
   130  	}
   131  	RinkebyFlag = cli.BoolFlag{
   132  		Name:  "rinkeby",
   133  		Usage: "Rinkeby network: pre-configured proof-of-authority test network",
   134  	}
   135  	RopstenFlag = cli.BoolFlag{
   136  		Name:  "ropsten",
   137  		Usage: "Ropsten network: pre-configured proof-of-work test network",
   138  	}
   139  	DeveloperFlag = cli.BoolFlag{
   140  		Name:  "dev",
   141  		Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   142  	}
   143  	DeveloperPeriodFlag = cli.IntFlag{
   144  		Name:  "dev.period",
   145  		Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   146  	}
   147  	IdentityFlag = cli.StringFlag{
   148  		Name:  "identity",
   149  		Usage: "Custom node name",
   150  	}
   151  	DocRootFlag = DirectoryFlag{
   152  		Name:  "docroot",
   153  		Usage: "Document Root for HTTPClient file scheme",
   154  		Value: DirectoryString(HomeDir()),
   155  	}
   156  	ExitWhenSyncedFlag = cli.BoolFlag{
   157  		Name:  "exitwhensynced",
   158  		Usage: "Exits after block synchronisation completes",
   159  	}
   160  	IterativeOutputFlag = cli.BoolTFlag{
   161  		Name:  "iterative",
   162  		Usage: "Print streaming JSON iteratively, delimited by newlines",
   163  	}
   164  	ExcludeStorageFlag = cli.BoolFlag{
   165  		Name:  "nostorage",
   166  		Usage: "Exclude storage entries (save db lookups)",
   167  	}
   168  	IncludeIncompletesFlag = cli.BoolFlag{
   169  		Name:  "incompletes",
   170  		Usage: "Include accounts for which we don't have the address (missing preimage)",
   171  	}
   172  	ExcludeCodeFlag = cli.BoolFlag{
   173  		Name:  "nocode",
   174  		Usage: "Exclude contract code (save db lookups)",
   175  	}
   176  	StartKeyFlag = cli.StringFlag{
   177  		Name:  "start",
   178  		Usage: "Start position. Either a hash or address",
   179  		Value: "0x0000000000000000000000000000000000000000000000000000000000000000",
   180  	}
   181  	DumpLimitFlag = cli.Uint64Flag{
   182  		Name:  "limit",
   183  		Usage: "Max number of elements (0 = no limit)",
   184  		Value: 0,
   185  	}
   186  	defaultSyncMode = ethconfig.Defaults.SyncMode
   187  	SyncModeFlag    = TextMarshalerFlag{
   188  		Name:  "syncmode",
   189  		Usage: `Blockchain sync mode ("fast", "full", "snap" or "light")`,
   190  		Value: &defaultSyncMode,
   191  	}
   192  	GCModeFlag = cli.StringFlag{
   193  		Name:  "gcmode",
   194  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   195  		Value: "full",
   196  	}
   197  	SnapshotFlag = cli.BoolTFlag{
   198  		Name:  "snapshot",
   199  		Usage: `Enables snapshot-database mode (default = enable)`,
   200  	}
   201  	TxLookupLimitFlag = cli.Uint64Flag{
   202  		Name:  "txlookuplimit",
   203  		Usage: "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)",
   204  		Value: ethconfig.Defaults.TxLookupLimit,
   205  	}
   206  	LightKDFFlag = cli.BoolFlag{
   207  		Name:  "lightkdf",
   208  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   209  	}
   210  	WhitelistFlag = cli.StringFlag{
   211  		Name:  "whitelist",
   212  		Usage: "Comma separated block number-to-hash mappings to enforce (<number>=<hash>)",
   213  	}
   214  	BloomFilterSizeFlag = cli.Uint64Flag{
   215  		Name:  "bloomfilter.size",
   216  		Usage: "Megabytes of memory allocated to bloom-filter for pruning",
   217  		Value: 2048,
   218  	}
   219  	OverrideLondonFlag = cli.Uint64Flag{
   220  		Name:  "override.london",
   221  		Usage: "Manually specify London fork-block, overriding the bundled setting",
   222  	}
   223  	// Light server and client settings
   224  	LightServeFlag = cli.IntFlag{
   225  		Name:  "light.serve",
   226  		Usage: "Maximum percentage of time allowed for serving LES requests (multi-threaded processing allows values over 100)",
   227  		Value: ethconfig.Defaults.LightServ,
   228  	}
   229  	LightIngressFlag = cli.IntFlag{
   230  		Name:  "light.ingress",
   231  		Usage: "Incoming bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
   232  		Value: ethconfig.Defaults.LightIngress,
   233  	}
   234  	LightEgressFlag = cli.IntFlag{
   235  		Name:  "light.egress",
   236  		Usage: "Outgoing bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
   237  		Value: ethconfig.Defaults.LightEgress,
   238  	}
   239  	LightMaxPeersFlag = cli.IntFlag{
   240  		Name:  "light.maxpeers",
   241  		Usage: "Maximum number of light clients to serve, or light servers to attach to",
   242  		Value: ethconfig.Defaults.LightPeers,
   243  	}
   244  	UltraLightServersFlag = cli.StringFlag{
   245  		Name:  "ulc.servers",
   246  		Usage: "List of trusted ultra-light servers",
   247  		Value: strings.Join(ethconfig.Defaults.UltraLightServers, ","),
   248  	}
   249  	UltraLightFractionFlag = cli.IntFlag{
   250  		Name:  "ulc.fraction",
   251  		Usage: "Minimum % of trusted ultra-light servers required to announce a new head",
   252  		Value: ethconfig.Defaults.UltraLightFraction,
   253  	}
   254  	UltraLightOnlyAnnounceFlag = cli.BoolFlag{
   255  		Name:  "ulc.onlyannounce",
   256  		Usage: "Ultra light server sends announcements only",
   257  	}
   258  	LightNoPruneFlag = cli.BoolFlag{
   259  		Name:  "light.nopruning",
   260  		Usage: "Disable ancient light chain data pruning",
   261  	}
   262  	LightNoSyncServeFlag = cli.BoolFlag{
   263  		Name:  "light.nosyncserve",
   264  		Usage: "Enables serving light clients before syncing",
   265  	}
   266  	// Transaction pool settings
   267  	TxPoolLocalsFlag = cli.StringFlag{
   268  		Name:  "txpool.locals",
   269  		Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
   270  	}
   271  	TxPoolNoLocalsFlag = cli.BoolFlag{
   272  		Name:  "txpool.nolocals",
   273  		Usage: "Disables price exemptions for locally submitted transactions",
   274  	}
   275  	TxPoolJournalFlag = cli.StringFlag{
   276  		Name:  "txpool.journal",
   277  		Usage: "Disk journal for local transaction to survive node restarts",
   278  		Value: core.DefaultTxPoolConfig.Journal,
   279  	}
   280  	TxPoolRejournalFlag = cli.DurationFlag{
   281  		Name:  "txpool.rejournal",
   282  		Usage: "Time interval to regenerate the local transaction journal",
   283  		Value: core.DefaultTxPoolConfig.Rejournal,
   284  	}
   285  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   286  		Name:  "txpool.pricelimit",
   287  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   288  		Value: ethconfig.Defaults.TxPool.PriceLimit,
   289  	}
   290  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   291  		Name:  "txpool.pricebump",
   292  		Usage: "Price bump percentage to replace an already existing transaction",
   293  		Value: ethconfig.Defaults.TxPool.PriceBump,
   294  	}
   295  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   296  		Name:  "txpool.accountslots",
   297  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   298  		Value: ethconfig.Defaults.TxPool.AccountSlots,
   299  	}
   300  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   301  		Name:  "txpool.globalslots",
   302  		Usage: "Maximum number of executable transaction slots for all accounts",
   303  		Value: ethconfig.Defaults.TxPool.GlobalSlots,
   304  	}
   305  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   306  		Name:  "txpool.accountqueue",
   307  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   308  		Value: ethconfig.Defaults.TxPool.AccountQueue,
   309  	}
   310  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   311  		Name:  "txpool.globalqueue",
   312  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   313  		Value: ethconfig.Defaults.TxPool.GlobalQueue,
   314  	}
   315  	TxPoolLifetimeFlag = cli.DurationFlag{
   316  		Name:  "txpool.lifetime",
   317  		Usage: "Maximum amount of time non-executable transaction are queued",
   318  		Value: ethconfig.Defaults.TxPool.Lifetime,
   319  	}
   320  	// Performance tuning settings
   321  	CacheFlag = cli.IntFlag{
   322  		Name:  "cache",
   323  		Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node, 128 light mode)",
   324  		Value: 1024,
   325  	}
   326  	CacheDatabaseFlag = cli.IntFlag{
   327  		Name:  "cache.database",
   328  		Usage: "Percentage of cache memory allowance to use for database io",
   329  		Value: 50,
   330  	}
   331  	CacheTrieFlag = cli.IntFlag{
   332  		Name:  "cache.trie",
   333  		Usage: "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)",
   334  		Value: 15,
   335  	}
   336  	CacheTrieJournalFlag = cli.StringFlag{
   337  		Name:  "cache.trie.journal",
   338  		Usage: "Disk journal directory for trie cache to survive node restarts",
   339  		Value: ethconfig.Defaults.TrieCleanCacheJournal,
   340  	}
   341  	CacheTrieRejournalFlag = cli.DurationFlag{
   342  		Name:  "cache.trie.rejournal",
   343  		Usage: "Time interval to regenerate the trie cache journal",
   344  		Value: ethconfig.Defaults.TrieCleanCacheRejournal,
   345  	}
   346  	CacheGCFlag = cli.IntFlag{
   347  		Name:  "cache.gc",
   348  		Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
   349  		Value: 25,
   350  	}
   351  	CacheSnapshotFlag = cli.IntFlag{
   352  		Name:  "cache.snapshot",
   353  		Usage: "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)",
   354  		Value: 10,
   355  	}
   356  	CacheNoPrefetchFlag = cli.BoolFlag{
   357  		Name:  "cache.noprefetch",
   358  		Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
   359  	}
   360  	CachePreimagesFlag = cli.BoolFlag{
   361  		Name:  "cache.preimages",
   362  		Usage: "Enable recording the SHA3/keccak preimages of trie keys",
   363  	}
   364  	// Account settings
   365  	UnlockedAccountFlag = cli.StringFlag{
   366  		Name:  "unlock",
   367  		Usage: "Comma separated list of accounts to unlock",
   368  		Value: "",
   369  	}
   370  	PasswordFileFlag = cli.StringFlag{
   371  		Name:  "password",
   372  		Usage: "Password file to use for non-interactive password input",
   373  		Value: "",
   374  	}
   375  	ExternalSignerFlag = cli.StringFlag{
   376  		Name:  "signer",
   377  		Usage: "External signer (url or path to ipc file)",
   378  		Value: "",
   379  	}
   380  	VMEnableDebugFlag = cli.BoolFlag{
   381  		Name:  "vmdebug",
   382  		Usage: "Record information useful for VM and contract debugging",
   383  	}
   384  	InsecureUnlockAllowedFlag = cli.BoolFlag{
   385  		Name:  "allow-insecure-unlock",
   386  		Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http",
   387  	}
   388  	RPCGlobalGasCapFlag = cli.Uint64Flag{
   389  		Name:  "rpc.gascap",
   390  		Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)",
   391  		Value: ethconfig.Defaults.RPCGasCap,
   392  	}
   393  	RPCGlobalTxFeeCapFlag = cli.Float64Flag{
   394  		Name:  "rpc.txfeecap",
   395  		Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)",
   396  		Value: ethconfig.Defaults.RPCTxFeeCap,
   397  	}
   398  	// Logging and debug settings
   399  	FakePoWFlag = cli.BoolFlag{
   400  		Name:  "fakepow",
   401  		Usage: "Disables proof-of-work verification",
   402  	}
   403  	NoCompactionFlag = cli.BoolFlag{
   404  		Name:  "nocompaction",
   405  		Usage: "Disables db compaction after import",
   406  	}
   407  	// RPC settings
   408  	IPCDisabledFlag = cli.BoolFlag{
   409  		Name:  "ipcdisable",
   410  		Usage: "Disable the IPC-RPC server",
   411  	}
   412  	IPCPathFlag = DirectoryFlag{
   413  		Name:  "ipcpath",
   414  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   415  	}
   416  	HTTPEnabledFlag = cli.BoolFlag{
   417  		Name:  "http",
   418  		Usage: "Enable the HTTP-RPC server",
   419  	}
   420  	HTTPListenAddrFlag = cli.StringFlag{
   421  		Name:  "http.addr",
   422  		Usage: "HTTP-RPC server listening interface",
   423  		Value: node.DefaultHTTPHost,
   424  	}
   425  	HTTPPortFlag = cli.IntFlag{
   426  		Name:  "http.port",
   427  		Usage: "HTTP-RPC server listening port",
   428  		Value: node.DefaultHTTPPort,
   429  	}
   430  	HTTPCORSDomainFlag = cli.StringFlag{
   431  		Name:  "http.corsdomain",
   432  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   433  		Value: "",
   434  	}
   435  	HTTPVirtualHostsFlag = cli.StringFlag{
   436  		Name:  "http.vhosts",
   437  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   438  		Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
   439  	}
   440  	HTTPApiFlag = cli.StringFlag{
   441  		Name:  "http.api",
   442  		Usage: "API's offered over the HTTP-RPC interface",
   443  		Value: "",
   444  	}
   445  	HTTPPathPrefixFlag = cli.StringFlag{
   446  		Name:  "http.rpcprefix",
   447  		Usage: "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
   448  		Value: "",
   449  	}
   450  	WSEnabledFlag = cli.BoolFlag{
   451  		Name:  "ws",
   452  		Usage: "Enable the WS-RPC server",
   453  	}
   454  	WSListenAddrFlag = cli.StringFlag{
   455  		Name:  "ws.addr",
   456  		Usage: "WS-RPC server listening interface",
   457  		Value: node.DefaultWSHost,
   458  	}
   459  	WSPortFlag = cli.IntFlag{
   460  		Name:  "ws.port",
   461  		Usage: "WS-RPC server listening port",
   462  		Value: node.DefaultWSPort,
   463  	}
   464  	WSApiFlag = cli.StringFlag{
   465  		Name:  "ws.api",
   466  		Usage: "API's offered over the WS-RPC interface",
   467  		Value: "",
   468  	}
   469  	WSAllowedOriginsFlag = cli.StringFlag{
   470  		Name:  "ws.origins",
   471  		Usage: "Origins from which to accept websockets requests",
   472  		Value: "",
   473  	}
   474  	WSPathPrefixFlag = cli.StringFlag{
   475  		Name:  "ws.rpcprefix",
   476  		Usage: "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
   477  		Value: "",
   478  	}
   479  	ExecFlag = cli.StringFlag{
   480  		Name:  "exec",
   481  		Usage: "Execute JavaScript statement",
   482  	}
   483  	PreloadJSFlag = cli.StringFlag{
   484  		Name:  "preload",
   485  		Usage: "Comma separated list of JavaScript files to preload into the console",
   486  	}
   487  	AllowUnprotectedTxs = cli.BoolFlag{
   488  		Name:  "rpc.allow-unprotected-txs",
   489  		Usage: "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC",
   490  	}
   491  
   492  	// Network Settings
   493  	MaxPeersFlag = cli.IntFlag{
   494  		Name:  "maxpeers",
   495  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   496  		Value: node.DefaultConfig.P2P.MaxPeers,
   497  	}
   498  	MaxPendingPeersFlag = cli.IntFlag{
   499  		Name:  "maxpendpeers",
   500  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   501  		Value: node.DefaultConfig.P2P.MaxPendingPeers,
   502  	}
   503  	ListenPortFlag = cli.IntFlag{
   504  		Name:  "port",
   505  		Usage: "Network listening port",
   506  		Value: 30303,
   507  	}
   508  	BootnodesFlag = cli.StringFlag{
   509  		Name:  "bootnodes",
   510  		Usage: "Comma separated enode URLs for P2P discovery bootstrap",
   511  		Value: "",
   512  	}
   513  	NodeKeyFileFlag = cli.StringFlag{
   514  		Name:  "nodekey",
   515  		Usage: "P2P node key file",
   516  	}
   517  	NodeKeyHexFlag = cli.StringFlag{
   518  		Name:  "nodekeyhex",
   519  		Usage: "P2P node key as hex (for testing)",
   520  	}
   521  	NATFlag = cli.StringFlag{
   522  		Name:  "nat",
   523  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   524  		Value: "any",
   525  	}
   526  	NoDiscoverFlag = cli.BoolFlag{
   527  		Name:  "nodiscover",
   528  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   529  	}
   530  	DiscoveryV5Flag = cli.BoolFlag{
   531  		Name:  "v5disc",
   532  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   533  	}
   534  	NetrestrictFlag = cli.StringFlag{
   535  		Name:  "netrestrict",
   536  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   537  	}
   538  	IPrestrictFlag = cli.StringFlag{
   539  		Name:  "iprestrict",
   540  		Usage: "Restricts network communication to the given IP addresses",
   541  	}
   542  	PrivateNodeFlag = cli.StringFlag{
   543  		Name:  "privatenodes",
   544  		Usage: "Comma separated enode URLs which must not be advertised as peers to public network",
   545  	}
   546  	DNSDiscoveryFlag = cli.StringFlag{
   547  		Name:  "discovery.dns",
   548  		Usage: "Sets DNS discovery entry points (use \"\" to disable DNS)",
   549  	}
   550  
   551  	// ATM the url is left to the user and deployment to
   552  	JSpathFlag = DirectoryFlag{
   553  		Name:  "jspath",
   554  		Usage: "JavaScript root path for `loadScript`",
   555  		Value: DirectoryString("."),
   556  	}
   557  
   558  	// Gas price oracle settings
   559  	GpoBlocksFlag = cli.IntFlag{
   560  		Name:  "gpo.blocks",
   561  		Usage: "Number of recent blocks to check for gas prices",
   562  		Value: ethconfig.Defaults.GPO.Blocks,
   563  	}
   564  	GpoPercentileFlag = cli.IntFlag{
   565  		Name:  "gpo.percentile",
   566  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   567  		Value: ethconfig.Defaults.GPO.Percentile,
   568  	}
   569  	GpoMaxGasPriceFlag = cli.Int64Flag{
   570  		Name:  "gpo.maxprice",
   571  		Usage: "Maximum gas price will be recommended by gpo",
   572  		Value: ethconfig.Defaults.GPO.MaxPrice.Int64(),
   573  	}
   574  	GpoIgnoreGasPriceFlag = cli.Int64Flag{
   575  		Name:  "gpo.ignoreprice",
   576  		Usage: "Gas price below which gpo will ignore transactions",
   577  		Value: ethconfig.Defaults.GPO.IgnorePrice.Int64(),
   578  	}
   579  
   580  	// Metrics flags
   581  	MetricsEnabledFlag = cli.BoolFlag{
   582  		Name:  "metrics",
   583  		Usage: "Enable metrics collection and reporting",
   584  	}
   585  	MetricsEnabledExpensiveFlag = cli.BoolFlag{
   586  		Name:  "metrics.expensive",
   587  		Usage: "Enable expensive metrics collection and reporting",
   588  	}
   589  
   590  	// MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint.
   591  	// Since the pprof service enables sensitive/vulnerable behavior, this allows a user
   592  	// to enable a public-OK metrics endpoint without having to worry about ALSO exposing
   593  	// other profiling behavior or information.
   594  	MetricsHTTPFlag = cli.StringFlag{
   595  		Name:  "metrics.addr",
   596  		Usage: "Enable stand-alone metrics HTTP server listening interface",
   597  		Value: metrics.DefaultConfig.HTTP,
   598  	}
   599  	MetricsPortFlag = cli.IntFlag{
   600  		Name:  "metrics.port",
   601  		Usage: "Metrics HTTP server listening port",
   602  		Value: metrics.DefaultConfig.Port,
   603  	}
   604  	MetricsEnableInfluxDBFlag = cli.BoolFlag{
   605  		Name:  "metrics.influxdb",
   606  		Usage: "Enable metrics export/push to an external InfluxDB database",
   607  	}
   608  	MetricsInfluxDBEndpointFlag = cli.StringFlag{
   609  		Name:  "metrics.influxdb.endpoint",
   610  		Usage: "InfluxDB API endpoint to report metrics to",
   611  		Value: metrics.DefaultConfig.InfluxDBEndpoint,
   612  	}
   613  	MetricsInfluxDBDatabaseFlag = cli.StringFlag{
   614  		Name:  "metrics.influxdb.database",
   615  		Usage: "InfluxDB database name to push reported metrics to",
   616  		Value: metrics.DefaultConfig.InfluxDBDatabase,
   617  	}
   618  	MetricsInfluxDBUsernameFlag = cli.StringFlag{
   619  		Name:  "metrics.influxdb.username",
   620  		Usage: "Username to authorize access to the database",
   621  		Value: metrics.DefaultConfig.InfluxDBUsername,
   622  	}
   623  	MetricsInfluxDBPasswordFlag = cli.StringFlag{
   624  		Name:  "metrics.influxdb.password",
   625  		Usage: "Password to authorize access to the database",
   626  		Value: metrics.DefaultConfig.InfluxDBPassword,
   627  	}
   628  	// Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB.
   629  	// For example `host` tag could be used so that we can group all nodes and average a measurement
   630  	// across all of them, but also so that we can select a specific node and inspect its measurements.
   631  	// https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key
   632  	MetricsInfluxDBTagsFlag = cli.StringFlag{
   633  		Name:  "metrics.influxdb.tags",
   634  		Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements",
   635  		Value: metrics.DefaultConfig.InfluxDBTags,
   636  	}
   637  
   638  	MetricsEnableInfluxDBV2Flag = cli.BoolFlag{
   639  		Name:  "metrics.influxdbv2",
   640  		Usage: "Enable metrics export/push to an external InfluxDB v2 database",
   641  	}
   642  
   643  	MetricsInfluxDBTokenFlag = cli.StringFlag{
   644  		Name:  "metrics.influxdb.token",
   645  		Usage: "Token to authorize access to the database (v2 only)",
   646  		Value: metrics.DefaultConfig.InfluxDBToken,
   647  	}
   648  
   649  	MetricsInfluxDBBucketFlag = cli.StringFlag{
   650  		Name:  "metrics.influxdb.bucket",
   651  		Usage: "InfluxDB bucket name to push reported metrics to (v2 only)",
   652  		Value: metrics.DefaultConfig.InfluxDBBucket,
   653  	}
   654  
   655  	MetricsInfluxDBOrganizationFlag = cli.StringFlag{
   656  		Name:  "metrics.influxdb.organization",
   657  		Usage: "InfluxDB organization name (v2 only)",
   658  		Value: metrics.DefaultConfig.InfluxDBOrganization,
   659  	}
   660  
   661  	MetricsPrometheusEndpointFlag = cli.StringFlag{
   662  		Name:  "metrics.prometheus.endpoint",
   663  		Usage: "Prometheus API endpoint to report metrics to",
   664  		Value: metrics.DefaultConfig.PrometheusEndpointPort,
   665  	}
   666  
   667  	CatalystFlag = cli.BoolFlag{
   668  		Name:  "catalyst",
   669  		Usage: "Catalyst mode (eth2 integration testing)",
   670  	}
   671  )
   672  
   673  // MakeDataDir retrieves the currently requested data directory, terminating
   674  // if none (or the empty string) is specified. If the node is starting a testnet,
   675  // then a subdirectory of the specified datadir will be used.
   676  func MakeDataDir(ctx *cli.Context) string {
   677  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   678  		if ctx.GlobalBool(RopstenFlag.Name) {
   679  			// Maintain compatibility with older Geth configurations storing the
   680  			// Ropsten database in `testnet` instead of `ropsten`.
   681  			return filepath.Join(path, "ropsten")
   682  		}
   683  		if ctx.GlobalBool(RinkebyFlag.Name) {
   684  			return filepath.Join(path, "rinkeby")
   685  		}
   686  		if ctx.GlobalBool(GoerliFlag.Name) {
   687  			return filepath.Join(path, "goerli")
   688  		}
   689  		return path
   690  	}
   691  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   692  	return ""
   693  }
   694  
   695  // setNodeKey creates a node key from set command line flags, either loading it
   696  // from a file or as a specified hex value. If neither flags were provided, this
   697  // method returns nil and an emphemeral key is to be generated.
   698  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   699  	var (
   700  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   701  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   702  		key  *ecdsa.PrivateKey
   703  		err  error
   704  	)
   705  	switch {
   706  	case file != "" && hex != "":
   707  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   708  	case file != "":
   709  		if key, err = crypto.LoadECDSA(file); err != nil {
   710  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   711  		}
   712  		cfg.PrivateKey = key
   713  	case hex != "":
   714  		if key, err = crypto.HexToECDSA(hex); err != nil {
   715  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   716  		}
   717  		cfg.PrivateKey = key
   718  	}
   719  }
   720  
   721  // setNodeUserIdent creates the user identifier from CLI flags.
   722  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   723  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   724  		cfg.UserIdent = identity
   725  	}
   726  }
   727  
   728  // setListenAddress creates a TCP listening address string from set command
   729  // line flags.
   730  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   731  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   732  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   733  	}
   734  }
   735  
   736  // setNAT creates a port mapper from command line flags.
   737  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   738  	if ctx.GlobalIsSet(NATFlag.Name) {
   739  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   740  		if err != nil {
   741  			Fatalf("Option %s: %v", NATFlag.Name, err)
   742  		}
   743  		cfg.NAT = natif
   744  	}
   745  }
   746  
   747  // SplitAndTrim splits input separated by a comma
   748  // and trims excessive white space from the substrings.
   749  func SplitAndTrim(input string) (ret []string) {
   750  	l := strings.Split(input, ",")
   751  	for _, r := range l {
   752  		if r = strings.TrimSpace(r); r != "" {
   753  			ret = append(ret, r)
   754  		}
   755  	}
   756  	return ret
   757  }
   758  
   759  // setHTTP creates the HTTP RPC listener interface string from the set
   760  // command line flags, returning empty if the HTTP endpoint is disabled.
   761  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   762  	if ctx.GlobalBool(LegacyRPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   763  		log.Warn("The flag --rpc is deprecated and will be removed June 2021, please use --http")
   764  		cfg.HTTPHost = "127.0.0.1"
   765  		if ctx.GlobalIsSet(LegacyRPCListenAddrFlag.Name) {
   766  			cfg.HTTPHost = ctx.GlobalString(LegacyRPCListenAddrFlag.Name)
   767  			log.Warn("The flag --rpcaddr is deprecated and will be removed June 2021, please use --http.addr")
   768  		}
   769  	}
   770  	if ctx.GlobalBool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" {
   771  		cfg.HTTPHost = "127.0.0.1"
   772  		if ctx.GlobalIsSet(HTTPListenAddrFlag.Name) {
   773  			cfg.HTTPHost = ctx.GlobalString(HTTPListenAddrFlag.Name)
   774  		}
   775  	}
   776  
   777  	if ctx.GlobalIsSet(LegacyRPCPortFlag.Name) {
   778  		cfg.HTTPPort = ctx.GlobalInt(LegacyRPCPortFlag.Name)
   779  		log.Warn("The flag --rpcport is deprecated and will be removed June 2021, please use --http.port")
   780  	}
   781  	if ctx.GlobalIsSet(HTTPPortFlag.Name) {
   782  		cfg.HTTPPort = ctx.GlobalInt(HTTPPortFlag.Name)
   783  	}
   784  
   785  	if ctx.GlobalIsSet(LegacyRPCCORSDomainFlag.Name) {
   786  		cfg.HTTPCors = SplitAndTrim(ctx.GlobalString(LegacyRPCCORSDomainFlag.Name))
   787  		log.Warn("The flag --rpccorsdomain is deprecated and will be removed June 2021, please use --http.corsdomain")
   788  	}
   789  	if ctx.GlobalIsSet(HTTPCORSDomainFlag.Name) {
   790  		cfg.HTTPCors = SplitAndTrim(ctx.GlobalString(HTTPCORSDomainFlag.Name))
   791  	}
   792  
   793  	if ctx.GlobalIsSet(LegacyRPCApiFlag.Name) {
   794  		cfg.HTTPModules = SplitAndTrim(ctx.GlobalString(LegacyRPCApiFlag.Name))
   795  		log.Warn("The flag --rpcapi is deprecated and will be removed June 2021, please use --http.api")
   796  	}
   797  	if ctx.GlobalIsSet(HTTPApiFlag.Name) {
   798  		cfg.HTTPModules = SplitAndTrim(ctx.GlobalString(HTTPApiFlag.Name))
   799  	}
   800  
   801  	if ctx.GlobalIsSet(LegacyRPCVirtualHostsFlag.Name) {
   802  		cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(LegacyRPCVirtualHostsFlag.Name))
   803  		log.Warn("The flag --rpcvhosts is deprecated and will be removed June 2021, please use --http.vhosts")
   804  	}
   805  	if ctx.GlobalIsSet(HTTPVirtualHostsFlag.Name) {
   806  		cfg.HTTPVirtualHosts = SplitAndTrim(ctx.GlobalString(HTTPVirtualHostsFlag.Name))
   807  	}
   808  
   809  	if ctx.GlobalIsSet(HTTPPathPrefixFlag.Name) {
   810  		cfg.HTTPPathPrefix = ctx.GlobalString(HTTPPathPrefixFlag.Name)
   811  	}
   812  	if ctx.GlobalIsSet(AllowUnprotectedTxs.Name) {
   813  		cfg.AllowUnprotectedTxs = ctx.GlobalBool(AllowUnprotectedTxs.Name)
   814  	}
   815  }
   816  
   817  // setWS creates the WebSocket RPC listener interface string from the set
   818  // command line flags, returning empty if the HTTP endpoint is disabled.
   819  func setWS(ctx *cli.Context, cfg *node.Config) {
   820  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   821  		cfg.WSHost = "127.0.0.1"
   822  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   823  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   824  		}
   825  	}
   826  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   827  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   828  	}
   829  
   830  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   831  		cfg.WSOrigins = SplitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   832  	}
   833  
   834  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   835  		cfg.WSModules = SplitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   836  	}
   837  
   838  	if ctx.GlobalIsSet(WSPathPrefixFlag.Name) {
   839  		cfg.WSPathPrefix = ctx.GlobalString(WSPathPrefixFlag.Name)
   840  	}
   841  }
   842  
   843  // setIPC creates an IPC path configuration from the set command line flags,
   844  // returning an empty string if IPC was explicitly disabled, or the set path.
   845  func setIPC(ctx *cli.Context, cfg *node.Config) {
   846  	CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   847  	switch {
   848  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   849  		cfg.IPCPath = ""
   850  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   851  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   852  	}
   853  }
   854  
   855  // MakeDatabaseHandles raises out the number of allowed file handles per process
   856  // for Geth and returns half of the allowance to assign to the database.
   857  func MakeDatabaseHandles() int {
   858  	limit, err := fdlimit.Maximum()
   859  	if err != nil {
   860  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   861  	}
   862  	raised, err := fdlimit.Raise(uint64(limit))
   863  	if err != nil {
   864  		Fatalf("Failed to raise file descriptor allowance: %v", err)
   865  	}
   866  	return int(raised / 2) // Leave half for networking and other stuff
   867  }
   868  
   869  // MakeAddress converts an account specified directly as a hex encoded string or
   870  // a key index in the key store to an internal account representation.
   871  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   872  	// If the specified account is a valid address, return it
   873  	if common.IsHexAddress(account) {
   874  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   875  	}
   876  	// Otherwise try to interpret the account as a keystore index
   877  	index, err := strconv.Atoi(account)
   878  	if err != nil || index < 0 {
   879  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   880  	}
   881  	log.Warn("-------------------------------------------------------------------")
   882  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   883  	log.Warn("This functionality is deprecated and will be removed in the future!")
   884  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   885  	log.Warn("-------------------------------------------------------------------")
   886  
   887  	accs := ks.Accounts()
   888  	if len(accs) <= index {
   889  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   890  	}
   891  	return accs[index], nil
   892  }
   893  
   894  // MakePasswordList reads password lines from the file specified by the global --password flag.
   895  func MakePasswordList(ctx *cli.Context) []string {
   896  	path := ctx.GlobalString(PasswordFileFlag.Name)
   897  	if path == "" {
   898  		return nil
   899  	}
   900  	text, err := ioutil.ReadFile(path)
   901  	if err != nil {
   902  		Fatalf("Failed to read password file: %v", err)
   903  	}
   904  	lines := strings.Split(string(text), "\n")
   905  	// Sanitise DOS line endings.
   906  	for i := range lines {
   907  		lines[i] = strings.TrimRight(lines[i], "\r")
   908  	}
   909  	return lines
   910  }
   911  
   912  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   913  	setNodeKey(ctx, cfg)
   914  	setNAT(ctx, cfg)
   915  	setListenAddress(ctx, cfg)
   916  	// setBootstrapNodes(ctx, cfg)
   917  	// setBootstrapNodesV5(ctx, cfg)
   918  
   919  	lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light"
   920  	lightServer := (ctx.GlobalInt(LightServeFlag.Name) != 0)
   921  
   922  	lightPeers := ctx.GlobalInt(LightMaxPeersFlag.Name)
   923  	if lightClient && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
   924  		// dynamic default - for clients we use 1/10th of the default for servers
   925  		lightPeers /= 10
   926  	}
   927  
   928  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   929  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   930  		if lightServer && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
   931  			cfg.MaxPeers += lightPeers
   932  		}
   933  	} else {
   934  		if lightServer {
   935  			cfg.MaxPeers += lightPeers
   936  		}
   937  		if lightClient && ctx.GlobalIsSet(LightMaxPeersFlag.Name) && cfg.MaxPeers < lightPeers {
   938  			cfg.MaxPeers = lightPeers
   939  		}
   940  	}
   941  	if !(lightClient || lightServer) {
   942  		lightPeers = 0
   943  	}
   944  	log.Info("Maximum peer count", "total", cfg.MaxPeers)
   945  
   946  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   947  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   948  	}
   949  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
   950  		cfg.NoDiscovery = true
   951  	}
   952  
   953  	// if we're running a light client or server, force enable the v5 peer discovery
   954  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   955  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   956  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   957  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   958  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   959  	} else if forceV5Discovery {
   960  		cfg.DiscoveryV5 = true
   961  	}
   962  
   963  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   964  		list, err := netutil.ParseNetlist(netrestrict)
   965  		if err != nil {
   966  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   967  		}
   968  		cfg.NetRestrict = list
   969  	}
   970  
   971  	var err error
   972  	if iprestrict := ctx.GlobalString(IPrestrictFlag.Name); iprestrict != "" {
   973  		cfg.IPRestrict, err = netutil.ParseIPs(iprestrict)
   974  		if err != nil {
   975  			Fatalf("Option %q: %v", IPrestrictFlag.Name, err)
   976  		}
   977  	}
   978  
   979  	if privatenodes := ctx.GlobalString(PrivateNodeFlag.Name); privatenodes != "" {
   980  		cfg.PrivateNodes, err = enode.ParseNodes(privatenodes)
   981  		if err != nil {
   982  			Fatalf("Option %q: %v", PrivateNodeFlag.Name, err)
   983  		}
   984  	}
   985  
   986  	if ctx.GlobalBool(DeveloperFlag.Name) || ctx.GlobalBool(CatalystFlag.Name) {
   987  		// --dev mode can't use p2p networking.
   988  		cfg.MaxPeers = 0
   989  		cfg.ListenAddr = ""
   990  		cfg.NoDial = true
   991  		cfg.NoDiscovery = true
   992  		cfg.DiscoveryV5 = false
   993  	}
   994  }
   995  
   996  // SetNodeConfig applies node-related command line flags to the config.
   997  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   998  	SetP2PConfig(ctx, &cfg.P2P)
   999  	setIPC(ctx, cfg)
  1000  	setHTTP(ctx, cfg)
  1001  	setWS(ctx, cfg)
  1002  	setNodeUserIdent(ctx, cfg)
  1003  	setDataDir(ctx, cfg)
  1004  	setSmartCard(ctx, cfg)
  1005  
  1006  	if ctx.GlobalIsSet(ExternalSignerFlag.Name) {
  1007  		cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name)
  1008  	}
  1009  
  1010  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
  1011  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
  1012  	}
  1013  	if ctx.GlobalIsSet(DeveloperFlag.Name) {
  1014  		cfg.UseLightweightKDF = true
  1015  	}
  1016  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
  1017  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
  1018  	}
  1019  	if ctx.GlobalIsSet(NoUSBFlag.Name) || cfg.NoUSB {
  1020  		log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable")
  1021  	}
  1022  	if ctx.GlobalIsSet(USBFlag.Name) {
  1023  		cfg.USB = ctx.GlobalBool(USBFlag.Name)
  1024  	}
  1025  	if ctx.GlobalIsSet(InsecureUnlockAllowedFlag.Name) {
  1026  		cfg.InsecureUnlockAllowed = ctx.GlobalBool(InsecureUnlockAllowedFlag.Name)
  1027  	}
  1028  }
  1029  
  1030  func setSmartCard(ctx *cli.Context, cfg *node.Config) {
  1031  	// Skip enabling smartcards if no path is set
  1032  	path := ctx.GlobalString(SmartCardDaemonPathFlag.Name)
  1033  	if path == "" {
  1034  		return
  1035  	}
  1036  	// Sanity check that the smartcard path is valid
  1037  	fi, err := os.Stat(path)
  1038  	if err != nil {
  1039  		log.Info("Smartcard socket not found, disabling", "err", err)
  1040  		return
  1041  	}
  1042  	if fi.Mode()&os.ModeType != os.ModeSocket {
  1043  		log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String())
  1044  		return
  1045  	}
  1046  	// Smartcard daemon path exists and is a socket, enable it
  1047  	cfg.SmartCardDaemonPath = path
  1048  }
  1049  
  1050  func setDataDir(ctx *cli.Context, cfg *node.Config) {
  1051  	switch {
  1052  	case ctx.GlobalIsSet(DataDirFlag.Name):
  1053  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
  1054  	case ctx.GlobalBool(DeveloperFlag.Name):
  1055  		cfg.DataDir = "" // unless explicitly requested, use memory databases
  1056  	case ctx.GlobalBool(RopstenFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1057  		// Maintain compatibility with older Geth configurations storing the
  1058  		// Ropsten database in `testnet` instead of `ropsten`.
  1059  		legacyPath := filepath.Join(node.DefaultDataDir(), "testnet")
  1060  		if _, err := os.Stat(legacyPath); !os.IsNotExist(err) {
  1061  			log.Warn("Using the deprecated `testnet` datadir. Future versions will store the Ropsten chain in `ropsten`.")
  1062  			cfg.DataDir = legacyPath
  1063  		} else {
  1064  			cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten")
  1065  		}
  1066  
  1067  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten")
  1068  	case ctx.GlobalBool(RinkebyFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1069  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
  1070  	case ctx.GlobalBool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1071  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
  1072  	}
  1073  }
  1074  
  1075  // CheckExclusive verifies that only a single instance of the provided flags was
  1076  // set by the user. Each flag might optionally be followed by a string type to
  1077  // specialize it further.
  1078  func CheckExclusive(ctx *cli.Context, args ...interface{}) {
  1079  	set := make([]string, 0, 1)
  1080  	for i := 0; i < len(args); i++ {
  1081  		// Make sure the next argument is a flag and skip if not set
  1082  		flag, ok := args[i].(cli.Flag)
  1083  		if !ok {
  1084  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1085  		}
  1086  		// Check if next arg extends current and expand its name if so
  1087  		name := flag.GetName()
  1088  
  1089  		if i+1 < len(args) {
  1090  			switch option := args[i+1].(type) {
  1091  			case string:
  1092  				// Extended flag check, make sure value set doesn't conflict with passed in option
  1093  				if ctx.GlobalString(flag.GetName()) == option {
  1094  					name += "=" + option
  1095  					set = append(set, "--"+name)
  1096  				}
  1097  				// shift arguments and continue
  1098  				i++
  1099  				continue
  1100  
  1101  			case cli.Flag:
  1102  			default:
  1103  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1104  			}
  1105  		}
  1106  		// Mark the flag if it's set
  1107  		if ctx.GlobalIsSet(flag.GetName()) {
  1108  			set = append(set, "--"+name)
  1109  		}
  1110  	}
  1111  	if len(set) > 1 {
  1112  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1113  	}
  1114  }
  1115  
  1116  func SetupMetrics(ctx *cli.Context) {
  1117  	if metrics.Enabled {
  1118  		log.Info("Enabling metrics collection")
  1119  
  1120  		var (
  1121  			enableExport   = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
  1122  			enableExportV2 = ctx.GlobalBool(MetricsEnableInfluxDBV2Flag.Name)
  1123  		)
  1124  
  1125  		if enableExport || enableExportV2 {
  1126  			CheckExclusive(ctx, MetricsEnableInfluxDBFlag, MetricsEnableInfluxDBV2Flag)
  1127  
  1128  			v1FlagIsSet := ctx.GlobalIsSet(MetricsInfluxDBUsernameFlag.Name) ||
  1129  				ctx.GlobalIsSet(MetricsInfluxDBPasswordFlag.Name)
  1130  
  1131  			v2FlagIsSet := ctx.GlobalIsSet(MetricsInfluxDBTokenFlag.Name) ||
  1132  				ctx.GlobalIsSet(MetricsInfluxDBOrganizationFlag.Name) ||
  1133  				ctx.GlobalIsSet(MetricsInfluxDBBucketFlag.Name)
  1134  
  1135  			if enableExport && v2FlagIsSet {
  1136  				Fatalf("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2")
  1137  			} else if enableExportV2 && v1FlagIsSet {
  1138  				Fatalf("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1")
  1139  			}
  1140  		}
  1141  
  1142  		var (
  1143  			endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
  1144  			database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
  1145  			username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
  1146  			password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
  1147  
  1148  			token        = ctx.GlobalString(MetricsInfluxDBTokenFlag.Name)
  1149  			bucket       = ctx.GlobalString(MetricsInfluxDBBucketFlag.Name)
  1150  			organization = ctx.GlobalString(MetricsInfluxDBOrganizationFlag.Name)
  1151  		)
  1152  
  1153  		if enableExport {
  1154  			tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name))
  1155  
  1156  			log.Info("Enabling metrics export to InfluxDB")
  1157  
  1158  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
  1159  		} else if enableExportV2 {
  1160  			tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name))
  1161  
  1162  			log.Info("Enabling metrics export to InfluxDB (v2)")
  1163  
  1164  			go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap)
  1165  		}
  1166  
  1167  		if ctx.GlobalIsSet(MetricsHTTPFlag.Name) {
  1168  			address := fmt.Sprintf("%s:%d", ctx.GlobalString(MetricsHTTPFlag.Name), ctx.GlobalInt(MetricsPortFlag.Name))
  1169  			log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address)
  1170  			exp.Setup(address)
  1171  		}
  1172  	}
  1173  }
  1174  
  1175  func SplitTagsFlag(tagsFlag string) map[string]string {
  1176  	tags := strings.Split(tagsFlag, ",")
  1177  	tagsMap := map[string]string{}
  1178  
  1179  	for _, t := range tags {
  1180  		if t != "" {
  1181  			kv := strings.Split(t, "=")
  1182  
  1183  			if len(kv) == 2 {
  1184  				tagsMap[kv[0]] = kv[1]
  1185  			}
  1186  		}
  1187  	}
  1188  
  1189  	return tagsMap
  1190  }
  1191  
  1192  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1193  // scripts to preload before starting.
  1194  func MakeConsolePreloads(ctx *cli.Context) []string {
  1195  	// Skip preloading if there's nothing to preload
  1196  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1197  		return nil
  1198  	}
  1199  	// Otherwise resolve absolute paths and return them
  1200  	var preloads []string
  1201  
  1202  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1203  		preloads = append(preloads, strings.TrimSpace(file))
  1204  	}
  1205  	return preloads
  1206  }
  1207  
  1208  // MigrateFlags sets the global flag from a local flag when it's set.
  1209  // This is a temporary function used for migrating old command/flags to the
  1210  // new format.
  1211  //
  1212  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1213  //
  1214  // is equivalent after calling this method with:
  1215  //
  1216  // geth --keystore /tmp/mykeystore --lightkdf account new
  1217  //
  1218  // This allows the use of the existing configuration functionality.
  1219  // When all flags are migrated this function can be removed and the existing
  1220  // configuration functionality must be changed that is uses local flags
  1221  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1222  	return func(ctx *cli.Context) error {
  1223  		for _, name := range ctx.FlagNames() {
  1224  			if ctx.IsSet(name) {
  1225  				ctx.GlobalSet(name, ctx.String(name))
  1226  			}
  1227  		}
  1228  		return action(ctx)
  1229  	}
  1230  }