fix tests

This commit is contained in:
Arpit Temani 2023-09-22 15:03:56 +05:30
commit 766a84558a
21 changed files with 620 additions and 141 deletions

View file

@ -2065,7 +2065,7 @@ func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconf
LogCacheSize: ethcfg.FilterLogCacheSize, LogCacheSize: ethcfg.FilterLogCacheSize,
}) })
filterAPI := filters.NewFilterAPI(filterSystem, isLightClient, ethconfig.Defaults.BorLogs) filterAPI := filters.NewFilterAPI(filterSystem, isLightClient, ethcfg.BorLogs)
stack.RegisterAPIs([]rpc.API{{ stack.RegisterAPIs([]rpc.API{{
Namespace: "eth", Namespace: "eth",
Service: filterAPI, Service: filterAPI,

View file

@ -5,17 +5,21 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/http"
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"strings" "strings"
"syscall" "syscall"
"time"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server" "github.com/ethereum/go-ethereum/internal/cli/server"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/metrics/prometheus"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
@ -26,14 +30,16 @@ import (
type BootnodeCommand struct { type BootnodeCommand struct {
UI cli.Ui UI cli.Ui
listenAddr string listenAddr string
v5 bool enableMetrics bool
verbosity int prometheusAddr string
logLevel string v5 bool
nat string verbosity int
nodeKey string logLevel string
saveKey string nat string
dryRun bool nodeKey string
saveKey string
dryRun bool
} }
// Help implements the cli.Command interface // Help implements the cli.Command interface
@ -60,6 +66,18 @@ func (b *BootnodeCommand) Flags() *flagset.Flagset {
Usage: "listening address of bootnode (<ip>:<port>)", Usage: "listening address of bootnode (<ip>:<port>)",
Value: &b.listenAddr, Value: &b.listenAddr,
}) })
flags.BoolFlag(&flagset.BoolFlag{
Name: "metrics",
Usage: "Enable metrics collection and reporting",
Value: &b.enableMetrics,
Default: true,
})
flags.StringFlag(&flagset.StringFlag{
Name: "prometheus-addr",
Default: "127.0.0.1:7071",
Usage: "listening address of bootnode (<ip>:<port>)",
Value: &b.prometheusAddr,
})
flags.BoolFlag(&flagset.BoolFlag{ flags.BoolFlag(&flagset.BoolFlag{
Name: "v5", Name: "v5",
Default: false, Default: false,
@ -237,6 +255,26 @@ func (b *BootnodeCommand) Run(args []string) int {
} }
} }
if b.enableMetrics {
prometheusMux := http.NewServeMux()
prometheusMux.Handle("/debug/metrics/prometheus", prometheus.Handler(metrics.DefaultRegistry))
promServer := &http.Server{
Addr: b.prometheusAddr,
Handler: prometheusMux,
ReadHeaderTimeout: 30 * time.Second,
}
go func() {
if err := promServer.ListenAndServe(); err != nil {
log.Error("Failure in running Prometheus server", "err", err)
}
}()
log.Info("Enabling metrics export to prometheus", "path", fmt.Sprintf("http://%s/debug/metrics/prometheus", b.prometheusAddr))
}
signalCh := make(chan os.Signal, 4) signalCh := make(chan os.Signal, 4)
signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP) signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)

View file

@ -42,7 +42,7 @@ func (c *DumpconfigCommand) Synopsis() string {
func (c *DumpconfigCommand) Run(args []string) int { func (c *DumpconfigCommand) Run(args []string) int {
// Initialize an empty command instance to get flags // Initialize an empty command instance to get flags
command := server.Command{} command := server.Command{}
flags := command.Flags() flags := command.Flags(nil)
if err := flags.Parse(args); err != nil { if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error()) c.UI.Error(err.Error())

View file

@ -5,33 +5,42 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"sort" "sort"
"strconv"
"strings" "strings"
"time" "time"
) )
type Flagset struct { type Flagset struct {
flags []*FlagVar flags map[string]*FlagVar
set *flag.FlagSet set *flag.FlagSet
} }
func NewFlagSet(name string) *Flagset { func NewFlagSet(name string) *Flagset {
f := &Flagset{ f := &Flagset{
flags: []*FlagVar{}, flags: make(map[string]*FlagVar, 0),
set: flag.NewFlagSet(name, flag.ContinueOnError), set: flag.NewFlagSet(name, flag.ContinueOnError),
} }
return f return f
} }
// Updatable is a minimalistic representation of a flag which has
// the method `UpdateValue` implemented which can be called while
// overwriting flags.
type Updatable interface {
UpdateValue(string)
}
type FlagVar struct { type FlagVar struct {
Name string Name string
Usage string Usage string
Group string Group string
Default any Default any
Value Updatable
} }
func (f *Flagset) addFlag(fl *FlagVar) { func (f *Flagset) addFlag(fl *FlagVar) {
f.flags = append(f.flags, fl) f.flags[fl.Name] = fl
} }
func (f *Flagset) Help() string { func (f *Flagset) Help() string {
@ -51,9 +60,12 @@ func (f *Flagset) Help() string {
} }
func (f *Flagset) GetAllFlags() []string { func (f *Flagset) GetAllFlags() []string {
flags := []string{} i := 0
for _, flag := range f.flags { flags := make([]string, 0, len(f.flags))
flags = append(flags, flag.Name)
for name := range f.flags {
flags[i] = name
i++
} }
return flags return flags
@ -110,6 +122,33 @@ func (f *Flagset) Args() []string {
return f.set.Args() return f.set.Args()
} }
// UpdateValue updates the underlying value of a flag
// given the flag name and value to update using pointer.
func (f *Flagset) UpdateValue(names []string, values []string) {
for i, name := range names {
if flag, ok := f.flags[name]; ok {
value := values[i]
// Call the underlying flag's `UpdateValue` method
flag.Value.UpdateValue(value)
}
}
}
// Visit visits all the set flags and returns the name and value
// in string to set later.
func (f *Flagset) Visit() ([]string, []string) {
names := make([]string, 0, len(f.flags))
values := make([]string, 0, len(f.flags))
f.set.Visit(func(flag *flag.Flag) {
names = append(names, flag.Name)
values = append(values, flag.Value.String())
})
return names, values
}
type BoolFlag struct { type BoolFlag struct {
Name string Name string
Usage string Usage string
@ -118,12 +157,19 @@ type BoolFlag struct {
Group string Group string
} }
func (b *BoolFlag) UpdateValue(value string) {
v, _ := strconv.ParseBool(value)
*b.Value = v
}
func (f *Flagset) BoolFlag(b *BoolFlag) { func (f *Flagset) BoolFlag(b *BoolFlag) {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
Name: b.Name, Name: b.Name,
Usage: b.Usage, Usage: b.Usage,
Group: b.Group, Group: b.Group,
Default: b.Default, Default: b.Default,
Value: b,
}) })
f.set.BoolVar(b.Value, b.Name, b.Default, b.Usage) f.set.BoolVar(b.Value, b.Name, b.Default, b.Usage)
} }
@ -137,6 +183,10 @@ type StringFlag struct {
HideDefaultFromDoc bool HideDefaultFromDoc bool
} }
func (b *StringFlag) UpdateValue(value string) {
*b.Value = value
}
func (f *Flagset) StringFlag(b *StringFlag) { func (f *Flagset) StringFlag(b *StringFlag) {
if b.Default == "" || b.HideDefaultFromDoc { if b.Default == "" || b.HideDefaultFromDoc {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
@ -144,6 +194,7 @@ func (f *Flagset) StringFlag(b *StringFlag) {
Usage: b.Usage, Usage: b.Usage,
Group: b.Group, Group: b.Group,
Default: nil, Default: nil,
Value: b,
}) })
} else { } else {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
@ -151,6 +202,7 @@ func (f *Flagset) StringFlag(b *StringFlag) {
Usage: b.Usage, Usage: b.Usage,
Group: b.Group, Group: b.Group,
Default: b.Default, Default: b.Default,
Value: b,
}) })
} }
@ -165,12 +217,19 @@ type IntFlag struct {
Group string Group string
} }
func (b *IntFlag) UpdateValue(value string) {
v, _ := strconv.ParseInt(value, 10, 64)
*b.Value = int(v)
}
func (f *Flagset) IntFlag(i *IntFlag) { func (f *Flagset) IntFlag(i *IntFlag) {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
Name: i.Name, Name: i.Name,
Usage: i.Usage, Usage: i.Usage,
Group: i.Group, Group: i.Group,
Default: i.Default, Default: i.Default,
Value: i,
}) })
f.set.IntVar(i.Value, i.Name, i.Default, i.Usage) f.set.IntVar(i.Value, i.Name, i.Default, i.Usage)
} }
@ -183,12 +242,19 @@ type Uint64Flag struct {
Group string Group string
} }
func (b *Uint64Flag) UpdateValue(value string) {
v, _ := strconv.ParseUint(value, 10, 64)
*b.Value = v
}
func (f *Flagset) Uint64Flag(i *Uint64Flag) { func (f *Flagset) Uint64Flag(i *Uint64Flag) {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
Name: i.Name, Name: i.Name,
Usage: i.Usage, Usage: i.Usage,
Group: i.Group, Group: i.Group,
Default: fmt.Sprintf("%d", i.Default), Default: fmt.Sprintf("%d", i.Default),
Value: i,
}) })
f.set.Uint64Var(i.Value, i.Name, i.Default, i.Usage) f.set.Uint64Var(i.Value, i.Name, i.Default, i.Usage)
} }
@ -209,31 +275,47 @@ func (b *BigIntFlag) String() string {
return b.Value.String() return b.Value.String()
} }
func (b *BigIntFlag) Set(value string) error { func parseBigInt(value string) *big.Int {
num := new(big.Int) num := new(big.Int)
var ok bool
if strings.HasPrefix(value, "0x") { if strings.HasPrefix(value, "0x") {
num, ok = num.SetString(value[2:], 16) num, _ = num.SetString(value[2:], 16)
*b.Value = *num
} else { } else {
num, ok = num.SetString(value, 10) num, _ = num.SetString(value, 10)
*b.Value = *num
} }
if !ok { return num
}
func (b *BigIntFlag) Set(value string) error {
num := parseBigInt(value)
if num == nil {
return fmt.Errorf("failed to set big int") return fmt.Errorf("failed to set big int")
} }
*b.Value = *num
return nil return nil
} }
func (b *BigIntFlag) UpdateValue(value string) {
num := parseBigInt(value)
if num == nil {
return
}
*b.Value = *num
}
func (f *Flagset) BigIntFlag(b *BigIntFlag) { func (f *Flagset) BigIntFlag(b *BigIntFlag) {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
Name: b.Name, Name: b.Name,
Usage: b.Usage, Usage: b.Usage,
Group: b.Group, Group: b.Group,
Default: b.Default, Default: b.Default,
Value: b,
}) })
f.set.Var(b, b.Name, b.Usage) f.set.Var(b, b.Name, b.Usage)
} }
@ -273,6 +355,10 @@ func (i *SliceStringFlag) Set(value string) error {
return nil return nil
} }
func (i *SliceStringFlag) UpdateValue(value string) {
*i.Value = SplitAndTrim(value)
}
func (f *Flagset) SliceStringFlag(s *SliceStringFlag) { func (f *Flagset) SliceStringFlag(s *SliceStringFlag) {
if s.Default == nil || len(s.Default) == 0 { if s.Default == nil || len(s.Default) == 0 {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
@ -280,6 +366,7 @@ func (f *Flagset) SliceStringFlag(s *SliceStringFlag) {
Usage: s.Usage, Usage: s.Usage,
Group: s.Group, Group: s.Group,
Default: nil, Default: nil,
Value: s,
}) })
} else { } else {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
@ -287,6 +374,7 @@ func (f *Flagset) SliceStringFlag(s *SliceStringFlag) {
Usage: s.Usage, Usage: s.Usage,
Group: s.Group, Group: s.Group,
Default: strings.Join(s.Default, ","), Default: strings.Join(s.Default, ","),
Value: s,
}) })
} }
@ -301,12 +389,19 @@ type DurationFlag struct {
Group string Group string
} }
func (d *DurationFlag) UpdateValue(value string) {
v, _ := time.ParseDuration(value)
*d.Value = v
}
func (f *Flagset) DurationFlag(d *DurationFlag) { func (f *Flagset) DurationFlag(d *DurationFlag) {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
Name: d.Name, Name: d.Name,
Usage: d.Usage, Usage: d.Usage,
Group: d.Group, Group: d.Group,
Default: d.Default, Default: d.Default,
Value: d,
}) })
f.set.DurationVar(d.Value, d.Name, d.Default, "") f.set.DurationVar(d.Value, d.Name, d.Default, "")
} }
@ -336,24 +431,38 @@ func (m *MapStringFlag) String() string {
return formatMapString(*m.Value) return formatMapString(*m.Value)
} }
func (m *MapStringFlag) Set(value string) error { func parseMap(value string) map[string]string {
if m.Value == nil { m := make(map[string]string)
m.Value = &map[string]string{}
}
for _, t := range strings.Split(value, ",") { for _, t := range strings.Split(value, ",") {
if t != "" { if t != "" {
kv := strings.Split(t, "=") kv := strings.Split(t, "=")
if len(kv) == 2 { if len(kv) == 2 {
(*m.Value)[kv[0]] = kv[1] m[kv[0]] = kv[1]
} }
} }
} }
return m
}
func (m *MapStringFlag) Set(value string) error {
if m.Value == nil {
m.Value = &map[string]string{}
}
m2 := parseMap(value)
*m.Value = m2
return nil return nil
} }
func (m *MapStringFlag) UpdateValue(value string) {
m2 := parseMap(value)
*m.Value = m2
}
func (f *Flagset) MapStringFlag(m *MapStringFlag) { func (f *Flagset) MapStringFlag(m *MapStringFlag) {
if m.Default == nil || len(m.Default) == 0 { if m.Default == nil || len(m.Default) == 0 {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
@ -361,6 +470,7 @@ func (f *Flagset) MapStringFlag(m *MapStringFlag) {
Usage: m.Usage, Usage: m.Usage,
Group: m.Group, Group: m.Group,
Default: nil, Default: nil,
Value: m,
}) })
} else { } else {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
@ -368,6 +478,7 @@ func (f *Flagset) MapStringFlag(m *MapStringFlag) {
Usage: m.Usage, Usage: m.Usage,
Group: m.Group, Group: m.Group,
Default: formatMapString(m.Default), Default: formatMapString(m.Default),
Value: m,
}) })
} }
@ -382,12 +493,19 @@ type Float64Flag struct {
Group string Group string
} }
func (f *Float64Flag) UpdateValue(value string) {
v, _ := strconv.ParseFloat(value, 64)
*f.Value = v
}
func (f *Flagset) Float64Flag(i *Float64Flag) { func (f *Flagset) Float64Flag(i *Float64Flag) {
f.addFlag(&FlagVar{ f.addFlag(&FlagVar{
Name: i.Name, Name: i.Name,
Usage: i.Usage, Usage: i.Usage,
Group: i.Group, Group: i.Group,
Default: i.Default, Default: i.Default,
Value: i,
}) })
f.set.Float64Var(i.Value, i.Name, i.Default, "") f.set.Float64Var(i.Value, i.Name, i.Default, "")
} }

View file

@ -1,26 +1,176 @@
package flagset package flagset
import ( import (
"math/big"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/require"
) )
func TestFlagsetBool(t *testing.T) { func TestFlagsetBool(t *testing.T) {
t.Parallel()
f := NewFlagSet("") f := NewFlagSet("")
value := false value := true
f.BoolFlag(&BoolFlag{ f.BoolFlag(&BoolFlag{
Name: "flag", Name: "flag",
Value: &value, Value: &value,
}) })
assert.NoError(t, f.Parse([]string{"--flag", "true"})) // Parse no value, should have default (of datatype)
assert.Equal(t, value, true) require.NoError(t, f.Parse([]string{}))
require.Equal(t, false, value)
// Parse --flag true
require.NoError(t, f.Parse([]string{"--flag", "true"}))
require.Equal(t, true, value)
// Parse --flag=true
require.NoError(t, f.Parse([]string{"--flag=true"}))
require.Equal(t, true, value)
// Parse --flag false: won't parse false
require.NoError(t, f.Parse([]string{"--flag", "false"}))
require.Equal(t, true, value)
// Parse --flag=false
require.NoError(t, f.Parse([]string{"--flag=false"}))
require.Equal(t, false, value)
// Parse --flag
require.NoError(t, f.Parse([]string{"--flag"}))
require.Equal(t, true, value)
}
func TestFlagsetString(t *testing.T) {
t.Parallel()
f := NewFlagSet("")
value := "hello"
f.StringFlag(&StringFlag{
Name: "flag",
Value: &value,
})
// Parse no value, should have default
require.NoError(t, f.Parse([]string{}))
require.Equal(t, "", value)
// Parse --flag value
require.NoError(t, f.Parse([]string{"--flag", "value"}))
require.Equal(t, "value", value)
// Parse --flag ""
require.NoError(t, f.Parse([]string{"--flag", ""}))
require.Equal(t, "", value)
// Parse --flag=newvalue
require.NoError(t, f.Parse([]string{"--flag=newvalue"}))
require.Equal(t, "newvalue", value)
// Parse --flag: should fail due to no args
require.Error(t, f.Parse([]string{"--flag"}))
}
func TestFlagsetInt(t *testing.T) {
t.Parallel()
f := NewFlagSet("")
value := 10
f.IntFlag(&IntFlag{
Name: "flag",
Value: &value,
})
// Parse no value, should have default
require.NoError(t, f.Parse([]string{}))
require.Equal(t, 0, value)
// Parse --flag 20
require.NoError(t, f.Parse([]string{"--flag", "20"}))
require.Equal(t, 20, value)
// Parse --flag 0
require.NoError(t, f.Parse([]string{"--flag", "0"}))
require.Equal(t, 0, value)
// Parse --flag=30
require.NoError(t, f.Parse([]string{"--flag=30"}))
require.Equal(t, 30, value)
// Parse --flag: should fail due to no args
require.Error(t, f.Parse([]string{"--flag"}))
}
func TestFlagsetFloat64(t *testing.T) {
t.Parallel()
f := NewFlagSet("")
value := 10.0
f.Float64Flag(&Float64Flag{
Name: "flag",
Value: &value,
})
// Parse no value, should have default
require.NoError(t, f.Parse([]string{}))
require.Equal(t, 0.0, value)
// Parse --flag 20
require.NoError(t, f.Parse([]string{"--flag", "20.1"}))
require.Equal(t, 20.1, value)
// Parse --flag 0
require.NoError(t, f.Parse([]string{"--flag", "0"}))
require.Equal(t, 0.0, value)
// Parse --flag 0.0
require.NoError(t, f.Parse([]string{"--flag", "0.0"}))
require.Equal(t, 0.0, value)
// Parse --flag=30.1
require.NoError(t, f.Parse([]string{"--flag=30.1"}))
require.Equal(t, 30.1, value)
// Parse --flag: should fail due to no args
require.Error(t, f.Parse([]string{"--flag"}))
}
func TestFlagsetBigInt(t *testing.T) {
t.Parallel()
f := NewFlagSet("")
value := big.NewInt(0)
f.BigIntFlag(&BigIntFlag{
Name: "flag",
Value: value,
})
// Parse no value, should have initial value (0 here)
require.NoError(t, f.Parse([]string{}))
require.Equal(t, big.NewInt(0), value)
// Parse --flag 20
require.NoError(t, f.Parse([]string{"--flag", "20"}))
require.Equal(t, big.NewInt(20), value)
// Parse --flag=30
require.NoError(t, f.Parse([]string{"--flag=30"}))
require.Equal(t, big.NewInt(30), value)
// Parse --flag: should fail due to no args
require.Error(t, f.Parse([]string{"--flag"}))
} }
func TestFlagsetSliceString(t *testing.T) { func TestFlagsetSliceString(t *testing.T) {
t.Parallel()
f := NewFlagSet("") f := NewFlagSet("")
value := []string{"a", "b", "c"} value := []string{"a", "b", "c"}
@ -30,13 +180,25 @@ func TestFlagsetSliceString(t *testing.T) {
Default: value, Default: value,
}) })
assert.NoError(t, f.Parse([]string{})) // Parse no value, should have initial value
assert.Equal(t, value, []string{"a", "b", "c"}) require.NoError(t, f.Parse([]string{}))
assert.NoError(t, f.Parse([]string{"--flag", "a,b"})) require.Equal(t, []string{"a", "b", "c"}, value)
assert.Equal(t, value, []string{"a", "b"})
// Parse --flag a,b
require.NoError(t, f.Parse([]string{"--flag", "a,b"}))
require.Equal(t, []string{"a", "b"}, value)
// Parse --flag ""
require.NoError(t, f.Parse([]string{"--flag", ""}))
require.Equal(t, []string(nil), value)
// Parse --flag: should fail due to no args
require.Error(t, f.Parse([]string{"--flag"}))
} }
func TestFlagsetDuration(t *testing.T) { func TestFlagsetDuration(t *testing.T) {
t.Parallel()
f := NewFlagSet("") f := NewFlagSet("")
value := time.Duration(0) value := time.Duration(0)
@ -45,11 +207,25 @@ func TestFlagsetDuration(t *testing.T) {
Value: &value, Value: &value,
}) })
assert.NoError(t, f.Parse([]string{"--flag", "1m"})) // Parse no value, should have initial value
assert.Equal(t, value, 1*time.Minute) require.NoError(t, f.Parse([]string{}))
require.Equal(t, time.Duration(0), value)
// Parse --flag 1m
require.NoError(t, f.Parse([]string{"--flag", "1m"}))
require.Equal(t, time.Minute, value)
// Parse --flag=1h
require.NoError(t, f.Parse([]string{"--flag=1h"}))
require.Equal(t, time.Hour, value)
// Parse --flag: should fail due to no args
require.Error(t, f.Parse([]string{"--flag"}))
} }
func TestFlagsetMapString(t *testing.T) { func TestFlagsetMapString(t *testing.T) {
t.Parallel()
f := NewFlagSet("") f := NewFlagSet("")
value := map[string]string{} value := map[string]string{}
@ -58,6 +234,18 @@ func TestFlagsetMapString(t *testing.T) {
Value: &value, Value: &value,
}) })
assert.NoError(t, f.Parse([]string{"--flag", "a=b,c=d"})) // Parse no value, should have initial value
assert.Equal(t, value, map[string]string{"a": "b", "c": "d"}) require.NoError(t, f.Parse([]string{}))
require.Equal(t, map[string]string{}, value)
// Parse --flag a=b,c=d
require.NoError(t, f.Parse([]string{"--flag", "a=b,c=d"}))
require.Equal(t, map[string]string{"a": "b", "c": "d"}, value)
// Parse --flag=x=y
require.NoError(t, f.Parse([]string{"--flag=x=y"}))
require.Equal(t, map[string]string{"x": "y"}, value)
// Parse --flag: should fail due to no args
require.Error(t, f.Parse([]string{"--flag"}))
} }

View file

@ -35,7 +35,7 @@ func (c *Command) MarkDown() string {
items := []string{ items := []string{
"# Server", "# Server",
"The ```bor server``` command runs the Bor client.", "The ```bor server``` command runs the Bor client.",
c.Flags().MarkDown(), c.Flags(nil).MarkDown(),
} }
return strings.Join(items, "\n\n") return strings.Join(items, "\n\n")
@ -46,7 +46,7 @@ func (c *Command) Help() string {
return `Usage: bor [options] return `Usage: bor [options]
Run the Bor server. Run the Bor server.
` + c.Flags().Help() ` + c.Flags(nil).Help()
} }
// Synopsis implements the cli.Command interface // Synopsis implements the cli.Command interface
@ -54,40 +54,69 @@ func (c *Command) Synopsis() string {
return "Run the Bor server" return "Run the Bor server"
} }
// checkConfigFlag checks if the config flag is set or not. If set,
// it returns the value else an empty string.
func checkConfigFlag(args []string) string {
for i := 0; i < len(args); i++ {
arg := args[i]
// Check for single or double dashes
if strings.HasPrefix(arg, "-config") || strings.HasPrefix(arg, "--config") {
parts := strings.SplitN(arg, "=", 2)
if len(parts) == 2 {
return parts[1]
}
// If there's no equal sign, check the next argument
if i+1 < len(args) {
return args[i+1]
}
}
}
return ""
}
func (c *Command) extractFlags(args []string) error { func (c *Command) extractFlags(args []string) error {
config := *DefaultConfig() // Check if config file is provided or not
configFilePath := checkConfigFlag(args)
flags := c.Flags() if configFilePath != "" {
if err := flags.Parse(args); err != nil { log.Info("Reading config file", "path", configFilePath)
c.UI.Error(err.Error())
c.config = &config
return err // Parse the config file
} cfg, err := readConfigFile(configFilePath)
// 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", "path", c.configFile)
cfg, err := readConfigFile(c.configFile)
if err != nil { if err != nil {
c.UI.Error(err.Error()) c.UI.Error(err.Error())
c.config = &config
return err return err
} }
if err := config.Merge(cfg); err != nil { log.Warn("Config set via config file will be overridden by cli flags")
// Initialse a flagset based on the config created above
flags := c.Flags(cfg)
// Check for explicit cli args
cmd := Command{} // use a new variable to keep the original config intact
cliFlags := cmd.Flags(nil)
if err := cliFlags.Parse(args); err != nil {
c.UI.Error(err.Error())
return err
}
// Get the list of flags set explicitly
names, values := cliFlags.Visit()
// Set these flags using the flagset created earlier
flags.UpdateValue(names, values)
} else {
flags := c.Flags(nil)
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error()) c.UI.Error(err.Error())
c.config = &config
return err return err
} }
@ -95,33 +124,33 @@ func (c *Command) extractFlags(args []string) error {
// nolint: nestif // nolint: nestif
// check for log-level and verbosity here // check for log-level and verbosity here
if c.configFile != "" { if configFilePath != "" {
data, _ := toml.LoadFile(c.configFile) data, _ := toml.LoadFile(configFilePath)
if data.Has("verbosity") && data.Has("log-level") { if data.Has("verbosity") && data.Has("log-level") {
log.Warn("Config contains both, verbosity and log-level, log-level will be deprecated soon. Use verbosity only.", "using", data.Get("verbosity")) log.Warn("Config contains both, verbosity and log-level, log-level will be deprecated soon. Use verbosity only.", "using", data.Get("verbosity"))
} else if !data.Has("verbosity") && data.Has("log-level") { } else if !data.Has("verbosity") && data.Has("log-level") {
log.Warn("Config contains log-level only, note that log-level will be deprecated soon. Use verbosity instead.", "using", data.Get("log-level")) log.Warn("Config contains log-level only, note that log-level will be deprecated soon. Use verbosity instead.", "using", data.Get("log-level"))
config.Verbosity = VerbosityStringToInt(strings.ToLower(data.Get("log-level").(string))) c.cliConfig.Verbosity = VerbosityStringToInt(strings.ToLower(data.Get("log-level").(string)))
} }
} else { } else {
tempFlag := 0 tempFlag := 0
for _, val := range args { for _, val := range args {
if (strings.HasPrefix(val, "-verbosity") || strings.HasPrefix(val, "--verbosity")) && config.LogLevel != "" { if (strings.HasPrefix(val, "-verbosity") || strings.HasPrefix(val, "--verbosity")) && c.cliConfig.LogLevel != "" {
tempFlag = 1 tempFlag = 1
break break
} }
} }
if tempFlag == 1 { if tempFlag == 1 {
log.Warn("Both, verbosity and log-level flags are provided, log-level will be deprecated soon. Use verbosity only.", "using", config.Verbosity) log.Warn("Both, verbosity and log-level flags are provided, log-level will be deprecated soon. Use verbosity only.", "using", c.cliConfig.Verbosity)
} else if tempFlag == 0 && config.LogLevel != "" { } else if tempFlag == 0 && c.cliConfig.LogLevel != "" {
log.Warn("Only log-level flag is provided, note that log-level will be deprecated soon. Use verbosity instead.", "using", config.LogLevel) log.Warn("Only log-level flag is provided, note that log-level will be deprecated soon. Use verbosity instead.", "using", c.cliConfig.LogLevel)
config.Verbosity = VerbosityStringToInt(strings.ToLower(config.LogLevel)) c.cliConfig.Verbosity = VerbosityStringToInt(strings.ToLower(c.cliConfig.LogLevel))
} }
} }
c.config = &config c.config = c.cliConfig
return nil return nil
} }

View file

@ -8,43 +8,135 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestFlags(t *testing.T) { // TestFlagsWithoutConfig tests all types of flags passed only
// via cli args.
func TestFlagsWithoutConfig(t *testing.T) {
t.Parallel() t.Parallel()
var c Command var c Command
args := []string{ args := []string{
"--txpool.rejournal", "30m0s", "--identity", "",
"--txpool.lifetime", "30m0s",
"--miner.gasprice", "20000000000",
"--gpo.maxprice", "70000000000",
"--gpo.ignoreprice", "1",
"--cache.trie.rejournal", "40m0s",
"--dev",
"--dev.period", "2",
"--datadir", "./data", "--datadir", "./data",
"--maxpeers", "30", "--verbosity", "3",
"--rpc.batchlimit", "0",
"--snapshot",
"--bor.logs=false",
"--eth.requiredblocks", "a=b", "--eth.requiredblocks", "a=b",
"--http.api", "eth,web3,bor", "--miner.gasprice", "30000000000",
"--miner.recommit", "20s",
"--rpc.evmtimeout", "5s",
"--rpc.txfeecap", "6.0",
"--http.api", "eth,bor",
"--ws.api", "",
"--gpo.maxprice", "5000000000000",
} }
err := c.extractFlags(args) err := c.extractFlags(args)
require.NoError(t, err) require.NoError(t, err)
txRe, _ := time.ParseDuration("30m0s") recommit, _ := time.ParseDuration("20s")
txLt, _ := time.ParseDuration("30m0s") evmTimeout, _ := time.ParseDuration("5s")
caRe, _ := time.ParseDuration("40m0s")
require.Equal(t, c.config.Identity, "")
require.Equal(t, c.config.DataDir, "./data") require.Equal(t, c.config.DataDir, "./data")
require.Equal(t, c.config.Developer.Enabled, true) require.Equal(t, c.config.Verbosity, 3)
require.Equal(t, c.config.Developer.Period, uint64(2)) require.Equal(t, c.config.RPCBatchLimit, uint64(0))
require.Equal(t, c.config.TxPool.Rejournal, txRe) require.Equal(t, c.config.Snapshot, true)
require.Equal(t, c.config.TxPool.LifeTime, txLt) require.Equal(t, c.config.BorLogs, false)
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.RequiredBlocks, map[string]string{"a": "b"})
require.Equal(t, c.config.JsonRPC.Http.API, []string{"eth", "web3", "bor"}) require.Equal(t, c.config.Sealer.GasPrice, big.NewInt(30000000000))
require.Equal(t, c.config.Sealer.Recommit, recommit)
require.Equal(t, c.config.JsonRPC.RPCEVMTimeout, evmTimeout)
require.Equal(t, c.config.JsonRPC.Http.API, []string{"eth", "bor"})
require.Equal(t, c.config.JsonRPC.Ws.API, []string(nil))
require.Equal(t, c.config.Gpo.MaxPrice, big.NewInt(5000000000000))
}
// TestFlagsWithoutConfig tests all types of flags passed only
// via config file.
func TestFlagsWithConfig(t *testing.T) {
t.Parallel()
var c Command
args := []string{
"--config", "./testdata/test.toml",
}
err := c.extractFlags(args)
require.NoError(t, err)
recommit, _ := time.ParseDuration("20s")
evmTimeout, _ := time.ParseDuration("5s")
require.Equal(t, c.config.Identity, "")
require.Equal(t, c.config.DataDir, "./data")
require.Equal(t, c.config.Verbosity, 3)
require.Equal(t, c.config.RPCBatchLimit, uint64(0))
require.Equal(t, c.config.Snapshot, true)
require.Equal(t, c.config.BorLogs, false)
require.Equal(t, c.config.RequiredBlocks,
map[string]string{
"31000000": "0x2087b9e2b353209c2c21e370c82daa12278efd0fe5f0febe6c29035352cf050e",
"32000000": "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68",
},
)
require.Equal(t, c.config.Sealer.GasPrice, big.NewInt(30000000000))
require.Equal(t, c.config.Sealer.Recommit, recommit)
require.Equal(t, c.config.JsonRPC.RPCEVMTimeout, evmTimeout)
require.Equal(t, c.config.JsonRPC.Http.API, []string{"eth", "bor"})
require.Equal(t, c.config.JsonRPC.Ws.API, []string{""})
require.Equal(t, c.config.Gpo.MaxPrice, big.NewInt(5000000000000))
}
// TestFlagsWithConfig tests all types of flags passed via both
// config file and cli args. The cli args should overwrite the
// value of flag.
func TestFlagsWithConfigAndFlags(t *testing.T) {
t.Parallel()
var c Command
// Set the config and also override
args := []string{
"--config", "./testdata/test.toml",
"--identity", "Anon",
"--datadir", "",
"--verbosity", "0",
"--rpc.batchlimit", "5",
"--snapshot=false",
"--bor.logs=true",
"--eth.requiredblocks", "x=y",
"--miner.gasprice", "60000000000",
"--miner.recommit", "30s",
"--rpc.evmtimeout", "0s",
"--rpc.txfeecap", "0",
"--http.api", "",
"--ws.api", "eth,bor,web3",
"--gpo.maxprice", "0",
}
err := c.extractFlags(args)
require.NoError(t, err)
recommit, _ := time.ParseDuration("30s")
evmTimeout, _ := time.ParseDuration("0s")
require.Equal(t, c.config.Identity, "Anon")
require.Equal(t, c.config.DataDir, "")
require.Equal(t, c.config.Verbosity, 0)
require.Equal(t, c.config.RPCBatchLimit, uint64(5))
require.Equal(t, c.config.Snapshot, false)
require.Equal(t, c.config.BorLogs, true)
require.Equal(t, c.config.RequiredBlocks, map[string]string{"x": "y"})
require.Equal(t, c.config.Sealer.GasPrice, big.NewInt(60000000000))
require.Equal(t, c.config.Sealer.Recommit, recommit)
require.Equal(t, c.config.JsonRPC.RPCEVMTimeout, evmTimeout)
require.Equal(t, c.config.JsonRPC.Http.API, []string(nil))
require.Equal(t, c.config.JsonRPC.Ws.API, []string{"eth", "bor", "web3"})
require.Equal(t, c.config.Gpo.MaxPrice, big.NewInt(0))
} }

View file

@ -15,21 +15,23 @@ func TestConfigLegacy(t *testing.T) {
testConfig := DefaultConfig() testConfig := DefaultConfig()
testConfig.Identity = ""
testConfig.DataDir = "./data" testConfig.DataDir = "./data"
testConfig.Snapshot = false testConfig.Verbosity = 3
testConfig.RPCBatchLimit = 0
testConfig.Snapshot = true
testConfig.BorLogs = false
testConfig.RequiredBlocks = map[string]string{ testConfig.RequiredBlocks = map[string]string{
"31000000": "0x2087b9e2b353209c2c21e370c82daa12278efd0fe5f0febe6c29035352cf050e", "31000000": "0x2087b9e2b353209c2c21e370c82daa12278efd0fe5f0febe6c29035352cf050e",
"32000000": "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68", "32000000": "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68",
} }
testConfig.P2P.MaxPeers = 30 testConfig.Sealer.GasPrice = big.NewInt(30000000000)
testConfig.TxPool.Locals = []string{} testConfig.Sealer.Recommit = 20 * time.Second
testConfig.TxPool.LifeTime = time.Second testConfig.JsonRPC.RPCEVMTimeout = 5 * time.Second
testConfig.Sealer.Enabled = true testConfig.JsonRPC.TxFeeCap = 6.0
testConfig.Sealer.GasCeil = 30000000 testConfig.JsonRPC.Http.API = []string{"eth", "bor"}
testConfig.Sealer.GasPrice = big.NewInt(1000000000) testConfig.JsonRPC.Ws.API = []string{""}
testConfig.Gpo.IgnorePrice = big.NewInt(4) testConfig.Gpo.MaxPrice = big.NewInt(5000000000000)
testConfig.Cache.Cache = 1024
testConfig.Cache.Rejournal = time.Second
assert.Equal(t, expectedConfig, testConfig) assert.Equal(t, expectedConfig, testConfig)
} }

View file

@ -4,8 +4,12 @@ import (
"github.com/ethereum/go-ethereum/internal/cli/flagset" "github.com/ethereum/go-ethereum/internal/cli/flagset"
) )
func (c *Command) Flags() *flagset.Flagset { func (c *Command) Flags(config *Config) *flagset.Flagset {
c.cliConfig = DefaultConfig() if config != nil {
c.cliConfig = config
} else {
c.cliConfig = DefaultConfig()
}
f := flagset.NewFlagSet("server") f := flagset.NewFlagSet("server")

View file

@ -1,25 +1,25 @@
identity = ""
datadir = "./data" datadir = "./data"
snapshot = false verbosity = 3
"rpc.batchlimit" = 0
snapshot = true
"bor.logs" = false
["eth.requiredblocks"] ["eth.requiredblocks"]
"31000000" = "0x2087b9e2b353209c2c21e370c82daa12278efd0fe5f0febe6c29035352cf050e" "31000000" = "0x2087b9e2b353209c2c21e370c82daa12278efd0fe5f0febe6c29035352cf050e"
"32000000" = "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68" "32000000" = "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68"
[p2p]
maxpeers = 30
[txpool]
locals = []
lifetime = "1s"
[miner] [miner]
mine = true gasprice = "30000000000"
gaslimit = 30000000 recommit = "20s"
gasprice = "1000000000"
[jsonrpc]
evmtimeout = "5s"
txfeecap = 6.0
[jsonrpc.http]
api = ["eth", "bor"]
[jsonrpc.ws]
api = [""]
[gpo] [gpo]
ignoreprice = "4" maxprice = "5000000000000"
[cache]
cache = 1024
rejournal = "1s"

View file

@ -1,5 +1,5 @@
Source: bor Source: bor
Version: 1.0.0-beta Version: 1.0.4
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor Source: bor
Version: 1.0.0-beta Version: 1.0.4
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor-profile Source: bor-profile
Version: 1.0.0-beta Version: 1.0.4
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor-profile Source: bor-profile
Version: 1.0.0-beta Version: 1.0.4
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor-profile Source: bor-profile
Version: 1.0.0-beta Version: 1.0.4
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -1,5 +1,5 @@
Source: bor-profile Source: bor-profile
Version: 1.0.0-beta Version: 1.0.4
Section: develop Section: develop
Priority: standard Priority: standard
Maintainer: Polygon <release-team@polygon.technology> Maintainer: Polygon <release-team@polygon.technology>

View file

@ -21,10 +21,10 @@ import (
) )
const ( const (
VersionMajor = 1 // Major version component of the current release VersionMajor = 1 // Major version component of the current release
VersionMinor = 0 // Minor version component of the current release VersionMinor = 0 // Minor version component of the current release
VersionPatch = 0 // Patch version component of the current release VersionPatch = 4 // Patch version component of the current release
VersionMeta = "beta" // Version metadata to append to the version string VersionMeta = "" // Version metadata to append to the version string
) )
var GitCommit string var GitCommit string

View file

@ -21,7 +21,8 @@ type SafePool struct {
service string // the service using ep service string // the service using ep
processed atomic.Int64 // keeps count of total processed requests processed atomic.Int64 // keeps count of total processed requests
close chan struct{} close chan struct{}
closeOnce sync.Once
// Skip sending task to execution pool // Skip sending task to execution pool
fastPath bool fastPath bool
@ -103,7 +104,9 @@ func (s *SafePool) Size() int {
} }
func (s *SafePool) Stop() { func (s *SafePool) Stop() {
close(s.close) s.closeOnce.Do(func() {
close(s.close)
})
if s.executionPool.Load() != nil { if s.executionPool.Load() != nil {
s.executionPool.Load().Stop() s.executionPool.Load().Stop()

View file

@ -331,6 +331,7 @@ func (h *handler) close(err error, inflightReq *requestOp) {
h.callWG.Wait() h.callWG.Wait()
h.cancelRoot() h.cancelRoot()
h.cancelServerSubscriptions(err) h.cancelServerSubscriptions(err)
h.executionPool.Stop()
} }
// addRequestOp registers a request operation. // addRequestOp registers a request operation.

View file

@ -699,7 +699,7 @@ func main() {
args, ignoreForNow := beautifyArgs(args) args, ignoreForNow := beautifyArgs(args)
c := server.Command{} c := server.Command{}
flags := c.Flags() flags := c.Flags(nil)
allFlags := flags.GetAllFlags() allFlags := flags.GetAllFlags()
flagsToCheck := getFlagsToCheck(args) flagsToCheck := getFlagsToCheck(args)

View file

@ -21,6 +21,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"sync"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -53,7 +54,8 @@ type Trie struct {
// tracer is the tool to track the trie changes. // tracer is the tool to track the trie changes.
// It will be reset after each commit operation. // It will be reset after each commit operation.
tracer *tracer tracer *tracer
tracerMutex sync.Mutex
} }
// newFlag returns the cache flag value for a newly created node. // newFlag returns the cache flag value for a newly created node.
@ -639,7 +641,9 @@ func (t *Trie) resolveAndTrack(n hashNode, prefix []byte) (node, error) {
return nil, err return nil, err
} }
t.tracerMutex.Lock()
t.tracer.onRead(prefix, blob) t.tracer.onRead(prefix, blob)
t.tracerMutex.Unlock()
return mustDecodeNode(n, blob), nil return mustDecodeNode(n, blob), nil
} }