diff --git a/beacon/params/config.go b/beacon/params/config.go index 2f6ba082c5..492ee53308 100644 --- a/beacon/params/config.go +++ b/beacon/params/config.go @@ -20,6 +20,7 @@ import ( "crypto/sha256" "fmt" "math" + "math/big" "os" "slices" "sort" @@ -90,12 +91,8 @@ func (c *ChainConfig) AddFork(name string, epoch uint64, version []byte) *ChainC // LoadForks parses the beacon chain configuration file (config.yaml) and extracts // the list of forks. -func (c *ChainConfig) LoadForks(path string) error { - file, err := os.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read beacon chain config file: %v", err) - } - config := make(map[string]string) +func (c *ChainConfig) LoadForks(file []byte) error { + config := make(map[string]any) if err := yaml.Unmarshal(file, &config); err != nil { return fmt.Errorf("failed to parse beacon chain config file: %v", err) } @@ -108,18 +105,36 @@ func (c *ChainConfig) LoadForks(path string) error { for key, value := range config { if strings.HasSuffix(key, "_FORK_VERSION") { name := key[:len(key)-len("_FORK_VERSION")] - if v, err := hexutil.Decode(value); err == nil { + switch version := value.(type) { + case int: + versions[name] = new(big.Int).SetUint64(uint64(version)).FillBytes(make([]byte, 4)) + case uint64: + versions[name] = new(big.Int).SetUint64(version).FillBytes(make([]byte, 4)) + case string: + v, err := hexutil.Decode(version) + if err != nil { + return fmt.Errorf("failed to decode hex fork id %q in beacon chain config file: %v", version, err) + } versions[name] = v - } else { - return fmt.Errorf("failed to decode hex fork id %q in beacon chain config file: %v", value, err) + default: + return fmt.Errorf("invalid fork version %q in beacon chain config file", version) } } if strings.HasSuffix(key, "_FORK_EPOCH") { name := key[:len(key)-len("_FORK_EPOCH")] - if v, err := strconv.ParseUint(value, 10, 64); err == nil { + switch epoch := value.(type) { + case int: + epochs[name] = uint64(epoch) + case uint64: + epochs[name] = epoch + case string: + v, err := strconv.ParseUint(epoch, 10, 64) + if err != nil { + return fmt.Errorf("failed to parse epoch number %q in beacon chain config file: %v", epoch, err) + } epochs[name] = v - } else { - return fmt.Errorf("failed to parse epoch number %q in beacon chain config file: %v", value, err) + default: + return fmt.Errorf("invalid fork epoch %q in beacon chain config file", epoch) } } } diff --git a/beacon/params/config_test.go b/beacon/params/config_test.go new file mode 100644 index 0000000000..41e120469b --- /dev/null +++ b/beacon/params/config_test.go @@ -0,0 +1,34 @@ +package params + +import ( + "bytes" + "testing" +) + +func TestChainConfig_LoadForks(t *testing.T) { + const config = ` +GENESIS_FORK_VERSION: 0x00000000 + +ALTAIR_FORK_VERSION: 0x00000001 +ALTAIR_FORK_EPOCH: 1 + +EIP7928_FORK_VERSION: 0xb0000038 +EIP7928_FORK_EPOCH: 18446744073709551615 + +BLOB_SCHEDULE: [] +` + c := &ChainConfig{} + err := c.LoadForks([]byte(config)) + if err != nil { + t.Fatal(err) + } + + for _, fork := range c.Forks { + if fork.Name == "GENESIS" && (fork.Epoch != 0) { + t.Errorf("unexpected genesis fork epoch %d", fork.Epoch) + } + if fork.Name == "ALTAIR" && (fork.Epoch != 1 || !bytes.Equal(fork.Version, []byte{0, 0, 0, 1})) { + t.Errorf("unexpected altair fork epoch %d version %x", fork.Epoch, fork.Version) + } + } +} diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 325f8250f8..5e96185dbd 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1931,11 +1931,15 @@ func MakeBeaconLightConfig(ctx *cli.Context) bparams.ClientConfig { } else { Fatalf("Could not parse --%s: %v", BeaconGenesisRootFlag.Name, err) } - configFile := ctx.String(BeaconConfigFlag.Name) - if err := config.ChainConfig.LoadForks(configFile); err != nil { - Fatalf("Could not load beacon chain config '%s': %v", configFile, err) + configPath := ctx.String(BeaconConfigFlag.Name) + file, err := os.ReadFile(configPath) + if err != nil { + Fatalf("failed to read beacon chain config file '%s': %v", configPath, err) } - log.Info("Using custom beacon chain config", "file", configFile) + if err := config.ChainConfig.LoadForks(file); err != nil { + Fatalf("Could not load beacon chain config '%s': %v", configPath, err) + } + log.Info("Using custom beacon chain config", "file", configPath) } else { if ctx.IsSet(BeaconGenesisRootFlag.Name) { Fatalf("Genesis root is specified but custom beacon chain config is missing")