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