github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/internal/cli/server/config.go (about)

     1  package server
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math"
     8  	"math/big"
     9  	"os"
    10  	"path/filepath"
    11  	"runtime"
    12  	"strconv"
    13  	"strings"
    14  	"time"
    15  
    16  	godebug "runtime/debug"
    17  
    18  	"github.com/hashicorp/hcl/v2/hclsimple"
    19  	"github.com/imdario/mergo"
    20  	"github.com/mitchellh/go-homedir"
    21  	gopsutil "github.com/shirou/gopsutil/mem"
    22  
    23  	"github.com/ethereum/go-ethereum/accounts"
    24  	"github.com/ethereum/go-ethereum/accounts/keystore"
    25  	"github.com/ethereum/go-ethereum/cmd/utils"
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/common/fdlimit"
    28  	"github.com/ethereum/go-ethereum/crypto"
    29  	"github.com/ethereum/go-ethereum/eth/downloader"
    30  	"github.com/ethereum/go-ethereum/eth/ethconfig"
    31  	"github.com/ethereum/go-ethereum/eth/gasprice"
    32  	"github.com/ethereum/go-ethereum/internal/cli/server/chains"
    33  	"github.com/ethereum/go-ethereum/log"
    34  	"github.com/ethereum/go-ethereum/node"
    35  	"github.com/ethereum/go-ethereum/p2p"
    36  	"github.com/ethereum/go-ethereum/p2p/enode"
    37  	"github.com/ethereum/go-ethereum/p2p/nat"
    38  	"github.com/ethereum/go-ethereum/p2p/netutil"
    39  	"github.com/ethereum/go-ethereum/params"
    40  	"github.com/ethereum/go-ethereum/rpc"
    41  )
    42  
    43  type Config struct {
    44  	chain *chains.Chain
    45  
    46  	// Chain is the chain to sync with
    47  	Chain string `hcl:"chain,optional" toml:"chain,optional"`
    48  
    49  	// Identity of the node
    50  	Identity string `hcl:"identity,optional" toml:"identity,optional"`
    51  
    52  	// RequiredBlocks is a list of required (block number, hash) pairs to accept
    53  	RequiredBlocks map[string]string `hcl:"eth.requiredblocks,optional" toml:"eth.requiredblocks,optional"`
    54  
    55  	// Verbosity is the level of the logs to put out
    56  	Verbosity int `hcl:"verbosity,optional" toml:"verbosity,optional"`
    57  
    58  	// LogLevel is the level of the logs to put out
    59  	LogLevel string `hcl:"log-level,optional" toml:"log-level,optional"`
    60  
    61  	// Record information useful for VM and contract debugging
    62  	EnablePreimageRecording bool `hcl:"vmdebug,optional" toml:"vmdebug,optional"`
    63  
    64  	// DataDir is the directory to store the state in
    65  	DataDir string `hcl:"datadir,optional" toml:"datadir,optional"`
    66  
    67  	// Ancient is the directory to store the state in
    68  	Ancient string `hcl:"ancient,optional" toml:"ancient,optional"`
    69  
    70  	// KeyStoreDir is the directory to store keystores
    71  	KeyStoreDir string `hcl:"keystore,optional" toml:"keystore,optional"`
    72  
    73  	// Maximum number of messages in a batch (default=100, use 0 for no limits)
    74  	RPCBatchLimit uint64 `hcl:"rpc.batchlimit,optional" toml:"rpc.batchlimit,optional"`
    75  
    76  	// Maximum size (in bytes) a result of an rpc request could have (default=100000, use 0 for no limits)
    77  	RPCReturnDataLimit uint64 `hcl:"rpc.returndatalimit,optional" toml:"rpc.returndatalimit,optional"`
    78  
    79  	// SyncMode selects the sync protocol
    80  	SyncMode string `hcl:"syncmode,optional" toml:"syncmode,optional"`
    81  
    82  	// GcMode selects the garbage collection mode for the trie
    83  	GcMode string `hcl:"gcmode,optional" toml:"gcmode,optional"`
    84  
    85  	// Snapshot enables the snapshot database mode
    86  	Snapshot bool `hcl:"snapshot,optional" toml:"snapshot,optional"`
    87  
    88  	// BorLogs enables bor log retrieval
    89  	BorLogs bool `hcl:"bor.logs,optional" toml:"bor.logs,optional"`
    90  
    91  	// Ethstats is the address of the ethstats server to send telemetry
    92  	Ethstats string `hcl:"ethstats,optional" toml:"ethstats,optional"`
    93  
    94  	// Logging has the logging related settings
    95  	Logging *LoggingConfig `hcl:"log,block" toml:"log,block"`
    96  
    97  	// P2P has the p2p network related settings
    98  	P2P *P2PConfig `hcl:"p2p,block" toml:"p2p,block"`
    99  
   100  	// Heimdall has the heimdall connection related settings
   101  	Heimdall *HeimdallConfig `hcl:"heimdall,block" toml:"heimdall,block"`
   102  
   103  	// TxPool has the transaction pool related settings
   104  	TxPool *TxPoolConfig `hcl:"txpool,block" toml:"txpool,block"`
   105  
   106  	// Sealer has the validator related settings
   107  	Sealer *SealerConfig `hcl:"miner,block" toml:"miner,block"`
   108  
   109  	// JsonRPC has the json-rpc related settings
   110  	JsonRPC *JsonRPCConfig `hcl:"jsonrpc,block" toml:"jsonrpc,block"`
   111  
   112  	// Gpo has the gas price oracle related settings
   113  	Gpo *GpoConfig `hcl:"gpo,block" toml:"gpo,block"`
   114  
   115  	// Telemetry has the telemetry related settings
   116  	Telemetry *TelemetryConfig `hcl:"telemetry,block" toml:"telemetry,block"`
   117  
   118  	// Cache has the cache related settings
   119  	Cache *CacheConfig `hcl:"cache,block" toml:"cache,block"`
   120  
   121  	// Account has the validator account related settings
   122  	Accounts *AccountsConfig `hcl:"accounts,block" toml:"accounts,block"`
   123  
   124  	// GRPC has the grpc server related settings
   125  	GRPC *GRPCConfig `hcl:"grpc,block" toml:"grpc,block"`
   126  
   127  	// Developer has the developer mode related settings
   128  	Developer *DeveloperConfig `hcl:"developer,block" toml:"developer,block"`
   129  
   130  	// ParallelEVM has the parallel evm related settings
   131  	ParallelEVM *ParallelEVMConfig `hcl:"parallelevm,block" toml:"parallelevm,block"`
   132  
   133  	// Develop Fake Author mode to produce blocks without authorisation
   134  	DevFakeAuthor bool `hcl:"devfakeauthor,optional" toml:"devfakeauthor,optional"`
   135  
   136  	// Pprof has the pprof related settings
   137  	Pprof *PprofConfig `hcl:"pprof,block" toml:"pprof,block"`
   138  }
   139  
   140  type LoggingConfig struct {
   141  	// Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)
   142  	Vmodule string `hcl:"vmodule,optional" toml:"vmodule,optional"`
   143  
   144  	// Format logs with JSON
   145  	Json bool `hcl:"json,optional" toml:"json,optional"`
   146  
   147  	// Request a stack trace at a specific logging statement (e.g. "block.go:271")
   148  	Backtrace string `hcl:"backtrace,optional" toml:"backtrace,optional"`
   149  
   150  	// Prepends log messages with call-site location (file and line number)
   151  	Debug bool `hcl:"debug,optional" toml:"debug,optional"`
   152  
   153  	// TODO - implement this
   154  	// // Write execution trace to the given file
   155  	// Trace string `hcl:"trace,optional" toml:"trace,optional"`
   156  }
   157  
   158  type PprofConfig struct {
   159  	// Enableed enable the pprof HTTP server
   160  	Enabled bool `hcl:"pprof,optional" toml:"pprof,optional"`
   161  
   162  	// pprof HTTP server listening port
   163  	Port int `hcl:"port,optional" toml:"port,optional"`
   164  
   165  	// pprof HTTP server listening interface
   166  	Addr string `hcl:"addr,optional" toml:"addr,optional"`
   167  
   168  	// Turn on memory profiling with the given rate
   169  	MemProfileRate int `hcl:"memprofilerate,optional" toml:"memprofilerate,optional"`
   170  
   171  	// Turn on block profiling with the given rate
   172  	BlockProfileRate int `hcl:"blockprofilerate,optional" toml:"blockprofilerate,optional"`
   173  
   174  	// // Write CPU profile to the given file
   175  	// CPUProfile string `hcl:"cpuprofile,optional" toml:"cpuprofile,optional"`
   176  }
   177  
   178  type P2PConfig struct {
   179  	// MaxPeers sets the maximum number of connected peers
   180  	MaxPeers uint64 `hcl:"maxpeers,optional" toml:"maxpeers,optional"`
   181  
   182  	// MaxPendPeers sets the maximum number of pending connected peers
   183  	MaxPendPeers uint64 `hcl:"maxpendpeers,optional" toml:"maxpendpeers,optional"`
   184  
   185  	// Bind is the bind address
   186  	Bind string `hcl:"bind,optional" toml:"bind,optional"`
   187  
   188  	// Port is the port number
   189  	Port uint64 `hcl:"port,optional" toml:"port,optional"`
   190  
   191  	// NoDiscover is used to disable discovery
   192  	NoDiscover bool `hcl:"nodiscover,optional" toml:"nodiscover,optional"`
   193  
   194  	// NAT it used to set NAT options
   195  	NAT string `hcl:"nat,optional" toml:"nat,optional"`
   196  
   197  	// Connectivity can be restricted to certain IP networks.
   198  	// If this option is set to a non-nil value, only hosts which match one of the
   199  	// IP networks contained in the list are considered.
   200  	NetRestrict string `hcl:"netrestrict,optional" toml:"netrestrict,optional"`
   201  
   202  	// P2P node key file
   203  	NodeKey string `hcl:"nodekey,optional" toml:"nodekey,optional"`
   204  
   205  	// P2P node key as hex
   206  	NodeKeyHex string `hcl:"nodekeyhex,optional" toml:"nodekeyhex,optional"`
   207  
   208  	// Discovery has the p2p discovery related settings
   209  	Discovery *P2PDiscovery `hcl:"discovery,block" toml:"discovery,block"`
   210  
   211  	// TxArrivalWait sets the maximum duration the transaction fetcher will wait for
   212  	// an announced transaction to arrive before explicitly requesting it
   213  	TxArrivalWait    time.Duration `hcl:"-,optional" toml:"-"`
   214  	TxArrivalWaitRaw string        `hcl:"txarrivalwait,optional" toml:"txarrivalwait,optional"`
   215  }
   216  
   217  type P2PDiscovery struct {
   218  	// V5Enabled is used to enable disc v5 discovery mode
   219  	V5Enabled bool `hcl:"v5disc,optional" toml:"v5disc,optional"`
   220  
   221  	// Bootnodes is the list of initial bootnodes
   222  	Bootnodes []string `hcl:"bootnodes,optional" toml:"bootnodes,optional"`
   223  
   224  	// BootnodesV4 is the list of initial v4 bootnodes
   225  	BootnodesV4 []string `hcl:"bootnodesv4,optional" toml:"bootnodesv4,optional"`
   226  
   227  	// BootnodesV5 is the list of initial v5 bootnodes
   228  	BootnodesV5 []string `hcl:"bootnodesv5,optional" toml:"bootnodesv5,optional"`
   229  
   230  	// StaticNodes is the list of static nodes
   231  	StaticNodes []string `hcl:"static-nodes,optional" toml:"static-nodes,optional"`
   232  
   233  	// TrustedNodes is the list of trusted nodes
   234  	TrustedNodes []string `hcl:"trusted-nodes,optional" toml:"trusted-nodes,optional"`
   235  
   236  	// DNS is the list of enrtree:// URLs which will be queried for nodes to connect to
   237  	DNS []string `hcl:"dns,optional" toml:"dns,optional"`
   238  }
   239  
   240  type HeimdallConfig struct {
   241  	// URL is the url of the heimdall server
   242  	URL string `hcl:"url,optional" toml:"url,optional"`
   243  
   244  	// Without is used to disable remote heimdall during testing
   245  	Without bool `hcl:"bor.without,optional" toml:"bor.without,optional"`
   246  
   247  	// GRPCAddress is the address of the heimdall grpc server
   248  	GRPCAddress string `hcl:"grpc-address,optional" toml:"grpc-address,optional"`
   249  
   250  	// RunHeimdall is used to run heimdall as a child process
   251  	RunHeimdall bool `hcl:"bor.runheimdall,optional" toml:"bor.runheimdall,optional"`
   252  
   253  	// RunHeimdal args are the arguments to run heimdall with
   254  	RunHeimdallArgs string `hcl:"bor.runheimdallargs,optional" toml:"bor.runheimdallargs,optional"`
   255  
   256  	// UseHeimdallApp is used to fetch data from heimdall app when running heimdall as a child process
   257  	UseHeimdallApp bool `hcl:"bor.useheimdallapp,optional" toml:"bor.useheimdallapp,optional"`
   258  }
   259  
   260  type TxPoolConfig struct {
   261  	// Locals are the addresses that should be treated by default as local
   262  	Locals []string `hcl:"locals,optional" toml:"locals,optional"`
   263  
   264  	// NoLocals enables whether local transaction handling should be disabled
   265  	NoLocals bool `hcl:"nolocals,optional" toml:"nolocals,optional"`
   266  
   267  	// Journal is the path to store local transactions to survive node restarts
   268  	Journal string `hcl:"journal,optional" toml:"journal,optional"`
   269  
   270  	// Rejournal is the time interval to regenerate the local transaction journal
   271  	Rejournal    time.Duration `hcl:"-,optional" toml:"-"`
   272  	RejournalRaw string        `hcl:"rejournal,optional" toml:"rejournal,optional"`
   273  
   274  	// PriceLimit is the minimum gas price to enforce for acceptance into the pool
   275  	PriceLimit uint64 `hcl:"pricelimit,optional" toml:"pricelimit,optional"`
   276  
   277  	// PriceBump is the minimum price bump percentage to replace an already existing transaction (nonce)
   278  	PriceBump uint64 `hcl:"pricebump,optional" toml:"pricebump,optional"`
   279  
   280  	// AccountSlots is the number of executable transaction slots guaranteed per account
   281  	AccountSlots uint64 `hcl:"accountslots,optional" toml:"accountslots,optional"`
   282  
   283  	// GlobalSlots is the maximum number of executable transaction slots for all accounts
   284  	GlobalSlots uint64 `hcl:"globalslots,optional" toml:"globalslots,optional"`
   285  
   286  	// AccountQueue is the maximum number of non-executable transaction slots permitted per account
   287  	AccountQueue uint64 `hcl:"accountqueue,optional" toml:"accountqueue,optional"`
   288  
   289  	// GlobalQueueis the maximum number of non-executable transaction slots for all accounts
   290  	GlobalQueue uint64 `hcl:"globalqueue,optional" toml:"globalqueue,optional"`
   291  
   292  	// lifetime is the maximum amount of time non-executable transaction are queued
   293  	LifeTime    time.Duration `hcl:"-,optional" toml:"-"`
   294  	LifeTimeRaw string        `hcl:"lifetime,optional" toml:"lifetime,optional"`
   295  }
   296  
   297  type SealerConfig struct {
   298  	// Enabled is used to enable validator mode
   299  	Enabled bool `hcl:"mine,optional" toml:"mine,optional"`
   300  
   301  	// Etherbase is the address of the validator
   302  	Etherbase string `hcl:"etherbase,optional" toml:"etherbase,optional"`
   303  
   304  	// ExtraData is the block extra data set by the miner
   305  	ExtraData string `hcl:"extradata,optional" toml:"extradata,optional"`
   306  
   307  	// GasCeil is the target gas ceiling for mined blocks.
   308  	GasCeil uint64 `hcl:"gaslimit,optional" toml:"gaslimit,optional"`
   309  
   310  	// GasPrice is the minimum gas price for mining a transaction
   311  	GasPrice    *big.Int `hcl:"-,optional" toml:"-"`
   312  	GasPriceRaw string   `hcl:"gasprice,optional" toml:"gasprice,optional"`
   313  
   314  	// The time interval for miner to re-create mining work.
   315  	Recommit    time.Duration `hcl:"-,optional" toml:"-"`
   316  	RecommitRaw string        `hcl:"recommit,optional" toml:"recommit,optional"`
   317  
   318  	CommitInterruptFlag bool `hcl:"commitinterrupt,optional" toml:"commitinterrupt,optional"`
   319  }
   320  
   321  type JsonRPCConfig struct {
   322  	// IPCDisable enables whether ipc is enabled or not
   323  	IPCDisable bool `hcl:"ipcdisable,optional" toml:"ipcdisable,optional"`
   324  
   325  	// IPCPath is the path of the ipc endpoint
   326  	IPCPath string `hcl:"ipcpath,optional" toml:"ipcpath,optional"`
   327  
   328  	// GasCap is the global gas cap for eth-call variants.
   329  	GasCap uint64 `hcl:"gascap,optional" toml:"gascap,optional"`
   330  
   331  	// Sets a timeout used for eth_call (0=infinite)
   332  	RPCEVMTimeout    time.Duration `hcl:"-,optional" toml:"-"`
   333  	RPCEVMTimeoutRaw string        `hcl:"evmtimeout,optional" toml:"evmtimeout,optional"`
   334  
   335  	// TxFeeCap is the global transaction fee cap for send-transaction variants
   336  	TxFeeCap float64 `hcl:"txfeecap,optional" toml:"txfeecap,optional"`
   337  
   338  	// Http has the json-rpc http related settings
   339  	Http *APIConfig `hcl:"http,block" toml:"http,block"`
   340  
   341  	// Ws has the json-rpc websocket related settings
   342  	Ws *APIConfig `hcl:"ws,block" toml:"ws,block"`
   343  
   344  	// Graphql has the json-rpc graphql related settings
   345  	Graphql *APIConfig `hcl:"graphql,block" toml:"graphql,block"`
   346  
   347  	// AUTH RPC related settings
   348  	Auth *AUTHConfig `hcl:"auth,block" toml:"auth,block"`
   349  
   350  	HttpTimeout *HttpTimeouts `hcl:"timeouts,block" toml:"timeouts,block"`
   351  
   352  	AllowUnprotectedTxs bool `hcl:"allow-unprotected-txs,optional" toml:"allow-unprotected-txs,optional"`
   353  }
   354  
   355  type AUTHConfig struct {
   356  	// JWTSecret is the hex-encoded jwt secret.
   357  	JWTSecret string `hcl:"jwtsecret,optional" toml:"jwtsecret,optional"`
   358  
   359  	// Addr is the listening address on which authenticated APIs are provided.
   360  	Addr string `hcl:"addr,optional" toml:"addr,optional"`
   361  
   362  	// Port is the port number on which authenticated APIs are provided.
   363  	Port uint64 `hcl:"port,optional" toml:"port,optional"`
   364  
   365  	// VHosts is the list of virtual hostnames which are allowed on incoming requests
   366  	// for the authenticated api. This is by default {'localhost'}.
   367  	VHosts []string `hcl:"vhosts,optional" toml:"vhosts,optional"`
   368  }
   369  
   370  type GRPCConfig struct {
   371  	// Addr is the bind address for the grpc rpc server
   372  	Addr string `hcl:"addr,optional" toml:"addr,optional"`
   373  }
   374  
   375  type APIConfig struct {
   376  	// Enabled selects whether the api is enabled
   377  	Enabled bool `hcl:"enabled,optional" toml:"enabled,optional"`
   378  
   379  	// Port is the port number for this api
   380  	Port uint64 `hcl:"port,optional" toml:"port,optional"`
   381  
   382  	// Prefix is the http prefix to expose this api
   383  	Prefix string `hcl:"prefix,optional" toml:"prefix,optional"`
   384  
   385  	// Host is the address to bind the api
   386  	Host string `hcl:"host,optional" toml:"host,optional"`
   387  
   388  	// API is the list of enabled api modules
   389  	API []string `hcl:"api,optional" toml:"api,optional"`
   390  
   391  	// VHost is the list of valid virtual hosts
   392  	VHost []string `hcl:"vhosts,optional" toml:"vhosts,optional"`
   393  
   394  	// Cors is the list of Cors endpoints
   395  	Cors []string `hcl:"corsdomain,optional" toml:"corsdomain,optional"`
   396  
   397  	// Origins is the list of endpoints to accept requests from (only consumed for websockets)
   398  	Origins []string `hcl:"origins,optional" toml:"origins,optional"`
   399  
   400  	// ExecutionPoolSize is max size of workers to be used for rpc execution
   401  	ExecutionPoolSize uint64 `hcl:"ep-size,optional" toml:"ep-size,optional"`
   402  
   403  	// ExecutionPoolRequestTimeout is timeout used by execution pool for rpc execution
   404  	ExecutionPoolRequestTimeout    time.Duration `hcl:"-,optional" toml:"-"`
   405  	ExecutionPoolRequestTimeoutRaw string        `hcl:"ep-requesttimeout,optional" toml:"ep-requesttimeout,optional"`
   406  }
   407  
   408  // Used from rpc.HTTPTimeouts
   409  type HttpTimeouts struct {
   410  	// ReadTimeout is the maximum duration for reading the entire
   411  	// request, including the body.
   412  	//
   413  	// Because ReadTimeout does not let Handlers make per-request
   414  	// decisions on each request body's acceptable deadline or
   415  	// upload rate, most users will prefer to use
   416  	// ReadHeaderTimeout. It is valid to use them both.
   417  	ReadTimeout    time.Duration `hcl:"-,optional" toml:"-"`
   418  	ReadTimeoutRaw string        `hcl:"read,optional" toml:"read,optional"`
   419  
   420  	// WriteTimeout is the maximum duration before timing out
   421  	// writes of the response. It is reset whenever a new
   422  	// request's header is read. Like ReadTimeout, it does not
   423  	// let Handlers make decisions on a per-request basis.
   424  	WriteTimeout    time.Duration `hcl:"-,optional" toml:"-"`
   425  	WriteTimeoutRaw string        `hcl:"write,optional" toml:"write,optional"`
   426  
   427  	// IdleTimeout is the maximum amount of time to wait for the
   428  	// next request when keep-alives are enabled. If IdleTimeout
   429  	// is zero, the value of ReadTimeout is used. If both are
   430  	// zero, ReadHeaderTimeout is used.
   431  	IdleTimeout    time.Duration `hcl:"-,optional" toml:"-"`
   432  	IdleTimeoutRaw string        `hcl:"idle,optional" toml:"idle,optional"`
   433  }
   434  
   435  type GpoConfig struct {
   436  	// Blocks is the number of blocks to track to compute the price oracle
   437  	Blocks uint64 `hcl:"blocks,optional" toml:"blocks,optional"`
   438  
   439  	// Percentile sets the weights to new blocks
   440  	Percentile uint64 `hcl:"percentile,optional" toml:"percentile,optional"`
   441  
   442  	// Maximum header history of gasprice oracle
   443  	MaxHeaderHistory int `hcl:"maxheaderhistory,optional" toml:"maxheaderhistory,optional"`
   444  
   445  	// Maximum block history of gasprice oracle
   446  	MaxBlockHistory int `hcl:"maxblockhistory,optional" toml:"maxblockhistory,optional"`
   447  
   448  	// MaxPrice is an upper bound gas price
   449  	MaxPrice    *big.Int `hcl:"-,optional" toml:"-"`
   450  	MaxPriceRaw string   `hcl:"maxprice,optional" toml:"maxprice,optional"`
   451  
   452  	// IgnorePrice is a lower bound gas price
   453  	IgnorePrice    *big.Int `hcl:"-,optional" toml:"-"`
   454  	IgnorePriceRaw string   `hcl:"ignoreprice,optional" toml:"ignoreprice,optional"`
   455  }
   456  
   457  type TelemetryConfig struct {
   458  	// Enabled enables metrics
   459  	Enabled bool `hcl:"metrics,optional" toml:"metrics,optional"`
   460  
   461  	// Expensive enables expensive metrics
   462  	Expensive bool `hcl:"expensive,optional" toml:"expensive,optional"`
   463  
   464  	// InfluxDB has the influxdb related settings
   465  	InfluxDB *InfluxDBConfig `hcl:"influx,block" toml:"influx,block"`
   466  
   467  	// Prometheus Address
   468  	PrometheusAddr string `hcl:"prometheus-addr,optional" toml:"prometheus-addr,optional"`
   469  
   470  	// Open collector endpoint
   471  	OpenCollectorEndpoint string `hcl:"opencollector-endpoint,optional" toml:"opencollector-endpoint,optional"`
   472  }
   473  
   474  type InfluxDBConfig struct {
   475  	// V1Enabled enables influx v1 mode
   476  	V1Enabled bool `hcl:"influxdb,optional" toml:"influxdb,optional"`
   477  
   478  	// Endpoint is the url endpoint of the influxdb service
   479  	Endpoint string `hcl:"endpoint,optional" toml:"endpoint,optional"`
   480  
   481  	// Database is the name of the database in Influxdb to store the metrics.
   482  	Database string `hcl:"database,optional" toml:"database,optional"`
   483  
   484  	// Enabled is the username to authorize access to Influxdb
   485  	Username string `hcl:"username,optional" toml:"username,optional"`
   486  
   487  	// Password is the password to authorize access to Influxdb
   488  	Password string `hcl:"password,optional" toml:"password,optional"`
   489  
   490  	// Tags are tags attaches to all generated metrics
   491  	Tags map[string]string `hcl:"tags,optional" toml:"tags,optional"`
   492  
   493  	// Enabled enables influx v2 mode
   494  	V2Enabled bool `hcl:"influxdbv2,optional" toml:"influxdbv2,optional"`
   495  
   496  	// Token is the token to authorize access to Influxdb V2.
   497  	Token string `hcl:"token,optional" toml:"token,optional"`
   498  
   499  	// Bucket is the bucket to store metrics in Influxdb V2.
   500  	Bucket string `hcl:"bucket,optional" toml:"bucket,optional"`
   501  
   502  	// Organization is the name of the organization for Influxdb V2.
   503  	Organization string `hcl:"organization,optional" toml:"organization,optional"`
   504  }
   505  
   506  type CacheConfig struct {
   507  	// Cache is the amount of cache of the node
   508  	Cache uint64 `hcl:"cache,optional" toml:"cache,optional"`
   509  
   510  	// PercGc is percentage of cache used for garbage collection
   511  	PercGc uint64 `hcl:"gc,optional" toml:"gc,optional"`
   512  
   513  	// PercSnapshot is percentage of cache used for snapshots
   514  	PercSnapshot uint64 `hcl:"snapshot,optional" toml:"snapshot,optional"`
   515  
   516  	// PercDatabase is percentage of cache used for the database
   517  	PercDatabase uint64 `hcl:"database,optional" toml:"database,optional"`
   518  
   519  	// PercTrie is percentage of cache used for the trie
   520  	PercTrie uint64 `hcl:"trie,optional" toml:"trie,optional"`
   521  
   522  	// Journal is the disk journal directory for trie cache to survive node restarts
   523  	Journal string `hcl:"journal,optional" toml:"journal,optional"`
   524  
   525  	// Rejournal is the time interval to regenerate the journal for clean cache
   526  	Rejournal    time.Duration `hcl:"-,optional" toml:"-"`
   527  	RejournalRaw string        `hcl:"rejournal,optional" toml:"rejournal,optional"`
   528  
   529  	// NoPrefetch is used to disable prefetch of tries
   530  	NoPrefetch bool `hcl:"noprefetch,optional" toml:"noprefetch,optional"`
   531  
   532  	// Preimages is used to enable the track of hash preimages
   533  	Preimages bool `hcl:"preimages,optional" toml:"preimages,optional"`
   534  
   535  	// TxLookupLimit sets the maximum number of blocks from head whose tx indices are reserved.
   536  	TxLookupLimit uint64 `hcl:"txlookuplimit,optional" toml:"txlookuplimit,optional"`
   537  
   538  	// Number of block states to keep in memory (default = 128)
   539  	TriesInMemory uint64 `hcl:"triesinmemory,optional" toml:"triesinmemory,optional"`
   540  	// Time after which the Merkle Patricia Trie is stored to disc from memory
   541  	TrieTimeout    time.Duration `hcl:"-,optional" toml:"-"`
   542  	TrieTimeoutRaw string        `hcl:"timeout,optional" toml:"timeout,optional"`
   543  
   544  	// Raise the open file descriptor resource limit (default = system fd limit)
   545  	FDLimit int `hcl:"fdlimit,optional" toml:"fdlimit,optional"`
   546  }
   547  
   548  type AccountsConfig struct {
   549  	// Unlock is the list of addresses to unlock in the node
   550  	Unlock []string `hcl:"unlock,optional" toml:"unlock,optional"`
   551  
   552  	// PasswordFile is the file where the account passwords are stored
   553  	PasswordFile string `hcl:"password,optional" toml:"password,optional"`
   554  
   555  	// AllowInsecureUnlock allows user to unlock accounts in unsafe http environment.
   556  	AllowInsecureUnlock bool `hcl:"allow-insecure-unlock,optional" toml:"allow-insecure-unlock,optional"`
   557  
   558  	// UseLightweightKDF enables a faster but less secure encryption of accounts
   559  	UseLightweightKDF bool `hcl:"lightkdf,optional" toml:"lightkdf,optional"`
   560  
   561  	// DisableBorWallet disables the personal wallet endpoints
   562  	DisableBorWallet bool `hcl:"disable-bor-wallet,optional" toml:"disable-bor-wallet,optional"`
   563  }
   564  
   565  type DeveloperConfig struct {
   566  	// Enabled enables the developer mode
   567  	Enabled bool `hcl:"dev,optional" toml:"dev,optional"`
   568  
   569  	// Period is the block period to use in developer mode
   570  	Period uint64 `hcl:"period,optional" toml:"period,optional"`
   571  
   572  	// Initial block gas limit
   573  	GasLimit uint64 `hcl:"gaslimit,optional" toml:"gaslimit,optional"`
   574  }
   575  
   576  type ParallelEVMConfig struct {
   577  	Enable bool `hcl:"enable,optional" toml:"enable,optional"`
   578  
   579  	SpeculativeProcesses int `hcl:"procs,optional" toml:"procs,optional"`
   580  }
   581  
   582  func DefaultConfig() *Config {
   583  	return &Config{
   584  		Chain:                   "mainnet",
   585  		Identity:                Hostname(),
   586  		RequiredBlocks:          map[string]string{},
   587  		Verbosity:               3,
   588  		LogLevel:                "",
   589  		EnablePreimageRecording: false,
   590  		DataDir:                 DefaultDataDir(),
   591  		Ancient:                 "",
   592  		Logging: &LoggingConfig{
   593  			Vmodule:   "",
   594  			Json:      false,
   595  			Backtrace: "",
   596  			Debug:     false,
   597  		},
   598  		RPCBatchLimit:      100,
   599  		RPCReturnDataLimit: 100000,
   600  		P2P: &P2PConfig{
   601  			MaxPeers:      50,
   602  			MaxPendPeers:  50,
   603  			Bind:          "0.0.0.0",
   604  			Port:          30303,
   605  			NoDiscover:    false,
   606  			NAT:           "any",
   607  			NetRestrict:   "",
   608  			TxArrivalWait: 500 * time.Millisecond,
   609  			Discovery: &P2PDiscovery{
   610  				V5Enabled:    false,
   611  				Bootnodes:    []string{},
   612  				BootnodesV4:  []string{},
   613  				BootnodesV5:  []string{},
   614  				StaticNodes:  []string{},
   615  				TrustedNodes: []string{},
   616  				DNS:          []string{},
   617  			},
   618  		},
   619  		Heimdall: &HeimdallConfig{
   620  			URL:         "http://localhost:1317",
   621  			Without:     false,
   622  			GRPCAddress: "",
   623  		},
   624  		SyncMode: "full",
   625  		GcMode:   "full",
   626  		Snapshot: true,
   627  		BorLogs:  false,
   628  		TxPool: &TxPoolConfig{
   629  			Locals:       []string{},
   630  			NoLocals:     false,
   631  			Journal:      "transactions.rlp",
   632  			Rejournal:    1 * time.Hour,
   633  			PriceLimit:   1, // geth's default
   634  			PriceBump:    10,
   635  			AccountSlots: 16,
   636  			GlobalSlots:  32768,
   637  			AccountQueue: 16,
   638  			GlobalQueue:  32768,
   639  			LifeTime:     3 * time.Hour,
   640  		},
   641  		Sealer: &SealerConfig{
   642  			Enabled:             false,
   643  			Etherbase:           "",
   644  			GasCeil:             30_000_000,                  // geth's default
   645  			GasPrice:            big.NewInt(1 * params.GWei), // geth's default
   646  			ExtraData:           "",
   647  			Recommit:            125 * time.Second,
   648  			CommitInterruptFlag: true,
   649  		},
   650  		Gpo: &GpoConfig{
   651  			Blocks:           20,
   652  			Percentile:       60,
   653  			MaxHeaderHistory: 1024,
   654  			MaxBlockHistory:  1024,
   655  			MaxPrice:         gasprice.DefaultMaxPrice,
   656  			IgnorePrice:      gasprice.DefaultIgnorePrice,
   657  		},
   658  		JsonRPC: &JsonRPCConfig{
   659  			IPCDisable:          false,
   660  			IPCPath:             "",
   661  			GasCap:              ethconfig.Defaults.RPCGasCap,
   662  			TxFeeCap:            ethconfig.Defaults.RPCTxFeeCap,
   663  			RPCEVMTimeout:       ethconfig.Defaults.RPCEVMTimeout,
   664  			AllowUnprotectedTxs: false,
   665  			Http: &APIConfig{
   666  				Enabled:                     false,
   667  				Port:                        8545,
   668  				Prefix:                      "",
   669  				Host:                        "localhost",
   670  				API:                         []string{"eth", "net", "web3", "txpool", "bor"},
   671  				Cors:                        []string{"localhost"},
   672  				VHost:                       []string{"localhost"},
   673  				ExecutionPoolSize:           40,
   674  				ExecutionPoolRequestTimeout: 0,
   675  			},
   676  			Ws: &APIConfig{
   677  				Enabled:                     false,
   678  				Port:                        8546,
   679  				Prefix:                      "",
   680  				Host:                        "localhost",
   681  				API:                         []string{"net", "web3"},
   682  				Origins:                     []string{"localhost"},
   683  				ExecutionPoolSize:           40,
   684  				ExecutionPoolRequestTimeout: 0,
   685  			},
   686  			Graphql: &APIConfig{
   687  				Enabled: false,
   688  				Cors:    []string{"localhost"},
   689  				VHost:   []string{"localhost"},
   690  			},
   691  			HttpTimeout: &HttpTimeouts{
   692  				ReadTimeout:  10 * time.Second,
   693  				WriteTimeout: 30 * time.Second,
   694  				IdleTimeout:  120 * time.Second,
   695  			},
   696  			Auth: &AUTHConfig{
   697  				JWTSecret: "",
   698  				Port:      node.DefaultAuthPort,
   699  				Addr:      node.DefaultAuthHost,
   700  				VHosts:    node.DefaultAuthVhosts,
   701  			},
   702  		},
   703  		Ethstats: "",
   704  		Telemetry: &TelemetryConfig{
   705  			Enabled:               false,
   706  			Expensive:             false,
   707  			PrometheusAddr:        "127.0.0.1:7071",
   708  			OpenCollectorEndpoint: "",
   709  			InfluxDB: &InfluxDBConfig{
   710  				V1Enabled:    false,
   711  				Endpoint:     "",
   712  				Database:     "",
   713  				Username:     "",
   714  				Password:     "",
   715  				Tags:         map[string]string{},
   716  				V2Enabled:    false,
   717  				Token:        "",
   718  				Bucket:       "",
   719  				Organization: "",
   720  			},
   721  		},
   722  		Cache: &CacheConfig{
   723  			Cache:         1024, // geth's default (suitable for mumbai)
   724  			PercDatabase:  50,
   725  			PercTrie:      15,
   726  			PercGc:        25,
   727  			PercSnapshot:  10,
   728  			Journal:       "triecache",
   729  			Rejournal:     60 * time.Minute,
   730  			NoPrefetch:    false,
   731  			Preimages:     false,
   732  			TxLookupLimit: 2350000,
   733  			TriesInMemory: 128,
   734  			TrieTimeout:   60 * time.Minute,
   735  			FDLimit:       0,
   736  		},
   737  		Accounts: &AccountsConfig{
   738  			Unlock:              []string{},
   739  			PasswordFile:        "",
   740  			AllowInsecureUnlock: false,
   741  			UseLightweightKDF:   false,
   742  			DisableBorWallet:    true,
   743  		},
   744  		GRPC: &GRPCConfig{
   745  			Addr: ":3131",
   746  		},
   747  		Developer: &DeveloperConfig{
   748  			Enabled:  false,
   749  			Period:   0,
   750  			GasLimit: 11500000,
   751  		},
   752  		DevFakeAuthor: false,
   753  		Pprof: &PprofConfig{
   754  			Enabled:          false,
   755  			Port:             6060,
   756  			Addr:             "127.0.0.1",
   757  			MemProfileRate:   512 * 1024,
   758  			BlockProfileRate: 0,
   759  			// CPUProfile:       "",
   760  		},
   761  		ParallelEVM: &ParallelEVMConfig{
   762  			Enable:               true,
   763  			SpeculativeProcesses: 8,
   764  		},
   765  	}
   766  }
   767  
   768  func (c *Config) fillBigInt() error {
   769  	tds := []struct {
   770  		path string
   771  		td   **big.Int
   772  		str  *string
   773  	}{
   774  		{"gpo.maxprice", &c.Gpo.MaxPrice, &c.Gpo.MaxPriceRaw},
   775  		{"gpo.ignoreprice", &c.Gpo.IgnorePrice, &c.Gpo.IgnorePriceRaw},
   776  		{"miner.gasprice", &c.Sealer.GasPrice, &c.Sealer.GasPriceRaw},
   777  	}
   778  
   779  	for _, x := range tds {
   780  		if *x.str != "" {
   781  			b := new(big.Int)
   782  
   783  			var ok bool
   784  
   785  			if strings.HasPrefix(*x.str, "0x") {
   786  				b, ok = b.SetString((*x.str)[2:], 16)
   787  			} else {
   788  				b, ok = b.SetString(*x.str, 10)
   789  			}
   790  
   791  			if !ok {
   792  				return fmt.Errorf("%s can't parse big int %s", x.path, *x.str)
   793  			}
   794  
   795  			*x.str = ""
   796  			*x.td = b
   797  		}
   798  	}
   799  
   800  	return nil
   801  }
   802  
   803  func (c *Config) fillTimeDurations() error {
   804  	tds := []struct {
   805  		path string
   806  		td   *time.Duration
   807  		str  *string
   808  	}{
   809  		{"jsonrpc.evmtimeout", &c.JsonRPC.RPCEVMTimeout, &c.JsonRPC.RPCEVMTimeoutRaw},
   810  		{"miner.recommit", &c.Sealer.Recommit, &c.Sealer.RecommitRaw},
   811  		{"jsonrpc.timeouts.read", &c.JsonRPC.HttpTimeout.ReadTimeout, &c.JsonRPC.HttpTimeout.ReadTimeoutRaw},
   812  		{"jsonrpc.timeouts.write", &c.JsonRPC.HttpTimeout.WriteTimeout, &c.JsonRPC.HttpTimeout.WriteTimeoutRaw},
   813  		{"jsonrpc.timeouts.idle", &c.JsonRPC.HttpTimeout.IdleTimeout, &c.JsonRPC.HttpTimeout.IdleTimeoutRaw},
   814  		{"jsonrpc.ws.ep-requesttimeout", &c.JsonRPC.Ws.ExecutionPoolRequestTimeout, &c.JsonRPC.Ws.ExecutionPoolRequestTimeoutRaw},
   815  		{"jsonrpc.http.ep-requesttimeout", &c.JsonRPC.Http.ExecutionPoolRequestTimeout, &c.JsonRPC.Http.ExecutionPoolRequestTimeoutRaw},
   816  		{"txpool.lifetime", &c.TxPool.LifeTime, &c.TxPool.LifeTimeRaw},
   817  		{"txpool.rejournal", &c.TxPool.Rejournal, &c.TxPool.RejournalRaw},
   818  		{"cache.rejournal", &c.Cache.Rejournal, &c.Cache.RejournalRaw},
   819  		{"cache.timeout", &c.Cache.TrieTimeout, &c.Cache.TrieTimeoutRaw},
   820  		{"p2p.txarrivalwait", &c.P2P.TxArrivalWait, &c.P2P.TxArrivalWaitRaw},
   821  	}
   822  
   823  	for _, x := range tds {
   824  		if x.td != nil && x.str != nil && *x.str != "" {
   825  			d, err := time.ParseDuration(*x.str)
   826  			if err != nil {
   827  				return fmt.Errorf("%s can't parse time duration %s", x.path, *x.str)
   828  			}
   829  
   830  			*x.str = ""
   831  			*x.td = d
   832  		}
   833  	}
   834  
   835  	return nil
   836  }
   837  
   838  func readConfigFile(path string) (*Config, error) {
   839  	ext := filepath.Ext(path)
   840  	if ext == ".toml" {
   841  		return readLegacyConfig(path)
   842  	}
   843  
   844  	config := &Config{
   845  		TxPool: &TxPoolConfig{},
   846  		Cache:  &CacheConfig{},
   847  		Sealer: &SealerConfig{},
   848  	}
   849  
   850  	if err := hclsimple.DecodeFile(path, nil, config); err != nil {
   851  		return nil, fmt.Errorf("failed to decode config file '%s': %v", path, err)
   852  	}
   853  
   854  	if err := config.fillBigInt(); err != nil {
   855  		return nil, err
   856  	}
   857  
   858  	if err := config.fillTimeDurations(); err != nil {
   859  		return nil, err
   860  	}
   861  
   862  	return config, nil
   863  }
   864  
   865  func (c *Config) loadChain() error {
   866  	chain, err := chains.GetChain(c.Chain)
   867  	if err != nil {
   868  		return err
   869  	}
   870  
   871  	c.chain = chain
   872  
   873  	// preload some default values that depend on the chain file
   874  	if c.P2P.Discovery.DNS == nil {
   875  		c.P2P.Discovery.DNS = c.chain.DNS
   876  	}
   877  
   878  	return nil
   879  }
   880  
   881  //nolint:gocognit
   882  func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (*ethconfig.Config, error) {
   883  	dbHandles, err := MakeDatabaseHandles(c.Cache.FDLimit)
   884  	if err != nil {
   885  		return nil, err
   886  	}
   887  
   888  	n := ethconfig.Defaults
   889  
   890  	// only update for non-developer mode as we don't yet
   891  	// have the chain object for it.
   892  	if !c.Developer.Enabled {
   893  		n.NetworkId = c.chain.NetworkId
   894  		n.Genesis = c.chain.Genesis
   895  	}
   896  
   897  	n.HeimdallURL = c.Heimdall.URL
   898  	n.WithoutHeimdall = c.Heimdall.Without
   899  	n.HeimdallgRPCAddress = c.Heimdall.GRPCAddress
   900  	n.RunHeimdall = c.Heimdall.RunHeimdall
   901  	n.RunHeimdallArgs = c.Heimdall.RunHeimdallArgs
   902  	n.UseHeimdallApp = c.Heimdall.UseHeimdallApp
   903  
   904  	// Developer Fake Author for producing blocks without authorisation on bor consensus
   905  	n.DevFakeAuthor = c.DevFakeAuthor
   906  
   907  	// Developer Fake Author for producing blocks without authorisation on bor consensus
   908  	n.DevFakeAuthor = c.DevFakeAuthor
   909  
   910  	// gas price oracle
   911  	{
   912  		n.GPO.Blocks = int(c.Gpo.Blocks)
   913  		n.GPO.Percentile = int(c.Gpo.Percentile)
   914  		n.GPO.MaxHeaderHistory = c.Gpo.MaxHeaderHistory
   915  		n.GPO.MaxBlockHistory = c.Gpo.MaxBlockHistory
   916  		n.GPO.MaxPrice = c.Gpo.MaxPrice
   917  		n.GPO.IgnorePrice = c.Gpo.IgnorePrice
   918  	}
   919  
   920  	n.EnablePreimageRecording = c.EnablePreimageRecording
   921  
   922  	// txpool options
   923  	{
   924  		n.TxPool.NoLocals = c.TxPool.NoLocals
   925  		n.TxPool.Journal = c.TxPool.Journal
   926  		n.TxPool.Rejournal = c.TxPool.Rejournal
   927  		n.TxPool.PriceLimit = c.TxPool.PriceLimit
   928  		n.TxPool.PriceBump = c.TxPool.PriceBump
   929  		n.TxPool.AccountSlots = c.TxPool.AccountSlots
   930  		n.TxPool.GlobalSlots = c.TxPool.GlobalSlots
   931  		n.TxPool.AccountQueue = c.TxPool.AccountQueue
   932  		n.TxPool.GlobalQueue = c.TxPool.GlobalQueue
   933  		n.TxPool.Lifetime = c.TxPool.LifeTime
   934  	}
   935  
   936  	// miner options
   937  	{
   938  		n.Miner.Recommit = c.Sealer.Recommit
   939  		n.Miner.GasPrice = c.Sealer.GasPrice
   940  		n.Miner.GasCeil = c.Sealer.GasCeil
   941  		n.Miner.ExtraData = []byte(c.Sealer.ExtraData)
   942  		n.Miner.CommitInterruptFlag = c.Sealer.CommitInterruptFlag
   943  
   944  		if etherbase := c.Sealer.Etherbase; etherbase != "" {
   945  			if !common.IsHexAddress(etherbase) {
   946  				return nil, fmt.Errorf("etherbase is not an address: %s", etherbase)
   947  			}
   948  
   949  			n.Miner.Etherbase = common.HexToAddress(etherbase)
   950  		}
   951  	}
   952  
   953  	// unlock accounts
   954  	if len(c.Accounts.Unlock) > 0 {
   955  		if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() {
   956  			return nil, fmt.Errorf("account unlock with HTTP access is forbidden")
   957  		}
   958  
   959  		ks := accountManager.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   960  
   961  		passwords, err := MakePasswordListFromFile(c.Accounts.PasswordFile)
   962  		if err != nil {
   963  			return nil, err
   964  		}
   965  
   966  		if len(passwords) < len(c.Accounts.Unlock) {
   967  			return nil, fmt.Errorf("number of passwords provided (%v) is less than number of accounts (%v) to unlock",
   968  				len(passwords), len(c.Accounts.Unlock))
   969  		}
   970  
   971  		for i, account := range c.Accounts.Unlock {
   972  			unlockAccount(ks, account, i, passwords)
   973  		}
   974  	}
   975  
   976  	// update for developer mode
   977  	if c.Developer.Enabled {
   978  		// Get a keystore
   979  		var ks *keystore.KeyStore
   980  		if keystores := accountManager.Backends(keystore.KeyStoreType); len(keystores) > 0 {
   981  			ks = keystores[0].(*keystore.KeyStore)
   982  		}
   983  
   984  		// Create new developer account or reuse existing one
   985  		var (
   986  			developer  accounts.Account
   987  			passphrase string
   988  			err        error
   989  		)
   990  
   991  		// etherbase has been set above, configuring the miner address from command line flags.
   992  		if n.Miner.Etherbase != (common.Address{}) {
   993  			developer = accounts.Account{Address: n.Miner.Etherbase}
   994  		} else if accs := ks.Accounts(); len(accs) > 0 {
   995  			developer = ks.Accounts()[0]
   996  		} else {
   997  			developer, err = ks.NewAccount(passphrase)
   998  			if err != nil {
   999  				return nil, fmt.Errorf("failed to create developer account: %v", err)
  1000  			}
  1001  		}
  1002  		if err := ks.Unlock(developer, passphrase); err != nil {
  1003  			return nil, fmt.Errorf("failed to unlock developer account: %v", err)
  1004  		}
  1005  
  1006  		log.Info("Using developer account", "address", developer.Address)
  1007  
  1008  		// Set the Etherbase
  1009  		c.Sealer.Etherbase = developer.Address.Hex()
  1010  		n.Miner.Etherbase = developer.Address
  1011  
  1012  		// get developer mode chain config
  1013  		c.chain = chains.GetDeveloperChain(c.Developer.Period, c.Developer.GasLimit, developer.Address)
  1014  
  1015  		// update the parameters
  1016  		n.NetworkId = c.chain.NetworkId
  1017  		n.Genesis = c.chain.Genesis
  1018  
  1019  		// Update cache
  1020  		c.Cache.Cache = 1024
  1021  
  1022  		// Update sync mode
  1023  		c.SyncMode = "full"
  1024  
  1025  		// update miner gas price
  1026  		if n.Miner.GasPrice == nil {
  1027  			n.Miner.GasPrice = big.NewInt(1)
  1028  		}
  1029  	}
  1030  
  1031  	// discovery (this params should be in node.Config)
  1032  	{
  1033  		n.EthDiscoveryURLs = c.P2P.Discovery.DNS
  1034  		n.SnapDiscoveryURLs = c.P2P.Discovery.DNS
  1035  	}
  1036  
  1037  	// RequiredBlocks
  1038  	{
  1039  		n.PeerRequiredBlocks = map[uint64]common.Hash{}
  1040  		for k, v := range c.RequiredBlocks {
  1041  			number, err := strconv.ParseUint(k, 0, 64)
  1042  			if err != nil {
  1043  				return nil, fmt.Errorf("invalid required block number %s: %v", k, err)
  1044  			}
  1045  
  1046  			var hash common.Hash
  1047  			if err = hash.UnmarshalText([]byte(v)); err != nil {
  1048  				return nil, fmt.Errorf("invalid required block hash %s: %v", v, err)
  1049  			}
  1050  
  1051  			n.PeerRequiredBlocks[number] = hash
  1052  		}
  1053  	}
  1054  
  1055  	// cache
  1056  	{
  1057  		cache := c.Cache.Cache
  1058  		calcPerc := func(val uint64) int {
  1059  			return int(cache * (val) / 100)
  1060  		}
  1061  
  1062  		// Cap the cache allowance
  1063  		mem, err := gopsutil.VirtualMemory()
  1064  		if err == nil {
  1065  			if 32<<(^uintptr(0)>>63) == 32 && mem.Total > 2*1024*1024*1024 {
  1066  				log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024)
  1067  				mem.Total = 2 * 1024 * 1024 * 1024
  1068  			}
  1069  
  1070  			allowance := uint64(mem.Total / 1024 / 1024 / 3)
  1071  			if cache > allowance {
  1072  				log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
  1073  				cache = allowance
  1074  			}
  1075  		}
  1076  		// Tune the garbage collector
  1077  		gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))
  1078  
  1079  		log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
  1080  		godebug.SetGCPercent(int(gogc))
  1081  
  1082  		n.TrieCleanCacheJournal = c.Cache.Journal
  1083  		n.TrieCleanCacheRejournal = c.Cache.Rejournal
  1084  		n.DatabaseCache = calcPerc(c.Cache.PercDatabase)
  1085  		n.SnapshotCache = calcPerc(c.Cache.PercSnapshot)
  1086  		n.TrieCleanCache = calcPerc(c.Cache.PercTrie)
  1087  		n.TrieDirtyCache = calcPerc(c.Cache.PercGc)
  1088  		n.NoPrefetch = c.Cache.NoPrefetch
  1089  		n.Preimages = c.Cache.Preimages
  1090  		n.TxLookupLimit = c.Cache.TxLookupLimit
  1091  		n.TrieTimeout = c.Cache.TrieTimeout
  1092  		n.TriesInMemory = c.Cache.TriesInMemory
  1093  	}
  1094  
  1095  	n.RPCGasCap = c.JsonRPC.GasCap
  1096  	if n.RPCGasCap != 0 {
  1097  		log.Info("Set global gas cap", "cap", n.RPCGasCap)
  1098  	} else {
  1099  		log.Info("Global gas cap disabled")
  1100  	}
  1101  
  1102  	n.RPCEVMTimeout = c.JsonRPC.RPCEVMTimeout
  1103  
  1104  	n.RPCTxFeeCap = c.JsonRPC.TxFeeCap
  1105  
  1106  	// sync mode. It can either be "fast", "full" or "snap". We disable
  1107  	// for now the "light" mode.
  1108  	switch c.SyncMode {
  1109  	case "full":
  1110  		n.SyncMode = downloader.FullSync
  1111  	case "snap":
  1112  		// n.SyncMode = downloader.SnapSync // TODO(snap): Uncomment when we have snap sync working
  1113  		n.SyncMode = downloader.FullSync
  1114  
  1115  		log.Warn("Bor doesn't support Snap Sync yet, switching to Full Sync mode")
  1116  	default:
  1117  		return nil, fmt.Errorf("sync mode '%s' not found", c.SyncMode)
  1118  	}
  1119  
  1120  	// archive mode. It can either be "archive" or "full".
  1121  	switch c.GcMode {
  1122  	case "full":
  1123  		n.NoPruning = false
  1124  	case "archive":
  1125  		n.NoPruning = true
  1126  		if !n.Preimages {
  1127  			n.Preimages = true
  1128  			log.Info("Enabling recording of key preimages since archive mode is used")
  1129  		}
  1130  	default:
  1131  		return nil, fmt.Errorf("gcmode '%s' not found", c.GcMode)
  1132  	}
  1133  
  1134  	// snapshot disable check
  1135  	if !c.Snapshot {
  1136  		if n.SyncMode == downloader.SnapSync {
  1137  			log.Info("Snap sync requested, enabling --snapshot")
  1138  		} else {
  1139  			// disable snapshot
  1140  			n.TrieCleanCache += n.SnapshotCache
  1141  			n.SnapshotCache = 0
  1142  		}
  1143  	}
  1144  
  1145  	n.BorLogs = c.BorLogs
  1146  	n.DatabaseHandles = dbHandles
  1147  
  1148  	n.ParallelEVM.Enable = c.ParallelEVM.Enable
  1149  	n.ParallelEVM.SpeculativeProcesses = c.ParallelEVM.SpeculativeProcesses
  1150  	n.RPCReturnDataLimit = c.RPCReturnDataLimit
  1151  
  1152  	if c.Ancient != "" {
  1153  		n.DatabaseFreezer = c.Ancient
  1154  	}
  1155  
  1156  	return &n, nil
  1157  }
  1158  
  1159  var (
  1160  	clientIdentifier = "bor"
  1161  	gitCommit        = "" // Git SHA1 commit hash of the release (set via linker flags)
  1162  	gitDate          = "" // Git commit date YYYYMMDD of the release (set via linker flags)
  1163  )
  1164  
  1165  // tries unlocking the specified account a few times.
  1166  func unlockAccount(ks *keystore.KeyStore, address string, i int, passwords []string) (accounts.Account, string) {
  1167  	account, err := utils.MakeAddress(ks, address)
  1168  
  1169  	if err != nil {
  1170  		utils.Fatalf("Could not list accounts: %v", err)
  1171  	}
  1172  
  1173  	for trials := 0; trials < 3; trials++ {
  1174  		prompt := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", address, trials+1, 3)
  1175  		password := utils.GetPassPhraseWithList(prompt, false, i, passwords)
  1176  		err = ks.Unlock(account, password)
  1177  
  1178  		if err == nil {
  1179  			log.Info("Unlocked account", "address", account.Address.Hex())
  1180  			return account, password
  1181  		}
  1182  
  1183  		if err, ok := err.(*keystore.AmbiguousAddrError); ok {
  1184  			log.Info("Unlocked account", "address", account.Address.Hex())
  1185  			return ambiguousAddrRecovery(ks, err, password), password
  1186  		}
  1187  
  1188  		if err != keystore.ErrDecrypt {
  1189  			// No need to prompt again if the error is not decryption-related.
  1190  			break
  1191  		}
  1192  	}
  1193  	// All trials expended to unlock account, bail out
  1194  	utils.Fatalf("Failed to unlock account %s (%v)", address, err)
  1195  
  1196  	return accounts.Account{}, ""
  1197  }
  1198  
  1199  func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrError, auth string) accounts.Account {
  1200  	log.Warn("Multiple key files exist for", "address", err.Addr)
  1201  
  1202  	for _, a := range err.Matches {
  1203  		log.Info("Multiple keys", "file", a.URL.String())
  1204  	}
  1205  
  1206  	log.Info("Testing your password against all of them...")
  1207  
  1208  	var match *accounts.Account
  1209  
  1210  	for _, a := range err.Matches {
  1211  		if err := ks.Unlock(a, auth); err == nil {
  1212  			// nolint: gosec, exportloopref
  1213  			match = &a
  1214  			break
  1215  		}
  1216  	}
  1217  
  1218  	if match == nil {
  1219  		utils.Fatalf("None of the listed files could be unlocked.")
  1220  	}
  1221  
  1222  	log.Info("Your password unlocked", "key", match.URL.String())
  1223  	log.Warn("In order to avoid this warning, you need to remove the following duplicate key files:")
  1224  
  1225  	for _, a := range err.Matches {
  1226  		if a != *match {
  1227  			log.Warn("Duplicate", "key", a.URL.String())
  1228  		}
  1229  	}
  1230  
  1231  	return *match
  1232  }
  1233  
  1234  // setNodeKey creates a node key from set command line flags, either loading it
  1235  // from a file or as a specified hex value. If neither flags were provided, this
  1236  // method returns nil and an emphemeral key is to be generated.
  1237  func getNodeKey(hex string, file string) *ecdsa.PrivateKey {
  1238  	var (
  1239  		key *ecdsa.PrivateKey
  1240  		err error
  1241  	)
  1242  
  1243  	switch {
  1244  	case file != "" && hex != "":
  1245  		utils.Fatalf("Options %q and %q are mutually exclusive", file, hex)
  1246  	case file != "":
  1247  		if key, err = crypto.LoadECDSA(file); err != nil {
  1248  			utils.Fatalf("Option %q: %v", file, err)
  1249  		}
  1250  
  1251  		return key
  1252  	case hex != "":
  1253  		if key, err = crypto.HexToECDSA(hex); err != nil {
  1254  			utils.Fatalf("Option %q: %v", hex, err)
  1255  		}
  1256  
  1257  		return key
  1258  	}
  1259  
  1260  	return nil
  1261  }
  1262  
  1263  func (c *Config) buildNode() (*node.Config, error) {
  1264  	ipcPath := ""
  1265  	if !c.JsonRPC.IPCDisable {
  1266  		ipcPath = clientIdentifier + ".ipc"
  1267  		if c.JsonRPC.IPCPath != "" {
  1268  			ipcPath = c.JsonRPC.IPCPath
  1269  		}
  1270  	}
  1271  
  1272  	cfg := &node.Config{
  1273  		Name:                  clientIdentifier,
  1274  		DataDir:               c.DataDir,
  1275  		KeyStoreDir:           c.KeyStoreDir,
  1276  		UseLightweightKDF:     c.Accounts.UseLightweightKDF,
  1277  		InsecureUnlockAllowed: c.Accounts.AllowInsecureUnlock,
  1278  		Version:               params.VersionWithCommit(gitCommit, gitDate),
  1279  		IPCPath:               ipcPath,
  1280  		AllowUnprotectedTxs:   c.JsonRPC.AllowUnprotectedTxs,
  1281  		P2P: p2p.Config{
  1282  			MaxPeers:        int(c.P2P.MaxPeers),
  1283  			MaxPendingPeers: int(c.P2P.MaxPendPeers),
  1284  			ListenAddr:      c.P2P.Bind + ":" + strconv.Itoa(int(c.P2P.Port)),
  1285  			DiscoveryV5:     c.P2P.Discovery.V5Enabled,
  1286  			TxArrivalWait:   c.P2P.TxArrivalWait,
  1287  		},
  1288  		HTTPModules:         c.JsonRPC.Http.API,
  1289  		HTTPCors:            c.JsonRPC.Http.Cors,
  1290  		HTTPVirtualHosts:    c.JsonRPC.Http.VHost,
  1291  		HTTPPathPrefix:      c.JsonRPC.Http.Prefix,
  1292  		WSModules:           c.JsonRPC.Ws.API,
  1293  		WSOrigins:           c.JsonRPC.Ws.Origins,
  1294  		WSPathPrefix:        c.JsonRPC.Ws.Prefix,
  1295  		GraphQLCors:         c.JsonRPC.Graphql.Cors,
  1296  		GraphQLVirtualHosts: c.JsonRPC.Graphql.VHost,
  1297  		HTTPTimeouts: rpc.HTTPTimeouts{
  1298  			ReadTimeout:  c.JsonRPC.HttpTimeout.ReadTimeout,
  1299  			WriteTimeout: c.JsonRPC.HttpTimeout.WriteTimeout,
  1300  			IdleTimeout:  c.JsonRPC.HttpTimeout.IdleTimeout,
  1301  		},
  1302  		JWTSecret:                              c.JsonRPC.Auth.JWTSecret,
  1303  		AuthPort:                               int(c.JsonRPC.Auth.Port),
  1304  		AuthAddr:                               c.JsonRPC.Auth.Addr,
  1305  		AuthVirtualHosts:                       c.JsonRPC.Auth.VHosts,
  1306  		RPCBatchLimit:                          c.RPCBatchLimit,
  1307  		WSJsonRPCExecutionPoolSize:             c.JsonRPC.Ws.ExecutionPoolSize,
  1308  		WSJsonRPCExecutionPoolRequestTimeout:   c.JsonRPC.Ws.ExecutionPoolRequestTimeout,
  1309  		HTTPJsonRPCExecutionPoolSize:           c.JsonRPC.Http.ExecutionPoolSize,
  1310  		HTTPJsonRPCExecutionPoolRequestTimeout: c.JsonRPC.Http.ExecutionPoolRequestTimeout,
  1311  	}
  1312  
  1313  	if c.P2P.NetRestrict != "" {
  1314  		list, err := netutil.ParseNetlist(c.P2P.NetRestrict)
  1315  		if err != nil {
  1316  			utils.Fatalf("Option %q: %v", c.P2P.NetRestrict, err)
  1317  		}
  1318  
  1319  		cfg.P2P.NetRestrict = list
  1320  	}
  1321  
  1322  	key := getNodeKey(c.P2P.NodeKeyHex, c.P2P.NodeKey)
  1323  	if key != nil {
  1324  		cfg.P2P.PrivateKey = key
  1325  	}
  1326  
  1327  	// dev mode
  1328  	if c.Developer.Enabled {
  1329  		cfg.UseLightweightKDF = true
  1330  
  1331  		// disable p2p networking
  1332  		c.P2P.NoDiscover = true
  1333  		cfg.P2P.ListenAddr = ""
  1334  		cfg.P2P.NoDial = true
  1335  		cfg.P2P.DiscoveryV5 = false
  1336  
  1337  		// enable JsonRPC HTTP API
  1338  		c.JsonRPC.Http.Enabled = true
  1339  		cfg.HTTPModules = []string{"admin", "debug", "eth", "miner", "net", "personal", "txpool", "web3", "bor"}
  1340  	}
  1341  
  1342  	// enable jsonrpc endpoints
  1343  	{
  1344  		if c.JsonRPC.Http.Enabled {
  1345  			cfg.HTTPHost = c.JsonRPC.Http.Host
  1346  			cfg.HTTPPort = int(c.JsonRPC.Http.Port)
  1347  		}
  1348  
  1349  		if c.JsonRPC.Ws.Enabled {
  1350  			cfg.WSHost = c.JsonRPC.Ws.Host
  1351  			cfg.WSPort = int(c.JsonRPC.Ws.Port)
  1352  		}
  1353  	}
  1354  
  1355  	natif, err := nat.Parse(c.P2P.NAT)
  1356  	if err != nil {
  1357  		return nil, fmt.Errorf("wrong 'nat' flag: %v", err)
  1358  	}
  1359  
  1360  	cfg.P2P.NAT = natif
  1361  
  1362  	// only check for non-developer modes
  1363  	if !c.Developer.Enabled {
  1364  		// Discovery
  1365  		// if no bootnodes are defined, use the ones from the chain file.
  1366  		bootnodes := c.P2P.Discovery.Bootnodes
  1367  		if len(bootnodes) == 0 {
  1368  			bootnodes = c.chain.Bootnodes
  1369  		}
  1370  
  1371  		if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil {
  1372  			return nil, err
  1373  		}
  1374  
  1375  		if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil {
  1376  			return nil, err
  1377  		}
  1378  
  1379  		if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil {
  1380  			return nil, err
  1381  		}
  1382  
  1383  		if len(cfg.P2P.StaticNodes) == 0 {
  1384  			cfg.P2P.StaticNodes = cfg.StaticNodes()
  1385  		}
  1386  
  1387  		if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil {
  1388  			return nil, err
  1389  		}
  1390  
  1391  		if len(cfg.P2P.TrustedNodes) == 0 {
  1392  			cfg.P2P.TrustedNodes = cfg.TrustedNodes()
  1393  		}
  1394  	}
  1395  
  1396  	if c.P2P.NoDiscover {
  1397  		// Disable peer discovery
  1398  		cfg.P2P.NoDiscovery = true
  1399  	}
  1400  
  1401  	return cfg, nil
  1402  }
  1403  
  1404  func (c *Config) Merge(cc ...*Config) error {
  1405  	for _, elem := range cc {
  1406  		if err := mergo.Merge(c, elem, mergo.WithOverwriteWithEmptyValue); err != nil {
  1407  			return fmt.Errorf("failed to merge configurations: %v", err)
  1408  		}
  1409  	}
  1410  
  1411  	return nil
  1412  }
  1413  
  1414  func MakeDatabaseHandles(max int) (int, error) {
  1415  	limit, err := fdlimit.Maximum()
  1416  	if err != nil {
  1417  		return -1, err
  1418  	}
  1419  
  1420  	switch {
  1421  	case max == 0:
  1422  		// User didn't specify a meaningful value, use system limits
  1423  	case max < 128:
  1424  		// User specified something unhealthy, just use system defaults
  1425  		log.Error("File descriptor limit invalid (<128)", "had", max, "updated", limit)
  1426  	case max > limit:
  1427  		// User requested more than the OS allows, notify that we can't allocate it
  1428  		log.Warn("Requested file descriptors denied by OS", "req", max, "limit", limit)
  1429  	default:
  1430  		// User limit is meaningful and within allowed range, use that
  1431  		limit = max
  1432  	}
  1433  
  1434  	raised, err := fdlimit.Raise(uint64(limit))
  1435  	if err != nil {
  1436  		return -1, err
  1437  	}
  1438  
  1439  	return int(raised / 2), nil // Leave half for networking and other stuff
  1440  }
  1441  
  1442  func parseBootnodes(urls []string) ([]*enode.Node, error) {
  1443  	dst := []*enode.Node{}
  1444  	for _, url := range urls {
  1445  		if url != "" {
  1446  			node, err := enode.Parse(enode.ValidSchemes, url)
  1447  			if err != nil {
  1448  				return nil, fmt.Errorf("invalid bootstrap url '%s': %v", url, err)
  1449  			}
  1450  			dst = append(dst, node)
  1451  		}
  1452  	}
  1453  
  1454  	return dst, nil
  1455  }
  1456  
  1457  func DefaultDataDir() string {
  1458  	// Try to place the data folder in the user's home dir
  1459  	home, _ := homedir.Dir()
  1460  	if home == "" {
  1461  		// we cannot guess a stable location
  1462  		return ""
  1463  	}
  1464  
  1465  	switch runtime.GOOS {
  1466  	case "darwin":
  1467  		return filepath.Join(home, "Library", "Bor")
  1468  	case "windows":
  1469  		appdata := os.Getenv("LOCALAPPDATA")
  1470  		if appdata == "" {
  1471  			// Windows XP and below don't have LocalAppData.
  1472  			panic("environment variable LocalAppData is undefined")
  1473  		}
  1474  
  1475  		return filepath.Join(appdata, "Bor")
  1476  	default:
  1477  		return filepath.Join(home, ".bor")
  1478  	}
  1479  }
  1480  
  1481  func Hostname() string {
  1482  	hostname, err := os.Hostname()
  1483  	if err != nil {
  1484  		return "bor"
  1485  	}
  1486  
  1487  	return hostname
  1488  }
  1489  
  1490  func MakePasswordListFromFile(path string) ([]string, error) {
  1491  	text, err := ioutil.ReadFile(path)
  1492  	if err != nil {
  1493  		return nil, fmt.Errorf("failed to read password file: %v", err)
  1494  	}
  1495  
  1496  	lines := strings.Split(string(text), "\n")
  1497  
  1498  	// Sanitise DOS line endings.
  1499  	for i := range lines {
  1500  		lines[i] = strings.TrimRight(lines[i], "\r")
  1501  	}
  1502  
  1503  	return lines, nil
  1504  }