Skip to content

Commit

Permalink
feat: Update fork epochs
Browse files Browse the repository at this point in the history
  • Loading branch information
samcm committed Oct 30, 2024
1 parent 5cc03d2 commit 38da10d
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 30 deletions.
12 changes: 6 additions & 6 deletions pkg/beacon/metrics_fork.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,22 +112,22 @@ func (f *ForkMetrics) calculateCurrent(ctx context.Context) error {
f.Epochs.Reset()

for _, fork := range spec.ForkEpochs {
f.Epochs.WithLabelValues(fork.Name).Set(float64(fork.Epoch))
f.Epochs.WithLabelValues(string(fork.Name)).Set(float64(fork.Epoch))

Check failure on line 115 in pkg/beacon/metrics_fork.go

View workflow job for this annotation

GitHub Actions / lint

stringintconv: conversion from DataVersion (uint64) to string yields a string of one rune, not a string of digits (govet)

Check failure on line 115 in pkg/beacon/metrics_fork.go

View workflow job for this annotation

GitHub Actions / lint

stringintconv: conversion from DataVersion (uint64) to string yields a string of one rune, not a string of digits (govet)

if fork.Active(phase0.Slot(slot.Number()), slotsPerEpoch) {
f.Activated.WithLabelValues(fork.Name).Set(1)
if fork.Active(phase0.Epoch(phase0.Slot(slot.Number()) / slotsPerEpoch)) {
f.Activated.WithLabelValues(string(fork.Name)).Set(1)

Check failure on line 118 in pkg/beacon/metrics_fork.go

View workflow job for this annotation

GitHub Actions / lint

stringintconv: conversion from DataVersion (uint64) to string yields a string of one rune, not a string of digits (govet)

Check failure on line 118 in pkg/beacon/metrics_fork.go

View workflow job for this annotation

GitHub Actions / lint

stringintconv: conversion from DataVersion (uint64) to string yields a string of one rune, not a string of digits (govet)
} else {
f.Activated.WithLabelValues(fork.Name).Set(0)
f.Activated.WithLabelValues(string(fork.Name)).Set(0)

Check failure on line 120 in pkg/beacon/metrics_fork.go

View workflow job for this annotation

GitHub Actions / lint

stringintconv: conversion from DataVersion (uint64) to string yields a string of one rune, not a string of digits (govet)

Check failure on line 120 in pkg/beacon/metrics_fork.go

View workflow job for this annotation

GitHub Actions / lint

stringintconv: conversion from DataVersion (uint64) to string yields a string of one rune, not a string of digits (govet)
}
}

current, err := spec.ForkEpochs.CurrentFork(phase0.Slot(slot.Number()), slotsPerEpoch)
current, err := spec.ForkEpochs.CurrentFork(phase0.Epoch(phase0.Slot(slot.Number()) / slotsPerEpoch))
if err != nil {
f.log.WithError(err).Error("Failed to set current fork")
} else {
f.Current.Reset()

f.Current.WithLabelValues(current.Name).Set(1)
f.Current.WithLabelValues(string(current.Name)).Set(1)
}

return nil
Expand Down
76 changes: 53 additions & 23 deletions pkg/beacon/state/fork_epoch.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,81 @@ package state

import (
"errors"
"sort"

"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/phase0"
)

var (
// ForkOrder is the canonical order of the forks.
ForkOrder = []spec.DataVersion{
spec.DataVersionPhase0,
spec.DataVersionAltair,
spec.DataVersionBellatrix,
spec.DataVersionCapella,
spec.DataVersionDeneb,
}
)

// ForkEpoch is a beacon fork that activates at a specific epoch.
type ForkEpoch struct {
Epoch phase0.Epoch `yaml:"epoch"`
Version string `json:"version"`
Name string `json:"name"`
Epoch phase0.Epoch `yaml:"epoch"`
Version string `json:"version"`
Name spec.DataVersion `json:"name"`
}

// Active returns true if the fork is active at the given slot.
func (f *ForkEpoch) Active(slot, slotsPerEpoch phase0.Slot) bool {
return phase0.Epoch(int(slot)/int(slotsPerEpoch)) >= f.Epoch
// Active returns true if the fork is active at the given epoch.
func (f *ForkEpoch) Active(epoch phase0.Epoch) bool {
return epoch >= f.Epoch
}

// ForkEpochs is a list of forks that activate at specific epochs.
type ForkEpochs []*ForkEpoch

// Active returns a list of forks that are active at the given slot.
func (f *ForkEpochs) Active(slot, slotsPerEpoch phase0.Slot) []*ForkEpoch {
// Active returns a list of forks that are active at the given epoch.
func (f *ForkEpochs) Active(epoch phase0.Epoch) []*ForkEpoch {
activated := []*ForkEpoch{}

for _, fork := range *f {
if fork.Active(slot, slotsPerEpoch) {
if fork.Active(epoch) {
activated = append(activated, fork)
}
}

// Sort them by our fork order since multiple forks can be activated on the same epoch.
// For example, a non-phase0 genesis.
sort.Slice(activated, func(i, j int) bool {
return f.IndexOf(activated[i].Name) < f.IndexOf(activated[j].Name)
})

return activated
}

// CurrentFork returns the current fork at the given slot.
func (f *ForkEpochs) Scheduled(slot, slotsPerEpoch phase0.Slot) []*ForkEpoch {
// Scheduled returns the scheduled forks at the given epoch.
func (f *ForkEpochs) Scheduled(epoch phase0.Epoch) []*ForkEpoch {
scheduled := []*ForkEpoch{}

for _, fork := range *f {
if !fork.Active(slot, slotsPerEpoch) {
if !fork.Active(epoch) {
scheduled = append(scheduled, fork)
}
}

return scheduled
}

// CurrentFork returns the current fork at the given slot.
func (f *ForkEpochs) CurrentFork(slot, slotsPerEpoch phase0.Slot) (*ForkEpoch, error) {
// CurrentFork returns the current fork at the given epoch.
func (f *ForkEpochs) CurrentFork(epoch phase0.Epoch) (*ForkEpoch, error) {
found := false

largest := &ForkEpoch{
Epoch: 0,
}

for _, fork := range f.Active(slot, slotsPerEpoch) {
if fork.Active(slot, slotsPerEpoch) && fork.Epoch >= largest.Epoch {
active := f.Active(epoch)
for _, fork := range active {
if fork.Epoch >= largest.Epoch {
found = true

largest = fork
Expand All @@ -70,13 +90,13 @@ func (f *ForkEpochs) CurrentFork(slot, slotsPerEpoch phase0.Slot) (*ForkEpoch, e
return largest, nil
}

// PreviousFork returns the previous fork at the given slot.
func (f *ForkEpochs) PreviousFork(slot, slotsPerEpoch phase0.Slot) (*ForkEpoch, error) {
// PreviousFork returns the previous fork at the given epoch.
func (f *ForkEpochs) PreviousFork(epoch phase0.Epoch) (*ForkEpoch, error) {
if len(*f) == 1 {
return f.CurrentFork(slot, slotsPerEpoch)
return f.CurrentFork(epoch)
}

current, err := f.CurrentFork(slot, slotsPerEpoch)
current, err := f.CurrentFork(epoch)
if err != nil {
return nil, err
}
Expand All @@ -87,8 +107,8 @@ func (f *ForkEpochs) PreviousFork(slot, slotsPerEpoch phase0.Slot) (*ForkEpoch,
Epoch: 0,
}

for _, fork := range f.Active(slot, slotsPerEpoch) {
if fork.Active(slot, slotsPerEpoch) && fork.Name != current.Name && fork.Epoch > largest.Epoch {
for _, fork := range f.Active(epoch) {
if fork.Active(epoch) && fork.Name != current.Name && fork.Epoch > largest.Epoch {
found = true

largest = fork
Expand All @@ -105,7 +125,7 @@ func (f *ForkEpochs) PreviousFork(slot, slotsPerEpoch phase0.Slot) (*ForkEpoch,
// GetByName returns the fork with the given name.
func (f *ForkEpochs) GetByName(name string) (*ForkEpoch, error) {
for _, fork := range *f {
if fork.Name == name {
if fork.Name.String() == name {
return fork, nil
}
}
Expand All @@ -117,3 +137,13 @@ func (f *ForkEpochs) GetByName(name string) (*ForkEpoch, error) {
func (f *ForkEpochs) AsScheduledForks() ([]*ScheduledFork, error) {
return ForkScheduleFromForkEpochs(*f)
}

// IndexOf returns the index of the given data version in the fork order.
func (f *ForkEpochs) IndexOf(name spec.DataVersion) int {
for i, version := range ForkOrder {
if version == name {
return i
}
}
return -1 // Return -1 if the name is not found
}
19 changes: 18 additions & 1 deletion pkg/beacon/state/spec.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package state

import (
"encoding/json"
"fmt"
"math/big"
"strings"

sp "github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/spf13/cast"
)
Expand Down Expand Up @@ -175,9 +177,15 @@ func NewSpec(data map[string]interface{}) Spec {
version = v
}

// Convert the name to a DataVersion.
dataVersion, err := dataVersionFromString(k)
if err != nil {
continue
}

spec.ForkEpochs = append(spec.ForkEpochs, &ForkEpoch{
Epoch: v,
Name: k,
Name: dataVersion,
Version: version,
})
}
Expand All @@ -189,3 +197,12 @@ func NewSpec(data map[string]interface{}) Spec {
func (s *Spec) Validate() error {
return nil
}

func dataVersionFromString(name string) (sp.DataVersion, error) {
var v sp.DataVersion
if err := json.Unmarshal([]byte(fmt.Sprintf("\"%q\"", name)), &v); err != nil {
return sp.DataVersionUnknown, err
}

return v, nil
}

0 comments on commit 38da10d

Please sign in to comment.