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 }