github.com/newbtp/btp@v0.0.0-20190709081714-e4aafa07224e/cmd/utils/flags.go (about)

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