github.com/bcskill/bcschain/v3@v3.4.9-beta2/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  	"bytes"
    22  	"context"
    23  	"crypto/ecdsa"
    24  	"fmt"
    25  	"io/ioutil"
    26  	"math/big"
    27  	"os"
    28  	"path/filepath"
    29  	"strconv"
    30  	"strings"
    31  
    32  	"github.com/bcskill/bcschain/v3/accounts"
    33  	"github.com/bcskill/bcschain/v3/accounts/keystore"
    34  	"github.com/bcskill/bcschain/v3/common"
    35  	"github.com/bcskill/bcschain/v3/common/fdlimit"
    36  	"github.com/bcskill/bcschain/v3/consensus"
    37  	"github.com/bcskill/bcschain/v3/consensus/clique"
    38  	"github.com/bcskill/bcschain/v3/core"
    39  	"github.com/bcskill/bcschain/v3/core/rawdb"
    40  	"github.com/bcskill/bcschain/v3/core/state"
    41  	"github.com/bcskill/bcschain/v3/core/vm"
    42  	"github.com/bcskill/bcschain/v3/crypto"
    43  	"github.com/bcskill/bcschain/v3/eth"
    44  	"github.com/bcskill/bcschain/v3/eth/downloader"
    45  	"github.com/bcskill/bcschain/v3/eth/gasprice"
    46  	"github.com/bcskill/bcschain/v3/ethdb"
    47  	"github.com/bcskill/bcschain/v3/les"
    48  	"github.com/bcskill/bcschain/v3/log"
    49  	"github.com/bcskill/bcschain/v3/metrics"
    50  	"github.com/bcskill/bcschain/v3/netstats"
    51  	"github.com/bcskill/bcschain/v3/node"
    52  	"github.com/bcskill/bcschain/v3/p2p"
    53  	"github.com/bcskill/bcschain/v3/p2p/discover"
    54  	"github.com/bcskill/bcschain/v3/p2p/nat"
    55  	"github.com/bcskill/bcschain/v3/p2p/netutil"
    56  	"github.com/bcskill/bcschain/v3/params"
    57  	whisper "github.com/bcskill/bcschain/v3/whisper/whisperv6"
    58  	"github.com/urfave/cli"
    59  )
    60  
    61  var (
    62  	CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...]
    63  {{if .cmd.Description}}{{.cmd.Description}}
    64  {{end}}{{if .cmd.Subcommands}}
    65  SUBCOMMANDS:
    66  	{{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    67  	{{end}}{{end}}{{if .categorizedFlags}}
    68  {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
    69  {{range $categorized.Flags}}{{"\t"}}{{.}}
    70  {{end}}
    71  {{end}}{{end}}`
    72  )
    73  
    74  func init() {
    75  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    76  
    77  VERSION:
    78     {{.Version}}
    79  
    80  COMMANDS:
    81     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    82     {{end}}{{if .Flags}}
    83  GLOBAL OPTIONS:
    84     {{range .Flags}}{{.}}
    85     {{end}}{{end}}
    86  `
    87  
    88  	cli.CommandHelpTemplate = CommandHelpTemplate
    89  }
    90  
    91  // NewApp creates an app with sane defaults.
    92  func NewApp(gitCommit, usage string) *cli.App {
    93  	app := cli.NewApp()
    94  	app.Name = filepath.Base(os.Args[0])
    95  	app.Author = ""
    96  	//app.Authors = nil
    97  	app.Email = ""
    98  	app.Version = params.Version
    99  	if len(gitCommit) >= 8 {
   100  		app.Version += "-" + gitCommit[:8]
   101  	}
   102  	app.Usage = usage
   103  	return app
   104  }
   105  
   106  // These are all the command line flags we support.
   107  // If you add to this list, please remember to include the
   108  // flag in the appropriate command definition.
   109  //
   110  // The flags are defined here so their names and help texts
   111  // are the same for all commands.
   112  
   113  var (
   114  	// General settings
   115  	DataDirFlag = DirectoryFlag{
   116  		Name:  "datadir",
   117  		Usage: "Data directory for the databases and keystore",
   118  		Value: DirectoryString{node.DefaultDataDir()},
   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",
   127  	}
   128  	NetworkIdFlag = cli.Uint64Flag{
   129  		Name:  "networkid",
   130  		Usage: "Network identifier (integer, 60=mainnet, 31337=testnet)",
   131  		Value: eth.DefaultConfig.NetworkId,
   132  	}
   133  	TestnetFlag = cli.BoolFlag{
   134  		Name:  "testnet",
   135  		Usage: "Gochain test network: pre-configured test network",
   136  	}
   137  	ConstantinopleOverrideFlag = cli.Uint64Flag{
   138  		Name:  "override.constantinople",
   139  		Usage: "Manually specify constantinople fork-block, overriding the bundled setting",
   140  	}
   141  	DeveloperFlag = cli.BoolFlag{
   142  		Name:  "dev",
   143  		Usage: "Ephemeral network with a pre-funded developer account",
   144  	}
   145  	DeveloperPeriodFlag = cli.IntFlag{
   146  		Name:  "dev.period",
   147  		Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   148  		Value: params.DefaultCliquePeriod,
   149  	}
   150  	LocalFlag = cli.BoolFlag{
   151  		Name:  "local",
   152  		Usage: "Persistent network with pre-funded accounts.",
   153  	}
   154  	LocalFundFlag = cli.StringSliceFlag{
   155  		Name:  "local.fund",
   156  		Usage: "Comma separated list of accounts (and optionally balances) to pre-fund: <addr> or <addr>:<amount>",
   157  	}
   158  	IdentityFlag = cli.StringFlag{
   159  		Name:  "identity",
   160  		Usage: "Custom node name",
   161  	}
   162  	DocRootFlag = DirectoryFlag{
   163  		Name:  "docroot",
   164  		Usage: "Document Root for HTTPClient file scheme",
   165  		Value: DirectoryString{homeDir()},
   166  	}
   167  	FastSyncFlag = cli.BoolFlag{
   168  		Name:  "fast",
   169  		Usage: "Enable fast syncing through state downloads",
   170  	}
   171  	LightModeFlag = cli.BoolFlag{
   172  		Name:  "light",
   173  		Usage: "Enable light client mode",
   174  	}
   175  	defaultSyncMode = eth.DefaultConfig.SyncMode
   176  	SyncModeFlag    = TextMarshalerFlag{
   177  		Name:  "syncmode",
   178  		Usage: `Blockchain sync mode ("fast", "full", or "light")`,
   179  		Value: &defaultSyncMode,
   180  	}
   181  	GCModeFlag = cli.StringFlag{
   182  		Name:  "gcmode",
   183  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   184  		Value: "full",
   185  	}
   186  	LightServFlag = cli.IntFlag{
   187  		Name:  "lightserv",
   188  		Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
   189  		Value: 0,
   190  	}
   191  	LightPeersFlag = cli.IntFlag{
   192  		Name:  "lightpeers",
   193  		Usage: "Maximum number of LES client peers",
   194  		Value: eth.DefaultConfig.LightPeers,
   195  	}
   196  	LightKDFFlag = cli.BoolFlag{
   197  		Name:  "lightkdf",
   198  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   199  	}
   200  	// Transaction pool settings
   201  	TxPoolLocalsFlag = cli.StringFlag{
   202  		Name:  "txpool.locals",
   203  		Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
   204  	}
   205  	TxPoolNoLocalsFlag = cli.BoolFlag{
   206  		Name:  "txpool.nolocals",
   207  		Usage: "Disables price exemptions for locally submitted transactions",
   208  	}
   209  	TxPoolJournalFlag = cli.StringFlag{
   210  		Name:  "txpool.journal",
   211  		Usage: "Disk journal for local transaction to survive node restarts",
   212  		Value: core.DefaultTxPoolConfig.Journal,
   213  	}
   214  	TxPoolRejournalFlag = cli.DurationFlag{
   215  		Name:  "txpool.rejournal",
   216  		Usage: "Time interval to regenerate the local transaction journal",
   217  		Value: core.DefaultTxPoolConfig.Rejournal,
   218  	}
   219  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   220  		Name:  "txpool.pricelimit",
   221  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   222  		Value: eth.DefaultConfig.TxPool.PriceLimit,
   223  	}
   224  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   225  		Name:  "txpool.pricebump",
   226  		Usage: "Price bump percentage to replace an already existing transaction",
   227  		Value: eth.DefaultConfig.TxPool.PriceBump,
   228  	}
   229  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   230  		Name:  "txpool.accountslots",
   231  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   232  		Value: eth.DefaultConfig.TxPool.AccountSlots,
   233  	}
   234  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   235  		Name:  "txpool.globalslots",
   236  		Usage: "Maximum number of executable transaction slots for all accounts",
   237  		Value: eth.DefaultConfig.TxPool.GlobalSlots,
   238  	}
   239  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   240  		Name:  "txpool.accountqueue",
   241  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   242  		Value: eth.DefaultConfig.TxPool.AccountQueue,
   243  	}
   244  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   245  		Name:  "txpool.globalqueue",
   246  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   247  		Value: eth.DefaultConfig.TxPool.GlobalQueue,
   248  	}
   249  	TxPoolLifetimeFlag = cli.DurationFlag{
   250  		Name:  "txpool.lifetime",
   251  		Usage: "Maximum amount of time non-executable transaction are queued",
   252  		Value: eth.DefaultConfig.TxPool.Lifetime,
   253  	}
   254  	// Performance tuning settings
   255  	CacheFlag = cli.IntFlag{
   256  		Name:  "cache",
   257  		Usage: "Megabytes of memory allocated to internal caching",
   258  		Value: 1024,
   259  	}
   260  	CacheDatabaseFlag = cli.IntFlag{
   261  		Name:  "cache.database",
   262  		Usage: "Percentage of cache memory allowance to use for database io",
   263  		Value: 75,
   264  	}
   265  	CacheGCFlag = cli.IntFlag{
   266  		Name:  "cache.gc",
   267  		Usage: "Percentage of cache memory allowance to use for trie pruning",
   268  		Value: 25,
   269  	}
   270  	TrieCacheGenFlag = cli.IntFlag{
   271  		Name:  "trie-cache-gens",
   272  		Usage: "Number of trie node generations to keep in memory",
   273  		Value: int(state.MaxTrieCacheGen),
   274  	}
   275  	// Miner settings
   276  	MiningEnabledFlag = cli.BoolFlag{
   277  		Name:  "mine",
   278  		Usage: "Enable mining",
   279  	}
   280  	MinerThreadsFlag = cli.IntFlag{
   281  		Name:  "miner.threads",
   282  		Usage: "Number of CPU threads to use for mining",
   283  		Value: 0,
   284  	}
   285  	MinerLegacyThreadsFlag = cli.IntFlag{
   286  		Name:  "minerthreads",
   287  		Usage: "Number of CPU threads to use for mining (deprecated, use --miner.threads)",
   288  		Value: 0,
   289  	}
   290  	MinerNotifyFlag = cli.StringFlag{
   291  		Name:  "miner.notify",
   292  		Usage: "Comma separated HTTP URL list to notify of new work packages",
   293  	}
   294  	MinerGasTargetFlag = cli.Uint64Flag{
   295  		Name:  "miner.gastarget",
   296  		Usage: "Target gas floor for mined blocks",
   297  		Value: eth.DefaultConfig.MinerGasFloor,
   298  	}
   299  	MinerLegacyGasTargetFlag = cli.Uint64Flag{
   300  		Name:  "targetgaslimit",
   301  		Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)",
   302  		Value: eth.DefaultConfig.MinerGasFloor,
   303  	}
   304  	MinerGasLimitFlag = cli.Uint64Flag{
   305  		Name:  "miner.gaslimit",
   306  		Usage: "Target gas ceiling for mined blocks",
   307  		Value: eth.DefaultConfig.MinerGasCeil,
   308  	}
   309  	MinerGasPriceFlag = BigFlag{
   310  		Name:  "miner.gasprice",
   311  		Usage: "Minimum gas price for mining a transaction",
   312  		Value: eth.DefaultConfig.MinerGasPrice,
   313  	}
   314  	MinerLegacyGasPriceFlag = BigFlag{
   315  		Name:  "gasprice",
   316  		Usage: "Minimum gas price for mining a transaction (deprecated, use --miner.gasprice)",
   317  		Value: eth.DefaultConfig.MinerGasPrice,
   318  	}
   319  	MinerEtherbaseFlag = cli.StringFlag{
   320  		Name:  "miner.etherbase",
   321  		Usage: "Public address for block mining rewards (default = first account)",
   322  		Value: "0",
   323  	}
   324  	MinerLegacyEtherbaseFlag = cli.StringFlag{
   325  		Name:  "etherbase",
   326  		Usage: "Public address for block mining rewards (default = first account, deprecated, use --miner.etherbase)",
   327  		Value: "0",
   328  	}
   329  	MinerExtraDataFlag = cli.StringFlag{
   330  		Name:  "miner.extradata",
   331  		Usage: "Block extra data set by the miner (default = client version)",
   332  	}
   333  	MinerLegacyExtraDataFlag = cli.StringFlag{
   334  		Name:  "extradata",
   335  		Usage: "Block extra data set by the miner (default = client version, deprecated, use --miner.extradata)",
   336  	}
   337  	MinerRecommitIntervalFlag = cli.DurationFlag{
   338  		Name:  "miner.recommit",
   339  		Usage: "Time interval to recreate the block being mined",
   340  		Value: eth.DefaultConfig.MinerRecommit,
   341  	}
   342  	MinerNoVerfiyFlag = cli.BoolFlag{
   343  		Name:  "miner.noverify",
   344  		Usage: "Disable remote sealing verification",
   345  	}
   346  	// Account settings
   347  	UnlockedAccountFlag = cli.StringFlag{
   348  		Name:  "unlock",
   349  		Usage: "Comma separated list of accounts to unlock",
   350  		Value: "",
   351  	}
   352  	PasswordFileFlag = cli.StringFlag{
   353  		Name:  "password",
   354  		Usage: "Password file to use for non-interactive password input",
   355  		Value: "",
   356  	}
   357  
   358  	VMEnableDebugFlag = cli.BoolFlag{
   359  		Name:  "vmdebug",
   360  		Usage: "Record information useful for VM and contract debugging",
   361  	}
   362  	// Logging and debug settings
   363  	NetStatsURLFlag = cli.StringFlag{
   364  		Name:  "netstats",
   365  		Usage: "Reporting URL of a netstats service (nodename:secret@host:port)",
   366  	}
   367  	MetricsEnabledFlag = cli.BoolFlag{
   368  		Name:  metrics.MetricsEnabledFlag,
   369  		Usage: "Enable metrics collection and reporting",
   370  	}
   371  	TracingStackdriverFlag = cli.StringFlag{
   372  		Name:  "tracing.stackdriver",
   373  		Usage: "GCP Project ID to enable stackdriver tracing",
   374  	}
   375  	TracingSampleRateFlag = cli.Float64Flag{
   376  		Name:  "tracing.samplerate",
   377  		Usage: "Tracing sample rate",
   378  	}
   379  	FakePoWFlag = cli.BoolFlag{
   380  		Name:  "fakepow",
   381  		Usage: "Disables proof-of-work verification",
   382  	}
   383  	NoCompactionFlag = cli.BoolFlag{
   384  		Name:  "nocompaction",
   385  		Usage: "Disables db compaction after import",
   386  	}
   387  	// RPC settings
   388  	RPCEnabledFlag = cli.BoolFlag{
   389  		Name:  "rpc",
   390  		Usage: "Enable the HTTP-RPC server",
   391  	}
   392  	RPCListenAddrFlag = cli.StringFlag{
   393  		Name:  "rpcaddr",
   394  		Usage: "HTTP-RPC server listening interface",
   395  		Value: node.DefaultHTTPHost,
   396  	}
   397  	RPCPortFlag = cli.IntFlag{
   398  		Name:  "rpcport",
   399  		Usage: "HTTP-RPC server listening port",
   400  		Value: node.DefaultHTTPPort,
   401  	}
   402  	RPCCORSDomainFlag = cli.StringFlag{
   403  		Name:  "rpccorsdomain",
   404  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   405  		Value: "",
   406  	}
   407  	RPCVirtualHostsFlag = cli.StringFlag{
   408  		Name:  "rpcvhosts",
   409  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts global ('*') or subdomain ('*.example.com') wildcards.",
   410  		Value: "localhost",
   411  	}
   412  	RPCApiFlag = cli.StringFlag{
   413  		Name:  "rpcapi",
   414  		Usage: "API's offered over the HTTP-RPC interface",
   415  		Value: "",
   416  	}
   417  	IPCDisabledFlag = cli.BoolFlag{
   418  		Name:  "ipcdisable",
   419  		Usage: "Disable the IPC-RPC server",
   420  	}
   421  	IPCPathFlag = DirectoryFlag{
   422  		Name:  "ipcpath",
   423  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   424  	}
   425  	WSEnabledFlag = cli.BoolFlag{
   426  		Name:  "ws",
   427  		Usage: "Enable the WS-RPC server",
   428  	}
   429  	WSListenAddrFlag = cli.StringFlag{
   430  		Name:  "wsaddr",
   431  		Usage: "WS-RPC server listening interface",
   432  		Value: node.DefaultWSHost,
   433  	}
   434  	WSPortFlag = cli.IntFlag{
   435  		Name:  "wsport",
   436  		Usage: "WS-RPC server listening port",
   437  		Value: node.DefaultWSPort,
   438  	}
   439  	WSApiFlag = cli.StringFlag{
   440  		Name:  "wsapi",
   441  		Usage: "API's offered over the WS-RPC interface",
   442  		Value: "",
   443  	}
   444  	WSAllowedOriginsFlag = cli.StringFlag{
   445  		Name:  "wsorigins",
   446  		Usage: "Origins from which to accept websockets requests",
   447  		Value: "",
   448  	}
   449  	ExecFlag = cli.StringFlag{
   450  		Name:  "exec",
   451  		Usage: "Execute JavaScript statement",
   452  	}
   453  	PreloadJSFlag = cli.StringFlag{
   454  		Name:  "preload",
   455  		Usage: "Comma separated list of JavaScript files to preload into the console",
   456  	}
   457  
   458  	// Network Settings
   459  	MaxPeersFlag = cli.IntFlag{
   460  		Name:  "maxpeers",
   461  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   462  		Value: 25,
   463  	}
   464  	MaxPendingPeersFlag = cli.IntFlag{
   465  		Name:  "maxpendpeers",
   466  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   467  		Value: 0,
   468  	}
   469  	ListenPortFlag = cli.IntFlag{
   470  		Name:  "port",
   471  		Usage: "Network listening port",
   472  		Value: 30303,
   473  	}
   474  	BootnodesFlag = cli.StringFlag{
   475  		Name:  "bootnodes",
   476  		Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
   477  		Value: "",
   478  	}
   479  	BootnodesV4Flag = cli.StringFlag{
   480  		Name:  "bootnodesv4",
   481  		Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
   482  		Value: "",
   483  	}
   484  	BootnodesV5Flag = cli.StringFlag{
   485  		Name:  "bootnodesv5",
   486  		Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
   487  		Value: "",
   488  	}
   489  	NodeKeyFileFlag = cli.StringFlag{
   490  		Name:  "nodekey",
   491  		Usage: "P2P node key file",
   492  	}
   493  	NodeKeyHexFlag = cli.StringFlag{
   494  		Name:  "nodekeyhex",
   495  		Usage: "P2P node key as hex (for testing)",
   496  	}
   497  	NATFlag = cli.StringFlag{
   498  		Name:  "nat",
   499  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   500  		Value: "any",
   501  	}
   502  	NoDiscoverFlag = cli.BoolFlag{
   503  		Name:  "nodiscover",
   504  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   505  	}
   506  	DiscoveryV5Flag = cli.BoolFlag{
   507  		Name:  "v5disc",
   508  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   509  	}
   510  	NetrestrictFlag = cli.StringFlag{
   511  		Name:  "netrestrict",
   512  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   513  	}
   514  
   515  	// ATM the url is left to the user and deployment to
   516  	JSpathFlag = cli.StringFlag{
   517  		Name:  "jspath",
   518  		Usage: "JavaScript root path for `loadScript`",
   519  		Value: ".",
   520  	}
   521  
   522  	// Gas price oracle settings
   523  	GpoBlocksFlag = cli.IntFlag{
   524  		Name:  "gpoblocks",
   525  		Usage: "Number of recent blocks to check for gas prices",
   526  		Value: eth.DefaultConfig.GPO.Blocks,
   527  	}
   528  	GpoPercentileFlag = cli.IntFlag{
   529  		Name:  "gpopercentile",
   530  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   531  		Value: eth.DefaultConfig.GPO.Percentile,
   532  	}
   533  	GpoMaxGasPriceFlag = cli.Int64Flag{
   534  		Name:  "gpomaxprice",
   535  		Usage: "Maximum gas price will be recommended by gpo",
   536  		Value: eth.DefaultConfig.GPO.MaxPrice.Int64(),
   537  	}
   538  	WhisperEnabledFlag = cli.BoolFlag{
   539  		Name:  "shh",
   540  		Usage: "Enable Whisper",
   541  	}
   542  	WhisperMaxMessageSizeFlag = cli.IntFlag{
   543  		Name:  "shh.maxmessagesize",
   544  		Usage: "Max message size accepted",
   545  		Value: int(whisper.DefaultMaxMessageSize),
   546  	}
   547  	WhisperMinPOWFlag = cli.Float64Flag{
   548  		Name:  "shh.pow",
   549  		Usage: "Minimum POW accepted",
   550  		Value: whisper.DefaultMinimumPoW,
   551  	}
   552  
   553  	// S3 archival settings
   554  	EthdbEndpointFlag = cli.StringFlag{
   555  		Name:  "ethdb.endpoint",
   556  		Usage: "S3 compatible archive endpoint.",
   557  	}
   558  	EthdbBucketFlag = cli.StringFlag{
   559  		Name:  "ethdb.bucket",
   560  		Usage: "Name of ethdb archive bucket. Must already exist.",
   561  	}
   562  	EthdbAccessKeyIDFlag = cli.StringFlag{
   563  		Name:  "ethdb.accesskeyid",
   564  		Usage: "Ethdb archive access key ID.",
   565  	}
   566  	EthdbSecretAccessKeyFlag = cli.StringFlag{
   567  		Name:  "ethdb.secretaccesskey",
   568  		Usage: "Ethdb archive secret access key.",
   569  	}
   570  	EthdbMaxOpenSegmentCountFlag = cli.IntFlag{
   571  		Name:  "ethdb.maxopensegmentcount",
   572  		Usage: "Ethdb per-table open segment count.",
   573  	}
   574  
   575  	EWASMInterpreterFlag = cli.StringFlag{
   576  		Name:  "vm.ewasm",
   577  		Usage: "External ewasm configuration (default = built-in interpreter)",
   578  		Value: "",
   579  	}
   580  	EVMInterpreterFlag = cli.StringFlag{
   581  		Name:  "vm.evm",
   582  		Usage: "External EVM configuration (default = built-in interpreter)",
   583  		Value: "",
   584  	}
   585  )
   586  
   587  // MakeDataDir retrieves the currently requested data directory, terminating
   588  // if none (or the empty string) is specified. If the node is starting a testnet,
   589  // the a subdirectory of the specified datadir will be used.
   590  func MakeDataDir(ctx *cli.Context) string {
   591  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   592  		if ctx.GlobalBool(TestnetFlag.Name) {
   593  			return filepath.Join(path, "testnet")
   594  		}
   595  		return path
   596  	}
   597  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   598  	return ""
   599  }
   600  
   601  // setNodeKey creates a node key from set command line flags, either loading it
   602  // from a file or as a specified hex value. If neither flags were provided, this
   603  // method returns nil and an emphemeral key is to be generated.
   604  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   605  	var (
   606  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   607  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   608  		key  *ecdsa.PrivateKey
   609  		err  error
   610  	)
   611  	switch {
   612  	case file != "" && hex != "":
   613  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   614  	case file != "":
   615  		if key, err = crypto.LoadECDSA(file); err != nil {
   616  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   617  		}
   618  		cfg.PrivateKey = key
   619  	case hex != "":
   620  		if key, err = crypto.HexToECDSA(hex); err != nil {
   621  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   622  		}
   623  		cfg.PrivateKey = key
   624  	}
   625  }
   626  
   627  // setNodeUserIdent creates the user identifier from CLI flags.
   628  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   629  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   630  		cfg.UserIdent = identity
   631  	}
   632  }
   633  
   634  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   635  // flags, reverting to pre-configured ones if none have been specified.
   636  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   637  	urls := params.MainnetBootnodes
   638  	switch {
   639  	case ctx.GlobalIsSet(BootnodesFlag.Name):
   640  		urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   641  	case ctx.GlobalBool(TestnetFlag.Name):
   642  		urls = params.TestnetBootnodes
   643  	case cfg.BootstrapNodes != nil:
   644  		return // already set, don't apply defaults.
   645  	}
   646  
   647  	cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls))
   648  	for _, url := range urls {
   649  		node, err := discover.ParseNode(url)
   650  		if err != nil {
   651  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   652  			continue
   653  		}
   654  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   655  	}
   656  }
   657  
   658  // setListenAddress creates a TCP listening address string from set command
   659  // line flags.
   660  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   661  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   662  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   663  	}
   664  }
   665  
   666  // setNAT creates a port mapper from command line flags.
   667  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   668  	if ctx.GlobalIsSet(NATFlag.Name) {
   669  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   670  		if err != nil {
   671  			Fatalf("Option %s: %v", NATFlag.Name, err)
   672  		}
   673  		cfg.NAT = natif
   674  	}
   675  }
   676  
   677  // splitAndTrim splits input separated by a comma
   678  // and trims excessive white space from the substrings.
   679  func splitAndTrim(input string) []string {
   680  	result := strings.Split(input, ",")
   681  	for i, r := range result {
   682  		result[i] = strings.TrimSpace(r)
   683  	}
   684  	return result
   685  }
   686  
   687  // setHTTP creates the HTTP RPC listener interface string from the set
   688  // command line flags, returning empty if the HTTP endpoint is disabled.
   689  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   690  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" || ctx.GlobalBool(LocalFlag.Name) {
   691  		cfg.HTTPHost = "127.0.0.1"
   692  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   693  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   694  		} else if ctx.GlobalBool(LocalFlag.Name) {
   695  			cfg.HTTPHost = "0.0.0.0"
   696  		}
   697  	}
   698  
   699  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   700  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   701  	}
   702  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   703  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   704  	}
   705  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   706  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   707  	}
   708  
   709  	cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
   710  	cfg.HTTPTracing = ctx.GlobalIsSet(TracingStackdriverFlag.Name)
   711  }
   712  
   713  // setWS creates the WebSocket RPC listener interface string from the set
   714  // command line flags, returning empty if the HTTP endpoint is disabled.
   715  func setWS(ctx *cli.Context, cfg *node.Config) {
   716  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" || ctx.GlobalBool(LocalFlag.Name) {
   717  		cfg.WSHost = "127.0.0.1"
   718  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   719  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   720  		} else if ctx.GlobalBool(LocalFlag.Name) {
   721  			cfg.WSHost = "0.0.0.0"
   722  		}
   723  	}
   724  
   725  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   726  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   727  	}
   728  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   729  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   730  	} else if ctx.GlobalBool(LocalFlag.Name) {
   731  		cfg.WSOrigins = []string{"*"}
   732  	}
   733  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   734  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   735  	}
   736  }
   737  
   738  // setIPC creates an IPC path configuration from the set command line flags,
   739  // returning an empty string if IPC was explicitly disabled, or the set path.
   740  func setIPC(ctx *cli.Context, cfg *node.Config) {
   741  	CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   742  	switch {
   743  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   744  		cfg.IPCPath = ""
   745  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   746  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   747  	}
   748  }
   749  
   750  // makeDatabaseHandles raises out the number of allowed file handles per process
   751  // for GoChain and returns half of the allowance to assign to the database.
   752  func makeDatabaseHandles() int {
   753  	limit, err := fdlimit.Current()
   754  	if err != nil {
   755  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   756  	}
   757  	if limit < 2048 {
   758  		if err := fdlimit.Raise(2048); err != nil {
   759  			Fatalf("Failed to raise file descriptor allowance: %v", err)
   760  		}
   761  	}
   762  	if limit > 2048 { // cap database file descriptors even if more is available
   763  		limit = 2048
   764  	}
   765  	return limit / 2 // Leave half for networking and other stuff
   766  }
   767  
   768  // MakeAddress converts an account specified directly as a hex encoded string or
   769  // a key index in the key store to an internal account representation.
   770  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   771  	// If the specified account is a valid address, return it
   772  	if common.IsHexAddress(account) {
   773  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   774  	}
   775  	// Otherwise try to interpret the account as a keystore index
   776  	index, err := strconv.Atoi(account)
   777  	if err != nil || index < 0 {
   778  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   779  	}
   780  	log.Warn("-------------------------------------------------------------------")
   781  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   782  	log.Warn("This functionality is deprecated and will be removed in the future!")
   783  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   784  	log.Warn("-------------------------------------------------------------------")
   785  
   786  	accs := ks.Accounts()
   787  	if len(accs) <= index {
   788  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   789  	}
   790  	return accs[index], nil
   791  }
   792  
   793  // setEtherbase retrieves the etherbase either from the directly specified
   794  // command line flags or from the keystore if CLI indexed.
   795  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
   796  	// Extract the current etherbase, new flag overriding legacy one
   797  	var etherbase string
   798  	if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) {
   799  		etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name)
   800  	}
   801  	if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) {
   802  		etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name)
   803  	}
   804  	// Convert the etherbase into an address and configure it
   805  	if etherbase != "" {
   806  		account, err := MakeAddress(ks, etherbase)
   807  		if err != nil {
   808  			Fatalf("Invalid miner etherbase: %v", err)
   809  		}
   810  		cfg.Etherbase = account.Address
   811  	}
   812  }
   813  
   814  // MakePasswordList reads password lines from the file specified by the global --password flag.
   815  func MakePasswordList(ctx *cli.Context) []string {
   816  	path := ctx.GlobalString(PasswordFileFlag.Name)
   817  	if path == "" {
   818  		return nil
   819  	}
   820  	text, err := ioutil.ReadFile(path)
   821  	if err != nil {
   822  		Fatalf("Failed to read password file: %v", err)
   823  	}
   824  	lines := strings.Split(string(text), "\n")
   825  	// Sanitise DOS line endings.
   826  	for i := range lines {
   827  		lines[i] = strings.TrimRight(lines[i], "\r")
   828  	}
   829  	return lines
   830  }
   831  
   832  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   833  	setNodeKey(ctx, cfg)
   834  	setNAT(ctx, cfg)
   835  	setListenAddress(ctx, cfg)
   836  	setBootstrapNodes(ctx, cfg)
   837  
   838  	lightClient := ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalString(SyncModeFlag.Name) == "light"
   839  	lightServer := ctx.GlobalInt(LightServFlag.Name) != 0
   840  	lightPeers := ctx.GlobalInt(LightPeersFlag.Name)
   841  
   842  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   843  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   844  	} else {
   845  		if lightServer {
   846  			cfg.MaxPeers += lightPeers
   847  		}
   848  		if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers {
   849  			cfg.MaxPeers = lightPeers
   850  		}
   851  	}
   852  	if !(lightClient || lightServer) {
   853  		lightPeers = 0
   854  	}
   855  	ethPeers := cfg.MaxPeers - lightPeers
   856  	if lightClient {
   857  		ethPeers = 0
   858  	}
   859  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
   860  
   861  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   862  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   863  	}
   864  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
   865  		cfg.NoDiscovery = true
   866  	}
   867  
   868  	// if we're running a light client or server, force enable the v5 peer discovery
   869  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   870  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   871  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   872  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   873  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   874  	} else if forceV5Discovery {
   875  		cfg.DiscoveryV5 = true
   876  	}
   877  
   878  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   879  		list, err := netutil.ParseNetlist(netrestrict)
   880  		if err != nil {
   881  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   882  		}
   883  		cfg.NetRestrict = list
   884  	}
   885  
   886  	if ctx.GlobalBool(DeveloperFlag.Name) || ctx.GlobalBool(LocalFlag.Name) {
   887  		// --dev mode can't use p2p networking.
   888  		cfg.MaxPeers = 0
   889  		cfg.ListenAddr = ":0"
   890  		cfg.NoDiscovery = true
   891  		cfg.DiscoveryV5 = false
   892  	}
   893  }
   894  
   895  // SetNodeConfig applies node-related command line flags to the config.
   896  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   897  	SetP2PConfig(ctx, &cfg.P2P)
   898  	setIPC(ctx, cfg)
   899  	setHTTP(ctx, cfg)
   900  	setWS(ctx, cfg)
   901  	setNodeUserIdent(ctx, cfg)
   902  	setEthdb(ctx, &cfg.Ethdb)
   903  
   904  	switch {
   905  	case ctx.GlobalIsSet(DataDirFlag.Name):
   906  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
   907  	case ctx.GlobalBool(DeveloperFlag.Name):
   908  		cfg.DataDir = "" // unless explicitly requested, use memory databases
   909  	case ctx.GlobalBool(LocalFlag.Name):
   910  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "local")
   911  	case ctx.GlobalBool(TestnetFlag.Name):
   912  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
   913  	}
   914  
   915  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
   916  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
   917  	}
   918  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
   919  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
   920  	}
   921  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
   922  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
   923  	}
   924  }
   925  
   926  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
   927  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
   928  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
   929  	}
   930  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
   931  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
   932  	}
   933  	if ctx.GlobalIsSet(GpoMaxGasPriceFlag.Name) {
   934  		cfg.MaxPrice = big.NewInt(ctx.GlobalInt64(GpoMaxGasPriceFlag.Name))
   935  	}
   936  }
   937  
   938  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
   939  	if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) {
   940  		locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",")
   941  		for _, account := range locals {
   942  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
   943  				Fatalf("Invalid account in --txpool.locals: %s", trimmed)
   944  			} else {
   945  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
   946  			}
   947  		}
   948  	}
   949  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
   950  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
   951  	}
   952  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
   953  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
   954  	}
   955  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
   956  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
   957  	}
   958  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
   959  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
   960  	}
   961  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
   962  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
   963  	}
   964  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
   965  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
   966  	}
   967  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
   968  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
   969  	}
   970  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
   971  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
   972  	}
   973  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
   974  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
   975  	}
   976  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
   977  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
   978  	}
   979  }
   980  
   981  func setEthdb(ctx *cli.Context, cfg *ethdb.Config) {
   982  	if ctx.GlobalIsSet(EthdbEndpointFlag.Name) {
   983  		cfg.Endpoint = ctx.GlobalString(EthdbEndpointFlag.Name)
   984  	}
   985  	if ctx.GlobalIsSet(EthdbBucketFlag.Name) {
   986  		cfg.Bucket = ctx.GlobalString(EthdbBucketFlag.Name)
   987  	}
   988  	if ctx.GlobalIsSet(EthdbAccessKeyIDFlag.Name) {
   989  		cfg.AccessKeyID = ctx.GlobalString(EthdbAccessKeyIDFlag.Name)
   990  	}
   991  	if ctx.GlobalIsSet(EthdbSecretAccessKeyFlag.Name) {
   992  		cfg.SecretAccessKey = ctx.GlobalString(EthdbSecretAccessKeyFlag.Name)
   993  	}
   994  	if ctx.GlobalIsSet(EthdbMaxOpenSegmentCountFlag.Name) {
   995  		cfg.MaxOpenSegmentCount = ctx.GlobalInt(EthdbMaxOpenSegmentCountFlag.Name)
   996  	}
   997  }
   998  
   999  // CheckExclusive verifies that only a single instance of the provided flags was
  1000  // set by the user. Each flag might optionally be followed by a string type to
  1001  // specialize it further.
  1002  func CheckExclusive(ctx *cli.Context, args ...interface{}) {
  1003  	set := make([]string, 0, 1)
  1004  	for i := 0; i < len(args); i++ {
  1005  		// Make sure the next argument is a flag and skip if not set
  1006  		flag, ok := args[i].(cli.Flag)
  1007  		if !ok {
  1008  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1009  		}
  1010  		// Check if next arg extends current and expand its name if so
  1011  		name := flag.GetName()
  1012  
  1013  		if i+1 < len(args) {
  1014  			switch option := args[i+1].(type) {
  1015  			case string:
  1016  				// Extended flag check, make sure value set doesn't conflict with passed in option
  1017  				if ctx.GlobalString(flag.GetName()) == option {
  1018  					name += "=" + option
  1019  					set = append(set, "--"+name)
  1020  				}
  1021  				// shift arguments and continue
  1022  				i++
  1023  				continue
  1024  
  1025  			case cli.Flag:
  1026  			default:
  1027  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1028  			}
  1029  		}
  1030  		// Mark the flag if it's set
  1031  		if ctx.GlobalIsSet(flag.GetName()) {
  1032  			set = append(set, "--"+name)
  1033  		}
  1034  	}
  1035  	if len(set) > 1 {
  1036  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1037  	}
  1038  }
  1039  
  1040  // SetShhConfig applies shh-related command line flags to the config.
  1041  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
  1042  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
  1043  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
  1044  	}
  1045  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
  1046  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
  1047  	}
  1048  }
  1049  
  1050  // SetEthConfig applies eth-related command line flags to the config.
  1051  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
  1052  	// Avoid conflicting network flags
  1053  	CheckExclusive(ctx, DeveloperFlag, TestnetFlag, LocalFlag)
  1054  	CheckExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag)
  1055  	CheckExclusive(ctx, LightServFlag, LightModeFlag)
  1056  	CheckExclusive(ctx, LightServFlag, SyncModeFlag, "light")
  1057  
  1058  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
  1059  	setEtherbase(ctx, ks, cfg)
  1060  	setGPO(ctx, &cfg.GPO)
  1061  	setTxPool(ctx, &cfg.TxPool)
  1062  
  1063  	switch {
  1064  	case ctx.GlobalIsSet(SyncModeFlag.Name):
  1065  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1066  	case ctx.GlobalBool(FastSyncFlag.Name):
  1067  		cfg.SyncMode = downloader.FastSync
  1068  	case ctx.GlobalBool(LightModeFlag.Name):
  1069  		cfg.SyncMode = downloader.LightSync
  1070  	}
  1071  	if ctx.GlobalIsSet(LightServFlag.Name) {
  1072  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
  1073  	}
  1074  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
  1075  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
  1076  	}
  1077  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1078  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1079  	}
  1080  
  1081  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
  1082  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1083  	}
  1084  	cfg.DatabaseHandles = makeDatabaseHandles()
  1085  
  1086  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1087  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1088  	}
  1089  	cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
  1090  
  1091  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1092  		cfg.TrieCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1093  	}
  1094  	if ctx.GlobalIsSet(MinerNotifyFlag.Name) {
  1095  		cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",")
  1096  	}
  1097  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1098  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1099  	}
  1100  	if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) {
  1101  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name))
  1102  	}
  1103  	if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
  1104  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
  1105  	}
  1106  	if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) {
  1107  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name)
  1108  	}
  1109  	if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
  1110  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
  1111  	}
  1112  	if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
  1113  		cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
  1114  	}
  1115  	if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1116  		cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name)
  1117  	}
  1118  	if ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
  1119  		cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name)
  1120  	}
  1121  	if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) {
  1122  		cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
  1123  	}
  1124  	if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
  1125  		cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name)
  1126  	}
  1127  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1128  		// TODO(fjl): force-enable this in --dev mode
  1129  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1130  	}
  1131  
  1132  	// Override any default configs for hard coded networks.
  1133  	switch {
  1134  	case ctx.GlobalBool(TestnetFlag.Name):
  1135  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1136  			cfg.NetworkId = params.TestnetChainID
  1137  		}
  1138  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1139  	case ctx.GlobalBool(DeveloperFlag.Name):
  1140  		if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1141  			Fatalf("%q cannot be used with %q", NetworkIdFlag.Name, DeveloperFlag.Name)
  1142  		}
  1143  		// Create new developer account or reuse existing one
  1144  		var (
  1145  			developer accounts.Account
  1146  			err       error
  1147  		)
  1148  		if accs := ks.Accounts(); len(accs) > 0 {
  1149  			developer = ks.Accounts()[0]
  1150  		} else {
  1151  			developer, err = ks.NewAccount("")
  1152  			if err != nil {
  1153  				Fatalf("Failed to create developer account: %v", err)
  1154  			}
  1155  		}
  1156  		if err := ks.Unlock(developer, ""); err != nil {
  1157  			Fatalf("Failed to unlock developer account: %v", err)
  1158  		}
  1159  
  1160  		log.Info("Using developer account", "address", developer.Address)
  1161  
  1162  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1163  		cfg.NetworkId = cfg.Genesis.Config.ChainId.Uint64()
  1164  		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1165  			cfg.MinerGasPrice = big.NewInt(1)
  1166  		}
  1167  	case ctx.GlobalBool(LocalFlag.Name):
  1168  		if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1169  			Fatalf("%q cannot be used with %q", NetworkIdFlag.Name, LocalFlag.Name)
  1170  		}
  1171  		if GenesisExists(ctx, stack) {
  1172  			accs := ks.Accounts()
  1173  			if len(accs) == 0 {
  1174  				Fatalf("Genesis exists but keystore is empty")
  1175  			}
  1176  			if err := ks.Unlock(accs[0], ""); err != nil {
  1177  				Fatalf("Failed to unlock signer account %q: %v", cfg.Etherbase, err)
  1178  			}
  1179  			break
  1180  		}
  1181  
  1182  		var (
  1183  			signer accounts.Account
  1184  			err    error
  1185  		)
  1186  		if accs := ks.Accounts(); len(accs) > 0 {
  1187  			signer = ks.Accounts()[0]
  1188  		} else {
  1189  			signer, err = ks.NewAccount("")
  1190  			if err != nil {
  1191  				Fatalf("Failed to create signer account: %v", err)
  1192  			}
  1193  		}
  1194  		if err := ks.Unlock(signer, ""); err != nil {
  1195  			Fatalf("Failed to unlock signer account: %v", err)
  1196  		}
  1197  		log.Info("Signing with account", "address", signer.Address)
  1198  
  1199  		oneGO, ok := new(big.Int).SetString("1000000000000000000", 10)
  1200  		if !ok {
  1201  			panic("failed to parse big.Int string")
  1202  		}
  1203  		oneThousandGO := new(big.Int).Mul(big.NewInt(1000), oneGO)
  1204  
  1205  		alloc := make(core.GenesisAlloc)
  1206  		seedStrs := ctx.GlobalStringSlice(LocalFundFlag.Name)
  1207  		if len(seedStrs) > 0 {
  1208  			for _, seed := range seedStrs {
  1209  				parts := strings.Split(seed, ":")
  1210  				if len(parts) > 2 {
  1211  					Fatalf("invalid seed format %q: expected <addr> or <addr>:<amount>")
  1212  				}
  1213  
  1214  				if !common.IsHexAddress(parts[0]) {
  1215  					Fatalf("Failed to parse hex address: %s", parts[0])
  1216  				}
  1217  				addr := common.HexToAddress(parts[0])
  1218  
  1219  				var amount *big.Int
  1220  				if len(parts) == 2 {
  1221  					a, ok := new(big.Int).SetString(parts[1], 10)
  1222  					if !ok {
  1223  						Fatalf("failed to parse seed amount: %s", parts[1])
  1224  					}
  1225  					amount = a.Mul(a, oneGO)
  1226  				} else {
  1227  					amount = oneThousandGO
  1228  				}
  1229  
  1230  				alloc[addr] = core.GenesisAccount{Balance: amount}
  1231  			}
  1232  		} else {
  1233  			keys := make(map[common.Address]string)
  1234  			for i := 0; i < 10; i++ {
  1235  				acc, err := crypto.CreateKey()
  1236  				if err != nil {
  1237  					Fatalf("Failed to create account: %v", err)
  1238  				}
  1239  				addr := crypto.PubkeyToAddress(acc.PrivateKey().PublicKey)
  1240  				alloc[addr] = core.GenesisAccount{Balance: oneThousandGO}
  1241  				keys[addr] = acc.PrivateKeyHex()
  1242  			}
  1243  
  1244  			var buf bytes.Buffer
  1245  			fmt.Fprintln(&buf, "Pre-funded accounts:")
  1246  			fmt.Fprintln(&buf)
  1247  			fmt.Fprintln(&buf, "\tAddress\t\t\t\t\t\tKey")
  1248  			for addr, key := range keys {
  1249  				fmt.Fprintf(&buf, "\t%s %s\n", addr.Hex(), key)
  1250  			}
  1251  			log.Info(buf.String())
  1252  		}
  1253  
  1254  		cfg.Genesis = core.LocalGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), signer.Address, alloc)
  1255  		cfg.NetworkId = cfg.Genesis.Config.ChainId.Uint64()
  1256  		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1257  			cfg.MinerGasPrice = big.NewInt(1)
  1258  		}
  1259  	}
  1260  	// TODO(fjl): move trie cache generations into config
  1261  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1262  		state.MaxTrieCacheGen = uint16(gen)
  1263  	}
  1264  }
  1265  
  1266  func GenesisExists(ctx *cli.Context, stack *node.Node) bool {
  1267  	db := MakeChainDatabase(ctx, stack)
  1268  	defer db.Close()
  1269  	stored := rawdb.ReadCanonicalHash(db, 0)
  1270  	return stored != common.Hash{}
  1271  }
  1272  
  1273  // RegisterEthService adds an GoChain client to the stack.
  1274  func RegisterEthService(ctx context.Context, stack *node.Node, cfg *eth.Config) {
  1275  	var err error
  1276  	if cfg.SyncMode == downloader.LightSync {
  1277  		err = stack.Register(func(sctx *node.ServiceContext) (node.Service, error) {
  1278  			return les.New(ctx, sctx, cfg)
  1279  		})
  1280  	} else {
  1281  		err = stack.Register(func(sctx *node.ServiceContext) (node.Service, error) {
  1282  			fullNode, err := eth.New(sctx, cfg)
  1283  			if fullNode != nil && cfg.LightServ > 0 {
  1284  				ls, _ := les.NewLesServer(fullNode, cfg)
  1285  				fullNode.AddLesServer(ls)
  1286  			}
  1287  			return fullNode, err
  1288  		})
  1289  	}
  1290  	if err != nil {
  1291  		Fatalf("Failed to register the GoChain service: %v", err)
  1292  	}
  1293  }
  1294  
  1295  // RegisterShhService configures Whisper and adds it to the given node.
  1296  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1297  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1298  		return whisper.New(cfg), nil
  1299  	}); err != nil {
  1300  		Fatalf("Failed to register the Whisper service: %v", err)
  1301  	}
  1302  }
  1303  
  1304  // RegisterNetStatsService configures the GoChain Stats daemon and adds it to
  1305  // the given node.
  1306  func RegisterNetStatsService(stack *node.Node, cfg netstats.Config) {
  1307  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1308  		// Retrieve both eth and les services
  1309  		var ethServ *eth.GoChain
  1310  		ctx.Service(&ethServ)
  1311  
  1312  		var lesServ *les.LightGoChain
  1313  		ctx.Service(&lesServ)
  1314  
  1315  		return netstats.New(cfg, ethServ, lesServ), nil
  1316  	}); err != nil {
  1317  		Fatalf("Failed to register the GoChain Stats service: %v", err)
  1318  	}
  1319  }
  1320  
  1321  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1322  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) common.Database {
  1323  	var (
  1324  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1325  		handles = makeDatabaseHandles()
  1326  	)
  1327  	name := "chaindata"
  1328  	if ctx.GlobalBool(LightModeFlag.Name) {
  1329  		name = "lightchaindata"
  1330  	}
  1331  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1332  	if err != nil {
  1333  		Fatalf("Could not open database: %v", err)
  1334  	}
  1335  	return chainDb
  1336  }
  1337  
  1338  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1339  	var genesis *core.Genesis
  1340  	switch {
  1341  	case ctx.GlobalBool(TestnetFlag.Name):
  1342  		genesis = core.DefaultTestnetGenesisBlock()
  1343  	case ctx.GlobalBool(DeveloperFlag.Name):
  1344  		Fatalf("Developer chains are ephemeral")
  1345  	case ctx.GlobalBool(LocalFlag.Name):
  1346  		Fatalf("Local chains not supported")
  1347  	default:
  1348  		genesis = core.DefaultGenesisBlock()
  1349  	}
  1350  	return genesis
  1351  }
  1352  
  1353  // MakeChain creates a chain manager from set command line flags.
  1354  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb common.Database) {
  1355  	var err error
  1356  	chainDb = MakeChainDatabase(ctx, stack)
  1357  
  1358  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1359  	if err != nil {
  1360  		Fatalf("%v", err)
  1361  	}
  1362  	var engine consensus.Engine
  1363  	if config.Clique != nil {
  1364  		engine = clique.New(config.Clique, chainDb)
  1365  	} else {
  1366  		panic(fmt.Errorf("illegal config, nil clique: %s", config))
  1367  	}
  1368  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1369  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1370  	}
  1371  	cache := &core.CacheConfig{
  1372  		Disabled:      ctx.GlobalString(GCModeFlag.Name) == "archive",
  1373  		TrieNodeLimit: eth.DefaultConfig.TrieCache,
  1374  		TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
  1375  	}
  1376  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1377  		cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1378  	}
  1379  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1380  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg)
  1381  	if err != nil {
  1382  		Fatalf("Can't create BlockChain: %v", err)
  1383  	}
  1384  	return chain, chainDb
  1385  }
  1386  
  1387  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1388  // scripts to preload before starting.
  1389  func MakeConsolePreloads(ctx *cli.Context) []string {
  1390  	// Skip preloading if there's nothing to preload
  1391  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1392  		return nil
  1393  	}
  1394  	// Otherwise resolve absolute paths and return them
  1395  	preloads := []string{}
  1396  
  1397  	assets := ctx.GlobalString(JSpathFlag.Name)
  1398  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1399  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1400  	}
  1401  	return preloads
  1402  }
  1403  
  1404  // MigrateFlags sets the global flag from a local flag when it's set.
  1405  // This is a temporary function used for migrating old command/flags to the
  1406  // new format.
  1407  //
  1408  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1409  //
  1410  // is equivalent after calling this method with:
  1411  //
  1412  // geth --keystore /tmp/mykeystore --lightkdf account new
  1413  //
  1414  // This allows the use of the existing configuration functionality.
  1415  // When all flags are migrated this function can be removed and the existing
  1416  // configuration functionality must be changed that is uses local flags
  1417  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1418  	return func(ctx *cli.Context) error {
  1419  		for _, name := range ctx.FlagNames() {
  1420  			if ctx.IsSet(name) {
  1421  				ctx.GlobalSet(name, ctx.String(name))
  1422  			}
  1423  		}
  1424  		return action(ctx)
  1425  	}
  1426  }