diff --git a/.goreleaser.yml b/.goreleaser.yml index d09cc43206..7fbc61ca4a 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -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: diff --git a/builder/files/bor.service b/builder/files/bor.service index da0338368c..4b628cbf6e 100644 --- a/builder/files/bor.service +++ b/builder/files/bor.service @@ -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 diff --git a/builder/files/config.toml b/builder/files/config.toml new file mode 100644 index 0000000000..c55a143ed7 --- /dev/null +++ b/builder/files/config.toml @@ -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"] \ No newline at end of file diff --git a/docs/cli/README.md b/docs/cli/README.md index d92a7b5a05..3bc3daddc5 100644 --- a/docs/cli/README.md +++ b/docs/cli/README.md @@ -26,6 +26,8 @@ - [```debug pprof```](./debug_pprof.md) +- [```dumpconfig```](./dumpconfig.md) + - [```fingerprint```](./fingerprint.md) - [```peers```](./peers.md) diff --git a/docs/cli/dumpconfig.md b/docs/cli/dumpconfig.md new file mode 100644 index 0000000000..0383c47310 --- /dev/null +++ b/docs/cli/dumpconfig.md @@ -0,0 +1,3 @@ +# Dumpconfig + +The ```bor dumpconfig ``` command will export the user provided flags into a configuration file \ No newline at end of file diff --git a/docs/config.md b/docs/config.md index 4f4dec157b..196a0bf388 100644 --- a/docs/config.md +++ b/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 - bind = "0.0.0.0" - port = 30303 - no-discover = false - nat = "any" - discovery { - v5-enabled = false - bootnodes = [] - bootnodesv4 = [] - bootnodesv5 = [] - staticNodes = [] - trustedNodes = [] - dns = [] - } -} - -heimdall { - url = "http://localhost:1317" - without = false -} - -txpool { - locals = [] - no-locals = false - journal = "" - rejournal = "1h" - price-limit = 1 - price-bump = 10 - account-slots = 16 - global-slots = 4096 - account-queue = 64 - global-queue = 1024 - lifetime = "3h" -} - -sealer { - enabled = false - etherbase = "" - gas-ceil = 8000000 - extra-data = "" -} - -gpo { - blocks = 20 - percentile = 60 -} - -jsonrpc { - ipc-disable = false - ipc-path = "" - modules = ["web3", "net"] - cors = ["*"] - vhost = ["*"] - - http { - enabled = false - port = 8545 - prefix = "" - host = "localhost" - } - - ws { - enabled = false - port = 8546 - prefix = "" - host = "localhost" - } - - graphqh { - enabled = false - } -} - -telemetry { - enabled = false - expensive = false - - influxdb { - v1-enabled = false - endpoint = "" - database = "" - username = "" - password = "" - v2-enabled = false - token = "" - bucket = "" - organization = "" - } -} - -cache { - cache = 1024 - perc-database = 50 - perc-trie = 15 - perc-gc = 25 - perc-snapshot = 10 - journal = "triecache" - rejournal = "60m" - no-prefetch = false - preimages = false - tx-lookup-limit = 2350000 -} - -accounts { - unlock = [] - password-file = "" - allow-insecure-unlock = false - use-lightweight-kdf = false -} - -grpc { - addr = ":3131" -} + +[p2p] +maxpeers = 30 +maxpendpeers = 50 +bind = "0.0.0.0" +port = 30303 +nodiscover = false +nat = "any" + +[p2p.discovery] +v5disc = false +bootnodes = ["enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303"] +bootnodesv4 = [] +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] +url = "http://localhost:1317" +"bor.without" = false + +[txpool] +locals = ["$ADDRESS1", "$ADDRESS2"] +nolocals = false +journal = "" +rejournal = "1h0m0s" +pricelimit = 30000000000 +pricebump = 10 +accountslots = 16 +globalslots = 32768 +accountqueue = 16 +globalqueue = 32768 +lifetime = "3h0m0s" + +[miner] +mine = false +etherbase = "" +extradata = "" +gaslimit = 20000000 +gasprice = "30000000000" + +[jsonrpc] +ipcdisable = false +ipcpath = "/var/lib/bor/bor.ipc" +gascap = 50000000 +txfeecap = 5e+00 + +[jsonrpc.http] +enabled = false +port = 8545 +prefix = "" +host = "localhost" +api = ["eth", "net", "web3", "txpool", "bor"] +vhosts = ["*"] +corsdomain = ["*"] + +[jsonrpc.ws] +enabled = false +port = 8546 +prefix = "" +host = "localhost" +api = ["web3", "net"] +vhosts = ["*"] +corsdomain = ["*"] + +[jsonrpc.graphql] +enabled = false +port = 0 +prefix = "" +host = "" +api = [] +vhosts = ["*"] +corsdomain = ["*"] + +[gpo] +blocks = 20 +percentile = 60 +maxprice = "5000000000000" +ignoreprice = "2" + +[telemetry] +metrics = false +expensive = false +prometheus-addr = "" +opencollector-endpoint = "" + +[telemetry.influx] +influxdb = false +endpoint = "" +database = "" +username = "" +password = "" +influxdbv2 = false +token = "" +bucket = "" +organization = "" + +[cache] +cache = 1024 +gc = 25 +snapshot = 10 +database = 50 +trie = 15 +journal = "triecache" +rejournal = "1h0m0s" +noprefetch = false +preimages = false +txlookuplimit = 2350000 + +[accounts] +unlock = ["$ADDRESS1", "$ADDRESS2"] +password = "path/to/password.txt" +allow-insecure-unlock = false +lightkdf = false +disable-bor-wallet = false + +[grpc] +addr = ":3131" + +[developer] +dev = false +period = 0 ``` diff --git a/go.mod b/go.mod index 1b452a67a1..3f90695d47 100644 --- a/go.mod +++ b/go.mod @@ -83,6 +83,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 diff --git a/go.sum b/go.sum index 374ab3066e..fc58b621e6 100644 --- a/go.sum +++ b/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/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= @@ -456,6 +458,10 @@ 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 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 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= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= diff --git a/internal/cli/command.go b/internal/cli/command.go index 1ff95b410f..06127a9823 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -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, diff --git a/internal/cli/dumpconfig.go b/internal/cli/dumpconfig.go new file mode 100644 index 0000000000..3e4688fc24 --- /dev/null +++ b/internal/cli/dumpconfig.go @@ -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 ``` 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 + + 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 +} diff --git a/internal/cli/flagset/flagset.go b/internal/cli/flagset/flagset.go index 0c19fa9758..d9e204f0e4 100644 --- a/internal/cli/flagset/flagset.go +++ b/internal/cli/flagset/flagset.go @@ -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 } diff --git a/internal/cli/server/command.go b/internal/cli/server/command.go index a0b8a6d87c..2995f10f69 100644 --- a/internal/cli/server/command.go +++ b/internal/cli/server/command.go @@ -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()) - return 1 + c.config = &config + + return err } if err := config.Merge(cfg); err != nil { c.UI.Error(err.Error()) - return 1 + c.config = &config + + return err } } - if err := config.Merge(c.cliConfig); err != nil { + + 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 } - 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 +} diff --git a/internal/cli/server/command_test.go b/internal/cli/server/command_test.go new file mode 100644 index 0000000000..9006559d0f --- /dev/null +++ b/internal/cli/server/command_test.go @@ -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"}) +} diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index fdf253a37e..819ab1aca5 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -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,360 +33,356 @@ 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"` } 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 { @@ -419,14 +420,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, @@ -526,7 +527,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 { @@ -582,13 +583,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{ @@ -1076,7 +1071,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") diff --git a/internal/cli/server/config_legacy.go b/internal/cli/server/config_legacy.go index 0d96b2e023..50508a58b6 100644 --- a/internal/cli/server/config_legacy.go +++ b/internal/cli/server/config_legacy.go @@ -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 + if err := conf.fillBigInt(); err != nil { + return nil, err + } - r := toml.NewDecoder(bytes.NewReader(data)) - if err := r.Decode(&legacy); err != nil { + if err := conf.fillTimeDurations(); err != nil { return nil, err } - return legacy.Config(), nil + + return &conf, nil } diff --git a/internal/cli/server/config_legacy_test.go b/internal/cli/server/config_legacy_test.go index 399481fc9b..6fb662d62b 100644 --- a/internal/cli/server/config_legacy_test.go +++ b/internal/cli/server/config_legacy_test.go @@ -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") + }) } diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go index c1c6c4ef4a..bf7787ac2e 100644 --- a/internal/cli/server/config_test.go +++ b/internal/cli/server/config_test.go @@ -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") }) } diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index e85428b9ee..bbc7f44036 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -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, diff --git a/internal/cli/server/proto/server.pb.go b/internal/cli/server/proto/server.pb.go index 5512d83b72..3e928ac170 100644 --- a/internal/cli/server/proto/server.pb.go +++ b/internal/cli/server/proto/server.pb.go @@ -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 ( diff --git a/internal/cli/server/proto/server_grpc.pb.go b/internal/cli/server/proto/server_grpc.pb.go index 63f1fa6187..bd4ecb660d 100644 --- a/internal/cli/server/proto/server_grpc.pb.go +++ b/internal/cli/server/proto/server_grpc.pb.go @@ -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" diff --git a/internal/cli/server/service_test.go b/internal/cli/server/service_test.go index 7850525686..86cf68e75e 100644 --- a/internal/cli/server/service_test.go +++ b/internal/cli/server/service_test.go @@ -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) { diff --git a/internal/cli/server/testdata/simple.json b/internal/cli/server/testdata/simple.json deleted file mode 100644 index 6270ee6d13..0000000000 --- a/internal/cli/server/testdata/simple.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "data-dir": "./data", - "requiredblocks": { - "a": "b" - }, - "p2p": { - "max-peers": 30 - }, - "txpool": { - "lifetime": "1s" - }, - "gpo": { - "max-price": "100" - } -} \ No newline at end of file diff --git a/internal/cli/server/testdata/simple.hcl b/internal/cli/server/testdata/test.hcl similarity index 57% rename from internal/cli/server/testdata/simple.hcl rename to internal/cli/server/testdata/test.hcl index 5afc091859..208fdc51c1 100644 --- a/internal/cli/server/testdata/simple.hcl +++ b/internal/cli/server/testdata/test.hcl @@ -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" +} \ No newline at end of file diff --git a/internal/cli/server/testdata/test.json b/internal/cli/server/testdata/test.json new file mode 100644 index 0000000000..467835e755 --- /dev/null +++ b/internal/cli/server/testdata/test.json @@ -0,0 +1,15 @@ +{ + "datadir": "./data", + "requiredblocks": { + "a": "b" + }, + "p2p": { + "maxpeers": 30 + }, + "txpool": { + "lifetime": "1s" + }, + "gpo": { + "maxprice": "100" + } +} \ No newline at end of file diff --git a/internal/cli/server/testdata/test.toml b/internal/cli/server/testdata/test.toml new file mode 100644 index 0000000000..81fc4c4630 --- /dev/null +++ b/internal/cli/server/testdata/test.toml @@ -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"