mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
Merge branch 'develop' into POS-648
This commit is contained in:
commit
75bb3bdeb1
27 changed files with 616 additions and 338 deletions
|
|
@ -90,6 +90,9 @@ nfpms:
|
|||
- src: builder/files/genesis-testnet-v4.json
|
||||
dst: /etc/bor/genesis-testnet-v4.json
|
||||
type: config
|
||||
- src: builder/files/config.toml
|
||||
dst: /var/lib/bor/config.toml
|
||||
type: config
|
||||
|
||||
overrides:
|
||||
rpm:
|
||||
|
|
|
|||
|
|
@ -6,34 +6,7 @@
|
|||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
ExecStart=/usr/local/bin/bor server \
|
||||
--chain=mumbai \
|
||||
# --chain=mainnet \
|
||||
--datadir /var/lib/bor/data \
|
||||
--metrics \
|
||||
--metrics.prometheus-addr="127.0.0.1:7071" \
|
||||
--syncmode 'full' \
|
||||
--miner.gasprice '30000000000' \
|
||||
--miner.gaslimit '20000000' \
|
||||
--miner.gastarget '20000000' \
|
||||
--txpool.nolocals \
|
||||
--txpool.accountslots 16 \
|
||||
--txpool.globalslots 32768 \
|
||||
--txpool.accountqueue 16 \
|
||||
--txpool.globalqueue 32768 \
|
||||
--txpool.pricelimit '30000000000' \
|
||||
--txpool.lifetime '1h30m0s' \
|
||||
--bootnodes "enode://0cb82b395094ee4a2915e9714894627de9ed8498fb881cec6db7c65e8b9a5bd7f2f25cc84e71e89d0947e51c76e85d0847de848c7782b13c0255247a6758178c@44.232.55.71:30303,enode://88116f4295f5a31538ae409e4d44ad40d22e44ee9342869e7d68bdec55b0f83c1530355ce8b41fbec0928a7d75a5745d528450d30aec92066ab6ba1ee351d710@159.203.9.164:30303"
|
||||
# Validator params
|
||||
# Uncomment and configure the following lines in case you run a validator. Don't forget to add backslash (\)
|
||||
# to previous command line.
|
||||
# --keystore /var/lib/bor/keystore \
|
||||
# --unlock [VALIDATOR ADDRESS] \
|
||||
# --password /var/lib/bor/password.txt \
|
||||
# --allow-insecure-unlock \
|
||||
# --nodiscover --maxpeers 1 \
|
||||
# --miner.etherbase [VALIDATOR ADDRESS] \
|
||||
# --mine
|
||||
ExecStart=/usr/local/bin/bor server -config="/var/lib/bor/config.toml"
|
||||
Type=simple
|
||||
User=ubuntu
|
||||
KillSignal=SIGINT
|
||||
|
|
|
|||
44
builder/files/config.toml
Normal file
44
builder/files/config.toml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# chain = "mumbai"
|
||||
chain = "mainnet"
|
||||
datadir = "/var/lib/bor/data"
|
||||
syncmode = "full"
|
||||
|
||||
[telemetry]
|
||||
metrics = true
|
||||
prometheus-addr = "127.0.0.1:7071"
|
||||
|
||||
[miner]
|
||||
# *** Validator params
|
||||
# *** Uncomment and configure the following lines in case you run a validator.
|
||||
# mine = true
|
||||
# etherbase = "VALIDATOR ADDRESS"
|
||||
gasprice = "30000000000"
|
||||
gasceil = 20000000
|
||||
|
||||
|
||||
[txpool]
|
||||
accountqueue = 16
|
||||
accountslots = 16
|
||||
globalqueue = 32768
|
||||
globalslots = 32768
|
||||
lifetime = "1h30m0s"
|
||||
nolocals = true
|
||||
pricelimit = 30000000000
|
||||
|
||||
[p2p]
|
||||
# *** Validator params
|
||||
# *** Uncomment and configure the following lines in case you run a validator.
|
||||
# nodiscover = true
|
||||
# maxpeers = 1
|
||||
[p2p.discovery]
|
||||
bootnodes = ["enode://0cb82b395094ee4a2915e9714894627de9ed8498fb881cec6db7c65e8b9a5bd7f2f25cc84e71e89d0947e51c76e85d0847de848c7782b13c0255247a6758178c@44.232.55.71:30303", "enode://88116f4295f5a31538ae409e4d44ad40d22e44ee9342869e7d68bdec55b0f83c1530355ce8b41fbec0928a7d75a5745d528450d30aec92066ab6ba1ee351d710@159.203.9.164:30303"]
|
||||
|
||||
# *** Validator params
|
||||
# *** Uncomment and configure the following lines in case you run a validator.
|
||||
|
||||
# keystore = "/var/lib/bor/keystore"
|
||||
|
||||
# [accounts]
|
||||
# allow-insecure-unlock = true
|
||||
# password = "/var/lib/bor/password.txt"
|
||||
# unlock = ["VALIDATOR ADDRESS"]
|
||||
|
|
@ -59,6 +59,8 @@ func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Dat
|
|||
return nil, err
|
||||
}
|
||||
|
||||
snap.ValidatorSet.UpdateValidatorMap()
|
||||
|
||||
snap.config = config
|
||||
snap.sigcache = sigcache
|
||||
|
||||
|
|
|
|||
|
|
@ -628,6 +628,10 @@ func (vals *ValidatorSet) updateValidators(updates []*Validator, deletes []*Vali
|
|||
vals.applyUpdates(updates)
|
||||
vals.applyRemovals(deletes)
|
||||
|
||||
vals.UpdateValidatorMap()
|
||||
}
|
||||
|
||||
func (vals *ValidatorSet) UpdateValidatorMap() {
|
||||
vals.validatorsMap = make(map[common.Address]int, len(vals.Validators))
|
||||
|
||||
for i, val := range vals.Validators {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
- [```debug pprof```](./debug_pprof.md)
|
||||
|
||||
- [```dumpconfig```](./dumpconfig.md)
|
||||
|
||||
- [```fingerprint```](./fingerprint.md)
|
||||
|
||||
- [```peers```](./peers.md)
|
||||
|
|
|
|||
3
docs/cli/dumpconfig.md
Normal file
3
docs/cli/dumpconfig.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Dumpconfig
|
||||
|
||||
The ```bor dumpconfig <your-favourite-flags>``` command will export the user provided flags into a configuration file
|
||||
175
docs/config.md
175
docs/config.md
|
|
@ -1,133 +1,144 @@
|
|||
|
||||
# Config
|
||||
|
||||
Toml files format used in geth are being deprecated.
|
||||
|
||||
Bor uses uses JSON and [HCL](https://github.com/hashicorp/hcl) formats to create configuration files. This is the format in HCL alongside the default values:
|
||||
|
||||
- The `bor dumpconfig` command prints the default configurations, in the TOML format, on the terminal.
|
||||
- One can `pipe (>)` this to a file (say `config.toml`) and use it to start bor.
|
||||
- Command to provide a config file: `bor server -config config.toml`
|
||||
- Bor uses TOML, HCL, and JSON format config files.
|
||||
- This is the format of the config file in TOML:
|
||||
- **NOTE: The values of these following flags are just for reference**
|
||||
- `config.toml` file:
|
||||
```
|
||||
chain = "mainnet"
|
||||
log-level = "info"
|
||||
data-dir = ""
|
||||
sync-mode = "fast"
|
||||
gc-mode = "full"
|
||||
identity = "myIdentity"
|
||||
log-level = "INFO"
|
||||
datadir = "/var/lib/bor/data"
|
||||
keystore = "path/to/keystore"
|
||||
syncmode = "full"
|
||||
gcmode = "full"
|
||||
snapshot = true
|
||||
ethstats = ""
|
||||
whitelist = {}
|
||||
|
||||
p2p {
|
||||
max-peers = 30
|
||||
max-pend-peers = 50
|
||||
[p2p]
|
||||
maxpeers = 30
|
||||
maxpendpeers = 50
|
||||
bind = "0.0.0.0"
|
||||
port = 30303
|
||||
no-discover = false
|
||||
nodiscover = false
|
||||
nat = "any"
|
||||
discovery {
|
||||
v5-enabled = false
|
||||
bootnodes = []
|
||||
|
||||
[p2p.discovery]
|
||||
v5disc = false
|
||||
bootnodes = ["enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303"]
|
||||
bootnodesv4 = []
|
||||
bootnodesv5 = []
|
||||
staticNodes = []
|
||||
trustedNodes = []
|
||||
bootnodesv5 = ["enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA", "enr:-KG4QDyytgmE4f7AnvW-ZaUOIi9i79qX4JwjRAiXBZCU65wOfBu-3Nb5I7b_Rmg3KCOcZM_C3y5pg7EBU5XGrcLTduQEhGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaEDKnz_-ps3UUOfHWVYaskI5kWYO_vtYMGYCQRAR3gHDouDdGNwgiMog3VkcIIjKA"]
|
||||
static-nodes = ["enode://8499da03c47d637b20eee24eec3c356c9a2e6148d6fe25ca195c7949ab8ec2c03e3556126b0d7ed644675e78c4318b08691b7b57de10e5f0d40d05b09238fa0a@52.187.207.27:30303"]
|
||||
trusted-nodes = ["enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303"]
|
||||
dns = []
|
||||
}
|
||||
}
|
||||
|
||||
heimdall {
|
||||
[heimdall]
|
||||
url = "http://localhost:1317"
|
||||
without = false
|
||||
}
|
||||
"bor.without" = false
|
||||
|
||||
txpool {
|
||||
locals = []
|
||||
no-locals = false
|
||||
[txpool]
|
||||
locals = ["$ADDRESS1", "$ADDRESS2"]
|
||||
nolocals = false
|
||||
journal = ""
|
||||
rejournal = "1h"
|
||||
price-limit = 1
|
||||
price-bump = 10
|
||||
account-slots = 16
|
||||
global-slots = 4096
|
||||
account-queue = 64
|
||||
global-queue = 1024
|
||||
lifetime = "3h"
|
||||
}
|
||||
rejournal = "1h0m0s"
|
||||
pricelimit = 30000000000
|
||||
pricebump = 10
|
||||
accountslots = 16
|
||||
globalslots = 32768
|
||||
accountqueue = 16
|
||||
globalqueue = 32768
|
||||
lifetime = "3h0m0s"
|
||||
|
||||
sealer {
|
||||
enabled = false
|
||||
[miner]
|
||||
mine = false
|
||||
etherbase = ""
|
||||
gas-ceil = 8000000
|
||||
extra-data = ""
|
||||
}
|
||||
extradata = ""
|
||||
gaslimit = 20000000
|
||||
gasprice = "30000000000"
|
||||
|
||||
gpo {
|
||||
blocks = 20
|
||||
percentile = 60
|
||||
}
|
||||
[jsonrpc]
|
||||
ipcdisable = false
|
||||
ipcpath = "/var/lib/bor/bor.ipc"
|
||||
gascap = 50000000
|
||||
txfeecap = 5e+00
|
||||
|
||||
jsonrpc {
|
||||
ipc-disable = false
|
||||
ipc-path = ""
|
||||
modules = ["web3", "net"]
|
||||
cors = ["*"]
|
||||
vhost = ["*"]
|
||||
|
||||
http {
|
||||
[jsonrpc.http]
|
||||
enabled = false
|
||||
port = 8545
|
||||
prefix = ""
|
||||
host = "localhost"
|
||||
}
|
||||
api = ["eth", "net", "web3", "txpool", "bor"]
|
||||
vhosts = ["*"]
|
||||
corsdomain = ["*"]
|
||||
|
||||
ws {
|
||||
[jsonrpc.ws]
|
||||
enabled = false
|
||||
port = 8546
|
||||
prefix = ""
|
||||
host = "localhost"
|
||||
}
|
||||
api = ["web3", "net"]
|
||||
vhosts = ["*"]
|
||||
corsdomain = ["*"]
|
||||
|
||||
graphqh {
|
||||
[jsonrpc.graphql]
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
port = 0
|
||||
prefix = ""
|
||||
host = ""
|
||||
api = []
|
||||
vhosts = ["*"]
|
||||
corsdomain = ["*"]
|
||||
|
||||
telemetry {
|
||||
enabled = false
|
||||
[gpo]
|
||||
blocks = 20
|
||||
percentile = 60
|
||||
maxprice = "5000000000000"
|
||||
ignoreprice = "2"
|
||||
|
||||
[telemetry]
|
||||
metrics = false
|
||||
expensive = false
|
||||
prometheus-addr = ""
|
||||
opencollector-endpoint = ""
|
||||
|
||||
influxdb {
|
||||
v1-enabled = false
|
||||
[telemetry.influx]
|
||||
influxdb = false
|
||||
endpoint = ""
|
||||
database = ""
|
||||
username = ""
|
||||
password = ""
|
||||
v2-enabled = false
|
||||
influxdbv2 = false
|
||||
token = ""
|
||||
bucket = ""
|
||||
organization = ""
|
||||
}
|
||||
}
|
||||
|
||||
cache {
|
||||
[cache]
|
||||
cache = 1024
|
||||
perc-database = 50
|
||||
perc-trie = 15
|
||||
perc-gc = 25
|
||||
perc-snapshot = 10
|
||||
gc = 25
|
||||
snapshot = 10
|
||||
database = 50
|
||||
trie = 15
|
||||
journal = "triecache"
|
||||
rejournal = "60m"
|
||||
no-prefetch = false
|
||||
rejournal = "1h0m0s"
|
||||
noprefetch = false
|
||||
preimages = false
|
||||
tx-lookup-limit = 2350000
|
||||
}
|
||||
txlookuplimit = 2350000
|
||||
|
||||
accounts {
|
||||
unlock = []
|
||||
password-file = ""
|
||||
[accounts]
|
||||
unlock = ["$ADDRESS1", "$ADDRESS2"]
|
||||
password = "path/to/password.txt"
|
||||
allow-insecure-unlock = false
|
||||
use-lightweight-kdf = false
|
||||
}
|
||||
lightkdf = false
|
||||
disable-bor-wallet = false
|
||||
|
||||
grpc {
|
||||
[grpc]
|
||||
addr = ":3131"
|
||||
}
|
||||
|
||||
[developer]
|
||||
dev = false
|
||||
period = 0
|
||||
```
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -84,6 +84,7 @@ require (
|
|||
require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect
|
||||
github.com/BurntSushi/toml v1.1.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.0 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
|
|
|
|||
3
go.sum
3
go.sum
|
|
@ -25,6 +25,8 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSu
|
|||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJNuUB6n7rs5Wsel4dXLe90Um2n4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
|
||||
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d h1:RO27lgfZF8s9lZ3pWyzc0gCE0RZC+6/PXbRjAa0CNp8=
|
||||
|
|
@ -461,6 +463,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||
|
|
|
|||
|
|
@ -82,6 +82,11 @@ func Commands() map[string]MarkDownCommandFactory {
|
|||
UI: ui,
|
||||
}, nil
|
||||
},
|
||||
"dumpconfig": func() (MarkDownCommand, error) {
|
||||
return &DumpconfigCommand{
|
||||
Meta2: meta2,
|
||||
}, nil
|
||||
},
|
||||
"debug": func() (MarkDownCommand, error) {
|
||||
return &DebugCommand{
|
||||
UI: ui,
|
||||
|
|
|
|||
82
internal/cli/dumpconfig.go
Normal file
82
internal/cli/dumpconfig.go
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/naoina/toml"
|
||||
|
||||
"github.com/ethereum/go-ethereum/internal/cli/server"
|
||||
)
|
||||
|
||||
// These settings ensure that TOML keys use the same names as Go struct fields.
|
||||
var tomlSettings = toml.Config{
|
||||
NormFieldName: func(rt reflect.Type, key string) string {
|
||||
return key
|
||||
},
|
||||
FieldToKey: func(rt reflect.Type, field string) string {
|
||||
return field
|
||||
},
|
||||
}
|
||||
|
||||
// DumpconfigCommand is for exporting user provided flags into a config file
|
||||
type DumpconfigCommand struct {
|
||||
*Meta2
|
||||
}
|
||||
|
||||
// MarkDown implements cli.MarkDown interface
|
||||
func (p *DumpconfigCommand) MarkDown() string {
|
||||
items := []string{
|
||||
"# Dumpconfig",
|
||||
"The ```bor dumpconfig <your-favourite-flags>``` command will export the user provided flags into a configuration file",
|
||||
}
|
||||
|
||||
return strings.Join(items, "\n\n")
|
||||
}
|
||||
|
||||
// Help implements the cli.Command interface
|
||||
func (c *DumpconfigCommand) Help() string {
|
||||
return `Usage: bor dumpconfig <your-favourite-flags>
|
||||
|
||||
This command will will export the user provided flags into a configuration file`
|
||||
}
|
||||
|
||||
// Synopsis implements the cli.Command interface
|
||||
func (c *DumpconfigCommand) Synopsis() string {
|
||||
return "Export configuration file"
|
||||
}
|
||||
|
||||
// TODO: add flags for file location and format (toml, json, hcl) of the configuration file.
|
||||
|
||||
// Run implements the cli.Command interface
|
||||
func (c *DumpconfigCommand) Run(args []string) int {
|
||||
// Initialize an empty command instance to get flags
|
||||
command := server.Command{}
|
||||
flags := command.Flags()
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
userConfig := command.GetConfig()
|
||||
|
||||
// convert the big.Int and time.Duration fields to their corresponding Raw fields
|
||||
userConfig.TxPool.RejournalRaw = userConfig.TxPool.Rejournal.String()
|
||||
userConfig.TxPool.LifeTimeRaw = userConfig.TxPool.LifeTime.String()
|
||||
userConfig.Sealer.GasPriceRaw = userConfig.Sealer.GasPrice.String()
|
||||
userConfig.Gpo.MaxPriceRaw = userConfig.Gpo.MaxPrice.String()
|
||||
userConfig.Gpo.IgnorePriceRaw = userConfig.Gpo.IgnorePrice.String()
|
||||
userConfig.Cache.RejournalRaw = userConfig.Cache.Rejournal.String()
|
||||
|
||||
// Currently, the configurations (userConfig) is exported into `toml` file format.
|
||||
out, err := tomlSettings.Marshal(&userConfig)
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
c.UI.Output(string(out))
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
@ -180,14 +180,15 @@ func (b *BigIntFlag) Set(value string) error {
|
|||
var ok bool
|
||||
if strings.HasPrefix(value, "0x") {
|
||||
num, ok = num.SetString(value[2:], 16)
|
||||
*b.Value = *num
|
||||
} else {
|
||||
num, ok = num.SetString(value, 10)
|
||||
*b.Value = *num
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to set big int")
|
||||
}
|
||||
b.Value = num
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -209,6 +210,19 @@ type SliceStringFlag struct {
|
|||
Group string
|
||||
}
|
||||
|
||||
// SplitAndTrim splits input separated by a comma
|
||||
// and trims excessive white space from the substrings.
|
||||
func SplitAndTrim(input string) (ret []string) {
|
||||
l := strings.Split(input, ",")
|
||||
for _, r := range l {
|
||||
if r = strings.TrimSpace(r); r != "" {
|
||||
ret = append(ret, r)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (i *SliceStringFlag) String() string {
|
||||
if i.Value == nil {
|
||||
return ""
|
||||
|
|
@ -219,7 +233,7 @@ func (i *SliceStringFlag) String() string {
|
|||
|
||||
func (i *SliceStringFlag) Set(value string) error {
|
||||
// overwritting insted of appending
|
||||
*i.Value = strings.Split(value, ",")
|
||||
*i.Value = SplitAndTrim(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ import (
|
|||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/mitchellh/cli"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
// Command is the command to start the sever
|
||||
|
|
@ -21,7 +22,7 @@ type Command struct {
|
|||
// final configuration
|
||||
config *Config
|
||||
|
||||
configFile []string
|
||||
configFile string
|
||||
|
||||
srv *Server
|
||||
}
|
||||
|
|
@ -50,34 +51,57 @@ func (c *Command) Synopsis() string {
|
|||
return "Run the Bor server"
|
||||
}
|
||||
|
||||
// Run implements the cli.Command interface
|
||||
func (c *Command) Run(args []string) int {
|
||||
func (c *Command) extractFlags(args []string) error {
|
||||
config := *DefaultConfig()
|
||||
|
||||
flags := c.Flags()
|
||||
if err := flags.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
c.config = &config
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// read config file
|
||||
config := DefaultConfig()
|
||||
for _, configFile := range c.configFile {
|
||||
cfg, err := readConfigFile(configFile)
|
||||
// TODO: Check if this can be removed or not
|
||||
// read cli flags
|
||||
if err := config.Merge(c.cliConfig); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
c.config = &config
|
||||
|
||||
return err
|
||||
}
|
||||
// read if config file is provided, this will overwrite the cli flags, if provided
|
||||
if c.configFile != "" {
|
||||
log.Warn("Config File provided, this will overwrite the cli flags.", "configFile:", c.configFile)
|
||||
cfg, err := readConfigFile(c.configFile)
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
c.config = &config
|
||||
|
||||
return err
|
||||
}
|
||||
if err := config.Merge(cfg); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
c.config = &config
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
c.config = &config
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run implements the cli.Command interface
|
||||
func (c *Command) Run(args []string) int {
|
||||
err := c.extractFlags(args)
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
if err := config.Merge(cfg); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if err := config.Merge(c.cliConfig); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
c.config = config
|
||||
|
||||
srv, err := NewServer(config)
|
||||
srv, err := NewServer(c.config)
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
|
|
@ -112,3 +136,8 @@ func (c *Command) handleSignals() int {
|
|||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// GetConfig returns the user specified config
|
||||
func (c *Command) GetConfig() *Config {
|
||||
return c.cliConfig
|
||||
}
|
||||
|
|
|
|||
50
internal/cli/server/command_test.go
Normal file
50
internal/cli/server/command_test.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFlags(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var c Command
|
||||
|
||||
args := []string{
|
||||
"--txpool.rejournal", "30m0s",
|
||||
"--txpool.lifetime", "30m0s",
|
||||
"--miner.gasprice", "20000000000",
|
||||
"--gpo.maxprice", "70000000000",
|
||||
"--gpo.ignoreprice", "1",
|
||||
"--cache.trie.rejournal", "40m0s",
|
||||
"--dev",
|
||||
"--dev.period", "2",
|
||||
"--datadir", "./data",
|
||||
"--maxpeers", "30",
|
||||
"--requiredblocks", "a=b",
|
||||
"--http.api", "eth,web3,bor",
|
||||
}
|
||||
err := c.extractFlags(args)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
txRe, _ := time.ParseDuration("30m0s")
|
||||
txLt, _ := time.ParseDuration("30m0s")
|
||||
caRe, _ := time.ParseDuration("40m0s")
|
||||
|
||||
require.Equal(t, c.config.DataDir, "./data")
|
||||
require.Equal(t, c.config.Developer.Enabled, true)
|
||||
require.Equal(t, c.config.Developer.Period, uint64(2))
|
||||
require.Equal(t, c.config.TxPool.Rejournal, txRe)
|
||||
require.Equal(t, c.config.TxPool.LifeTime, txLt)
|
||||
require.Equal(t, c.config.Sealer.GasPrice, big.NewInt(20000000000))
|
||||
require.Equal(t, c.config.Gpo.MaxPrice, big.NewInt(70000000000))
|
||||
require.Equal(t, c.config.Gpo.IgnorePrice, big.NewInt(1))
|
||||
require.Equal(t, c.config.Cache.Rejournal, caRe)
|
||||
require.Equal(t, c.config.P2P.MaxPeers, uint64(30))
|
||||
require.Equal(t, c.config.RequiredBlocks, map[string]string{"a": "b"})
|
||||
require.Equal(t, c.config.JsonRPC.Http.API, []string{"eth", "web3", "bor"})
|
||||
}
|
||||
|
|
@ -14,6 +14,11 @@ import (
|
|||
|
||||
godebug "runtime/debug"
|
||||
|
||||
"github.com/hashicorp/hcl/v2/hclsimple"
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
gopsutil "github.com/shirou/gopsutil/mem"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -28,363 +33,359 @@ import (
|
|||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/hashicorp/hcl/v2/hclsimple"
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
gopsutil "github.com/shirou/gopsutil/mem"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
chain *chains.Chain
|
||||
|
||||
// Chain is the chain to sync with
|
||||
Chain string `hcl:"chain,optional"`
|
||||
Chain string `hcl:"chain,optional" toml:"chain,optional"`
|
||||
|
||||
// Identity of the node
|
||||
Identity string `hcl:"identity,optional"`
|
||||
Identity string `hcl:"identity,optional" toml:"identity,optional"`
|
||||
|
||||
// RequiredBlocks is a list of required (block number, hash) pairs to accept
|
||||
RequiredBlocks map[string]string `hcl:"requiredblocks,optional"`
|
||||
RequiredBlocks map[string]string `hcl:"requiredblocks,optional" toml:"requiredblocks,optional"`
|
||||
|
||||
// LogLevel is the level of the logs to put out
|
||||
LogLevel string `hcl:"log-level,optional"`
|
||||
LogLevel string `hcl:"log-level,optional" toml:"log-level,optional"`
|
||||
|
||||
// DataDir is the directory to store the state in
|
||||
DataDir string `hcl:"data-dir,optional"`
|
||||
DataDir string `hcl:"datadir,optional" toml:"datadir,optional"`
|
||||
|
||||
// KeyStoreDir is the directory to store keystores
|
||||
KeyStoreDir string `hcl:"keystore-dir,optional"`
|
||||
KeyStoreDir string `hcl:"keystore,optional" toml:"keystore,optional"`
|
||||
|
||||
// SyncMode selects the sync protocol
|
||||
SyncMode string `hcl:"sync-mode,optional"`
|
||||
SyncMode string `hcl:"syncmode,optional" toml:"syncmode,optional"`
|
||||
|
||||
// GcMode selects the garbage collection mode for the trie
|
||||
GcMode string `hcl:"gc-mode,optional"`
|
||||
GcMode string `hcl:"gcmode,optional" toml:"gcmode,optional"`
|
||||
|
||||
// Snapshot disables/enables the snapshot database mode
|
||||
Snapshot bool `hcl:"snapshot,optional"`
|
||||
Snapshot bool `hcl:"snapshot,optional" toml:"snapshot,optional"`
|
||||
|
||||
// Ethstats is the address of the ethstats server to send telemetry
|
||||
Ethstats string `hcl:"ethstats,optional"`
|
||||
Ethstats string `hcl:"ethstats,optional" toml:"ethstats,optional"`
|
||||
|
||||
// P2P has the p2p network related settings
|
||||
P2P *P2PConfig `hcl:"p2p,block"`
|
||||
P2P *P2PConfig `hcl:"p2p,block" toml:"p2p,block"`
|
||||
|
||||
// Heimdall has the heimdall connection related settings
|
||||
Heimdall *HeimdallConfig `hcl:"heimdall,block"`
|
||||
Heimdall *HeimdallConfig `hcl:"heimdall,block" toml:"heimdall,block"`
|
||||
|
||||
// TxPool has the transaction pool related settings
|
||||
TxPool *TxPoolConfig `hcl:"txpool,block"`
|
||||
TxPool *TxPoolConfig `hcl:"txpool,block" toml:"txpool,block"`
|
||||
|
||||
// Sealer has the validator related settings
|
||||
Sealer *SealerConfig `hcl:"sealer,block"`
|
||||
Sealer *SealerConfig `hcl:"miner,block" toml:"miner,block"`
|
||||
|
||||
// JsonRPC has the json-rpc related settings
|
||||
JsonRPC *JsonRPCConfig `hcl:"jsonrpc,block"`
|
||||
JsonRPC *JsonRPCConfig `hcl:"jsonrpc,block" toml:"jsonrpc,block"`
|
||||
|
||||
// Gpo has the gas price oracle related settings
|
||||
Gpo *GpoConfig `hcl:"gpo,block"`
|
||||
Gpo *GpoConfig `hcl:"gpo,block" toml:"gpo,block"`
|
||||
|
||||
// Telemetry has the telemetry related settings
|
||||
Telemetry *TelemetryConfig `hcl:"telemetry,block"`
|
||||
Telemetry *TelemetryConfig `hcl:"telemetry,block" toml:"telemetry,block"`
|
||||
|
||||
// Cache has the cache related settings
|
||||
Cache *CacheConfig `hcl:"cache,block"`
|
||||
Cache *CacheConfig `hcl:"cache,block" toml:"cache,block"`
|
||||
|
||||
// Account has the validator account related settings
|
||||
Accounts *AccountsConfig `hcl:"accounts,block"`
|
||||
Accounts *AccountsConfig `hcl:"accounts,block" toml:"accounts,block"`
|
||||
|
||||
// GRPC has the grpc server related settings
|
||||
GRPC *GRPCConfig
|
||||
GRPC *GRPCConfig `hcl:"grpc,block" toml:"grpc,block"`
|
||||
|
||||
// Developer has the developer mode related settings
|
||||
Developer *DeveloperConfig
|
||||
Developer *DeveloperConfig `hcl:"developer,block" toml:"developer,block"`
|
||||
}
|
||||
|
||||
type P2PConfig struct {
|
||||
// MaxPeers sets the maximum number of connected peers
|
||||
MaxPeers uint64 `hcl:"max-peers,optional"`
|
||||
MaxPeers uint64 `hcl:"maxpeers,optional" toml:"maxpeers,optional"`
|
||||
|
||||
// MaxPendPeers sets the maximum number of pending connected peers
|
||||
MaxPendPeers uint64 `hcl:"max-pend-peers,optional"`
|
||||
MaxPendPeers uint64 `hcl:"maxpendpeers,optional" toml:"maxpendpeers,optional"`
|
||||
|
||||
// Bind is the bind address
|
||||
Bind string `hcl:"bind,optional"`
|
||||
Bind string `hcl:"bind,optional" toml:"bind,optional"`
|
||||
|
||||
// Port is the port number
|
||||
Port uint64 `hcl:"port,optional"`
|
||||
Port uint64 `hcl:"port,optional" toml:"port,optional"`
|
||||
|
||||
// NoDiscover is used to disable discovery
|
||||
NoDiscover bool `hcl:"no-discover,optional"`
|
||||
NoDiscover bool `hcl:"nodiscover,optional" toml:"nodiscover,optional"`
|
||||
|
||||
// NAT it used to set NAT options
|
||||
NAT string `hcl:"nat,optional"`
|
||||
NAT string `hcl:"nat,optional" toml:"nat,optional"`
|
||||
|
||||
// Discovery has the p2p discovery related settings
|
||||
Discovery *P2PDiscovery `hcl:"discovery,block"`
|
||||
Discovery *P2PDiscovery `hcl:"discovery,block" toml:"discovery,block"`
|
||||
}
|
||||
|
||||
type P2PDiscovery struct {
|
||||
// V5Enabled is used to enable disc v5 discovery mode
|
||||
V5Enabled bool `hcl:"v5-enabled,optional"`
|
||||
V5Enabled bool `hcl:"v5disc,optional" toml:"v5disc,optional"`
|
||||
|
||||
// Bootnodes is the list of initial bootnodes
|
||||
Bootnodes []string `hcl:"bootnodes,optional"`
|
||||
Bootnodes []string `hcl:"bootnodes,optional" toml:"bootnodes,optional"`
|
||||
|
||||
// BootnodesV4 is the list of initial v4 bootnodes
|
||||
BootnodesV4 []string `hcl:"bootnodesv4,optional"`
|
||||
BootnodesV4 []string `hcl:"bootnodesv4,optional" toml:"bootnodesv4,optional"`
|
||||
|
||||
// BootnodesV5 is the list of initial v5 bootnodes
|
||||
BootnodesV5 []string `hcl:"bootnodesv5,optional"`
|
||||
BootnodesV5 []string `hcl:"bootnodesv5,optional" toml:"bootnodesv5,optional"`
|
||||
|
||||
// StaticNodes is the list of static nodes
|
||||
StaticNodes []string `hcl:"static-nodes,optional"`
|
||||
StaticNodes []string `hcl:"static-nodes,optional" toml:"static-nodes,optional"`
|
||||
|
||||
// TrustedNodes is the list of trusted nodes
|
||||
TrustedNodes []string `hcl:"trusted-nodes,optional"`
|
||||
TrustedNodes []string `hcl:"trusted-nodes,optional" toml:"trusted-nodes,optional"`
|
||||
|
||||
// DNS is the list of enrtree:// URLs which will be queried for nodes to connect to
|
||||
DNS []string `hcl:"dns,optional"`
|
||||
DNS []string `hcl:"dns,optional" toml:"dns,optional"`
|
||||
}
|
||||
|
||||
type HeimdallConfig struct {
|
||||
// URL is the url of the heimdall server
|
||||
URL string `hcl:"url,optional"`
|
||||
URL string `hcl:"url,optional" toml:"url,optional"`
|
||||
|
||||
// Without is used to disable remote heimdall during testing
|
||||
Without bool `hcl:"without,optional"`
|
||||
Without bool `hcl:"bor.without,optional" toml:"bor.without,optional"`
|
||||
|
||||
// GRPCAddress is the address of the heimdall grpc server
|
||||
GRPCAddress string `hcl:"grpc-address,optional"`
|
||||
GRPCAddress string `hcl:"grpc-address,optional" toml:"grpc-address,optional"`
|
||||
}
|
||||
|
||||
type TxPoolConfig struct {
|
||||
// Locals are the addresses that should be treated by default as local
|
||||
Locals []string `hcl:"locals,optional"`
|
||||
Locals []string `hcl:"locals,optional" toml:"locals,optional"`
|
||||
|
||||
// NoLocals enables whether local transaction handling should be disabled
|
||||
NoLocals bool `hcl:"no-locals,optional"`
|
||||
NoLocals bool `hcl:"nolocals,optional" toml:"nolocals,optional"`
|
||||
|
||||
// Journal is the path to store local transactions to survive node restarts
|
||||
Journal string `hcl:"journal,optional"`
|
||||
Journal string `hcl:"journal,optional" toml:"journal,optional"`
|
||||
|
||||
// Rejournal is the time interval to regenerate the local transaction journal
|
||||
Rejournal time.Duration
|
||||
RejournalRaw string `hcl:"rejournal,optional"`
|
||||
Rejournal time.Duration `hcl:"-,optional" toml:"-,optional"`
|
||||
RejournalRaw string `hcl:"rejournal,optional" toml:"rejournal,optional"`
|
||||
|
||||
// PriceLimit is the minimum gas price to enforce for acceptance into the pool
|
||||
PriceLimit uint64 `hcl:"price-limit,optional"`
|
||||
PriceLimit uint64 `hcl:"pricelimit,optional" toml:"pricelimit,optional"`
|
||||
|
||||
// PriceBump is the minimum price bump percentage to replace an already existing transaction (nonce)
|
||||
PriceBump uint64 `hcl:"price-bump,optional"`
|
||||
PriceBump uint64 `hcl:"pricebump,optional" toml:"pricebump,optional"`
|
||||
|
||||
// AccountSlots is the number of executable transaction slots guaranteed per account
|
||||
AccountSlots uint64 `hcl:"account-slots,optional"`
|
||||
AccountSlots uint64 `hcl:"accountslots,optional" toml:"accountslots,optional"`
|
||||
|
||||
// GlobalSlots is the maximum number of executable transaction slots for all accounts
|
||||
GlobalSlots uint64 `hcl:"global-slots,optional"`
|
||||
GlobalSlots uint64 `hcl:"globalslots,optional" toml:"globalslots,optional"`
|
||||
|
||||
// AccountQueue is the maximum number of non-executable transaction slots permitted per account
|
||||
AccountQueue uint64 `hcl:"account-queue,optional"`
|
||||
AccountQueue uint64 `hcl:"accountqueue,optional" toml:"accountqueue,optional"`
|
||||
|
||||
// GlobalQueueis the maximum number of non-executable transaction slots for all accounts
|
||||
GlobalQueue uint64 `hcl:"global-queue,optional"`
|
||||
GlobalQueue uint64 `hcl:"globalqueue,optional" toml:"globalqueue,optional"`
|
||||
|
||||
// Lifetime is the maximum amount of time non-executable transaction are queued
|
||||
LifeTime time.Duration
|
||||
LifeTimeRaw string `hcl:"lifetime,optional"`
|
||||
// lifetime is the maximum amount of time non-executable transaction are queued
|
||||
LifeTime time.Duration `hcl:"-,optional" toml:"-,optional"`
|
||||
LifeTimeRaw string `hcl:"lifetime,optional" toml:"lifetime,optional"`
|
||||
}
|
||||
|
||||
type SealerConfig struct {
|
||||
// Enabled is used to enable validator mode
|
||||
Enabled bool `hcl:"enabled,optional"`
|
||||
Enabled bool `hcl:"mine,optional" toml:"mine,optional"`
|
||||
|
||||
// Etherbase is the address of the validator
|
||||
Etherbase string `hcl:"etherbase,optional"`
|
||||
Etherbase string `hcl:"etherbase,optional" toml:"etherbase,optional"`
|
||||
|
||||
// ExtraData is the block extra data set by the miner
|
||||
ExtraData string `hcl:"extra-data,optional"`
|
||||
ExtraData string `hcl:"extradata,optional" toml:"extradata,optional"`
|
||||
|
||||
// GasCeil is the target gas ceiling for mined blocks.
|
||||
GasCeil uint64 `hcl:"gas-ceil,optional"`
|
||||
GasCeil uint64 `hcl:"gaslimit,optional" toml:"gaslimit,optional"`
|
||||
|
||||
// GasPrice is the minimum gas price for mining a transaction
|
||||
GasPrice *big.Int
|
||||
GasPriceRaw string `hcl:"gas-price,optional"`
|
||||
GasPrice *big.Int `hcl:"-,optional" toml:"-,optional"`
|
||||
GasPriceRaw string `hcl:"gasprice,optional" toml:"gasprice,optional"`
|
||||
}
|
||||
|
||||
type JsonRPCConfig struct {
|
||||
// IPCDisable enables whether ipc is enabled or not
|
||||
IPCDisable bool `hcl:"ipc-disable,optional"`
|
||||
IPCDisable bool `hcl:"ipcdisable,optional" toml:"ipcdisable,optional"`
|
||||
|
||||
// IPCPath is the path of the ipc endpoint
|
||||
IPCPath string `hcl:"ipc-path,optional"`
|
||||
IPCPath string `hcl:"ipcpath,optional" toml:"ipcpath,optional"`
|
||||
|
||||
// GasCap is the global gas cap for eth-call variants.
|
||||
GasCap uint64 `hcl:"gas-cap,optional"`
|
||||
GasCap uint64 `hcl:"gascap,optional" toml:"gascap,optional"`
|
||||
|
||||
// TxFeeCap is the global transaction fee cap for send-transaction variants
|
||||
TxFeeCap float64 `hcl:"tx-fee-cap,optional"`
|
||||
TxFeeCap float64 `hcl:"txfeecap,optional" toml:"txfeecap,optional"`
|
||||
|
||||
// Http has the json-rpc http related settings
|
||||
Http *APIConfig `hcl:"http,block"`
|
||||
Http *APIConfig `hcl:"http,block" toml:"http,block"`
|
||||
|
||||
// Ws has the json-rpc websocket related settings
|
||||
Ws *APIConfig `hcl:"ws,block"`
|
||||
Ws *APIConfig `hcl:"ws,block" toml:"ws,block"`
|
||||
|
||||
// Graphql has the json-rpc graphql related settings
|
||||
Graphql *APIConfig `hcl:"graphql,block"`
|
||||
Graphql *APIConfig `hcl:"graphql,block" toml:"graphql,block"`
|
||||
}
|
||||
|
||||
type GRPCConfig struct {
|
||||
// Addr is the bind address for the grpc rpc server
|
||||
Addr string
|
||||
Addr string `hcl:"addr,optional" toml:"addr,optional"`
|
||||
}
|
||||
|
||||
type APIConfig struct {
|
||||
// Enabled selects whether the api is enabled
|
||||
Enabled bool `hcl:"enabled,optional"`
|
||||
Enabled bool `hcl:"enabled,optional" toml:"enabled,optional"`
|
||||
|
||||
// Port is the port number for this api
|
||||
Port uint64 `hcl:"port,optional"`
|
||||
Port uint64 `hcl:"port,optional" toml:"port,optional"`
|
||||
|
||||
// Prefix is the http prefix to expose this api
|
||||
Prefix string `hcl:"prefix,optional"`
|
||||
Prefix string `hcl:"prefix,optional" toml:"prefix,optional"`
|
||||
|
||||
// Host is the address to bind the api
|
||||
Host string `hcl:"host,optional"`
|
||||
Host string `hcl:"host,optional" toml:"host,optional"`
|
||||
|
||||
// Modules is the list of enabled api modules
|
||||
API []string `hcl:"modules,optional"`
|
||||
// API is the list of enabled api modules
|
||||
API []string `hcl:"api,optional" toml:"api,optional"`
|
||||
|
||||
// VHost is the list of valid virtual hosts
|
||||
VHost []string `hcl:"vhost,optional"`
|
||||
VHost []string `hcl:"vhosts,optional" toml:"vhosts,optional"`
|
||||
|
||||
// Cors is the list of Cors endpoints
|
||||
Cors []string `hcl:"cors,optional"`
|
||||
Cors []string `hcl:"corsdomain,optional" toml:"corsdomain,optional"`
|
||||
}
|
||||
|
||||
type GpoConfig struct {
|
||||
// Blocks is the number of blocks to track to compute the price oracle
|
||||
Blocks uint64 `hcl:"blocks,optional"`
|
||||
Blocks uint64 `hcl:"blocks,optional" toml:"blocks,optional"`
|
||||
|
||||
// Percentile sets the weights to new blocks
|
||||
Percentile uint64 `hcl:"percentile,optional"`
|
||||
Percentile uint64 `hcl:"percentile,optional" toml:"percentile,optional"`
|
||||
|
||||
// MaxPrice is an upper bound gas price
|
||||
MaxPrice *big.Int
|
||||
MaxPriceRaw string `hcl:"max-price,optional"`
|
||||
MaxPrice *big.Int `hcl:"-,optional" toml:"-,optional"`
|
||||
MaxPriceRaw string `hcl:"maxprice,optional" toml:"maxprice,optional"`
|
||||
|
||||
// IgnorePrice is a lower bound gas price
|
||||
IgnorePrice *big.Int
|
||||
IgnorePriceRaw string `hcl:"ignore-price,optional"`
|
||||
IgnorePrice *big.Int `hcl:"-,optional" toml:"-,optional"`
|
||||
IgnorePriceRaw string `hcl:"ignoreprice,optional" toml:"ignoreprice,optional"`
|
||||
}
|
||||
|
||||
type TelemetryConfig struct {
|
||||
// Enabled enables metrics
|
||||
Enabled bool `hcl:"enabled,optional"`
|
||||
Enabled bool `hcl:"metrics,optional" toml:"metrics,optional"`
|
||||
|
||||
// Expensive enables expensive metrics
|
||||
Expensive bool `hcl:"expensive,optional"`
|
||||
Expensive bool `hcl:"expensive,optional" toml:"expensive,optional"`
|
||||
|
||||
// InfluxDB has the influxdb related settings
|
||||
InfluxDB *InfluxDBConfig `hcl:"influx,block"`
|
||||
InfluxDB *InfluxDBConfig `hcl:"influx,block" toml:"influx,block"`
|
||||
|
||||
// Prometheus Address
|
||||
PrometheusAddr string `hcl:"prometheus-addr,optional"`
|
||||
PrometheusAddr string `hcl:"prometheus-addr,optional" toml:"prometheus-addr,optional"`
|
||||
|
||||
// Open collector endpoint
|
||||
OpenCollectorEndpoint string `hcl:"opencollector-endpoint,optional"`
|
||||
OpenCollectorEndpoint string `hcl:"opencollector-endpoint,optional" toml:"opencollector-endpoint,optional"`
|
||||
}
|
||||
|
||||
type InfluxDBConfig struct {
|
||||
// V1Enabled enables influx v1 mode
|
||||
V1Enabled bool `hcl:"v1-enabled,optional"`
|
||||
V1Enabled bool `hcl:"influxdb,optional" toml:"influxdb,optional"`
|
||||
|
||||
// Endpoint is the url endpoint of the influxdb service
|
||||
Endpoint string `hcl:"endpoint,optional"`
|
||||
Endpoint string `hcl:"endpoint,optional" toml:"endpoint,optional"`
|
||||
|
||||
// Database is the name of the database in Influxdb to store the metrics.
|
||||
Database string `hcl:"database,optional"`
|
||||
Database string `hcl:"database,optional" toml:"database,optional"`
|
||||
|
||||
// Enabled is the username to authorize access to Influxdb
|
||||
Username string `hcl:"username,optional"`
|
||||
Username string `hcl:"username,optional" toml:"username,optional"`
|
||||
|
||||
// Password is the password to authorize access to Influxdb
|
||||
Password string `hcl:"password,optional"`
|
||||
Password string `hcl:"password,optional" toml:"password,optional"`
|
||||
|
||||
// Tags are tags attaches to all generated metrics
|
||||
Tags map[string]string `hcl:"tags,optional"`
|
||||
Tags map[string]string `hcl:"tags,optional" toml:"tags,optional"`
|
||||
|
||||
// Enabled enables influx v2 mode
|
||||
V2Enabled bool `hcl:"v2-enabled,optional"`
|
||||
V2Enabled bool `hcl:"influxdbv2,optional" toml:"influxdbv2,optional"`
|
||||
|
||||
// Token is the token to authorize access to Influxdb V2.
|
||||
Token string `hcl:"token,optional"`
|
||||
Token string `hcl:"token,optional" toml:"token,optional"`
|
||||
|
||||
// Bucket is the bucket to store metrics in Influxdb V2.
|
||||
Bucket string `hcl:"bucket,optional"`
|
||||
Bucket string `hcl:"bucket,optional" toml:"bucket,optional"`
|
||||
|
||||
// Organization is the name of the organization for Influxdb V2.
|
||||
Organization string `hcl:"organization,optional"`
|
||||
Organization string `hcl:"organization,optional" toml:"organization,optional"`
|
||||
}
|
||||
|
||||
type CacheConfig struct {
|
||||
// Cache is the amount of cache of the node
|
||||
Cache uint64 `hcl:"cache,optional"`
|
||||
Cache uint64 `hcl:"cache,optional" toml:"cache,optional"`
|
||||
|
||||
// PercGc is percentage of cache used for garbage collection
|
||||
PercGc uint64 `hcl:"perc-gc,optional"`
|
||||
PercGc uint64 `hcl:"gc,optional" toml:"gc,optional"`
|
||||
|
||||
// PercSnapshot is percentage of cache used for snapshots
|
||||
PercSnapshot uint64 `hcl:"perc-snapshot,optional"`
|
||||
PercSnapshot uint64 `hcl:"snapshot,optional" toml:"snapshot,optional"`
|
||||
|
||||
// PercDatabase is percentage of cache used for the database
|
||||
PercDatabase uint64 `hcl:"perc-database,optional"`
|
||||
PercDatabase uint64 `hcl:"database,optional" toml:"database,optional"`
|
||||
|
||||
// PercTrie is percentage of cache used for the trie
|
||||
PercTrie uint64 `hcl:"perc-trie,optional"`
|
||||
PercTrie uint64 `hcl:"trie,optional" toml:"trie,optional"`
|
||||
|
||||
// Journal is the disk journal directory for trie cache to survive node restarts
|
||||
Journal string `hcl:"journal,optional"`
|
||||
Journal string `hcl:"journal,optional" toml:"journal,optional"`
|
||||
|
||||
// Rejournal is the time interval to regenerate the journal for clean cache
|
||||
Rejournal time.Duration
|
||||
RejournalRaw string `hcl:"rejournal,optional"`
|
||||
Rejournal time.Duration `hcl:"-,optional" toml:"-,optional"`
|
||||
RejournalRaw string `hcl:"rejournal,optional" toml:"rejournal,optional"`
|
||||
|
||||
// NoPrefetch is used to disable prefetch of tries
|
||||
NoPrefetch bool `hcl:"no-prefetch,optional"`
|
||||
NoPrefetch bool `hcl:"noprefetch,optional" toml:"noprefetch,optional"`
|
||||
|
||||
// Preimages is used to enable the track of hash preimages
|
||||
Preimages bool `hcl:"preimages,optional"`
|
||||
Preimages bool `hcl:"preimages,optional" toml:"preimages,optional"`
|
||||
|
||||
// TxLookupLimit sets the maximum number of blocks from head whose tx indices are reserved.
|
||||
TxLookupLimit uint64 `hcl:"tx-lookup-limit,optional"`
|
||||
TxLookupLimit uint64 `hcl:"txlookuplimit,optional" toml:"txlookuplimit,optional"`
|
||||
}
|
||||
|
||||
type AccountsConfig struct {
|
||||
// Unlock is the list of addresses to unlock in the node
|
||||
Unlock []string `hcl:"unlock,optional"`
|
||||
Unlock []string `hcl:"unlock,optional" toml:"unlock,optional"`
|
||||
|
||||
// PasswordFile is the file where the account passwords are stored
|
||||
PasswordFile string `hcl:"password-file,optional"`
|
||||
PasswordFile string `hcl:"password,optional" toml:"password,optional"`
|
||||
|
||||
// AllowInsecureUnlock allows user to unlock accounts in unsafe http environment.
|
||||
AllowInsecureUnlock bool `hcl:"allow-insecure-unlock,optional"`
|
||||
AllowInsecureUnlock bool `hcl:"allow-insecure-unlock,optional" toml:"allow-insecure-unlock,optional"`
|
||||
|
||||
// UseLightweightKDF enables a faster but less secure encryption of accounts
|
||||
UseLightweightKDF bool `hcl:"use-lightweight-kdf,optional"`
|
||||
UseLightweightKDF bool `hcl:"lightkdf,optional" toml:"lightkdf,optional"`
|
||||
|
||||
// DisableBorWallet disables the personal wallet endpoints
|
||||
DisableBorWallet bool `hcl:"disable-bor-wallet,optional"`
|
||||
DisableBorWallet bool `hcl:"disable-bor-wallet,optional" toml:"disable-bor-wallet,optional"`
|
||||
}
|
||||
|
||||
type DeveloperConfig struct {
|
||||
// Enabled enables the developer mode
|
||||
Enabled bool `hcl:"dev,optional"`
|
||||
Enabled bool `hcl:"dev,optional" toml:"dev,optional"`
|
||||
|
||||
// Period is the block period to use in developer mode
|
||||
Period uint64 `hcl:"period,optional"`
|
||||
Period uint64 `hcl:"period,optional" toml:"period,optional"`
|
||||
}
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
|
|
@ -423,14 +424,14 @@ func DefaultConfig() *Config {
|
|||
Locals: []string{},
|
||||
NoLocals: false,
|
||||
Journal: "",
|
||||
Rejournal: time.Duration(1 * time.Hour),
|
||||
Rejournal: 1 * time.Hour,
|
||||
PriceLimit: 30000000000,
|
||||
PriceBump: 10,
|
||||
AccountSlots: 16,
|
||||
GlobalSlots: 32768,
|
||||
AccountQueue: 16,
|
||||
GlobalQueue: 32768,
|
||||
LifeTime: time.Duration(3 * time.Hour),
|
||||
LifeTime: 3 * time.Hour,
|
||||
},
|
||||
Sealer: &SealerConfig{
|
||||
Enabled: false,
|
||||
|
|
@ -530,7 +531,7 @@ func (c *Config) fillBigInt() error {
|
|||
}{
|
||||
{"gpo.maxprice", &c.Gpo.MaxPrice, &c.Gpo.MaxPriceRaw},
|
||||
{"gpo.ignoreprice", &c.Gpo.IgnorePrice, &c.Gpo.IgnorePriceRaw},
|
||||
{"sealer.gasprice", &c.Sealer.GasPrice, &c.Sealer.GasPriceRaw},
|
||||
{"miner.gasprice", &c.Sealer.GasPrice, &c.Sealer.GasPriceRaw},
|
||||
}
|
||||
|
||||
for _, x := range tds {
|
||||
|
|
@ -586,13 +587,7 @@ func (c *Config) fillTimeDurations() error {
|
|||
func readConfigFile(path string) (*Config, error) {
|
||||
ext := filepath.Ext(path)
|
||||
if ext == ".toml" {
|
||||
// read file and apply the legacy config
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return readLegacyConfig(data)
|
||||
return readLegacyConfig(path)
|
||||
}
|
||||
|
||||
config := &Config{
|
||||
|
|
@ -1081,7 +1076,7 @@ func Hostname() string {
|
|||
func MakePasswordListFromFile(path string) ([]string, error) {
|
||||
text, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to read password file: %v", err)
|
||||
return nil, fmt.Errorf("failed to read password file: %v", err)
|
||||
}
|
||||
|
||||
lines := strings.Split(string(text), "\n")
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/naoina/toml"
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
type legacyConfig struct {
|
||||
Node struct {
|
||||
P2P struct {
|
||||
StaticNodes []string
|
||||
TrustedNodes []string
|
||||
}
|
||||
}
|
||||
func readLegacyConfig(path string) (*Config, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
tomlData := string(data)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read toml config file: %v", err)
|
||||
}
|
||||
|
||||
func (l *legacyConfig) Config() *Config {
|
||||
c := DefaultConfig()
|
||||
c.P2P.Discovery.StaticNodes = l.Node.P2P.StaticNodes
|
||||
c.P2P.Discovery.TrustedNodes = l.Node.P2P.TrustedNodes
|
||||
return c
|
||||
var conf Config
|
||||
|
||||
if _, err := toml.Decode(tomlData, &conf); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode toml config file: %v", err)
|
||||
}
|
||||
|
||||
func readLegacyConfig(data []byte) (*Config, error) {
|
||||
var legacy legacyConfig
|
||||
|
||||
r := toml.NewDecoder(bytes.NewReader(data))
|
||||
if err := r.Decode(&legacy); err != nil {
|
||||
if err := conf.fillBigInt(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return legacy.Config(), nil
|
||||
|
||||
if err := conf.fillTimeDurations(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &conf, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,50 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConfigLegacy(t *testing.T) {
|
||||
toml := `[Node.P2P]
|
||||
StaticNodes = ["node1"]
|
||||
TrustedNodes = ["node2"]`
|
||||
|
||||
config, err := readLegacyConfig([]byte(toml))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
readFile := func(path string) {
|
||||
config, err := readLegacyConfig(path)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, config, &Config{
|
||||
DataDir: "./data",
|
||||
RequiredBlocks: map[string]string{
|
||||
"a": "b",
|
||||
},
|
||||
P2P: &P2PConfig{
|
||||
MaxPeers: 30,
|
||||
},
|
||||
TxPool: &TxPoolConfig{
|
||||
Locals: []string{},
|
||||
Rejournal: 1 * time.Hour,
|
||||
LifeTime: 1 * time.Second,
|
||||
},
|
||||
Gpo: &GpoConfig{
|
||||
MaxPrice: big.NewInt(100),
|
||||
IgnorePrice: big.NewInt(2),
|
||||
},
|
||||
Sealer: &SealerConfig{
|
||||
Enabled: false,
|
||||
GasCeil: 20000000,
|
||||
GasPrice: big.NewInt(30000000000),
|
||||
},
|
||||
Cache: &CacheConfig{
|
||||
Cache: 1024,
|
||||
Rejournal: 1 * time.Hour,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
assert.Equal(t, config.P2P.Discovery.StaticNodes, []string{"node1"})
|
||||
assert.Equal(t, config.P2P.Discovery.TrustedNodes, []string{"node2"})
|
||||
// read file in hcl format
|
||||
t.Run("toml", func(t *testing.T) {
|
||||
readFile("./testdata/test.toml")
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ func TestConfigLoadFile(t *testing.T) {
|
|||
MaxPeers: 30,
|
||||
},
|
||||
TxPool: &TxPoolConfig{
|
||||
LifeTime: time.Duration(1 * time.Second),
|
||||
LifeTime: 1 * time.Second,
|
||||
},
|
||||
Gpo: &GpoConfig{
|
||||
MaxPrice: big.NewInt(100),
|
||||
|
|
@ -127,12 +127,12 @@ func TestConfigLoadFile(t *testing.T) {
|
|||
|
||||
// read file in hcl format
|
||||
t.Run("hcl", func(t *testing.T) {
|
||||
readFile("./testdata/simple.hcl")
|
||||
readFile("./testdata/test.hcl")
|
||||
})
|
||||
|
||||
// read file in json format
|
||||
t.Run("json", func(t *testing.T) {
|
||||
readFile("./testdata/simple.json")
|
||||
readFile("./testdata/test.json")
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ func (c *Command) Flags() *flagset.Flagset {
|
|||
Usage: "Path of the directory to store keystores",
|
||||
Value: &c.cliConfig.KeyStoreDir,
|
||||
})
|
||||
f.SliceStringFlag(&flagset.SliceStringFlag{
|
||||
f.StringFlag(&flagset.StringFlag{
|
||||
Name: "config",
|
||||
Usage: "File for the config file",
|
||||
Value: &c.configFile,
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
package proto
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ package proto
|
|||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ import (
|
|||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
|
||||
)
|
||||
|
||||
func TestGatherBlocks(t *testing.T) {
|
||||
|
|
|
|||
15
internal/cli/server/testdata/simple.json
vendored
15
internal/cli/server/testdata/simple.json
vendored
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"data-dir": "./data",
|
||||
"requiredblocks": {
|
||||
"a": "b"
|
||||
},
|
||||
"p2p": {
|
||||
"max-peers": 30
|
||||
},
|
||||
"txpool": {
|
||||
"lifetime": "1s"
|
||||
},
|
||||
"gpo": {
|
||||
"max-price": "100"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
data-dir = "./data"
|
||||
datadir = "./data"
|
||||
|
||||
requiredblocks = {
|
||||
a = "b"
|
||||
}
|
||||
|
||||
p2p {
|
||||
max-peers = 30
|
||||
maxpeers = 30
|
||||
}
|
||||
|
||||
txpool {
|
||||
|
|
@ -13,5 +13,5 @@ txpool {
|
|||
}
|
||||
|
||||
gpo {
|
||||
max-price = "100"
|
||||
maxprice = "100"
|
||||
}
|
||||
15
internal/cli/server/testdata/test.json
vendored
Normal file
15
internal/cli/server/testdata/test.json
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"datadir": "./data",
|
||||
"requiredblocks": {
|
||||
"a": "b"
|
||||
},
|
||||
"p2p": {
|
||||
"maxpeers": 30
|
||||
},
|
||||
"txpool": {
|
||||
"lifetime": "1s"
|
||||
},
|
||||
"gpo": {
|
||||
"maxprice": "100"
|
||||
}
|
||||
}
|
||||
25
internal/cli/server/testdata/test.toml
vendored
Normal file
25
internal/cli/server/testdata/test.toml
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
datadir = "./data"
|
||||
|
||||
[requiredblocks]
|
||||
a = "b"
|
||||
|
||||
[p2p]
|
||||
maxpeers = 30
|
||||
|
||||
[txpool]
|
||||
locals = []
|
||||
rejournal = "1h0m0s"
|
||||
lifetime = "1s"
|
||||
|
||||
[miner]
|
||||
mine = false
|
||||
gaslimit = 20000000
|
||||
gasprice = "30000000000"
|
||||
|
||||
[gpo]
|
||||
maxprice = "100"
|
||||
ignoreprice = "2"
|
||||
|
||||
[cache]
|
||||
cache = 1024
|
||||
rejournal = "1h0m0s"
|
||||
Loading…
Reference in a new issue