Skip to content

Commit

Permalink
Custom Fallback TOML Config
Browse files Browse the repository at this point in the history
This commit provides setting a new env var `CL_CHAIN_FALLBACK` as a path to a custom `fallback.toml`. This allows
plugins to define their own set of fallback options apart from the core node which override the default fallback
options.
  • Loading branch information
EasterTheBunny committed Dec 10, 2024
1 parent 9d8d9f4 commit 1d753ac
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 45 deletions.
140 changes: 95 additions & 45 deletions core/chains/evm/config/toml/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package toml
import (
"bytes"
"embed"
"errors"
"fmt"
"io"
"log"
"os"
"path/filepath"
Expand Down Expand Up @@ -33,48 +33,83 @@ var (
)

func init() {
// read the defaults first
// read all default configs
initReadDefaults()

// overrides should be applied as:
// fallback.toml(defaults dir) <- fallback.toml(env CL_CHAIN_FALLBACK) <- ChainSpecific.toml(env CL_CHAIN_DEFAULTS)
//
// the custom fallback gets processed and overrides the default fallback
if path := env.CustomFallback.Get(); path != "" {
_, chain, err := readConfig(path, os.ReadFile, true)
if err != nil {
if !errors.Is(err, errFallbackConfig) {
log.Fatalf("custom fallback config error: %s", err.Error())
}

fallback = chain
}
}

// check for and apply any overrides
initApplyEVMOverrides()
}

var (
errRead = errors.New("error reading file")
errDecode = errors.New("error in TOML decoding")
errMissingChainID = errors.New("missing ChainID")
errNonNilChainID = errors.New("fallback ChainID must be nil")
errFallbackConfig = errors.New("fallback config")
)

func initReadDefaults() {
// read the defaults first
fes, err := defaultsFS.ReadDir("defaults")
if err != nil {
log.Fatalf("failed to read defaults/: %v", err)
}

for _, fe := range fes {
path := filepath.Join("defaults", fe.Name())
b, err2 := defaultsFS.ReadFile(path)
if err2 != nil {
log.Fatalf("failed to read %q: %v", path, err2)
if fe.IsDir() {
// Skip directories
continue
}
var config = struct {
ChainID *big.Big
Chain
}{}

if err3 := cconfig.DecodeTOML(bytes.NewReader(b), &config); err3 != nil {
log.Fatalf("failed to decode %q: %v", path, err3)
}
if fe.Name() == "fallback.toml" {
if config.ChainID != nil {
log.Fatalf("fallback ChainID must be nil, not: %s", config.ChainID)
// read the file to bytes
path := filepath.Join("defaults", fe.Name())
chainID, chain, err := readConfig(path, defaultsFS.ReadFile, fe.Name() == "fallback.toml")
if err != nil {
if errors.Is(err, errFallbackConfig) {
fallback = chain

continue
}
fallback = config.Chain
continue
}
if config.ChainID == nil {
log.Fatalf("missing ChainID: %s", path)

log.Fatal(err.Error())
}
DefaultIDs = append(DefaultIDs, config.ChainID)
id := config.ChainID.String()

// add ChainID to set of default IDs
DefaultIDs = append(DefaultIDs, chainID)

// ChainID as a default should not be duplicated
id := chainID.String()
if _, ok := defaults[id]; ok {
log.Fatalf("%q contains duplicate ChainID: %s", path, id)
}
defaults[id] = config.Chain

// set default lookups
defaults[id] = chain
defaultNames[id] = strings.ReplaceAll(strings.TrimSuffix(fe.Name(), ".toml"), "_", " ")
}

// sort default IDs in numeric order
slices.SortFunc(DefaultIDs, func(a, b *big.Big) int {
return a.Cmp(b)
})
}

func initApplyEVMOverrides() {
// read the custom defaults overrides
dir := env.CustomDefaults.Get()
if dir == "" {
Expand All @@ -98,39 +133,54 @@ func init() {
continue
}

// read the file to bytes
path := evmDir + "/" + entry.Name()
file, err := os.Open(path)
chainID, chain, err := readConfig(path, defaultsFS.ReadFile, false)
if err != nil {
log.Fatalf("error opening file (name: %v) in custom defaults override directory: %v", entry.Name(), err)
log.Fatalf("custom defaults override failure (%s): %s", entry.Name(), err.Error())
}

// Read file contents
b, err := io.ReadAll(file)
file.Close()
if err != nil {
log.Fatalf("error reading file (name: %v) contents in custom defaults override directory: %v", entry.Name(), err)
// ChainID as a default should not be duplicated
id := chainID.String()
if _, ok := customDefaults[id]; ok {
log.Fatalf("%q contains duplicate ChainID: %s", path, id)
}

var config = struct {
ChainID *big.Big
Chain
}{}
// set default lookups
customDefaults[id] = chain
}
}

func readConfig(path string, reader func(name string) ([]byte, error), fallback bool) (*big.Big, Chain, error) {
bts, err := reader(path)
if err != nil {
return nil, Chain{}, fmt.Errorf("%w: %s", errRead, err.Error())
}

var config = struct {
ChainID *big.Big
Chain
}{}

if err := cconfig.DecodeTOML(bytes.NewReader(b), &config); err != nil {
log.Fatalf("failed to decode %q in custom defaults override directory: %v", path, err)
}
// decode from toml to a chain config
if err := cconfig.DecodeTOML(bytes.NewReader(bts), &config); err != nil {
return nil, Chain{}, fmt.Errorf("%w %q: %v", errDecode, path, err)

Check failure on line 167 in core/chains/evm/config/toml/defaults.go

View workflow job for this annotation

GitHub Actions / lint

non-wrapping format verb for fmt.Errorf. Use `%w` to format errors (errorlint)
}

if config.ChainID == nil {
log.Fatalf("missing ChainID in: %s in custom defaults override directory. exiting", path)
if fallback {
if config.ChainID != nil {
return nil, Chain{}, fmt.Errorf("%w: found: %s", errNonNilChainID, config.ChainID)
}

id := config.ChainID.String()
return nil, config.Chain, errFallbackConfig
}

if _, ok := customDefaults[id]; ok {
log.Fatalf("%q contains duplicate ChainID: %s", path, id)
}
customDefaults[id] = config.Chain
// ensure ChainID is set
if config.ChainID == nil {
return nil, Chain{}, fmt.Errorf("%w: %s", errMissingChainID, path)
}

return config.ChainID, config.Chain, nil
}

// DefaultsNamed returns the default Chain values, optionally for the given chainID, as well as a name if the chainID is known.
Expand Down
1 change: 1 addition & 0 deletions core/config/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var (
// Migrations env vars
EVMChainIDNotNullMigration0195 = "CL_EVM_CHAINID_NOT_NULL_MIGRATION_0195"
CustomDefaults = Var("CL_CHAIN_DEFAULTS")
CustomFallback = Var("CL_CHAIN_FALLBACK")
)

// LOOPP commands and vars
Expand Down

0 comments on commit 1d753ac

Please sign in to comment.