Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
feat: modify the order and priority when loading the config
Browse files Browse the repository at this point in the history
  • Loading branch information
YoGhurt111 committed Apr 16, 2024
1 parent 96f0bef commit 13f4ce7
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 36 deletions.
7 changes: 7 additions & 0 deletions cmd/flags/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ var (
Category: commonCategory,
Value: 12 * time.Second,
}
// ConfigFile Path to a config file
ConfigFile = &cli.StringFlag{
Name: "config.file",
Usage: "Path to a config file to use for setting up application",
Category: commonCategory,
}
)

// CommonFlags All common flags.
Expand All @@ -145,6 +151,7 @@ var CommonFlags = []cli.Flag{
BackOffMaxRetrys,
BackOffRetryInterval,
RPCTimeout,
ConfigFile,
}

// MergeFlags merges the given flag slices.
Expand Down
44 changes: 44 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package utils

import (
"bufio"
"errors"
"fmt"
"os"
"reflect"
"unicode"

"github.com/naoina/toml"
)

var tomlSettings = toml.Config{
NormFieldName: func(_ reflect.Type, key string) string {
return key
},
FieldToKey: func(_ reflect.Type, field string) string {
return field
},
MissingField: func(rt reflect.Type, field string) error {
var link string
if unicode.IsUpper(rune(rt.Name()[0])) && rt.PkgPath() != "main" {
link = fmt.Sprintf(", see https://godoc.org/%s#%s for available fields", rt.PkgPath(), rt.Name())
}
return fmt.Errorf("field '%s' is not defined in %s%s", field, rt.String(), link)
},
}

func LoadConfigFile(file string, cfg interface{}) error {
f, err := os.Open(file)
if err != nil {
return err
}
defer f.Close()

err = tomlSettings.NewDecoder(bufio.NewReader(f)).Decode(cfg)
// Add file name to errors that have a line number.
var lineError *toml.LineError
if errors.As(err, &lineError) {
err = errors.New(file + ", " + err.Error())
}
return err
}
124 changes: 88 additions & 36 deletions driver/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import (
"net/url"
"time"

"github.com/cenkalti/backoff/v4"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2"

"github.com/taikoxyz/taiko-client/cmd/flags"
"github.com/taikoxyz/taiko-client/cmd/utils"
"github.com/taikoxyz/taiko-client/pkg/jwt"
"github.com/taikoxyz/taiko-client/pkg/rpc"
"github.com/urfave/cli/v2"
)

// Config contains the configurations to initialize a Taiko driver.
Expand All @@ -28,51 +29,102 @@ type Config struct {
// NewConfigFromCliContext creates a new config instance from
// the command line inputs.
func NewConfigFromCliContext(c *cli.Context) (*Config, error) {
jwtSecret, err := jwt.ParseSecretFromFile(c.String(flags.JWTSecret.Name))
if err != nil {
return nil, fmt.Errorf("invalid JWT secret file: %w", err)
// Defaults config
cfg := Config{
ClientConfig: &rpc.ClientConfig{
// TODO: To be confirmed whether taiko addresses in L1 or L2 are constant
TaikoL1Address: common.HexToAddress(c.String(flags.TaikoL1Address.Name)),
TaikoL2Address: common.HexToAddress(c.String(flags.TaikoL2Address.Name)),
Timeout: 12 * time.Second,
},
RetryInterval: backoff.DefaultMaxInterval,
P2PSyncVerifiedBlocks: false,
P2PSyncTimeout: 1 * time.Hour,
RPCTimeout: 12 * time.Second,
MaxExponent: 0,
}

var (
p2pSyncVerifiedBlocks = c.Bool(flags.P2PSyncVerifiedBlocks.Name)
l2CheckPoint = c.String(flags.CheckPointSyncURL.Name)
)
// Load config file
if file := c.String(flags.ConfigFile.Name); file != "" {
if err := utils.LoadConfigFile(file, &cfg); err != nil {
return nil, fmt.Errorf("%w", err)
}
}
// Apply flag value
err := ApplyFlagValue(c, &cfg)
if err != nil {
return nil, err
}
return &cfg, nil
}

if p2pSyncVerifiedBlocks && len(l2CheckPoint) == 0 {
return nil, errors.New("empty L2 check point URL")
func ApplyFlagValue(c *cli.Context, cfg *Config) error {
if c.IsSet(flags.L1WSEndpoint.Name) {
cfg.ClientConfig.L1Endpoint = c.String(flags.L1WSEndpoint.Name)
}

if !c.IsSet(flags.L1BeaconEndpoint.Name) {
return nil, errors.New("empty L1 beacon endpoint")
return errors.New("empty L1 beacon endpoint")
}
cfg.ClientConfig.L1BeaconEndpoint = c.String(flags.L1BeaconEndpoint.Name)

if c.IsSet(flags.L2WSEndpoint.Name) {
cfg.ClientConfig.L2Endpoint = c.String(flags.L2WSEndpoint.Name)
}

if c.IsSet(flags.TaikoL1Address.Name) {
cfg.ClientConfig.TaikoL1Address = common.HexToAddress(c.String(flags.TaikoL1Address.Name))
}

if c.IsSet(flags.TaikoL2Address.Name) {
cfg.ClientConfig.TaikoL2Address = common.HexToAddress(c.String(flags.TaikoL2Address.Name))
}

if c.IsSet(flags.L2AuthEndpoint.Name) {
cfg.ClientConfig.L2EngineEndpoint = c.String(flags.L2AuthEndpoint.Name)
}

if c.IsSet(flags.RPCTimeout.Name) {
cfg.ClientConfig.Timeout = c.Duration(flags.RPCTimeout.Name)
cfg.RPCTimeout = c.Duration(flags.RPCTimeout.Name)
}

if c.IsSet(flags.BackOffRetryInterval.Name) {
cfg.RetryInterval = c.Duration(flags.BackOffRetryInterval.Name)
}

if c.IsSet(flags.P2PSyncTimeout.Name) {
cfg.P2PSyncTimeout = c.Duration(flags.P2PSyncTimeout.Name)
}

if c.IsSet(flags.MaxExponent.Name) {
cfg.MaxExponent = c.Uint64(flags.MaxExponent.Name)
}

var blobServerEndpoint *url.URL
if c.IsSet(flags.BlobServerEndpoint.Name) {
if blobServerEndpoint, err = url.Parse(
blobServerEndpoint, err := url.Parse(
c.String(flags.BlobServerEndpoint.Name),
); err != nil {
return nil, err
)
if err != nil {
return err
}
cfg.BlobServerEndpoint = blobServerEndpoint
}

var timeout = c.Duration(flags.RPCTimeout.Name)
return &Config{
ClientConfig: &rpc.ClientConfig{
L1Endpoint: c.String(flags.L1WSEndpoint.Name),
L1BeaconEndpoint: c.String(flags.L1BeaconEndpoint.Name),
L2Endpoint: c.String(flags.L2WSEndpoint.Name),
L2CheckPoint: l2CheckPoint,
TaikoL1Address: common.HexToAddress(c.String(flags.TaikoL1Address.Name)),
TaikoL2Address: common.HexToAddress(c.String(flags.TaikoL2Address.Name)),
L2EngineEndpoint: c.String(flags.L2AuthEndpoint.Name),
JwtSecret: string(jwtSecret),
Timeout: timeout,
},
RetryInterval: c.Duration(flags.BackOffRetryInterval.Name),
P2PSyncVerifiedBlocks: p2pSyncVerifiedBlocks,
P2PSyncTimeout: c.Duration(flags.P2PSyncTimeout.Name),
RPCTimeout: timeout,
MaxExponent: c.Uint64(flags.MaxExponent.Name),
BlobServerEndpoint: blobServerEndpoint,
}, nil
jwtSecret, err := jwt.ParseSecretFromFile(c.String(flags.JWTSecret.Name))
if err != nil {
return fmt.Errorf("invalid JWT secret file: %w", err)
}
cfg.ClientConfig.JwtSecret = string(jwtSecret)

// Must be defined via flags
p2pSyncVerifiedBlocks := c.Bool(flags.P2PSyncVerifiedBlocks.Name)
l2CheckPoint := c.String(flags.CheckPointSyncURL.Name)
if p2pSyncVerifiedBlocks && len(l2CheckPoint) == 0 {
return errors.New("empty L2 check point URL")
}
cfg.ClientConfig.L2CheckPoint = l2CheckPoint
cfg.P2PSyncVerifiedBlocks = p2pSyncVerifiedBlocks

return nil
}
39 changes: 39 additions & 0 deletions driver/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,42 @@ var (
rpcTimeout = 5 * time.Second
)

func (s *DriverTestSuite) TestNewConfigFromFile() {
app := s.SetupApp()
app.Action = func(ctx *cli.Context) error {
c, err := NewConfigFromCliContext(ctx)
s.Nil(err)
s.Equal("ws://localhost:10000", c.L1Endpoint)
return err
}

s.Nil(app.Run([]string{
"TestNewConfigFromFile",
"--" + flags.L1BeaconEndpoint.Name, l1BeaconEndpoint,
"--" + flags.JWTSecret.Name, os.Getenv("JWT_SECRET"),
"--" + flags.ConfigFile.Name, "config_test.toml",
}))
}

func (s *DriverTestSuite) TestDefaultOverwrite() {
app := s.SetupApp()
app.Action = func(ctx *cli.Context) error {
c, err := NewConfigFromCliContext(ctx)
s.Nil(err)
s.Equal(true, c.P2PSyncVerifiedBlocks)
return err
}

s.Nil(app.Run([]string{
"TestDefaultOverwrite",
"--" + flags.L1BeaconEndpoint.Name, l1BeaconEndpoint,
"--" + flags.JWTSecret.Name, os.Getenv("JWT_SECRET"),
"--" + flags.P2PSyncVerifiedBlocks.Name,
"--" + flags.CheckPointSyncURL.Name, os.Getenv("L2_EXECUTION_ENGINE_HTTP_ENDPOINT"),
"--" + flags.ConfigFile.Name, "config_test.toml",
}))
}

func (s *DriverTestSuite) TestNewConfigFromCliContext() {
app := s.SetupApp()

Expand Down Expand Up @@ -63,6 +99,7 @@ func (s *DriverTestSuite) TestNewConfigFromCliContextJWTError() {
app := s.SetupApp()
s.ErrorContains(app.Run([]string{
"TestNewConfigFromCliContext",
"--" + flags.L1BeaconEndpoint.Name, l1BeaconEndpoint,
"--" + flags.JWTSecret.Name, "wrongsecretfile.txt",
}), "invalid JWT secret file")
}
Expand All @@ -71,6 +108,7 @@ func (s *DriverTestSuite) TestNewConfigFromCliContextEmptyL2CheckPoint() {
app := s.SetupApp()
s.ErrorContains(app.Run([]string{
"TestNewConfigFromCliContext",
"--" + flags.L1BeaconEndpoint.Name, l1BeaconEndpoint,
"--" + flags.JWTSecret.Name, os.Getenv("JWT_SECRET"),
"--" + flags.P2PSyncVerifiedBlocks.Name,
"--" + flags.L2WSEndpoint.Name, "",
Expand All @@ -91,6 +129,7 @@ func (s *DriverTestSuite) SetupApp() *cli.App {
&cli.DurationFlag{Name: flags.P2PSyncTimeout.Name},
&cli.DurationFlag{Name: flags.RPCTimeout.Name},
&cli.StringFlag{Name: flags.CheckPointSyncURL.Name},
&cli.StringFlag{Name: flags.ConfigFile.Name},
}
app.Action = func(ctx *cli.Context) error {
_, err := NewConfigFromCliContext(ctx)
Expand Down
3 changes: 3 additions & 0 deletions driver/config_test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
P2PSyncVerifiedBlocks = false
[ClientConfig]
L1Endpoint = "ws://localhost:10000"
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ require (
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/naoina/go-stringutil v0.1.0 // indirect
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,10 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0=
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
Expand Down

0 comments on commit 13f4ce7

Please sign in to comment.