Compare commits

...

10 Commits

Author SHA1 Message Date
Kasey Kirkham
57e94b89db completely remove network/forks package 2025-06-12 12:34:36 +02:00
Kasey Kirkham
5666a73f70 rm ordered for schedule stuff 2025-06-12 12:31:18 +02:00
Kasey Kirkham
05aa803377 removing ordered schedule 2025-06-12 12:04:35 +02:00
Kasey Kirkham
7cb856be9a move SortedForkVersions 2025-06-12 10:56:41 +02:00
Kasey Kirkham
196d26465d fix tests, bugs and remove more network/forks methods 2025-06-12 10:06:03 +02:00
Kasey Kirkham
5e278329ae rm unused VersionForName 2025-06-12 07:51:04 +02:00
Kasey Kirkham
756b5c1598 replace ComputeForkDigest and ForkDigestForEpoch 2025-06-12 07:51:04 +02:00
Kasey Kirkham
0190e4addd adds pre-computed bpo+fork schedule and updates network/forks to use it 2025-06-12 07:51:04 +02:00
Kasey Kirkham
3f302ad4b6 move network package into config/params 2025-06-12 07:51:04 +02:00
Kasey Kirkham
684a55384b remove unused singing helper 2025-06-12 07:51:04 +02:00
78 changed files with 726 additions and 1683 deletions

View File

@@ -16,7 +16,6 @@ go_library(
"//api/server/structs:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_pkg_errors//:go_default_library",

View File

@@ -9,7 +9,6 @@ import (
"net/url"
"path"
"regexp"
"sort"
"strconv"
"github.com/OffchainLabs/prysm/v6/api/client"
@@ -17,7 +16,6 @@ import (
"github.com/OffchainLabs/prysm/v6/api/server/structs"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
@@ -137,24 +135,6 @@ func (c *Client) GetFork(ctx context.Context, stateId StateOrBlockId) (*ethpb.Fo
return fr.ToConsensus()
}
// GetForkSchedule retrieve all forks, past present and future, of which this node is aware.
func (c *Client) GetForkSchedule(ctx context.Context) (forks.OrderedSchedule, error) {
body, err := c.Get(ctx, getForkSchedulePath)
if err != nil {
return nil, errors.Wrap(err, "error requesting fork schedule")
}
fsr := &forkScheduleResponse{}
err = json.Unmarshal(body, fsr)
if err != nil {
return nil, err
}
ofs, err := fsr.OrderedForkSchedule()
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("problem unmarshaling %s response", getForkSchedulePath))
}
return ofs, nil
}
// GetConfigSpec retrieve the current configs of the network used by the beacon node.
func (c *Client) GetConfigSpec(ctx context.Context) (*structs.GetSpecResponse, error) {
body, err := c.Get(ctx, getConfigSpecPath)
@@ -334,31 +314,3 @@ func (c *Client) GetBLStoExecutionChanges(ctx context.Context) (*structs.BLSToEx
}
return poolResponse, nil
}
type forkScheduleResponse struct {
Data []structs.Fork
}
func (fsr *forkScheduleResponse) OrderedForkSchedule() (forks.OrderedSchedule, error) {
ofs := make(forks.OrderedSchedule, 0)
for _, d := range fsr.Data {
epoch, err := strconv.ParseUint(d.Epoch, 10, 64)
if err != nil {
return nil, errors.Wrapf(err, "error parsing epoch %s", d.Epoch)
}
vSlice, err := hexutil.Decode(d.CurrentVersion)
if err != nil {
return nil, err
}
if len(vSlice) != 4 {
return nil, fmt.Errorf("got %d byte version, expected 4 bytes. version hex=%s", len(vSlice), d.CurrentVersion)
}
version := bytesutil.ToBytes4(vSlice)
ofs = append(ofs, forks.ForkScheduleEntry{
Version: version,
Epoch: primitives.Epoch(epoch),
})
}
sort.Sort(ofs)
return ofs, nil
}

View File

@@ -41,7 +41,6 @@ go_library(
"//encoding/ssz:go_default_library",
"//math:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//network/forks:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",

View File

@@ -11,7 +11,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/crypto/bls"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1/attestation"
"github.com/OffchainLabs/prysm/v6/time/slots"
@@ -101,7 +100,7 @@ func VerifyBlockHeaderSignature(beaconState state.BeaconState, header *ethpb.Sig
// via the respective epoch.
func VerifyBlockSignatureUsingCurrentFork(beaconState state.ReadOnlyBeaconState, blk interfaces.ReadOnlySignedBeaconBlock, blkRoot [32]byte) error {
currentEpoch := slots.ToEpoch(blk.Block().Slot())
fork, err := forks.Fork(currentEpoch)
fork, err := params.Fork(currentEpoch)
if err != nil {
return err
}

View File

@@ -4,7 +4,6 @@ go_library(
name = "go_default_library",
srcs = [
"domain.go",
"signature.go",
"signing_root.go",
],
importpath = "github.com/OffchainLabs/prysm/v6/beacon-chain/core/signing",
@@ -25,7 +24,6 @@ go_test(
name = "go_default_test",
srcs = [
"domain_test.go",
"signature_test.go",
"signing_root_test.go",
],
embed = [":go_default_library"],

View File

@@ -1,34 +0,0 @@
package signing
import (
"github.com/OffchainLabs/prysm/v6/config/params"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/pkg/errors"
)
var ErrNilRegistration = errors.New("nil signed registration")
// VerifyRegistrationSignature verifies the signature of a validator's registration.
func VerifyRegistrationSignature(
sr *ethpb.SignedValidatorRegistrationV1,
) error {
if sr == nil || sr.Message == nil {
return ErrNilRegistration
}
d := params.BeaconConfig().DomainApplicationBuilder
// Per spec, we want the fork version and genesis validator to be nil.
// Which is genesis value and zero by default.
sd, err := ComputeDomain(
d,
nil, /* fork version */
nil /* genesis val root */)
if err != nil {
return err
}
if err := VerifySigningRoot(sr.Message, sr.Message.Pubkey, sr.Signature, sd); err != nil {
return ErrSigFailedToVerify
}
return nil
}

View File

@@ -1,42 +0,0 @@
package signing_test
import (
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/signing"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/crypto/bls"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/require"
)
func TestVerifyRegistrationSignature(t *testing.T) {
sk, err := bls.RandKey()
require.NoError(t, err)
reg := &ethpb.ValidatorRegistrationV1{
FeeRecipient: bytesutil.PadTo([]byte("fee"), 20),
GasLimit: 123456,
Timestamp: uint64(time.Now().Unix()),
Pubkey: sk.PublicKey().Marshal(),
}
d := params.BeaconConfig().DomainApplicationBuilder
domain, err := signing.ComputeDomain(d, nil, nil)
require.NoError(t, err)
sr, err := signing.ComputeSigningRoot(reg, domain)
require.NoError(t, err)
sk.Sign(sr[:]).Marshal()
sReg := &ethpb.SignedValidatorRegistrationV1{
Message: reg,
Signature: sk.Sign(sr[:]).Marshal(),
}
require.NoError(t, signing.VerifyRegistrationSignature(sReg))
sReg.Signature = []byte("bad")
require.ErrorIs(t, signing.VerifyRegistrationSignature(sReg), signing.ErrSigFailedToVerify)
sReg.Message = nil
require.ErrorIs(t, signing.VerifyRegistrationSignature(sReg), signing.ErrNilRegistration)
}

View File

@@ -71,7 +71,6 @@ go_library(
"//monitoring/tracing:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//network:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/metadata:go_default_library",
"//runtime:go_default_library",
@@ -168,7 +167,6 @@ go_test(
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network:go_default_library",
"//network/forks:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/metadata:go_default_library",

View File

@@ -15,7 +15,6 @@ import (
"github.com/OffchainLabs/prysm/v6/crypto/hash"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing/trace"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/time/slots"
"github.com/pkg/errors"
@@ -279,14 +278,8 @@ func (s *Service) BroadcastLightClientOptimisticUpdate(ctx context.Context, upda
return errors.New("attempted to broadcast nil light client optimistic update")
}
forkDigest, err := forks.ForkDigestFromEpoch(slots.ToEpoch(update.AttestedHeader().Beacon().Slot), s.genesisValidatorsRoot)
if err != nil {
err := errors.Wrap(err, "could not retrieve fork digest")
tracing.AnnotateError(span, err)
return err
}
if err := s.broadcastObject(ctx, update, lcOptimisticToTopic(forkDigest)); err != nil {
digest := params.ForkDigest(slots.ToEpoch(update.AttestedHeader().Beacon().Slot))
if err := s.broadcastObject(ctx, update, lcOptimisticToTopic(digest)); err != nil {
log.WithError(err).Debug("Failed to broadcast light client optimistic update")
err := errors.Wrap(err, "could not publish message")
tracing.AnnotateError(span, err)
@@ -305,13 +298,7 @@ func (s *Service) BroadcastLightClientFinalityUpdate(ctx context.Context, update
return errors.New("attempted to broadcast nil light client finality update")
}
forkDigest, err := forks.ForkDigestFromEpoch(slots.ToEpoch(update.AttestedHeader().Beacon().Slot), s.genesisValidatorsRoot)
if err != nil {
err := errors.Wrap(err, "could not retrieve fork digest")
tracing.AnnotateError(span, err)
return err
}
forkDigest := params.ForkDigest(slots.ToEpoch(update.AttestedHeader().Beacon().Slot))
if err := s.broadcastObject(ctx, update, lcFinalityToTopic(forkDigest)); err != nil {
log.WithError(err).Debug("Failed to broadcast light client finality update")
err := errors.Wrap(err, "could not publish message")

View File

@@ -18,10 +18,10 @@ import (
p2ptest "github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/testing"
"github.com/OffchainLabs/prysm/v6/cmd/beacon-chain/flags"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v6/consensus-types/wrapper"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
testpb "github.com/OffchainLabs/prysm/v6/proto/testing"
"github.com/OffchainLabs/prysm/v6/runtime/version"
@@ -550,9 +550,7 @@ func TestService_BroadcastLightClientOptimisticUpdate(t *testing.T) {
require.NoError(t, err)
GossipTypeMapping[reflect.TypeOf(msg)] = LightClientOptimisticUpdateTopicFormat
digest, err := forks.ForkDigestFromEpoch(slots.ToEpoch(msg.AttestedHeader().Beacon().Slot), p.genesisValidatorsRoot)
require.NoError(t, err)
topic := fmt.Sprintf(LightClientOptimisticUpdateTopicFormat, digest)
topic := fmt.Sprintf(LightClientOptimisticUpdateTopicFormat, params.ForkDigest(slots.ToEpoch(msg.AttestedHeader().Beacon().Slot)))
// External peer subscribes to the topic.
topic += p.Encoding().ProtocolSuffix()
@@ -617,9 +615,7 @@ func TestService_BroadcastLightClientFinalityUpdate(t *testing.T) {
require.NoError(t, err)
GossipTypeMapping[reflect.TypeOf(msg)] = LightClientFinalityUpdateTopicFormat
digest, err := forks.ForkDigestFromEpoch(slots.ToEpoch(msg.AttestedHeader().Beacon().Slot), p.genesisValidatorsRoot)
require.NoError(t, err)
topic := fmt.Sprintf(LightClientFinalityUpdateTopicFormat, digest)
topic := fmt.Sprintf(LightClientFinalityUpdateTopicFormat, params.ForkDigest(slots.ToEpoch(msg.AttestedHeader().Beacon().Slot)))
// External peer subscribes to the topic.
topic += p.Encoding().ProtocolSuffix()

View File

@@ -504,7 +504,7 @@ func (s *Service) createLocalNode(
localNode.SetFallbackIP(ipAddr)
localNode.SetFallbackUDP(udpPort)
localNode, err = addForkEntry(localNode, s.genesisTime, s.genesisValidatorsRoot)
localNode, err = addForkEntry(localNode, s.clock.CurrentEpoch())
if err != nil {
return nil, errors.Wrap(err, "could not add eth2 fork version entry to enr")
}

View File

@@ -3,13 +3,10 @@ package p2p
import (
"bytes"
"fmt"
"time"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
prysmTime "github.com/OffchainLabs/prysm/v6/time"
"github.com/OffchainLabs/prysm/v6/time/slots"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/pkg/errors"
@@ -25,7 +22,7 @@ func (s *Service) currentForkDigest() ([4]byte, error) {
if !s.isInitialized() {
return [4]byte{}, errors.New("state is not initialized")
}
return forks.CreateForkDigest(s.genesisTime, s.genesisValidatorsRoot)
return params.ForkDigest(s.clock.CurrentEpoch()), nil
}
// Compares fork ENRs between an incoming peer's record and our node's
@@ -79,24 +76,9 @@ func (s *Service) compareForkENR(record *enr.Record) error {
// which takes into account the current fork version from the current
// epoch to create a fork digest, the next fork version,
// and the next fork epoch.
func addForkEntry(
node *enode.LocalNode,
genesisTime time.Time,
genesisValidatorsRoot []byte,
) (*enode.LocalNode, error) {
digest, err := forks.CreateForkDigest(genesisTime, genesisValidatorsRoot)
if err != nil {
return nil, err
}
currentSlot := slots.Since(genesisTime)
currentEpoch := slots.ToEpoch(currentSlot)
if prysmTime.Now().Before(genesisTime) {
currentEpoch = 0
}
nextForkVersion, nextForkEpoch, err := forks.NextForkData(currentEpoch)
if err != nil {
return nil, err
}
func addForkEntry(node *enode.LocalNode, current primitives.Epoch) (*enode.LocalNode, error) {
digest := params.ForkDigest(current)
nextForkVersion, nextForkEpoch := params.NextForkData(current)
enrForkID := &pb.ENRForkID{
CurrentForkDigest: digest[:],
NextForkVersion: nextForkVersion[:],

View File

@@ -11,11 +11,11 @@ import (
mock "github.com/OffchainLabs/prysm/v6/beacon-chain/blockchain/testing"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/signing"
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -231,10 +231,8 @@ func TestDiscv5_AddRetrieveForkEntryENR(t *testing.T) {
nextForkVersion := []byte{0, 0, 0, 1}
params.OverrideBeaconConfig(c)
genesisTime := time.Now()
genesisValidatorsRoot := make([]byte, 32)
digest, err := forks.CreateForkDigest(genesisTime, make([]byte, 32))
require.NoError(t, err)
clock := startup.NewClock(time.Now(), [32]byte{})
digest := params.ForkDigest(clock.CurrentEpoch())
enrForkID := &pb.ENRForkID{
CurrentForkDigest: digest[:],
NextForkVersion: nextForkVersion,
@@ -256,7 +254,7 @@ func TestDiscv5_AddRetrieveForkEntryENR(t *testing.T) {
localNode := enode.NewLocalNode(db, pkey)
localNode.Set(entry)
want, err := signing.ComputeForkDigest([]byte{0, 0, 0, 0}, genesisValidatorsRoot)
want, err := signing.ComputeForkDigest([]byte{0, 0, 0, 0}, clock.GenesisValidatorsRootSlice())
require.NoError(t, err)
resp, err := forkEntry(localNode.Node().Record())
@@ -283,7 +281,8 @@ func TestAddForkEntry_Genesis(t *testing.T) {
params.OverrideBeaconConfig(bCfg)
localNode := enode.NewLocalNode(db, pkey)
localNode, err = addForkEntry(localNode, time.Now().Add(10*time.Second), bytesutil.PadTo([]byte{'A', 'B', 'C', 'D'}, 32))
clock := startup.NewClock(time.Now(), bCfg.GenesisValidatorsRoot)
localNode, err = addForkEntry(localNode, clock.CurrentEpoch())
require.NoError(t, err)
forkEntry, err := forkEntry(localNode.Node().Record())
require.NoError(t, err)

View File

@@ -25,7 +25,7 @@ func (s *Service) forkWatcher() {
// this over the epoch, which might be slightly wasteful
// but is fine nonetheless.
if s.dv5Listener != nil { // make sure it's not a local network
_, err := addForkEntry(s.dv5Listener.LocalNode(), s.genesisTime, s.genesisValidatorsRoot)
_, err := addForkEntry(s.dv5Listener.LocalNode(), s.clock.CurrentEpoch())
if err != nil {
log.WithError(err).Error("Could not add fork entry")
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/OffchainLabs/prysm/v6/crypto/hash"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/math"
"github.com/OffchainLabs/prysm/v6/network/forks"
pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
)
@@ -39,7 +38,7 @@ func MsgID(genesisValidatorsRoot []byte, pmsg *pubsubpb.Message) string {
copy(msg, "invalid")
return bytesutil.UnsafeCastToString(msg)
}
_, fEpoch, err := forks.RetrieveForkDataFromDigest(digest, genesisValidatorsRoot)
_, fEpoch, err := params.ForkDataFromDigest(digest)
if err != nil {
// Impossible condition that should
// never be hit.

View File

@@ -7,10 +7,10 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/signing"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/crypto/hash"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/golang/snappy"
pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
@@ -18,22 +18,22 @@ import (
func TestMsgID_HashesCorrectly(t *testing.T) {
params.SetupTestConfigCleanup(t)
genesisValidatorsRoot := bytesutil.PadTo([]byte{'A'}, 32)
d, err := forks.CreateForkDigest(time.Now(), genesisValidatorsRoot)
assert.NoError(t, err)
clock := startup.NewClock(time.Now(), bytesutil.ToBytes32([]byte{'A'}))
valRoot := clock.GenesisValidatorsRoot()
d := params.ForkDigest(clock.CurrentEpoch())
tpc := fmt.Sprintf(p2p.BlockSubnetTopicFormat, d)
invalidSnappy := [32]byte{'J', 'U', 'N', 'K'}
pMsg := &pubsubpb.Message{Data: invalidSnappy[:], Topic: &tpc}
hashedData := hash.Hash(append(params.BeaconConfig().MessageDomainInvalidSnappy[:], pMsg.Data...))
msgID := string(hashedData[:20])
assert.Equal(t, msgID, p2p.MsgID(genesisValidatorsRoot, pMsg), "Got incorrect msg id")
assert.Equal(t, msgID, p2p.MsgID(valRoot[:], pMsg), "Got incorrect msg id")
validObj := [32]byte{'v', 'a', 'l', 'i', 'd'}
enc := snappy.Encode(nil, validObj[:])
nMsg := &pubsubpb.Message{Data: enc, Topic: &tpc}
hashedData = hash.Hash(append(params.BeaconConfig().MessageDomainValidSnappy[:], validObj[:]...))
msgID = string(hashedData[:20])
assert.Equal(t, msgID, p2p.MsgID(genesisValidatorsRoot, nMsg), "Got incorrect msg id")
assert.Equal(t, msgID, p2p.MsgID(valRoot[:], nMsg), "Got incorrect msg id")
}
func TestMessageIDFunction_HashesCorrectlyAltair(t *testing.T) {

View File

@@ -6,7 +6,6 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/encoder"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/network/forks"
pubsub "github.com/libp2p/go-libp2p-pubsub"
pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
"github.com/libp2p/go-libp2p/core/peer"
@@ -53,36 +52,12 @@ func (s *Service) CanSubscribe(topic string) bool {
log.WithError(err).Error("Could not determine fork digest")
return false
}
altairForkDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().AltairForkEpoch, s.genesisValidatorsRoot)
if err != nil {
log.WithError(err).Error("Could not determine altair fork digest")
return false
}
bellatrixForkDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, s.genesisValidatorsRoot)
if err != nil {
log.WithError(err).Error("Could not determine Bellatrix fork digest")
return false
}
capellaForkDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().CapellaForkEpoch, s.genesisValidatorsRoot)
if err != nil {
log.WithError(err).Error("Could not determine Capella fork digest")
return false
}
denebForkDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().DenebForkEpoch, s.genesisValidatorsRoot)
if err != nil {
log.WithError(err).Error("Could not determine Deneb fork digest")
return false
}
electraForkDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().ElectraForkEpoch, s.genesisValidatorsRoot)
if err != nil {
log.WithError(err).Error("Could not determine Electra fork digest")
return false
}
fuluForkDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().FuluForkEpoch, s.genesisValidatorsRoot)
if err != nil {
log.WithError(err).Error("Could not determine Fulu fork digest")
return false
}
altairForkDigest := params.ForkDigest(params.BeaconConfig().AltairForkEpoch)
bellatrixForkDigest := params.ForkDigest(params.BeaconConfig().BellatrixForkEpoch)
capellaForkDigest := params.ForkDigest(params.BeaconConfig().CapellaForkEpoch)
denebForkDigest := params.ForkDigest(params.BeaconConfig().DenebForkEpoch)
electraForkDigest := params.ForkDigest(params.BeaconConfig().ElectraForkEpoch)
fuluForkDigest := params.ForkDigest(params.BeaconConfig().FuluForkEpoch)
switch parts[2] {
case fmt.Sprintf("%x", phase0ForkDigest):
case fmt.Sprintf("%x", altairForkDigest):

View File

@@ -11,8 +11,6 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
prysmTime "github.com/OffchainLabs/prysm/v6/time"
pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
@@ -23,10 +21,8 @@ func TestService_CanSubscribe(t *testing.T) {
params.SetupTestConfigCleanup(t)
currentFork := [4]byte{0x01, 0x02, 0x03, 0x04}
validProtocolSuffix := "/" + encoder.ProtocolSuffixSSZSnappy
genesisTime := time.Now()
var valRoot [32]byte
digest, err := forks.CreateForkDigest(genesisTime, valRoot[:])
assert.NoError(t, err)
clock := startup.NewClock(time.Now(), [32]byte{})
digest := params.ForkDigest(clock.CurrentEpoch())
type test struct {
name string
topic string
@@ -108,11 +104,12 @@ func TestService_CanSubscribe(t *testing.T) {
}
tests = append(tests, tt)
}
valRoot := clock.GenesisValidatorsRoot()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Service{
genesisValidatorsRoot: valRoot[:],
genesisTime: genesisTime,
genesisTime: clock.GenesisTime(),
}
if got := s.CanSubscribe(tt.topic); got != tt.want {
t.Errorf("CanSubscribe(%s) = %v, want %v", tt.topic, got, tt.want)
@@ -220,10 +217,8 @@ func TestGossipTopicMapping_scanfcheck_GossipTopicFormattingSanityCheck(t *testi
func TestService_FilterIncomingSubscriptions(t *testing.T) {
params.SetupTestConfigCleanup(t)
validProtocolSuffix := "/" + encoder.ProtocolSuffixSSZSnappy
genesisTime := time.Now()
var valRoot [32]byte
digest, err := forks.CreateForkDigest(genesisTime, valRoot[:])
assert.NoError(t, err)
clock := startup.NewClock(time.Now(), [32]byte{})
digest := params.ForkDigest(clock.CurrentEpoch())
type args struct {
id peer.ID
subs []*pubsubpb.RPC_SubOpts
@@ -320,11 +315,12 @@ func TestService_FilterIncomingSubscriptions(t *testing.T) {
},
},
}
valRoot := clock.GenesisValidatorsRoot()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &Service{
genesisValidatorsRoot: valRoot[:],
genesisTime: genesisTime,
genesisTime: clock.GenesisTime(),
}
got, err := s.FilterIncomingSubscriptions(tt.args.id, tt.args.subs)
if (err != nil) != tt.wantErr {

View File

@@ -14,6 +14,7 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/peers"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/peers/scorers"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/types"
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/config/features"
"github.com/OffchainLabs/prysm/v6/config/params"
leakybucket "github.com/OffchainLabs/prysm/v6/container/leaky-bucket"
@@ -82,6 +83,7 @@ type Service struct {
genesisTime time.Time
genesisValidatorsRoot []byte
activeValidatorCount uint64
clock *startup.Clock
}
// NewService initializes a new p2p service compatible with shared.Service interface. No

View File

@@ -15,7 +15,6 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
prysmTime "github.com/OffchainLabs/prysm/v6/time"
@@ -348,14 +347,12 @@ func TestService_JoinLeaveTopic(t *testing.T) {
func initializeStateWithForkDigest(_ context.Context, t *testing.T, gs startup.ClockSetter) [4]byte {
gt := prysmTime.Now()
gvr := bytesutil.ToBytes32(bytesutil.PadTo([]byte("genesis validators root"), 32))
require.NoError(t, gs.SetClock(startup.NewClock(gt, gvr)))
fd, err := forks.CreateForkDigest(gt, gvr[:])
require.NoError(t, err)
clock := startup.NewClock(gt, gvr)
require.NoError(t, gs.SetClock(clock))
time.Sleep(50 * time.Millisecond) // wait for pubsub filter to initialize.
return fd
return params.ForkDigest(clock.CurrentEpoch())
}
func TestService_connectWithPeer(t *testing.T) {

View File

@@ -9,7 +9,6 @@ go_library(
"//api/server/structs:go_default_library",
"//config/params:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//network/forks:go_default_library",
"//network/httputil:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
],
@@ -24,7 +23,6 @@ go_test(
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network/forks:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",

View File

@@ -10,7 +10,6 @@ import (
"github.com/OffchainLabs/prysm/v6/api/server/structs"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing/trace"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/network/httputil"
"github.com/ethereum/go-ethereum/common/hexutil"
)
@@ -33,34 +32,25 @@ func GetForkSchedule(w http.ResponseWriter, r *http.Request) {
_, span := trace.StartSpan(r.Context(), "config.GetForkSchedule")
defer span.End()
schedule := params.BeaconConfig().ForkVersionSchedule
schedule := params.SortedForkSchedule()
data := make([]*structs.Fork, 0, len(schedule))
if len(schedule) == 0 {
httputil.WriteJson(w, &structs.GetForkScheduleResponse{
Data: make([]*structs.Fork, 0),
Data: data,
})
return
}
versions := forks.SortedForkVersions(schedule)
chainForks := make([]*structs.Fork, len(schedule))
var previous, current []byte
for i, v := range versions {
if i == 0 {
previous = params.BeaconConfig().GenesisForkVersion
} else {
previous = current
}
copyV := v
current = copyV[:]
chainForks[i] = &structs.Fork{
PreviousVersion: hexutil.Encode(previous),
CurrentVersion: hexutil.Encode(current),
Epoch: fmt.Sprintf("%d", schedule[v]),
}
previous := schedule[0]
for _, entry := range schedule {
data = append(data, &structs.Fork{
PreviousVersion: hexutil.Encode(previous.ForkVersion[:]),
CurrentVersion: hexutil.Encode(entry.ForkVersion[:]),
Epoch: fmt.Sprintf("%d", entry.Epoch),
})
previous = entry
}
httputil.WriteJson(w, &structs.GetForkScheduleResponse{
Data: chainForks,
Data: data,
})
}

View File

@@ -13,7 +13,6 @@ import (
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/ethereum/go-ethereum/common"
@@ -633,7 +632,7 @@ func TestForkSchedule_Ok(t *testing.T) {
require.Equal(t, http.StatusOK, writer.Code)
resp := &structs.GetForkScheduleResponse{}
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp))
os := forks.NewOrderedSchedule(params.BeaconConfig())
assert.Equal(t, os.Len(), len(resp.Data))
os := params.SortedForkSchedule()
assert.Equal(t, len(os), len(resp.Data))
})
}

View File

@@ -20,7 +20,6 @@ go_library(
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//network/forks:go_default_library",
"//network/httputil:go_default_library",
"//runtime/version:go_default_library",
"//time/slots:go_default_library",

View File

@@ -11,7 +11,6 @@ import (
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing/trace"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/network/httputil"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/time/slots"
@@ -115,7 +114,7 @@ func (s *Server) GetLightClientUpdatesByRange(w http.ResponseWriter, req *http.R
updateSlot := update.AttestedHeader().Beacon().Slot
updateEpoch := slots.ToEpoch(updateSlot)
updateFork, err := forks.Fork(updateEpoch)
updateFork, err := params.Fork(updateEpoch)
if err != nil {
httputil.HandleError(w, "Could not get fork Version: "+err.Error(), http.StatusInternalServerError)
return

View File

@@ -19,7 +19,6 @@ import (
"github.com/OffchainLabs/prysm/v6/encoding/ssz"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing/trace"
"github.com/OffchainLabs/prysm/v6/network/forks"
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/time/slots"
@@ -220,7 +219,7 @@ func (vs *Server) getPayloadHeaderFromBuilder(
if signedBid == nil || signedBid.IsNil() {
return nil, errors.New("builder returned nil bid")
}
fork, err := forks.Fork(slots.ToEpoch(slot))
fork, err := params.Fork(slots.ToEpoch(slot))
if err != nil {
return nil, errors.Wrap(err, "unable to get fork information")
}

View File

@@ -29,7 +29,6 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/sync"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"google.golang.org/grpc/codes"
@@ -155,7 +154,7 @@ func (vs *Server) ValidatorIndex(ctx context.Context, req *ethpb.ValidatorIndexR
//
// DomainData fetches the current domain version information from the beacon state.
func (vs *Server) DomainData(ctx context.Context, request *ethpb.DomainRequest) (*ethpb.DomainResponse, error) {
fork, err := forks.Fork(request.Epoch)
fork, err := params.Fork(request.Epoch)
if err != nil {
return nil, err
}

View File

@@ -35,12 +35,21 @@ func (g *Clock) GenesisValidatorsRoot() [32]byte {
return g.vr
}
// GenesisValidatorsRoot returns the genesis state validator root as a slice for convenience.
func (g *Clock) GenesisValidatorsRootSlice() []byte {
return g.vr[:]
}
// CurrentSlot returns the current slot relative to the time.Time value that Clock embeds.
func (g *Clock) CurrentSlot() types.Slot {
now := g.now()
return slots.Duration(g.t, now)
}
func (g *Clock) CurrentEpoch() types.Epoch {
return slots.ToEpoch(g.CurrentSlot())
}
// SlotStart computes the time the given slot begins.
func (g *Clock) SlotStart(slot types.Slot) time.Time {
return slots.BeginsAt(slot, g.t)

View File

@@ -119,7 +119,6 @@ go_library(
"//math:go_default_library",
"//monitoring/tracing:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",
"//proto/prysm/v1alpha1/metadata:go_default_library",
@@ -250,7 +249,6 @@ go_test(
"//crypto/rand:go_default_library",
"//encoding/bytesutil:go_default_library",
"//encoding/ssz/equality:go_default_library",
"//network/forks:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",

View File

@@ -35,7 +35,6 @@ go_library(
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network/forks:go_default_library",
"//proto/dbval:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime:go_default_library",
@@ -80,7 +79,6 @@ go_test(
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network/forks:go_default_library",
"//proto/dbval:go_default_library",
"//runtime/interop:go_default_library",
"//testing/require:go_default_library",

View File

@@ -9,7 +9,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/crypto/bls"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/time/slots"
"github.com/pkg/errors"
@@ -107,8 +106,7 @@ func (vr verifier) blockSignatureBatch(b blocks.ROBlock) (*bls.SignatureBatch, e
}
func newBackfillVerifier(vr []byte, keys [][fieldparams.BLSPubkeyLength]byte) (*verifier, error) {
dc, err := newDomainCache(vr, params.BeaconConfig().DomainBeaconProposer,
forks.NewOrderedSchedule(params.BeaconConfig()))
dc, err := newDomainCache(vr, params.BeaconConfig().DomainBeaconProposer)
if err != nil {
return nil, err
}
@@ -122,33 +120,31 @@ func newBackfillVerifier(vr []byte, keys [][fieldparams.BLSPubkeyLength]byte) (*
// domainCache provides a fast signing domain lookup by epoch.
type domainCache struct {
fsched forks.OrderedSchedule
forkDomains map[[4]byte][]byte
dType [bls.DomainByteLength]byte
}
func newDomainCache(vRoot []byte, dType [bls.DomainByteLength]byte, fsched forks.OrderedSchedule) (*domainCache, error) {
func newDomainCache(vRoot []byte, dType [bls.DomainByteLength]byte) (*domainCache, error) {
dc := &domainCache{
fsched: fsched,
forkDomains: make(map[[4]byte][]byte),
dType: dType,
}
for _, entry := range fsched {
d, err := signing.ComputeDomain(dc.dType, entry.Version[:], vRoot)
for _, entry := range params.SortedForkSchedule() {
d, err := signing.ComputeDomain(dc.dType, entry.ForkVersion[:], vRoot)
if err != nil {
return nil, errors.Wrapf(err, "failed to pre-compute signing domain for fork version=%#x", entry.Version)
return nil, errors.Wrapf(err, "failed to pre-compute signing domain for fork version=%#x", entry.ForkVersion)
}
dc.forkDomains[entry.Version] = d
dc.forkDomains[entry.ForkVersion] = d
}
return dc, nil
}
func (dc *domainCache) forEpoch(e primitives.Epoch) ([]byte, error) {
fork, err := dc.fsched.VersionForEpoch(e)
fork, err := params.Fork(e)
if err != nil {
return nil, err
}
d, ok := dc.forkDomains[fork]
d, ok := dc.forkDomains[[4]byte(fork.CurrentVersion)]
if !ok {
return nil, errors.Wrapf(errUnknownDomain, "fork version=%#x, epoch=%d", fork, e)
}

View File

@@ -12,7 +12,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/crypto/bls"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/runtime/interop"
"github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/OffchainLabs/prysm/v6/testing/util"
@@ -30,18 +29,17 @@ func TestDomainCache(t *testing.T) {
}
vRoot, err := hexutil.Decode("0x0011223344556677889900112233445566778899001122334455667788990011")
require.NoError(t, err)
dType := cfg.DomainBeaconProposer
require.NoError(t, err)
require.Equal(t, 32, len(vRoot))
fsched := forks.NewOrderedSchedule(cfg)
dc, err := newDomainCache(vRoot, dType, fsched)
dc, err := newDomainCache(vRoot, dType)
require.NoError(t, err)
require.Equal(t, len(fsched), len(dc.forkDomains))
for i := range fsched {
e := fsched[i].Epoch
ad, err := dc.forEpoch(e)
schedule := params.SortedForkSchedule()
require.Equal(t, len(schedule), len(dc.forkDomains))
for _, entry := range schedule {
ad, err := dc.forEpoch(entry.Epoch)
require.NoError(t, err)
ed, err := signing.ComputeDomain(dType, fsched[i].Version[:], vRoot)
ed, err := signing.ComputeDomain(dType, entry.ForkVersion[:], vRoot)
require.NoError(t, err)
require.DeepEqual(t, ed, ad)
}

View File

@@ -22,7 +22,6 @@ import (
types "github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
leakybucket "github.com/OffchainLabs/prysm/v6/container/leaky-bucket"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -157,11 +156,7 @@ func (r *expectedBlobChunk) requireExpected(t *testing.T, s *Service, stream net
c, err := readContextFromStream(stream)
require.NoError(t, err)
valRoot := s.cfg.chain.GenesisValidatorsRoot()
ctxBytes, err := forks.ForkDigestFromEpoch(slots.ToEpoch(r.sidecar.Slot()), valRoot[:])
require.NoError(t, err)
require.Equal(t, ctxBytes, bytesutil.ToBytes4(c))
require.Equal(t, params.ForkDigest(slots.ToEpoch(r.sidecar.Slot())), bytesutil.ToBytes4(c))
sc := &ethpb.BlobSidecar{}
require.NoError(t, encoding.DecodeWithMaxLength(stream, sc))
@@ -281,7 +276,7 @@ func repositionFutureEpochs(cfg *params.BeaconChainConfig) {
func defaultMockChain(t *testing.T) (*mock.ChainService, *startup.Clock) {
de := params.BeaconConfig().DenebForkEpoch
df, err := forks.Fork(de)
df, err := params.Fork(de)
require.NoError(t, err)
denebBuffer := params.BeaconConfig().MinEpochsForBlobsSidecarsRequest + 1000
ce := de + denebBuffer

View File

@@ -46,7 +46,6 @@ go_test(
"//consensus-types/blocks/testing:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/ssz/detect:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//testing/require:go_default_library",

View File

@@ -13,7 +13,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
blocktest "github.com/OffchainLabs/prysm/v6/consensus-types/blocks/testing"
"github.com/OffchainLabs/prysm/v6/encoding/ssz/detect"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/OffchainLabs/prysm/v6/testing/util"
"github.com/OffchainLabs/prysm/v6/time/slots"
@@ -31,7 +30,7 @@ func TestDownloadFinalizedData(t *testing.T) {
require.NoError(t, err)
st, err := util.NewBeaconState()
require.NoError(t, err)
fork, err := forks.ForkForEpochFromConfig(cfg, epoch)
fork, err := params.ForkFromConfig(cfg, epoch)
require.NoError(t, err)
require.NoError(t, st.SetFork(fork))
require.NoError(t, st.SetSlot(slot))

View File

@@ -17,7 +17,6 @@ import (
blocktest "github.com/OffchainLabs/prysm/v6/consensus-types/blocks/testing"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/ssz/detect"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -84,7 +83,7 @@ func TestDownloadWeakSubjectivityCheckpoint(t *testing.T) {
require.NoError(t, err)
wst, err := util.NewBeaconState()
require.NoError(t, err)
fork, err := forkForEpoch(cfg, epoch)
fork, err := params.Fork(epoch)
require.NoError(t, err)
require.NoError(t, wst.SetFork(fork))
@@ -183,7 +182,7 @@ func TestDownloadBackwardsCompatibleCombined(t *testing.T) {
require.NoError(t, err)
wst, err := util.NewBeaconState()
require.NoError(t, err)
fork, err := forkForEpoch(cfg, cfg.GenesisEpoch)
fork, err := params.Fork(cfg.GenesisEpoch)
require.NoError(t, err)
require.NoError(t, wst.SetFork(fork))
@@ -280,33 +279,11 @@ func TestGetWeakSubjectivityEpochFromHead(t *testing.T) {
require.Equal(t, expectedEpoch, actualEpoch)
}
func forkForEpoch(cfg *params.BeaconChainConfig, epoch primitives.Epoch) (*ethpb.Fork, error) {
os := forks.NewOrderedSchedule(cfg)
currentVersion, err := os.VersionForEpoch(epoch)
if err != nil {
return nil, err
}
prevVersion, err := os.Previous(currentVersion)
if err != nil {
if !errors.Is(err, forks.ErrNoPreviousVersion) {
return nil, err
}
// use same version for both in the case of genesis
prevVersion = currentVersion
}
forkEpoch := cfg.ForkVersionSchedule[currentVersion]
return &ethpb.Fork{
PreviousVersion: prevVersion[:],
CurrentVersion: currentVersion[:],
Epoch: forkEpoch,
}, nil
}
func defaultTestHeadState(t *testing.T, cfg *params.BeaconChainConfig) (state.BeaconState, primitives.Epoch) {
st, err := util.NewBeaconStateAltair()
require.NoError(t, err)
fork, err := forkForEpoch(cfg, cfg.AltairForkEpoch)
fork, err := params.Fork(cfg.AltairForkEpoch)
require.NoError(t, err)
require.NoError(t, st.SetFork(fork))

View File

@@ -4,7 +4,6 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/time/slots"
"github.com/libp2p/go-libp2p/core/protocol"
"github.com/pkg/errors"
@@ -42,54 +41,41 @@ func (s *Service) forkWatcher() {
// registerForUpcomingFork registers appropriate gossip and RPC topic if there is a fork in the next epoch.
func (s *Service) registerForUpcomingFork(currentEpoch primitives.Epoch) error {
// Get the genesis validators root.
genesisValidatorsRoot := s.cfg.clock.GenesisValidatorsRoot()
// Check if there is a fork in the next epoch.
isForkNextEpoch, err := forks.IsForkNextEpoch(s.cfg.clock.GenesisTime(), genesisValidatorsRoot[:])
if err != nil {
return errors.Wrap(err, "Could not retrieve next fork epoch")
}
isForkNextEpoch := params.IsForkNextEpoch(currentEpoch)
// Exit early if there is no fork in the next epoch.
if !isForkNextEpoch {
return nil
}
beforeForkEpoch := currentEpoch
forkEpoch := beforeForkEpoch + 1
// Get the fork afterForkDigest for the next epoch.
afterForkDigest, err := forks.ForkDigestFromEpoch(forkEpoch, genesisValidatorsRoot[:])
if err != nil {
return errors.Wrap(err, "could not retrieve fork digest")
}
nextForkEpoch := currentEpoch + 1
nextForkDigest := params.ForkDigest(nextForkEpoch)
// Exit early if the topics for the next epoch are already registered.
// It likely to be the case for all slots of the epoch that are not the first one.
if s.subHandler.digestExists(afterForkDigest) {
if s.subHandler.digestExists(nextForkDigest) {
return nil
}
// Register the subscribers (gossipsub) for the next epoch.
s.registerSubscribers(forkEpoch, afterForkDigest)
s.registerSubscribers(nextForkEpoch, nextForkDigest)
// Get the handlers for the current and next fork.
beforeForkHandlerByTopic, err := s.rpcHandlerByTopicFromEpoch(beforeForkEpoch)
currentHandler, err := s.rpcHandlerByTopicFromEpoch(currentEpoch)
if err != nil {
return errors.Wrap(err, "RPC handler by topic from before fork epoch")
}
forkHandlerByTopic, err := s.rpcHandlerByTopicFromEpoch(forkEpoch)
nextHandler, err := s.rpcHandlerByTopicFromEpoch(nextForkEpoch)
if err != nil {
return errors.Wrap(err, "RPC handler by topic from fork epoch")
}
// Compute newly added topics.
newRPCHandlerByTopic := addedRPCHandlerByTopic(beforeForkHandlerByTopic, forkHandlerByTopic)
newHandlersByTopic := addedRPCHandlerByTopic(currentHandler, nextHandler)
// Register the new RPC handlers.
for topic, handler := range newRPCHandlerByTopic {
for topic, handler := range newHandlersByTopic {
s.registerRPC(topic, handler)
}
@@ -98,11 +84,8 @@ func (s *Service) registerForUpcomingFork(currentEpoch primitives.Epoch) error {
// deregisterFromPastFork deregisters appropriate gossip and RPC topic if there is a fork in the current epoch.
func (s *Service) deregisterFromPastFork(currentEpoch primitives.Epoch) error {
// Extract the genesis validators root.
genesisValidatorsRoot := s.cfg.clock.GenesisValidatorsRoot()
// Get the fork.
currentFork, err := forks.Fork(currentEpoch)
currentFork, err := params.Fork(currentEpoch)
if err != nil {
return errors.Wrap(err, "genesis validators root")
}
@@ -123,10 +106,7 @@ func (s *Service) deregisterFromPastFork(currentEpoch primitives.Epoch) error {
// Look at the previous fork's digest.
beforeForkEpoch := currentFork.Epoch - 1
beforeForkDigest, err := forks.ForkDigestFromEpoch(beforeForkEpoch, genesisValidatorsRoot[:])
if err != nil {
return errors.Wrap(err, "fork digest from epoch")
}
beforeForkDigest := params.ForkDigest(beforeForkEpoch)
// Exit early if there are no topics with that particular digest.
if !s.subHandler.digestExists(beforeForkDigest) {

View File

@@ -13,7 +13,6 @@ import (
mockSync "github.com/OffchainLabs/prysm/v6/beacon-chain/sync/initial-sync/testing"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/testing/assert"
)
@@ -90,9 +89,7 @@ func TestService_CheckForNextEpochFork(t *testing.T) {
currEpoch: 4,
wantErr: false,
postSvcCheck: func(t *testing.T, s *Service) {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(5, genRoot[:])
assert.NoError(t, err)
digest := params.ForkDigest(5)
assert.Equal(t, true, s.subHandler.digestExists(digest))
rpcMap := make(map[string]bool)
for _, p := range s.cfg.p2p.Host().Mux().Protocols() {
@@ -134,9 +131,7 @@ func TestService_CheckForNextEpochFork(t *testing.T) {
currEpoch: 4,
wantErr: false,
postSvcCheck: func(t *testing.T, s *Service) {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(5, genRoot[:])
assert.NoError(t, err)
digest := params.ForkDigest(5)
assert.Equal(t, true, s.subHandler.digestExists(digest))
rpcMap := make(map[string]bool)
for _, p := range s.cfg.p2p.Host().Mux().Protocols() {
@@ -176,9 +171,7 @@ func TestService_CheckForNextEpochFork(t *testing.T) {
currEpoch: 4,
wantErr: false,
postSvcCheck: func(t *testing.T, s *Service) {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(5, genRoot[:])
assert.NoError(t, err)
digest := params.ForkDigest(5)
assert.Equal(t, true, s.subHandler.digestExists(digest))
rpcMap := make(map[string]bool)
for _, p := range s.cfg.p2p.Host().Mux().Protocols() {
@@ -220,9 +213,7 @@ func TestService_CheckForNextEpochFork(t *testing.T) {
currEpoch: 4,
wantErr: false,
postSvcCheck: func(t *testing.T, s *Service) {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(5, genRoot[:])
assert.NoError(t, err)
digest := params.ForkDigest(5)
assert.Equal(t, true, s.subHandler.digestExists(digest))
rpcMap := make(map[string]bool)
for _, p := range s.cfg.p2p.Host().Mux().Protocols() {
@@ -264,9 +255,7 @@ func TestService_CheckForNextEpochFork(t *testing.T) {
currEpoch: 4,
wantErr: false,
postSvcCheck: func(t *testing.T, s *Service) {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(5, genRoot[:])
assert.NoError(t, err)
digest := params.ForkDigest(5)
assert.Equal(t, true, s.subHandler.digestExists(digest))
rpcMap := make(map[string]bool)
for _, p := range s.cfg.p2p.Host().Mux().Protocols() {
@@ -384,14 +373,12 @@ func TestService_CheckForPreviousEpochFork(t *testing.T) {
r.registerRPC(topic, handler)
}
genRoot := r.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(0, genRoot[:])
digest := params.ForkDigest(0)
assert.NoError(t, err)
r.registerSubscribers(0, digest)
assert.Equal(t, true, r.subHandler.digestExists(digest))
digest, err = forks.ForkDigestFromEpoch(3, genRoot[:])
assert.NoError(t, err)
digest = params.ForkDigest(3)
r.registerSubscribers(3, digest)
assert.Equal(t, true, r.subHandler.digestExists(digest))
@@ -400,12 +387,9 @@ func TestService_CheckForPreviousEpochFork(t *testing.T) {
currEpoch: 4,
wantErr: false,
postSvcCheck: func(t *testing.T, s *Service) {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(0, genRoot[:])
assert.NoError(t, err)
digest := params.ForkDigest(0)
assert.Equal(t, false, s.subHandler.digestExists(digest))
digest, err = forks.ForkDigestFromEpoch(3, genRoot[:])
assert.NoError(t, err)
digest = params.ForkDigest(3)
assert.Equal(t, true, s.subHandler.digestExists(digest))
ptcls := s.cfg.p2p.Host().Mux().Protocols()
@@ -452,14 +436,11 @@ func TestService_CheckForPreviousEpochFork(t *testing.T) {
chainStarted: abool.New(),
subHandler: newSubTopicHandler(),
}
genRoot := r.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(1, genRoot[:])
assert.NoError(t, err)
digest := params.ForkDigest(1)
r.registerSubscribers(1, digest)
assert.Equal(t, true, r.subHandler.digestExists(digest))
digest, err = forks.ForkDigestFromEpoch(3, genRoot[:])
assert.NoError(t, err)
digest = params.ForkDigest(3)
r.registerSubscribers(3, digest)
assert.Equal(t, true, r.subHandler.digestExists(digest))
@@ -468,12 +449,9 @@ func TestService_CheckForPreviousEpochFork(t *testing.T) {
currEpoch: 4,
wantErr: false,
postSvcCheck: func(t *testing.T, s *Service) {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(1, genRoot[:])
assert.NoError(t, err)
digest := params.ForkDigest(1)
assert.Equal(t, false, s.subHandler.digestExists(digest))
digest, err = forks.ForkDigestFromEpoch(3, genRoot[:])
assert.NoError(t, err)
digest = params.ForkDigest(3)
assert.Equal(t, true, s.subHandler.digestExists(digest))
},
},

View File

@@ -8,8 +8,6 @@ import (
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
"github.com/OffchainLabs/prysm/v6/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/time/slots"
libp2pcore "github.com/libp2p/go-libp2p/core"
"github.com/pkg/errors"
@@ -29,57 +27,9 @@ func WriteBlockChunk(stream libp2pcore.Stream, tor blockchain.TemporalOracle, en
if _, err := stream.Write([]byte{responseCodeSuccess}); err != nil {
return err
}
var obtainedCtx []byte
valRoot := tor.GenesisValidatorsRoot()
switch blk.Version() {
case version.Phase0:
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().GenesisEpoch, valRoot[:])
if err != nil {
return err
}
obtainedCtx = digest[:]
case version.Altair:
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().AltairForkEpoch, valRoot[:])
if err != nil {
return err
}
obtainedCtx = digest[:]
case version.Bellatrix:
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, valRoot[:])
if err != nil {
return err
}
obtainedCtx = digest[:]
case version.Capella:
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().CapellaForkEpoch, valRoot[:])
if err != nil {
return err
}
obtainedCtx = digest[:]
case version.Deneb:
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().DenebForkEpoch, valRoot[:])
if err != nil {
return err
}
obtainedCtx = digest[:]
case version.Electra:
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().ElectraForkEpoch, valRoot[:])
if err != nil {
return err
}
obtainedCtx = digest[:]
case version.Fulu:
digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().FuluForkEpoch, valRoot[:])
if err != nil {
return err
}
obtainedCtx = digest[:]
default:
return errors.Wrapf(ErrUnrecognizedVersion, "block version %d is not recognized", blk.Version())
}
if err := writeContextToStream(obtainedCtx, stream); err != nil {
digest := params.ForkDigest(slots.ToEpoch(blk.Block().Slot()))
if err := writeContextToStream(digest[:], stream); err != nil {
return err
}
_, err := encoding.EncodeWithMaxLength(stream, blk)
@@ -149,16 +99,11 @@ func WriteBlobSidecarChunk(stream libp2pcore.Stream, tor blockchain.TemporalOrac
if _, err := stream.Write([]byte{responseCodeSuccess}); err != nil {
return err
}
valRoot := tor.GenesisValidatorsRoot()
ctxBytes, err := forks.ForkDigestFromEpoch(slots.ToEpoch(sidecar.Slot()), valRoot[:])
if err != nil {
return err
}
ctxBytes := params.ForkDigest(slots.ToEpoch(sidecar.Slot()))
if err := writeContextToStream(ctxBytes[:], stream); err != nil {
return err
}
_, err = encoding.EncodeWithMaxLength(stream, sidecar)
_, err := encoding.EncodeWithMaxLength(stream, sidecar)
return err
}
@@ -167,18 +112,12 @@ func WriteLightClientBootstrapChunk(stream libp2pcore.Stream, tor blockchain.Tem
return err
}
valRoot := tor.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(slots.ToEpoch(bootstrap.Header().Beacon().Slot), valRoot[:])
if err != nil {
digest := params.ForkDigest(slots.ToEpoch(bootstrap.Header().Beacon().Slot))
if err := writeContextToStream(digest[:], stream); err != nil {
return err
}
obtainedCtx := digest[:]
if err = writeContextToStream(obtainedCtx, stream); err != nil {
return err
}
_, err = encoding.EncodeWithMaxLength(stream, bootstrap)
_, err := encoding.EncodeWithMaxLength(stream, bootstrap)
return err
}
@@ -187,17 +126,11 @@ func WriteLightClientUpdateChunk(stream libp2pcore.Stream, tor blockchain.Tempor
return err
}
valRoot := tor.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(slots.ToEpoch(update.AttestedHeader().Beacon().Slot), valRoot[:])
if err != nil {
digest := params.ForkDigest(slots.ToEpoch(update.AttestedHeader().Beacon().Slot))
if err := writeContextToStream(digest[:], stream); err != nil {
return err
}
obtainedCtx := digest[:]
if err = writeContextToStream(obtainedCtx, stream); err != nil {
return err
}
_, err = encoding.EncodeWithMaxLength(stream, update)
_, err := encoding.EncodeWithMaxLength(stream, update)
return err
}
@@ -206,17 +139,12 @@ func WriteLightClientOptimisticUpdateChunk(stream libp2pcore.Stream, tor blockch
return err
}
valRoot := tor.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(slots.ToEpoch(update.AttestedHeader().Beacon().Slot), valRoot[:])
if err != nil {
return err
}
obtainedCtx := digest[:]
digest := params.ForkDigest(slots.ToEpoch(update.AttestedHeader().Beacon().Slot))
if err = writeContextToStream(obtainedCtx, stream); err != nil {
if err := writeContextToStream(digest[:], stream); err != nil {
return err
}
_, err = encoding.EncodeWithMaxLength(stream, update)
_, err := encoding.EncodeWithMaxLength(stream, update)
return err
}
@@ -225,16 +153,11 @@ func WriteLightClientFinalityUpdateChunk(stream libp2pcore.Stream, tor blockchai
return err
}
valRoot := tor.GenesisValidatorsRoot()
digest, err := forks.ForkDigestFromEpoch(slots.ToEpoch(update.AttestedHeader().Beacon().Slot), valRoot[:])
if err != nil {
return err
}
obtainedCtx := digest[:]
digest := params.ForkDigest(slots.ToEpoch(update.AttestedHeader().Beacon().Slot))
if err = writeContextToStream(obtainedCtx, stream); err != nil {
if err := writeContextToStream(digest[:], stream); err != nil {
return err
}
_, err = encoding.EncodeWithMaxLength(stream, update)
_, err := encoding.EncodeWithMaxLength(stream, update)
return err
}

View File

@@ -17,7 +17,6 @@ import (
"github.com/OffchainLabs/prysm/v6/config/features"
"github.com/OffchainLabs/prysm/v6/config/params"
leakybucket "github.com/OffchainLabs/prysm/v6/container/leaky-bucket"
"github.com/OffchainLabs/prysm/v6/network/forks"
pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -63,17 +62,11 @@ func TestRPC_LightClientBootstrap(t *testing.T) {
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, time.Second, false)
altairDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().AltairForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
bellatrixDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
capellaDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().CapellaForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
denebDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().DenebForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
electraDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().ElectraForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
altairDigest := params.ForkDigest(params.BeaconConfig().AltairForkEpoch)
bellatrixDigest := params.ForkDigest(params.BeaconConfig().BellatrixForkEpoch)
capellaDigest := params.ForkDigest(params.BeaconConfig().CapellaForkEpoch)
denebDigest := params.ForkDigest(params.BeaconConfig().DenebForkEpoch)
electraDigest := params.ForkDigest(params.BeaconConfig().ElectraForkEpoch)
for i := 1; i <= 5; i++ {
t.Run(version.String(i), func(t *testing.T) {
l := util.NewTestLightClient(t, i)
@@ -185,16 +178,11 @@ func TestRPC_LightClientOptimisticUpdate(t *testing.T) {
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, time.Second, false)
altairDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().AltairForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
bellatrixDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
capellaDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().CapellaForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
denebDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().DenebForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
electraDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().ElectraForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
altairDigest := params.ForkDigest(params.BeaconConfig().AltairForkEpoch)
bellatrixDigest := params.ForkDigest(params.BeaconConfig().BellatrixForkEpoch)
capellaDigest := params.ForkDigest(params.BeaconConfig().CapellaForkEpoch)
denebDigest := params.ForkDigest(params.BeaconConfig().DenebForkEpoch)
electraDigest := params.ForkDigest(params.BeaconConfig().ElectraForkEpoch)
for i := 1; i <= 5; i++ {
t.Run(version.String(i), func(t *testing.T) {
@@ -305,16 +293,11 @@ func TestRPC_LightClientFinalityUpdate(t *testing.T) {
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, time.Second, false)
altairDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().AltairForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
bellatrixDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
capellaDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().CapellaForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
denebDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().DenebForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
electraDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().ElectraForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
altairDigest := params.ForkDigest(params.BeaconConfig().AltairForkEpoch)
bellatrixDigest := params.ForkDigest(params.BeaconConfig().BellatrixForkEpoch)
capellaDigest := params.ForkDigest(params.BeaconConfig().CapellaForkEpoch)
denebDigest := params.ForkDigest(params.BeaconConfig().DenebForkEpoch)
electraDigest := params.ForkDigest(params.BeaconConfig().ElectraForkEpoch)
for i := 1; i <= 5; i++ {
t.Run(version.String(i), func(t *testing.T) {
@@ -425,16 +408,11 @@ func TestRPC_LightClientUpdatesByRange(t *testing.T) {
topic := string(pcl)
r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(10000, 10000, time.Second, false)
altairDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().AltairForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
bellatrixDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().BellatrixForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
capellaDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().CapellaForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
denebDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().DenebForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
electraDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().ElectraForkEpoch, chainService.ValidatorsRoot[:])
require.NoError(t, err)
altairDigest := params.ForkDigest(params.BeaconConfig().AltairForkEpoch)
bellatrixDigest := params.ForkDigest(params.BeaconConfig().BellatrixForkEpoch)
capellaDigest := params.ForkDigest(params.BeaconConfig().CapellaForkEpoch)
denebDigest := params.ForkDigest(params.BeaconConfig().DenebForkEpoch)
electraDigest := params.ForkDigest(params.BeaconConfig().ElectraForkEpoch)
for i := 1; i <= 5; i++ {
t.Run(version.String(i), func(t *testing.T) {

View File

@@ -5,8 +5,8 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/types"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/wrapper"
"github.com/OffchainLabs/prysm/v6/network/forks"
pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1/metadata"
"github.com/OffchainLabs/prysm/v6/runtime/version"
@@ -148,17 +148,9 @@ func (s *Service) sendMetaDataRequest(ctx context.Context, peerID peer.ID) (meta
return nil, errors.New(errMsg)
}
// Get the genesis validators root.
valRoot := s.cfg.clock.GenesisValidatorsRoot()
// Get the fork digest from the current epoch and the genesis validators root.
rpcCtx, err := forks.ForkDigestFromEpoch(currentEpoch, valRoot[:])
if err != nil {
return nil, errors.Wrap(err, "fork digest from epoch")
}
digest := params.ForkDigestFromEpoch(currentEpoch)
// Instantiate zero value of the metadata.
msg, err := extractDataTypeFromTypeMap(types.MetaDataMap, rpcCtx[:], s.cfg.clock)
msg, err := extractDataTypeFromTypeMap(types.MetaDataMap, digest[:], s.cfg.clock)
if err != nil {
return nil, errors.Wrap(err, "extract data type from type map")
}

View File

@@ -14,15 +14,14 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/helpers"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/peers"
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/cmd/beacon-chain/flags"
"github.com/OffchainLabs/prysm/v6/config/features"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/container/slice"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing/trace"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/runtime/messagehandler"
"github.com/OffchainLabs/prysm/v6/time/slots"
@@ -204,8 +203,7 @@ func (s *Service) registerSubscribers(epoch primitives.Epoch, digest [4]byte) {
// subscribe to a given topic with a given validator and subscription handler.
// The base protobuf message is used to initialize new messages for decoding.
func (s *Service) subscribe(topic string, validator wrappedVal, handle subHandler, digest [4]byte) *pubsub.Subscription {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
_, e, err := forks.RetrieveForkDataFromDigest(digest, genRoot[:])
_, e, err := params.ForkDataFromDigest(digest)
if err != nil {
// Impossible condition as it would mean digest does not exist.
panic(err) // lint:nopanic -- Impossible condition.
@@ -443,10 +441,8 @@ func (s *Service) searchForPeers(
func (s *Service) subscribeToSubnets(
topicFormat string,
digest [4]byte,
genesisValidatorsRoot [fieldparams.RootLength]byte,
genesisTime time.Time,
clock *startup.Clock,
subscriptions map[uint64]*pubsub.Subscription,
currentSlot primitives.Slot,
validate wrappedVal,
handle subHandler,
getSubnetsToSubscribe func(currentSlot primitives.Slot) []uint64,
@@ -457,7 +453,7 @@ func (s *Service) subscribeToSubnets(
}
// Check the validity of the digest.
valid, err := isDigestValid(digest, genesisTime, genesisValidatorsRoot)
valid, err := isDigestValid(digest, clock)
if err != nil {
log.Error(err)
return true
@@ -483,7 +479,7 @@ func (s *Service) subscribeToSubnets(
}
// Retrieve the subnets we want to subscribe to.
subnetsToSubscribeIndex := getSubnetsToSubscribe(currentSlot)
subnetsToSubscribeIndex := getSubnetsToSubscribe(clock.CurrentSlot())
// Remove subscriptions that are no longer wanted.
s.pruneSubscriptions(subscriptions, subnetsToSubscribeIndex, topicFormat, digest)
@@ -516,11 +512,8 @@ func (s *Service) subscribeWithParameters(
// Initialize the subscriptions map.
subscriptions := make(map[uint64]*pubsub.Subscription)
// Retrieve the genesis validators root.
genesisValidatorsRoot := s.cfg.clock.GenesisValidatorsRoot()
// Retrieve the epoch of the fork corresponding to the digest.
_, epoch, err := forks.RetrieveForkDataFromDigest(digest, genesisValidatorsRoot[:])
_, epoch, err := params.ForkDataFromDigest(digest)
if err != nil {
panic(err) // lint:nopanic -- Impossible condition.
}
@@ -542,7 +535,7 @@ func (s *Service) subscribeWithParameters(
currentSlot := s.cfg.clock.CurrentSlot()
// Subscribe to subnets.
s.subscribeToSubnets(topicFormat, digest, genesisValidatorsRoot, genesisTime, subscriptions, currentSlot, validate, handle, getSubnetsToSubscribe)
s.subscribeToSubnets(topicFormat, digest, s.cfg.clock, subscriptions, validate, handle, getSubnetsToSubscribe)
// Derive a new context and cancel function.
ctx, cancel := context.WithCancel(s.ctx)
@@ -554,7 +547,7 @@ func (s *Service) subscribeWithParameters(
for {
select {
case currentSlot := <-ticker.C():
isDigestValid := s.subscribeToSubnets(topicFormat, digest, genesisValidatorsRoot, genesisTime, subscriptions, currentSlot, validate, handle, getSubnetsToSubscribe)
isDigestValid := s.subscribeToSubnets(topicFormat, digest, s.cfg.clock, subscriptions, validate, handle, getSubnetsToSubscribe)
// Stop the ticker if the digest is not valid. Likely to happen after a hard fork.
if !isDigestValid {
@@ -678,27 +671,19 @@ func (*Service) addDigestAndIndexToTopic(topic string, digest [4]byte, idx uint6
}
func (s *Service) currentForkDigest() ([4]byte, error) {
genRoot := s.cfg.clock.GenesisValidatorsRoot()
return forks.CreateForkDigest(s.cfg.clock.GenesisTime(), genRoot[:])
return params.ForkDigest(s.cfg.clock.CurrentEpoch()), nil
}
// Checks if the provided digest matches up with the current supposed digest.
func isDigestValid(digest [4]byte, genesis time.Time, genValRoot [32]byte) (bool, error) {
retDigest, err := forks.CreateForkDigest(genesis, genValRoot[:])
if err != nil {
return false, err
}
isNextEpoch, err := forks.IsForkNextEpoch(genesis, genValRoot[:])
if err != nil {
return false, err
}
func isDigestValid(digest [4]byte, clock *startup.Clock) (bool, error) {
currentEpoch := clock.CurrentEpoch()
// In the event there is a fork the next epoch,
// we skip the check, as we subscribe subnets an
// epoch in advance.
if isNextEpoch {
if params.IsForkNextEpoch(currentEpoch) {
return true, nil
}
return retDigest == digest, nil
return params.ForkDigest(currentEpoch) == digest, nil
}
func agentString(pid peer.ID, hst host.Host) string {

View File

@@ -26,7 +26,6 @@ import (
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/testing/assert"
@@ -319,8 +318,8 @@ func Test_wrapAndReportValidation(t *testing.T) {
Genesis: time.Now(),
ValidatorsRoot: [32]byte{0x01},
}
fd, err := forks.CreateForkDigest(mChain.GenesisTime(), mChain.ValidatorsRoot[:])
assert.NoError(t, err)
clock := startup.NewClock(mChain.Genesis, mChain.ValidatorsRoot)
fd := params.ForkDigest(clock.CurrentEpoch())
mockTopic := fmt.Sprintf(p2p.BlockSubnetTopicFormat, fd) + encoder.SszNetworkEncoder{}.ProtocolSuffix()
type args struct {
topic string
@@ -610,17 +609,18 @@ func TestSubscribeWithSyncSubnets_DynamicSwitchFork(t *testing.T) {
}
func TestIsDigestValid(t *testing.T) {
clock := startup.NewClock(time.Now().Add(-100*time.Second), [32]byte{'A'})
genRoot := [32]byte{'A'}
digest, err := signing.ComputeForkDigest(params.BeaconConfig().GenesisForkVersion, genRoot[:])
assert.NoError(t, err)
valid, err := isDigestValid(digest, time.Now().Add(-100*time.Second), genRoot)
valid, err := isDigestValid(digest, clock)
assert.NoError(t, err)
assert.Equal(t, true, valid)
// Compute future fork digest that will be invalid currently.
digest, err = signing.ComputeForkDigest(params.BeaconConfig().AltairForkVersion, genRoot[:])
assert.NoError(t, err)
valid, err = isDigestValid(digest, time.Now().Add(-100*time.Second), genRoot)
valid, err = isDigestValid(digest, clock)
assert.NoError(t, err)
assert.Equal(t, false, valid)
}

View File

@@ -7,7 +7,8 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/encoder"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/testing/assert"
pubsub "github.com/libp2p/go-libp2p-pubsub"
)
@@ -18,8 +19,8 @@ func TestSubTopicHandler_CRUD(t *testing.T) {
assert.Equal(t, false, h.topicExists("junk"))
assert.Equal(t, false, h.digestExists([4]byte{}))
digest, err := forks.CreateForkDigest(time.Now(), make([]byte, 32))
assert.NoError(t, err)
clock := startup.NewClock(time.Now(), [32]byte{})
digest := params.ForkDigest(clock.CurrentEpoch())
enc := encoder.SszNetworkEncoder{}
// Valid topic added in.

View File

@@ -22,7 +22,6 @@ import (
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -224,8 +223,7 @@ func TestService_ValidateSyncCommitteeMessage(t *testing.T) {
gt := time.Now().Add(-time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Duration(slots.PrevSlot(hState.Slot())))
vr := [32]byte{'A'}
clock := startup.NewClock(gt, vr)
digest, err := forks.CreateForkDigest(gt, vr[:])
assert.NoError(t, err)
digest := params.ForkDigest(slots.ToEpoch(clock.CurrentSlot()))
actualTopic := fmt.Sprintf(defaultTopic, digest, 5)
return s, actualTopic, clock
@@ -270,8 +268,8 @@ func TestService_ValidateSyncCommitteeMessage(t *testing.T) {
gt := time.Now().Add(-time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Duration(slots.PrevSlot(hState.Slot())))
vr := [32]byte{'A'}
digest, err := forks.CreateForkDigest(gt, vr[:])
assert.NoError(t, err)
clock := startup.NewClock(gt, vr)
digest := params.ForkDigest(clock.CurrentEpoch())
actualTopic := fmt.Sprintf(defaultTopic, digest, 5)
return s, actualTopic, startup.NewClock(gt, vr)
@@ -324,8 +322,8 @@ func TestService_ValidateSyncCommitteeMessage(t *testing.T) {
// Set Topic and Subnet
gt := time.Now().Add(-time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Duration(slots.PrevSlot(hState.Slot())))
vr := [32]byte{'A'}
digest, err := forks.CreateForkDigest(gt, vr[:])
assert.NoError(t, err)
clock := startup.NewClock(gt, vr)
digest := params.ForkDigest(slots.ToEpoch(clock.CurrentSlot()))
actualTopic := fmt.Sprintf(defaultTopic, digest, 5)
return s, actualTopic, startup.NewClock(gt, vr)
@@ -382,8 +380,8 @@ func TestService_ValidateSyncCommitteeMessage(t *testing.T) {
// Set Topic and Subnet
gt := time.Now().Add(-time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Duration(slots.PrevSlot(hState.Slot())))
vr := [32]byte{'A'}
digest, err := forks.CreateForkDigest(gt, vr[:])
assert.NoError(t, err)
clock := startup.NewClock(gt, vr)
digest := params.ForkDigest(slots.ToEpoch(clock.CurrentSlot()))
actualTopic := fmt.Sprintf(defaultTopic, digest, 1)
return s, actualTopic, startup.NewClock(gt, vr)

View File

@@ -35,7 +35,6 @@ go_library(
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/logging:go_default_library",
"//time/slots:go_default_library",

View File

@@ -13,7 +13,6 @@ import (
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/crypto/bls"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/time/slots"
lru "github.com/hashicorp/golang-lru"
@@ -63,7 +62,7 @@ func (d signatureData) logFields() logrus.Fields {
func newSigCache(vr []byte, size int, gf forkLookup) *sigCache {
if gf == nil {
gf = forks.Fork
gf = params.Fork
}
return &sigCache{Cache: lruwrpr.New(size), valRoot: vr, getFork: gf}
}

View File

@@ -10,9 +10,9 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/beacon-chain/state"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
)
@@ -108,7 +108,7 @@ func NewInitializerWaiter(cw startup.ClockWaiter, fc Forkchoicer, sr StateByRoot
o(iw)
}
if iw.getFork == nil {
iw.getFork = forks.Fork
iw.getFork = params.Fork
}
return iw
}

View File

@@ -20,6 +20,7 @@ go_library(
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/p2p/encoder:go_default_library",
"//beacon-chain/p2p/types:go_default_library",
"//beacon-chain/startup:go_default_library",
"//beacon-chain/sync:go_default_library",
"//cmd:go_default_library",
"//config/params:go_default_library",
@@ -31,7 +32,6 @@ go_library(
"//monitoring/tracing:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//network:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/metadata:go_default_library",
"//runtime/version:go_default_library",

View File

@@ -9,13 +9,13 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/encoder"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/wrapper"
ecdsaprysm "github.com/OffchainLabs/prysm/v6/crypto/ecdsa"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing"
"github.com/OffchainLabs/prysm/v6/monitoring/tracing/trace"
"github.com/OffchainLabs/prysm/v6/network"
"github.com/OffchainLabs/prysm/v6/network/forks"
pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1/metadata"
"github.com/OffchainLabs/prysm/v6/runtime/version"
@@ -178,7 +178,7 @@ func (c *client) initializeMockChainService(ctx context.Context) (*mockChain, er
return nil, err
}
currEpoch := slots.ToEpoch(slots.SinceGenesis(genesisResp.GenesisTime.AsTime()))
currFork, err := forks.Fork(currEpoch)
currFork, err := params.Fork(currEpoch)
if err != nil {
return nil, err
}

View File

@@ -4,8 +4,10 @@ import (
"context"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/time/slots"
libp2pcore "github.com/libp2p/go-libp2p/core"
@@ -50,11 +52,9 @@ func (c *client) statusRPCHandler(ctx context.Context, _ interface{}, stream lib
if err != nil {
return err
}
digest, err := forks.CreateForkDigest(resp.GenesisTime.AsTime(), resp.GenesisValidatorsRoot)
if err != nil {
return err
}
kindOfFork, err := forks.Fork(slots.ToEpoch(chainHead.HeadSlot))
clock := startup.NewClock(resp.GenesisTime.AsTime(), bytesutil.ToBytes32(resp.GenesisValidatorsRoot))
digest := params.ForkDigest(slots.ToEpoch(clock.CurrentSlot()))
kindOfFork, err := params.Fork(slots.ToEpoch(chainHead.HeadSlot))
if err != nil {
return err
}

View File

@@ -7,6 +7,8 @@ go_library(
"config_utils_develop.go", # keep
"config_utils_prod.go",
"configset.go",
"errors.go",
"fork.go",
"init.go",
"interop.go",
"io_config.go",
@@ -27,9 +29,11 @@ go_library(
deps = [
"//config/fieldparams:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",
"//math:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//params:go_default_library",
@@ -47,6 +51,8 @@ go_test(
"checktags_test.go",
"config_test.go",
"configset_test.go",
"export_test.go",
"fork_test.go",
"loader_test.go",
"mainnet_config_export_test.go",
"mainnet_config_test.go",
@@ -73,6 +79,7 @@ go_test(
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//io/file:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",

View File

@@ -2,16 +2,23 @@
package params
import (
"encoding/binary"
"fmt"
"math"
"slices"
"sort"
"time"
log "github.com/sirupsen/logrus"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/crypto/hash"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
)
// BeaconChainConfig contains constant configs for node to participate in beacon chain.
@@ -314,6 +321,9 @@ type BeaconChainConfig struct {
// DeprecatedMaxBlobsPerBlockFulu defines the max blobs that could exist in a block post Fulu hard fork.
// Deprecated: This field is no longer supported. Avoid using it.
DeprecatedMaxBlobsPerBlockFulu int `yaml:"MAX_BLOBS_PER_BLOCK_FULU" spec:"true"`
forkSchedule *NetworkSchedule
bpoSchedule *NetworkSchedule
networkSchedule *NetworkSchedule
}
func (b *BeaconChainConfig) ExecutionRequestLimits() enginev1.ExecutionRequestLimits {
@@ -324,16 +334,209 @@ func (b *BeaconChainConfig) ExecutionRequestLimits() enginev1.ExecutionRequestLi
}
}
type BlobScheduleEntry struct {
Epoch primitives.Epoch `yaml:"EPOCH"`
type NetworkScheduleEntry struct {
ForkVersion [fieldparams.VersionLength]byte
ForkDigest [4]byte
MaxBlobsPerBlock uint64 `yaml:"MAX_BLOBS_PER_BLOCK"`
Epoch primitives.Epoch `yaml:"EPOCH"`
isFork bool
}
func (ns NetworkScheduleEntry) Copy() NetworkScheduleEntry {
return NetworkScheduleEntry{
ForkVersion: ns.ForkVersion,
ForkDigest: ns.ForkDigest,
MaxBlobsPerBlock: ns.MaxBlobsPerBlock,
Epoch: ns.Epoch,
isFork: ns.isFork,
}
}
type BlobScheduleEntry NetworkScheduleEntry
// TODO: this needs to be able to return an error
// InitializeForkSchedule initializes the schedules forks baked into the config.
func (b *BeaconChainConfig) InitializeForkSchedule() {
// Reset Fork Version Schedule.
b.ForkVersionSchedule = configForkSchedule(b)
b.ForkVersionNames = configForkNames(b)
b.forkSchedule = initForkSchedule(b)
b.bpoSchedule = initBPOSchedule(b)
combined := b.forkSchedule.merge(b.bpoSchedule)
if err := combined.prepare(b); err != nil {
log.WithError(err).Error("failed to prepare network schedule", "error", err)
}
b.networkSchedule = combined
}
type NetworkSchedule struct {
entries []NetworkScheduleEntry
byEpoch map[primitives.Epoch]*NetworkScheduleEntry
byVersion map[[4]byte]*NetworkScheduleEntry
byDigest map[[4]byte]*NetworkScheduleEntry
}
func newNetworkSchedule(entries []NetworkScheduleEntry) *NetworkSchedule {
return &NetworkSchedule{
entries: entries,
byEpoch: make(map[primitives.Epoch]*NetworkScheduleEntry),
byVersion: make(map[[4]byte]*NetworkScheduleEntry),
byDigest: make(map[[4]byte]*NetworkScheduleEntry),
}
}
func (ns *NetworkSchedule) nextEpochIdx(epoch primitives.Epoch) int {
return sort.Search(len(ns.entries), func(i int) bool {
return ns.entries[i].Epoch > epoch
})
}
func (ns *NetworkSchedule) Next(epoch primitives.Epoch) NetworkScheduleEntry {
nextIdx := ns.nextEpochIdx(epoch)
if nextIdx < len(ns.entries) && ns.entries[nextIdx].Epoch != BeaconConfig().FarFutureEpoch {
return ns.entries[nextIdx]
}
return ns.LastEntry()
}
func (ns *NetworkSchedule) LastEntry() NetworkScheduleEntry {
for i := len(ns.entries) - 1; i >= 0; i-- {
if ns.entries[i].Epoch != BeaconConfig().FarFutureEpoch {
return ns.entries[i]
}
}
return ns.entries[0]
}
// LastFork is the last full fork (this is used by e2e testing)
func (ns *NetworkSchedule) LastFork() NetworkScheduleEntry {
for i := len(ns.entries) - 1; i >= 0; i-- {
if ns.entries[i].isFork && ns.entries[i].Epoch != BeaconConfig().FarFutureEpoch {
return ns.entries[i]
}
}
return ns.entries[0]
}
func (ns *NetworkSchedule) ForEpoch(epoch primitives.Epoch) NetworkScheduleEntry {
nextIdx := ns.nextEpochIdx(epoch)
if nextIdx > 0 {
return ns.entries[nextIdx-1]
}
return ns.entries[0]
}
func (ns *NetworkSchedule) activatedAt(epoch primitives.Epoch) (*NetworkScheduleEntry, bool) {
entry, ok := ns.byEpoch[epoch]
return entry, ok
}
func (ns *NetworkSchedule) merge(other *NetworkSchedule) *NetworkSchedule {
merged := make([]NetworkScheduleEntry, 0, len(ns.entries)+len(other.entries))
merged = append(merged, ns.entries...)
merged = append(merged, other.entries...)
sort.Slice(merged, func(i, j int) bool {
if merged[i].Epoch == merged[j].Epoch {
return merged[i].isFork
}
return merged[i].Epoch < merged[j].Epoch
})
return newNetworkSchedule(merged)
}
func (ns *NetworkSchedule) index(e NetworkScheduleEntry) {
if _, ok := ns.byEpoch[e.Epoch]; !ok {
ns.byDigest[e.ForkDigest] = &e
}
if _, ok := ns.byVersion[e.ForkVersion]; !ok {
ns.byVersion[e.ForkVersion] = &e
}
if _, ok := ns.byEpoch[e.Epoch]; !ok {
ns.byEpoch[e.Epoch] = &e
}
}
func (ns *NetworkSchedule) prepare(b *BeaconChainConfig) error {
if len(ns.entries) == 0 {
return errors.New("cannot compute digests for an empty network schedule")
}
if !ns.entries[0].isFork {
return errors.New("cannot compute digests for a network schedule without a fork entry")
}
lastFork, err := entryWithForkDigest(ns.entries[0], b)
if err != nil {
return err
}
// TODO: I don't think I need this copy thing but I'm paranoid and tired, remove it later
ns.entries[0] = lastFork.Copy()
ns.index(ns.entries[0])
lastBlobs := lastFork.MaxBlobsPerBlock
for i := 1; i < len(ns.entries); i++ {
entry := ns.entries[i]
if entry.isFork {
lastFork = entry
} else {
entry.ForkVersion = lastFork.ForkVersion
}
if entry.MaxBlobsPerBlock > 0 {
lastBlobs = entry.MaxBlobsPerBlock
} else {
entry.MaxBlobsPerBlock = lastBlobs
}
entry, err = entryWithForkDigest(entry, b)
if err != nil {
return err
}
ns.entries[i] = entry
ns.index(entry)
}
return nil
}
func entryWithForkDigest(entry NetworkScheduleEntry, b *BeaconChainConfig) (NetworkScheduleEntry, error) {
root, err := computeForkDataRoot(entry.ForkVersion, b.GenesisValidatorsRoot)
if err != nil {
return entry, err
}
entry.ForkDigest = bytesutil.ToBytes4(root[:])
if entry.Epoch < b.FuluForkEpoch {
return entry, nil
}
if entry.MaxBlobsPerBlock > math.MaxUint32 {
return entry, fmt.Errorf("max blobs per block exceeds maximum uint32 value")
}
hb := make([]byte, 16)
binary.LittleEndian.PutUint64(hb[0:8], uint64(entry.Epoch))
binary.LittleEndian.PutUint64(hb[8:], uint64(entry.MaxBlobsPerBlock))
bpoHash := hash.Hash(hb)
entry.ForkDigest[0] = entry.ForkDigest[0] ^ bpoHash[0]
entry.ForkDigest[1] = entry.ForkDigest[1] ^ bpoHash[1]
entry.ForkDigest[2] = entry.ForkDigest[2] ^ bpoHash[2]
entry.ForkDigest[3] = entry.ForkDigest[3] ^ bpoHash[3]
return entry, nil
}
func initForkSchedule(b *BeaconChainConfig) *NetworkSchedule {
return newNetworkSchedule([]NetworkScheduleEntry{
{Epoch: b.GenesisEpoch, isFork: true, ForkVersion: [4]byte(b.GenesisForkVersion)},
{Epoch: b.AltairForkEpoch, isFork: true, ForkVersion: [4]byte(b.AltairForkVersion)},
{Epoch: b.BellatrixForkEpoch, isFork: true, ForkVersion: [4]byte(b.BellatrixForkVersion)},
{Epoch: b.CapellaForkEpoch, isFork: true, ForkVersion: [4]byte(b.CapellaForkVersion)},
{Epoch: b.DenebForkEpoch, isFork: true, ForkVersion: [4]byte(b.DenebForkVersion), MaxBlobsPerBlock: uint64(b.DeprecatedMaxBlobsPerBlock)},
{Epoch: b.ElectraForkEpoch, isFork: true, ForkVersion: [4]byte(b.ElectraForkVersion), MaxBlobsPerBlock: uint64(b.DeprecatedMaxBlobsPerBlockElectra)},
{Epoch: b.FuluForkEpoch, isFork: true, ForkVersion: [4]byte(b.FuluForkVersion)},
})
}
func initBPOSchedule(b *BeaconChainConfig) *NetworkSchedule {
sort.Slice(b.BlobSchedule, func(i, j int) bool {
return b.BlobSchedule[i].Epoch < b.BlobSchedule[j].Epoch
})
entries := make([]NetworkScheduleEntry, len(b.BlobSchedule))
for i := range b.BlobSchedule {
entries[i] = NetworkScheduleEntry(b.BlobSchedule[i])
}
return newNetworkSchedule(entries)
}
func configForkSchedule(b *BeaconChainConfig) map[[fieldparams.VersionLength]byte]primitives.Epoch {

View File

@@ -22,6 +22,7 @@ func BeaconConfig() *BeaconChainConfig {
// OverrideBeaconConfig(c). Any subsequent calls to params.BeaconConfig() will
// return this new configuration.
func OverrideBeaconConfig(c *BeaconChainConfig) {
c.InitializeForkSchedule()
cfgrw.Lock()
defer cfgrw.Unlock()
configs.active = c

View File

@@ -16,6 +16,7 @@ func BeaconConfig() *BeaconChainConfig {
// OverrideBeaconConfig(c). Any subsequent calls to params.BeaconConfig() will
// return this new configuration.
func OverrideBeaconConfig(c *BeaconChainConfig) {
c.InitializeForkSchedule()
configs.active = c
}

View File

@@ -1,4 +1,4 @@
package forks
package params
import "github.com/pkg/errors"

View File

@@ -0,0 +1,3 @@
package params
var ComputeForkDataRoot = computeForkDataRoot

122
config/params/fork.go Normal file
View File

@@ -0,0 +1,122 @@
package params
import (
"bytes"
"sort"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/pkg/errors"
)
// IsForkNextEpoch checks if an allotted fork is in the following epoch.
func IsForkNextEpoch(currentEpoch primitives.Epoch) bool {
entry, ok := BeaconConfig().networkSchedule.activatedAt(currentEpoch + 1)
return ok && entry.isFork
}
// ForkDigestFromEpoch retrieves the fork digest from the current schedule determined
// by the provided epoch.
func ForkDigestFromEpoch(epoch primitives.Epoch) [4]byte {
return BeaconConfig().networkSchedule.ForEpoch(epoch).ForkDigest
}
// CreateForkDigest creates a fork digest from a genesis time and genesis
// validators root, utilizing the current slot to determine
// the active fork version in the node.
func ForkDigest(epoch primitives.Epoch) [4]byte {
return BeaconConfig().networkSchedule.ForEpoch(epoch).ForkDigest
}
func computeForkDataRoot(version [4]byte, root [32]byte) ([32]byte, error) {
r, err := (&ethpb.ForkData{
CurrentVersion: version[:],
GenesisValidatorsRoot: root[:],
}).HashTreeRoot()
if err != nil {
return [32]byte{}, nil
}
return r, nil
}
// Fork returns the fork version for the given epoch.
func Fork(epoch primitives.Epoch) (*ethpb.Fork, error) {
cfg := BeaconConfig()
return ForkFromConfig(cfg, epoch), nil
}
func ForkFromConfig(cfg *BeaconChainConfig, epoch primitives.Epoch) *ethpb.Fork {
current := cfg.networkSchedule.ForEpoch(epoch)
previous := current
if current.Epoch > 0 {
previous = BeaconConfig().networkSchedule.ForEpoch(current.Epoch - 1)
}
return &ethpb.Fork{
PreviousVersion: previous.ForkVersion[:],
CurrentVersion: current.ForkVersion[:],
Epoch: current.Epoch,
}
}
// RetrieveForkDataFromDigest performs the inverse, where it tries to determine the fork version
// and epoch from a provided digest by looping through our current fork schedule.
func ForkDataFromDigest(digest [4]byte) ([4]byte, primitives.Epoch, error) {
cfg := BeaconConfig()
entry, ok := cfg.networkSchedule.byDigest[digest]
if !ok {
return [4]byte{}, 0, errors.Errorf("no fork exists for a digest of %#x", digest)
}
return entry.ForkVersion, entry.Epoch, nil
}
// NextForkData retrieves the next fork data according to the
// provided current epoch.
func NextForkData(epoch primitives.Epoch) ([4]byte, primitives.Epoch) {
entry := BeaconConfig().networkSchedule.Next(epoch)
return entry.ForkVersion, entry.Epoch
}
// SortedForkVersions sorts the provided fork schedule in ascending order
// by epoch.
func SortedForkVersions() [][4]byte {
forkSchedule := BeaconConfig().ForkVersionSchedule
sortedVersions := make([][4]byte, len(forkSchedule))
i := 0
for k := range forkSchedule {
sortedVersions[i] = k
i++
}
sort.Slice(sortedVersions, func(a, b int) bool {
// va == "version" a, ie the [4]byte version id
va, vb := sortedVersions[a], sortedVersions[b]
// ea == "epoch" a, ie the types.Epoch corresponding to va
ea, eb := forkSchedule[va], forkSchedule[vb]
// Try to sort by epochs first, which works fine when epochs are all distinct.
// in the case of testnets starting from a given fork, all epochs leading to the fork will be zero.
if ea != eb {
return ea < eb
}
// If the epochs are equal, break the tie with a lexicographic comparison of the fork version bytes.
// eg 2 versions both with a fork epoch of 0, 0x00000000 would come before 0x01000000.
// sort.Slice takes a 'less' func, ie `return a < b`, and when va < vb, bytes.Compare will return -1
return bytes.Compare(va[:], vb[:]) < 0
})
return sortedVersions
}
func SortedForkSchedule() []NetworkScheduleEntry {
entries := BeaconConfig().networkSchedule.entries
schedule := make([]NetworkScheduleEntry, 0, len(entries))
for _, entry := range entries {
if entry.isFork {
schedule = append(schedule, entry)
}
}
return schedule
}
// LastForkEpoch returns the last valid fork epoch that exists in our
// fork schedule.
func LastForkEpoch() primitives.Epoch {
return BeaconConfig().networkSchedule.LastFork().Epoch
}

165
config/params/fork_test.go Normal file
View File

@@ -0,0 +1,165 @@
package params_test
import (
"reflect"
"testing"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/require"
)
func TestFork(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
tests := []struct {
name string
targetEpoch primitives.Epoch
want *ethpb.Fork
wantErr bool
setConfg func()
}{
{
name: "genesis fork",
targetEpoch: 0,
want: &ethpb.Fork{
Epoch: cfg.GenesisEpoch,
CurrentVersion: cfg.GenesisForkVersion,
PreviousVersion: cfg.GenesisForkVersion,
},
},
{
name: "altair on fork",
targetEpoch: cfg.AltairForkEpoch,
want: &ethpb.Fork{
Epoch: cfg.AltairForkEpoch,
CurrentVersion: cfg.AltairForkVersion,
PreviousVersion: cfg.GenesisForkVersion,
},
},
{
name: "altair post fork",
targetEpoch: cfg.CapellaForkEpoch + 1,
want: &ethpb.Fork{
Epoch: cfg.CapellaForkEpoch,
CurrentVersion: cfg.CapellaForkVersion,
PreviousVersion: cfg.BellatrixForkVersion,
},
},
{
name: "3 forks, pre-fork",
targetEpoch: cfg.ElectraForkEpoch - 1,
want: &ethpb.Fork{
Epoch: cfg.DenebForkEpoch,
CurrentVersion: cfg.DenebForkVersion,
PreviousVersion: cfg.CapellaForkVersion,
},
},
{
name: "3 forks, on fork",
targetEpoch: cfg.ElectraForkEpoch,
want: &ethpb.Fork{
Epoch: cfg.ElectraForkEpoch,
CurrentVersion: cfg.ElectraForkVersion,
PreviousVersion: cfg.DenebForkVersion,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
copied := cfg.Copy()
params.OverrideBeaconConfig(copied)
got, err := params.Fork(tt.targetEpoch)
if (err != nil) != tt.wantErr {
t.Errorf("Fork() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Fork() got = %v, want %v", got, tt.want)
}
})
}
}
func TestRetrieveForkDataFromDigest(t *testing.T) {
params.SetupTestConfigCleanup(t)
digest := params.ForkDigest(params.BeaconConfig().AltairForkEpoch)
version, epoch, err := params.ForkDataFromDigest(digest)
require.NoError(t, err)
require.Equal(t, [4]byte(params.BeaconConfig().AltairForkVersion), version)
require.Equal(t, params.BeaconConfig().AltairForkEpoch, epoch)
}
func TestIsForkNextEpoch(t *testing.T) {
// at
assert.Equal(t, false, params.IsForkNextEpoch(params.BeaconConfig().ElectraForkEpoch))
// just before
assert.Equal(t, true, params.IsForkNextEpoch(params.BeaconConfig().ElectraForkEpoch-1))
// just after
assert.Equal(t, false, params.IsForkNextEpoch(params.BeaconConfig().ElectraForkEpoch+1))
}
func TestNextForkData(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
tests := []struct {
name string
setConfg func()
currEpoch primitives.Epoch
wantedForkVersion [4]byte
wantedEpoch primitives.Epoch
}{
{
name: "genesis",
currEpoch: 0,
wantedForkVersion: [4]byte(cfg.AltairForkVersion),
wantedEpoch: cfg.AltairForkEpoch,
},
{
name: "altair pre-fork",
currEpoch: cfg.AltairForkEpoch - 1,
wantedForkVersion: [4]byte(cfg.AltairForkVersion),
wantedEpoch: cfg.AltairForkEpoch,
},
{
name: "altair on fork",
currEpoch: cfg.AltairForkEpoch,
wantedForkVersion: [4]byte(cfg.BellatrixForkVersion),
wantedEpoch: cfg.BellatrixForkEpoch,
},
{
name: "altair post fork",
currEpoch: cfg.AltairForkEpoch + 1,
wantedForkVersion: [4]byte(cfg.BellatrixForkVersion),
wantedEpoch: cfg.BellatrixForkEpoch,
},
{
name: "electra post fork",
currEpoch: cfg.ElectraForkEpoch + 1,
wantedForkVersion: [4]byte(cfg.ElectraForkVersion),
wantedEpoch: cfg.ElectraForkEpoch,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
params.OverrideBeaconConfig(cfg.Copy())
fVersion, fEpoch := params.NextForkData(tt.currEpoch)
if fVersion != tt.wantedForkVersion {
t.Errorf("NextForkData() fork version = %v, want %v", fVersion, tt.wantedForkVersion)
}
if fEpoch != tt.wantedEpoch {
t.Errorf("NextForkData() fork epoch = %v, want %v", fEpoch, tt.wantedEpoch)
}
})
}
}
func TestLastForkEpoch(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
require.Equal(t, cfg.ElectraForkEpoch, params.LastForkEpoch())
}

View File

@@ -17,7 +17,6 @@ go_library(
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//time/slots:go_default_library",

View File

@@ -11,7 +11,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/runtime/version"
"github.com/OffchainLabs/prysm/v6/time/slots"
@@ -55,14 +54,12 @@ func FromBlock(marshaled []byte) (*VersionedUnmarshaler, error) {
if err != nil {
return nil, err
}
copiedCfg := params.BeaconConfig().Copy()
epoch := slots.ToEpoch(slot)
fs := forks.NewOrderedSchedule(copiedCfg)
ver, err := fs.VersionForEpoch(epoch)
fs, err := params.Fork(epoch)
if err != nil {
return nil, err
}
return FromForkVersion(ver)
return FromForkVersion([4]byte(fs.CurrentVersion))
}
var ErrForkNotFound = errors.New("version found in fork schedule but can't be matched to a named fork")
@@ -282,13 +279,13 @@ func (cf *VersionedUnmarshaler) UnmarshalBlindedBeaconBlock(marshaled []byte) (i
// VersionedUnmarshaler.
func (cf *VersionedUnmarshaler) validateVersion(slot primitives.Slot) error {
epoch := slots.ToEpoch(slot)
fs := forks.NewOrderedSchedule(cf.Config)
ver, err := fs.VersionForEpoch(epoch)
fork, err := params.Fork(epoch)
if err != nil {
return err
}
ver := [4]byte(fork.CurrentVersion)
if ver != cf.Version {
return errors.Wrapf(errBlockForkMismatch, "slot=%d, epoch=%d, version=%#x", slot, epoch, ver)
return errors.Wrapf(errBlockForkMismatch, "slot=%d, epoch=%d, version=%#x", slot, epoch, fork.CurrentVersion)
}
return nil
}

View File

@@ -113,11 +113,9 @@ func TestByState(t *testing.T) {
for _, c := range cases {
st, err := stateForVersion(c.version)
require.NoError(t, err)
require.NoError(t, st.SetFork(&ethpb.Fork{
PreviousVersion: make([]byte, 4),
CurrentVersion: c.forkversion[:],
Epoch: 0,
}))
fork, err := params.Fork(slots.ToEpoch(c.slot))
require.NoError(t, err)
require.NoError(t, st.SetFork(fork))
require.NoError(t, st.SetSlot(c.slot))
m, err := st.MarshalSSZ()
require.NoError(t, err)

View File

@@ -1,39 +0,0 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"errors.go",
"fork.go",
"ordered.go",
],
importpath = "github.com/OffchainLabs/prysm/v6/network/forks",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/core/signing:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//time/slots:go_default_library",
"@com_github_pkg_errors//:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"fork_test.go",
"ordered_test.go",
],
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/signing:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
],
)

View File

@@ -1,202 +0,0 @@
// Package forks contains useful helpers for Ethereum consensus fork-related functionality.
package forks
import (
"bytes"
"math"
"sort"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/signing"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/time/slots"
"github.com/pkg/errors"
)
// IsForkNextEpoch checks if an allotted fork is in the following epoch.
func IsForkNextEpoch(genesisTime time.Time, genesisValidatorsRoot []byte) (bool, error) {
if genesisTime.IsZero() {
return false, errors.New("genesis time is not set")
}
if len(genesisValidatorsRoot) == 0 {
return false, errors.New("genesis validators root is not set")
}
currentSlot := slots.Since(genesisTime)
currentEpoch := slots.ToEpoch(currentSlot)
fSchedule := params.BeaconConfig().ForkVersionSchedule
scheduledForks := SortedForkVersions(fSchedule)
isForkEpoch := false
for _, forkVersion := range scheduledForks {
epoch := fSchedule[forkVersion]
if currentEpoch+1 == epoch {
isForkEpoch = true
break
}
}
return isForkEpoch, nil
}
// ForkDigestFromEpoch retrieves the fork digest from the current schedule determined
// by the provided epoch.
func ForkDigestFromEpoch(currentEpoch primitives.Epoch, genesisValidatorsRoot []byte) ([4]byte, error) {
if len(genesisValidatorsRoot) == 0 {
return [4]byte{}, errors.New("genesis validators root is not set")
}
forkData, err := Fork(currentEpoch)
if err != nil {
return [4]byte{}, err
}
return signing.ComputeForkDigest(forkData.CurrentVersion, genesisValidatorsRoot)
}
// CreateForkDigest creates a fork digest from a genesis time and genesis
// validators root, utilizing the current slot to determine
// the active fork version in the node.
func CreateForkDigest(
genesisTime time.Time,
genesisValidatorsRoot []byte,
) ([4]byte, error) {
if genesisTime.IsZero() {
return [4]byte{}, errors.New("genesis time is not set")
}
if len(genesisValidatorsRoot) == 0 {
return [4]byte{}, errors.New("genesis validators root is not set")
}
currentSlot := slots.Since(genesisTime)
currentEpoch := slots.ToEpoch(currentSlot)
forkData, err := Fork(currentEpoch)
if err != nil {
return [4]byte{}, err
}
digest, err := signing.ComputeForkDigest(forkData.CurrentVersion, genesisValidatorsRoot)
if err != nil {
return [4]byte{}, err
}
return digest, nil
}
// Fork given a target epoch,
// returns the active fork version during this epoch.
func Fork(
targetEpoch primitives.Epoch,
) (*ethpb.Fork, error) {
currentForkVersion := bytesutil.ToBytes4(params.BeaconConfig().GenesisForkVersion)
previousForkVersion := bytesutil.ToBytes4(params.BeaconConfig().GenesisForkVersion)
fSchedule := params.BeaconConfig().ForkVersionSchedule
sortedForkVersions := SortedForkVersions(fSchedule)
forkEpoch := primitives.Epoch(0)
for _, forkVersion := range sortedForkVersions {
epoch, ok := fSchedule[forkVersion]
if !ok {
return nil, errors.Errorf("fork version %x doesn't exist in schedule", forkVersion)
}
if targetEpoch >= epoch {
previousForkVersion = currentForkVersion
currentForkVersion = forkVersion
forkEpoch = epoch
}
}
return &ethpb.Fork{
PreviousVersion: previousForkVersion[:],
CurrentVersion: currentForkVersion[:],
Epoch: forkEpoch,
}, nil
}
// RetrieveForkDataFromDigest performs the inverse, where it tries to determine the fork version
// and epoch from a provided digest by looping through our current fork schedule.
func RetrieveForkDataFromDigest(digest [4]byte, genesisValidatorsRoot []byte) ([4]byte, primitives.Epoch, error) {
fSchedule := params.BeaconConfig().ForkVersionSchedule
for v, e := range fSchedule {
rDigest, err := signing.ComputeForkDigest(v[:], genesisValidatorsRoot)
if err != nil {
return [4]byte{}, 0, err
}
if rDigest == digest {
return v, e, nil
}
}
return [4]byte{}, 0, errors.Errorf("no fork exists for a digest of %#x", digest)
}
// NextForkData retrieves the next fork data according to the
// provided current epoch.
func NextForkData(currEpoch primitives.Epoch) ([4]byte, primitives.Epoch, error) {
fSchedule := params.BeaconConfig().ForkVersionSchedule
sortedForkVersions := SortedForkVersions(fSchedule)
nextForkEpoch := primitives.Epoch(math.MaxUint64)
var nextForkVersion [4]byte
for _, forkVersion := range sortedForkVersions {
epoch, ok := fSchedule[forkVersion]
if !ok {
return [4]byte{}, 0, errors.Errorf("fork version %x doesn't exist in schedule", forkVersion)
}
// If we get an epoch larger than out current epoch
// we set this as our next fork epoch and exit the
// loop.
if epoch > currEpoch {
nextForkEpoch = epoch
nextForkVersion = forkVersion
break
}
// In the event the retrieved epoch is less than
// our current epoch, we mark the previous
// fork's version as the next fork version.
if epoch <= currEpoch {
// The next fork version is updated to
// always include the most current fork version.
nextForkVersion = forkVersion
}
}
return nextForkVersion, nextForkEpoch, nil
}
// SortedForkVersions sorts the provided fork schedule in ascending order
// by epoch.
func SortedForkVersions(forkSchedule map[[4]byte]primitives.Epoch) [][4]byte {
sortedVersions := make([][4]byte, len(forkSchedule))
i := 0
for k := range forkSchedule {
sortedVersions[i] = k
i++
}
sort.Slice(sortedVersions, func(a, b int) bool {
// va == "version" a, ie the [4]byte version id
va, vb := sortedVersions[a], sortedVersions[b]
// ea == "epoch" a, ie the types.Epoch corresponding to va
ea, eb := forkSchedule[va], forkSchedule[vb]
// Try to sort by epochs first, which works fine when epochs are all distinct.
// in the case of testnets starting from a given fork, all epochs leading to the fork will be zero.
if ea != eb {
return ea < eb
}
// If the epochs are equal, break the tie with a lexicographic comparison of the fork version bytes.
// eg 2 versions both with a fork epoch of 0, 0x00000000 would come before 0x01000000.
// sort.Slice takes a 'less' func, ie `return a < b`, and when va < vb, bytes.Compare will return -1
return bytes.Compare(va[:], vb[:]) < 0
})
return sortedVersions
}
// LastForkEpoch returns the last valid fork epoch that exists in our
// fork schedule.
func LastForkEpoch() primitives.Epoch {
fSchedule := params.BeaconConfig().ForkVersionSchedule
sortedForkVersions := SortedForkVersions(fSchedule)
lastValidEpoch := primitives.Epoch(0)
numOfVersions := len(sortedForkVersions)
for i := numOfVersions - 1; i >= 0; i-- {
v := sortedForkVersions[i]
fEpoch := fSchedule[v]
if fEpoch != math.MaxUint64 {
lastValidEpoch = fEpoch
break
}
}
return lastValidEpoch
}

View File

@@ -1,485 +0,0 @@
package forks
import (
"math"
"reflect"
"testing"
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/signing"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/assert"
)
func TestFork(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
tests := []struct {
name string
targetEpoch primitives.Epoch
want *ethpb.Fork
wantErr bool
setConfg func()
}{
{
name: "no fork",
targetEpoch: 0,
want: &ethpb.Fork{
Epoch: 0,
CurrentVersion: []byte{'A', 'B', 'C', 'D'},
PreviousVersion: []byte{'A', 'B', 'C', 'D'},
},
wantErr: false,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "genesis fork",
targetEpoch: 0,
want: &ethpb.Fork{
Epoch: 0,
CurrentVersion: []byte{'A', 'B', 'C', 'D'},
PreviousVersion: []byte{'A', 'B', 'C', 'D'},
},
wantErr: false,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "altair pre-fork",
targetEpoch: 0,
want: &ethpb.Fork{
Epoch: 0,
CurrentVersion: []byte{'A', 'B', 'C', 'D'},
PreviousVersion: []byte{'A', 'B', 'C', 'D'},
},
wantErr: false,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.AltairForkVersion = []byte{'A', 'B', 'C', 'F'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "altair on fork",
targetEpoch: 10,
want: &ethpb.Fork{
Epoch: 10,
CurrentVersion: []byte{'A', 'B', 'C', 'F'},
PreviousVersion: []byte{'A', 'B', 'C', 'D'},
},
wantErr: false,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.AltairForkVersion = []byte{'A', 'B', 'C', 'F'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "altair post fork",
targetEpoch: 10,
want: &ethpb.Fork{
Epoch: 10,
CurrentVersion: []byte{'A', 'B', 'C', 'F'},
PreviousVersion: []byte{'A', 'B', 'C', 'D'},
},
wantErr: false,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.AltairForkVersion = []byte{'A', 'B', 'C', 'F'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "3 forks, pre-fork",
targetEpoch: 20,
want: &ethpb.Fork{
Epoch: 10,
CurrentVersion: []byte{'A', 'B', 'C', 'F'},
PreviousVersion: []byte{'A', 'B', 'C', 'D'},
},
wantErr: false,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
{'A', 'B', 'C', 'Z'}: 100,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "3 forks, on fork",
targetEpoch: 100,
want: &ethpb.Fork{
Epoch: 100,
CurrentVersion: []byte{'A', 'B', 'C', 'Z'},
PreviousVersion: []byte{'A', 'B', 'C', 'F'},
},
wantErr: false,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
{'A', 'B', 'C', 'Z'}: 100,
}
params.OverrideBeaconConfig(cfg)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.setConfg()
got, err := Fork(tt.targetEpoch)
if (err != nil) != tt.wantErr {
t.Errorf("Fork() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Fork() got = %v, want %v", got, tt.want)
}
})
}
}
func TestRetrieveForkDataFromDigest(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.GenesisEpoch = 0
cfg.AltairForkVersion = []byte{'A', 'B', 'C', 'F'}
cfg.AltairForkEpoch = 10
cfg.BellatrixForkVersion = []byte{'A', 'B', 'C', 'Z'}
cfg.BellatrixForkEpoch = 100
cfg.InitializeForkSchedule()
params.OverrideBeaconConfig(cfg)
genValRoot := [32]byte{'A', 'B', 'C', 'D'}
digest, err := signing.ComputeForkDigest([]byte{'A', 'B', 'C', 'F'}, genValRoot[:])
assert.NoError(t, err)
version, epoch, err := RetrieveForkDataFromDigest(digest, genValRoot[:])
assert.NoError(t, err)
assert.Equal(t, [4]byte{'A', 'B', 'C', 'F'}, version)
assert.Equal(t, epoch, primitives.Epoch(10))
digest, err = signing.ComputeForkDigest([]byte{'A', 'B', 'C', 'Z'}, genValRoot[:])
assert.NoError(t, err)
version, epoch, err = RetrieveForkDataFromDigest(digest, genValRoot[:])
assert.NoError(t, err)
assert.Equal(t, [4]byte{'A', 'B', 'C', 'Z'}, version)
assert.Equal(t, epoch, primitives.Epoch(100))
}
func TestIsForkNextEpoch(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
{'A', 'B', 'C', 'Z'}: 100,
}
params.OverrideBeaconConfig(cfg)
genTimeCreator := func(epoch primitives.Epoch) time.Time {
return time.Now().Add(-time.Duration(uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(epoch)*params.BeaconConfig().SecondsPerSlot) * time.Second)
}
// Is at Fork Epoch
genesisTime := genTimeCreator(10)
genRoot := [32]byte{'A'}
isFork, err := IsForkNextEpoch(genesisTime, genRoot[:])
assert.NoError(t, err)
assert.Equal(t, false, isFork)
// Is right before fork epoch
genesisTime = genTimeCreator(9)
isFork, err = IsForkNextEpoch(genesisTime, genRoot[:])
assert.NoError(t, err)
assert.Equal(t, true, isFork)
// Is at fork epoch
genesisTime = genTimeCreator(100)
isFork, err = IsForkNextEpoch(genesisTime, genRoot[:])
assert.NoError(t, err)
assert.Equal(t, false, isFork)
genesisTime = genTimeCreator(99)
// Is right before fork epoch.
isFork, err = IsForkNextEpoch(genesisTime, genRoot[:])
assert.NoError(t, err)
assert.Equal(t, true, isFork)
}
func TestNextForkData(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
tests := []struct {
name string
setConfg func()
currEpoch primitives.Epoch
wantedForkVersion [4]byte
wantedEpoch primitives.Epoch
}{
{
name: "genesis fork",
currEpoch: 0,
wantedForkVersion: [4]byte{'A', 'B', 'C', 'D'},
wantedEpoch: math.MaxUint64,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "altair pre-fork",
currEpoch: 5,
wantedForkVersion: [4]byte{'A', 'B', 'C', 'F'},
wantedEpoch: 10,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.AltairForkVersion = []byte{'A', 'B', 'C', 'F'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "altair on fork",
currEpoch: 10,
wantedForkVersion: [4]byte{'A', 'B', 'C', 'F'},
wantedEpoch: math.MaxUint64,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.AltairForkVersion = []byte{'A', 'B', 'C', 'F'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "altair post fork",
currEpoch: 20,
wantedForkVersion: [4]byte{'A', 'B', 'C', 'F'},
wantedEpoch: math.MaxUint64,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.AltairForkVersion = []byte{'A', 'B', 'C', 'F'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "3 forks, pre-fork, 1st fork",
currEpoch: 5,
wantedForkVersion: [4]byte{'A', 'B', 'C', 'F'},
wantedEpoch: 10,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
{'A', 'B', 'C', 'Z'}: 100,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "3 forks, pre-fork, 2nd fork",
currEpoch: 50,
wantedForkVersion: [4]byte{'A', 'B', 'C', 'Z'},
wantedEpoch: 100,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
{'A', 'B', 'C', 'Z'}: 100,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "3 forks, on fork",
currEpoch: 100,
wantedForkVersion: [4]byte{'A', 'B', 'C', 'Z'},
wantedEpoch: math.MaxUint64,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
{'A', 'B', 'C', 'Z'}: 100,
}
params.OverrideBeaconConfig(cfg)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.setConfg()
fVersion, fEpoch, err := NextForkData(tt.currEpoch)
assert.NoError(t, err)
if fVersion != tt.wantedForkVersion {
t.Errorf("NextForkData() fork version = %v, want %v", fVersion, tt.wantedForkVersion)
}
if fEpoch != tt.wantedEpoch {
t.Errorf("NextForkData() fork epoch = %v, want %v", fEpoch, tt.wantedEpoch)
}
})
}
}
func TestLastForkEpoch(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
tests := []struct {
name string
setConfg func()
wantedEpoch primitives.Epoch
}{
{
name: "no schedule",
wantedEpoch: 0,
setConfg: func() {
cfg = cfg.Copy()
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "genesis fork",
wantedEpoch: 0,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "altair post fork",
wantedEpoch: 10,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.AltairForkVersion = []byte{'A', 'B', 'C', 'F'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "3 forks, 1 valid fork",
wantedEpoch: 5,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 5,
{'A', 'B', 'C', 'F'}: math.MaxUint64,
{'A', 'B', 'C', 'Z'}: math.MaxUint64,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "3 forks, 2 valid ones",
wantedEpoch: 10,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
{'A', 'B', 'C', 'Z'}: math.MaxUint64,
}
params.OverrideBeaconConfig(cfg)
},
},
{
name: "3 forks",
wantedEpoch: 100,
setConfg: func() {
cfg = cfg.Copy()
cfg.GenesisForkVersion = []byte{'A', 'B', 'C', 'D'}
cfg.ForkVersionSchedule = map[[4]byte]primitives.Epoch{
{'A', 'B', 'C', 'D'}: 0,
{'A', 'B', 'C', 'F'}: 10,
{'A', 'B', 'C', 'Z'}: 100,
}
params.OverrideBeaconConfig(cfg)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.setConfg()
fEpoch := LastForkEpoch()
if fEpoch != tt.wantedEpoch {
t.Errorf("LastForkEpoch() fork epoch = %v, want %v", fEpoch, tt.wantedEpoch)
}
})
}
}

View File

@@ -1,125 +0,0 @@
package forks
import (
"bytes"
"sort"
"strings"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/pkg/errors"
)
// ForkScheduleEntry is a Version+Epoch tuple for sorted storage in an OrderedSchedule
type ForkScheduleEntry struct {
Version [fieldparams.VersionLength]byte
Epoch primitives.Epoch
Name string
}
// OrderedSchedule provides a type that can be used to sort the fork schedule and find the Version
// the chain should be at for a given epoch (via VersionForEpoch) or name (via VersionForName).
type OrderedSchedule []ForkScheduleEntry
// Len implements the Len method of sort.Interface
func (o OrderedSchedule) Len() int { return len(o) }
// Swap implements the Swap method of sort.Interface
func (o OrderedSchedule) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
// Less implements the Less method of sort.Interface
func (o OrderedSchedule) Less(i, j int) bool {
if o[i].Epoch == o[j].Epoch {
return bytes.Compare(o[i].Version[:], o[j].Version[:]) < 0
}
return o[i].Epoch < o[j].Epoch
}
// VersionForEpoch finds the Version with the highest epoch <= the given epoch
func (o OrderedSchedule) VersionForEpoch(epoch primitives.Epoch) ([fieldparams.VersionLength]byte, error) {
for i := len(o) - 1; i >= 0; i-- {
if o[i].Epoch <= epoch {
return o[i].Version, nil
}
}
return [fieldparams.VersionLength]byte{}, errors.Wrapf(ErrVersionNotFound, "no epoch in list <= %d", epoch)
}
// VersionForName finds the Version corresponding to the lowercase version of the provided name.
func (o OrderedSchedule) VersionForName(name string) ([fieldparams.VersionLength]byte, error) {
lower := strings.ToLower(name)
for _, e := range o {
if e.Name == lower {
return e.Version, nil
}
}
return [4]byte{}, errors.Wrapf(ErrVersionNotFound, "no version with name %s", lower)
}
func (o OrderedSchedule) ForkFromVersion(version [fieldparams.VersionLength]byte) (*ethpb.Fork, error) {
for i := range o {
e := o[i]
if e.Version == version {
f := &ethpb.Fork{Epoch: e.Epoch, CurrentVersion: version[:], PreviousVersion: version[:]}
if i > 0 {
f.PreviousVersion = o[i-1].Version[:]
}
return f, nil
}
}
return nil, errors.Wrapf(ErrVersionNotFound, "could not determine fork for version %#x", version)
}
func (o OrderedSchedule) Previous(version [fieldparams.VersionLength]byte) ([fieldparams.VersionLength]byte, error) {
for i := len(o) - 1; i >= 0; i-- {
if o[i].Version == version {
if i-1 >= 0 {
return o[i-1].Version, nil
} else {
return [fieldparams.VersionLength]byte{}, errors.Wrapf(ErrNoPreviousVersion, "%#x is the first version", version)
}
}
}
return [fieldparams.VersionLength]byte{}, errors.Wrapf(ErrVersionNotFound, "no version in list == %#x", version)
}
// NewOrderedSchedule Converts fork version maps into a list of Version+Epoch+Name values, ordered by Epoch from lowest to highest.
// See docs for OrderedSchedule for more detail on what you can do with this type.
func NewOrderedSchedule(b *params.BeaconChainConfig) OrderedSchedule {
ofs := make(OrderedSchedule, 0)
for version, epoch := range b.ForkVersionSchedule {
fse := ForkScheduleEntry{
Version: version,
Epoch: epoch,
Name: b.ForkVersionNames[version],
}
ofs = append(ofs, fse)
}
sort.Sort(ofs)
return ofs
}
// ForkForEpochFromConfig returns the fork data for the given epoch from the provided config.
func ForkForEpochFromConfig(cfg *params.BeaconChainConfig, epoch primitives.Epoch) (*ethpb.Fork, error) {
os := NewOrderedSchedule(cfg)
currentVersion, err := os.VersionForEpoch(epoch)
if err != nil {
return nil, err
}
prevVersion, err := os.Previous(currentVersion)
if err != nil {
if !errors.Is(err, ErrNoPreviousVersion) {
return nil, err
}
// use same version for both in the case of genesis
prevVersion = currentVersion
}
forkEpoch := cfg.ForkVersionSchedule[currentVersion]
return &ethpb.Fork{
PreviousVersion: prevVersion[:],
CurrentVersion: currentVersion[:],
Epoch: forkEpoch,
}, nil
}

View File

@@ -1,169 +0,0 @@
package forks
import (
"math"
"testing"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/testing/require"
)
func TestOrderedConfigSchedule(t *testing.T) {
params.SetupTestConfigCleanup(t)
for _, cfg := range params.All() {
t.Run(cfg.ConfigName, func(t *testing.T) {
prevVersion := [4]byte{0, 0, 0, 0}
// epoch 0 is genesis, and it's a uint so can't make it -1
// so we use a pointer to detect the boundary condition and skip it
var prevEpoch *primitives.Epoch
for _, fse := range NewOrderedSchedule(cfg) {
// copy loop variable so we can take the address of fields
f := fse
if prevEpoch == nil {
prevEpoch = &f.Epoch
prevVersion = f.Version
continue
}
if *prevEpoch > f.Epoch {
t.Errorf("Epochs out of order! %#x/%d before %#x/%d", f.Version, f.Epoch, prevVersion, prevEpoch)
}
prevEpoch = &f.Epoch
prevVersion = f.Version
}
})
}
bc := testForkVersionBCC()
ofs := NewOrderedSchedule(bc)
for i := range ofs {
if ofs[i].Epoch != primitives.Epoch(math.Pow(2, float64(i))) {
t.Errorf("expected %dth element of list w/ epoch=%d, got=%d. list=%v", i, primitives.Epoch(2^i), ofs[i].Epoch, ofs)
}
}
}
func TestVersionForEpoch(t *testing.T) {
bc := testForkVersionBCC()
ofs := NewOrderedSchedule(bc)
testCases := []struct {
name string
version [4]byte
epoch primitives.Epoch
err error
}{
{
name: "found between versions",
version: [4]byte{2, 1, 2, 3},
epoch: primitives.Epoch(7),
},
{
name: "found at end",
version: [4]byte{4, 1, 2, 3},
epoch: primitives.Epoch(100),
},
{
name: "found at start",
version: [4]byte{0, 1, 2, 3},
epoch: primitives.Epoch(1),
},
{
name: "found at boundary",
version: [4]byte{1, 1, 2, 3},
epoch: primitives.Epoch(2),
},
{
name: "not found before",
epoch: primitives.Epoch(0),
err: ErrVersionNotFound,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
v, err := ofs.VersionForEpoch(tc.epoch)
if tc.err == nil {
require.NoError(t, err)
} else {
require.ErrorIs(t, err, tc.err)
}
require.Equal(t, tc.version, v)
})
}
}
func TestVersionForName(t *testing.T) {
bc := testForkVersionBCC()
ofs := NewOrderedSchedule(bc)
testCases := []struct {
testName string
version [4]byte
versionName string
err error
}{
{
testName: "found",
version: [4]byte{2, 1, 2, 3},
versionName: "third",
},
{
testName: "found lowercase",
version: [4]byte{4, 1, 2, 3},
versionName: "FiFtH",
},
{
testName: "not found",
versionName: "nonexistent",
err: ErrVersionNotFound,
},
}
for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
v, err := ofs.VersionForName(tc.versionName)
if tc.err == nil {
require.NoError(t, err)
} else {
require.ErrorIs(t, err, tc.err)
}
require.Equal(t, tc.version, v)
})
}
}
func testForkVersionBCC() *params.BeaconChainConfig {
return &params.BeaconChainConfig{
ForkVersionSchedule: map[[4]byte]primitives.Epoch{
{1, 1, 2, 3}: primitives.Epoch(2),
{0, 1, 2, 3}: primitives.Epoch(1),
{4, 1, 2, 3}: primitives.Epoch(16),
{3, 1, 2, 3}: primitives.Epoch(8),
{2, 1, 2, 3}: primitives.Epoch(4),
},
ForkVersionNames: map[[4]byte]string{
{1, 1, 2, 3}: "second",
{0, 1, 2, 3}: "first",
{4, 1, 2, 3}: "fifth",
{3, 1, 2, 3}: "fourth",
{2, 1, 2, 3}: "third",
},
}
}
func TestPrevious(t *testing.T) {
cfg := testForkVersionBCC()
os := NewOrderedSchedule(cfg)
unreal := [4]byte{255, 255, 255, 255}
_, err := os.Previous(unreal)
require.ErrorIs(t, err, ErrVersionNotFound)
// first element has no previous, should return appropriate error
_, err = os.Previous(os[0].Version)
require.ErrorIs(t, err, ErrNoPreviousVersion)
// work up the list from the second element to the last, make sure each result matches the previous element
// this test of course relies on TestOrderedConfigSchedule to be correct!
prev := os[0].Version
for i := 1; i < len(os); i++ {
p, err := os.Previous(os[i].Version)
require.NoError(t, err)
require.Equal(t, prev, p)
prev = os[i].Version
}
}

View File

@@ -22,7 +22,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/io/file"
"github.com/OffchainLabs/prysm/v6/network/forks"
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
eth "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/assert"
@@ -639,7 +638,7 @@ func (r *testRunner) multiScenarioMulticlient(ec *e2etypes.EvaluationContext, ep
Status *enginev1.PayloadStatus `json:"payloadStatus"`
PayloadId *enginev1.PayloadIDBytes `json:"payloadId"`
}
lastForkEpoch := forks.LastForkEpoch()
lastForkEpoch := params.LastForkEpoch()
freezeStartEpoch := lastForkEpoch + 1
freezeEndEpoch := lastForkEpoch + 2
optimisticStartEpoch := lastForkEpoch + 6
@@ -756,7 +755,7 @@ func (r *testRunner) eeOffline(_ *e2etypes.EvaluationContext, epoch uint64, _ []
// will test this with our optimistic sync evaluator to ensure everything works
// as expected.
func (r *testRunner) multiScenario(ec *e2etypes.EvaluationContext, epoch uint64, conns []*grpc.ClientConn) bool {
lastForkEpoch := forks.LastForkEpoch()
lastForkEpoch := params.LastForkEpoch()
freezeStartEpoch := lastForkEpoch + 1
freezeEndEpoch := lastForkEpoch + 2
valOfflineStartEpoch := lastForkEpoch + 6

View File

@@ -27,6 +27,7 @@ go_library(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/p2p:go_default_library",
"//beacon-chain/startup:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
@@ -38,7 +39,6 @@ go_library(
"//encoding/bytesutil:go_default_library",
"//encoding/ssz:go_default_library",
"//encoding/ssz/detect:go_default_library",
"//network/forks:go_default_library",
"//network/httputil:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/interop:go_default_library",

View File

@@ -11,7 +11,9 @@ import (
"time"
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
"github.com/OffchainLabs/prysm/v6/network/forks"
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
eth "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
e2e "github.com/OffchainLabs/prysm/v6/testing/endtoend/params"
"github.com/OffchainLabs/prysm/v6/testing/endtoend/policies"
@@ -90,10 +92,8 @@ func metricsTest(_ *types.EvaluationContext, conns ...*grpc.ClientConn) error {
if err != nil {
return err
}
forkDigest, err := forks.CreateForkDigest(time.Unix(genesis.GenesisTime.Seconds, 0), genesis.GenesisValidatorsRoot)
if err != nil {
return err
}
clock := startup.NewClock(time.Unix(genesis.GenesisTime.Seconds, 0), bytesutil.ToBytes32(genesis.GenesisValidatorsRoot))
forkDigest := params.ForkDigest(clock.CurrentEpoch())
for i := 0; i < len(conns); i++ {
response, err := http.Get(fmt.Sprintf("http://localhost:%d/metrics", e2e.TestParams.Ports.PrysmBeaconNodeMetricsPort+i))
if err != nil {

View File

@@ -60,7 +60,6 @@ go_library(
"//crypto/random:go_default_library",
"//encoding/bytesutil:go_default_library",
"//encoding/ssz:go_default_library",
"//network/forks:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/eth/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",

View File

@@ -13,7 +13,6 @@ import (
"github.com/OffchainLabs/prysm/v6/crypto/bls"
"github.com/OffchainLabs/prysm/v6/crypto/random"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -126,11 +125,7 @@ func GenerateTestDenebBlockWithSidecar(t *testing.T, parent [32]byte, slot primi
}
if g.sign {
epoch := slots.ToEpoch(block.Block.Slot)
schedule := forks.NewOrderedSchedule(params.BeaconConfig())
version, err := schedule.VersionForEpoch(epoch)
require.NoError(t, err)
fork, err := schedule.ForkFromVersion(version)
require.NoError(t, err)
fork := params.ForkFromConfig(params.BeaconConfig(), epoch)
domain := params.BeaconConfig().DomainBeaconProposer
sig, err := signing.ComputeDomainAndSignWithoutState(fork, epoch, domain, g.valRoot, block.Block, g.sk)
require.NoError(t, err)

View File

@@ -12,7 +12,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/crypto/bls"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/require"
@@ -131,11 +130,7 @@ func GenerateTestElectraBlockWithSidecar(t *testing.T, parent [32]byte, slot pri
if g.sign {
epoch := slots.ToEpoch(block.Block.Slot)
schedule := forks.NewOrderedSchedule(params.BeaconConfig())
version, err := schedule.VersionForEpoch(epoch)
require.NoError(t, err)
fork, err := schedule.ForkFromVersion(version)
require.NoError(t, err)
fork := params.ForkFromConfig(params.BeaconConfig(), epoch)
domain := params.BeaconConfig().DomainBeaconProposer
sig, err := signing.ComputeDomainAndSignWithoutState(fork, epoch, domain, g.valRoot, block.Block, g.sk)
require.NoError(t, err)

View File

@@ -14,7 +14,6 @@ import (
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/crypto/bls"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
enginev1 "github.com/OffchainLabs/prysm/v6/proto/engine/v1"
"github.com/OffchainLabs/prysm/v6/testing/require"
"github.com/OffchainLabs/prysm/v6/time/slots"
@@ -131,13 +130,7 @@ func GenerateTestFuluBlockWithSidecars(t *testing.T, blobCount int, options ...F
if generator.sign {
epoch := slots.ToEpoch(block.Block.Slot)
schedule := forks.NewOrderedSchedule(params.BeaconConfig())
version, err := schedule.VersionForEpoch(epoch)
require.NoError(t, err)
fork, err := schedule.ForkFromVersion(version)
require.NoError(t, err)
fork := params.ForkFromConfig(params.BeaconConfig(), epoch)
domain := params.BeaconConfig().DomainBeaconProposer
sig, err := signing.ComputeDomainAndSignWithoutState(fork, epoch, domain, generator.valRoot, block.Block, generator.sk)

View File

@@ -53,7 +53,6 @@ go_library(
"//consensus-types/validator:go_default_library",
"//encoding/bytesutil:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//network/forks:go_default_library",
"//network/httputil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",

View File

@@ -5,16 +5,16 @@ import (
"github.com/OffchainLabs/prysm/v6/beacon-chain/core/signing"
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/pkg/errors"
)
func (c *beaconApiValidatorClient) domainData(ctx context.Context, epoch primitives.Epoch, domainType [4]byte) (*ethpb.DomainResponse, error) {
// Get the fork version from the given epoch
fork, err := forks.Fork(epoch)
fork, err := params.Fork(epoch)
if err != nil {
return nil, errors.Wrapf(err, "failed to get fork version for epoch %d", epoch)
}

View File

@@ -10,10 +10,10 @@ go_library(
importpath = "github.com/OffchainLabs/prysm/v6/validator/keymanager/remote-web3signer/types",
visibility = ["//visibility:public"],
deps = [
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/validator-client:go_default_library",
"//runtime/version:go_default_library",

View File

@@ -3,8 +3,8 @@ package types
import (
"fmt"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v6/network/forks"
ethpb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/time/slots"
"github.com/ethereum/go-ethereum/common/hexutil"
@@ -13,7 +13,7 @@ import (
// MapForkInfo maps the eth2.ForkInfo proto to the Web3Signer spec.
func MapForkInfo(slot primitives.Slot, genesisValidatorsRoot []byte) (*ForkInfo, error) {
fork, err := forks.Fork(slots.ToEpoch(slot))
fork, err := params.Fork(slots.ToEpoch(slot))
if err != nil {
return nil, errors.Wrap(err, "could not get fork info")
}