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