mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-02-18 00:41:38 -05:00
Compare commits
1 Commits
gloas-goss
...
remove_hea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
322fbee924 |
@@ -136,7 +136,6 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *fcuConfig) (*
|
||||
return nil, nil
|
||||
}
|
||||
pid, err := s.notifyForkchoiceUpdate(ctx, &fcuConfig{
|
||||
headState: st,
|
||||
headRoot: r,
|
||||
headBlock: b,
|
||||
attributes: arg.attributes,
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
mockExecution "github.com/OffchainLabs/prysm/v7/beacon-chain/execution/testing"
|
||||
forkchoicetypes "github.com/OffchainLabs/prysm/v7/beacon-chain/forkchoice/types"
|
||||
bstate "github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
||||
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
|
||||
"github.com/OffchainLabs/prysm/v7/config/features"
|
||||
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
@@ -73,11 +72,7 @@ func Test_NotifyForkchoiceUpdate_GetPayloadAttrErrorCanContinue(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, bellatrixBlkRoot))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bellatrixBlkRoot))
|
||||
|
||||
// Intentionally generate a bad state such that `hash_tree_root` fails during `process_slot`
|
||||
s, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||
require.NoError(t, err)
|
||||
arg := &fcuConfig{
|
||||
headState: s,
|
||||
headRoot: [32]byte{},
|
||||
headBlock: b,
|
||||
}
|
||||
@@ -233,8 +228,7 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, tt.finalizedRoot))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, tt.finalizedRoot))
|
||||
arg := &fcuConfig{
|
||||
headState: st,
|
||||
headRoot: tt.headRoot,
|
||||
headRoot: tt.headRoot,
|
||||
headBlock: tt.blk,
|
||||
}
|
||||
_, err = service.notifyForkchoiceUpdate(ctx, arg)
|
||||
@@ -314,7 +308,6 @@ func Test_NotifyForkchoiceUpdate_NIlLVH(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, bra))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bra))
|
||||
a := &fcuConfig{
|
||||
headState: st,
|
||||
headBlock: wbd,
|
||||
headRoot: brd,
|
||||
}
|
||||
@@ -452,7 +445,6 @@ func Test_NotifyForkchoiceUpdateRecursive_DoublyLinkedTree(t *testing.T) {
|
||||
require.NoError(t, beaconDB.SaveState(ctx, st, bra))
|
||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bra))
|
||||
a := &fcuConfig{
|
||||
headState: st,
|
||||
headBlock: wbg,
|
||||
headRoot: brg,
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ func (s *Service) getStateAndBlock(ctx context.Context, r [32]byte) (state.Beaco
|
||||
}
|
||||
|
||||
type fcuConfig struct {
|
||||
headState state.BeaconState
|
||||
headBlock interfaces.ReadOnlySignedBeaconBlock
|
||||
headRoot [32]byte
|
||||
proposingSlot primitives.Slot
|
||||
@@ -64,7 +63,8 @@ func (s *Service) sendFCU(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) {
|
||||
s.updateCachesPostBlockProcessing(cfg)
|
||||
s.ForkChoicer().Lock()
|
||||
}
|
||||
if err := s.getFCUArgs(cfg, fcuArgs); err != nil {
|
||||
headState, err := s.getFCUArgs(cfg, fcuArgs)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not get forkchoice update argument")
|
||||
return
|
||||
}
|
||||
@@ -81,10 +81,10 @@ func (s *Service) sendFCU(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) {
|
||||
}
|
||||
|
||||
if s.isNewHead(fcuArgs.headRoot) {
|
||||
if err := s.saveHead(cfg.ctx, fcuArgs.headRoot, fcuArgs.headBlock, fcuArgs.headState); err != nil {
|
||||
if err := s.saveHead(cfg.ctx, fcuArgs.headRoot, fcuArgs.headBlock, headState); err != nil {
|
||||
log.WithError(err).Error("Could not save head")
|
||||
}
|
||||
s.pruneAttsFromPool(s.ctx, fcuArgs.headState, fcuArgs.headBlock)
|
||||
s.pruneAttsFromPool(s.ctx, headState, fcuArgs.headBlock)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,6 @@ func TestService_forkchoiceUpdateWithExecution_exceptionalCases(t *testing.T) {
|
||||
}
|
||||
service.cfg.PayloadIDCache.Set(2, [32]byte{2}, [8]byte{1})
|
||||
args := &fcuConfig{
|
||||
headState: st,
|
||||
headRoot: r1,
|
||||
headBlock: wsb,
|
||||
proposingSlot: service.CurrentSlot() + 1,
|
||||
@@ -146,7 +145,6 @@ func TestService_forkchoiceUpdateWithExecution_SameHeadRootNewProposer(t *testin
|
||||
service.head.state = st
|
||||
service.cfg.PayloadIDCache.Set(service.CurrentSlot()+1, [32]byte{} /* root */, [8]byte{})
|
||||
args := &fcuConfig{
|
||||
headState: st,
|
||||
headBlock: sb,
|
||||
headRoot: r,
|
||||
proposingSlot: service.CurrentSlot() + 1,
|
||||
|
||||
@@ -170,7 +170,7 @@ func (s *Service) saveHead(ctx context.Context, newHeadRoot [32]byte, headBlock
|
||||
// Forward an event capturing a new chain head over a common event feed
|
||||
// done in a goroutine to avoid blocking the critical runtime main routine.
|
||||
go func() {
|
||||
if err := s.notifyNewHeadEvent(ctx, newHeadSlot, headState, newStateRoot[:], newHeadRoot[:]); err != nil {
|
||||
if err := s.notifyNewHeadEvent(ctx, newHeadSlot, newStateRoot[:], newHeadRoot[:]); err != nil {
|
||||
log.WithError(err).Error("Could not notify event feed of new chain head")
|
||||
}
|
||||
}()
|
||||
@@ -322,7 +322,6 @@ func (s *Service) hasHeadState() bool {
|
||||
func (s *Service) notifyNewHeadEvent(
|
||||
ctx context.Context,
|
||||
newHeadSlot primitives.Slot,
|
||||
newHeadState state.BeaconState,
|
||||
newHeadStateRoot,
|
||||
newHeadRoot []byte,
|
||||
) error {
|
||||
|
||||
@@ -152,7 +152,6 @@ func TestSaveHead_Different_Reorg(t *testing.T) {
|
||||
|
||||
func Test_notifyNewHeadEvent(t *testing.T) {
|
||||
t.Run("genesis_state_root", func(t *testing.T) {
|
||||
bState, _ := util.DeterministicGenesisState(t, 10)
|
||||
srv := testServiceWithDB(t)
|
||||
srv.SetGenesisTime(time.Now())
|
||||
notifier := srv.cfg.StateNotifier.(*mock.MockStateNotifier)
|
||||
@@ -165,7 +164,7 @@ func Test_notifyNewHeadEvent(t *testing.T) {
|
||||
st, blk, err = prepareForkchoiceState(t.Context(), 1, newHeadRoot, [32]byte{}, [32]byte{}, ðpb.Checkpoint{}, ðpb.Checkpoint{})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
|
||||
require.NoError(t, srv.notifyNewHeadEvent(t.Context(), 1, bState, newHeadStateRoot[:], newHeadRoot[:]))
|
||||
require.NoError(t, srv.notifyNewHeadEvent(t.Context(), 1, newHeadStateRoot[:], newHeadRoot[:]))
|
||||
events := notifier.ReceivedEvents()
|
||||
require.Equal(t, 1, len(events))
|
||||
|
||||
@@ -202,7 +201,7 @@ func Test_notifyNewHeadEvent(t *testing.T) {
|
||||
st, blk, err = prepareForkchoiceState(t.Context(), 0, newHeadRoot, [32]byte{}, [32]byte{}, ðpb.Checkpoint{}, ðpb.Checkpoint{})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
|
||||
err = srv.notifyNewHeadEvent(t.Context(), epoch2Start, bState, newHeadStateRoot[:], newHeadRoot[:])
|
||||
err = srv.notifyNewHeadEvent(t.Context(), epoch2Start, newHeadStateRoot[:], newHeadRoot[:])
|
||||
require.NoError(t, err)
|
||||
events := notifier.ReceivedEvents()
|
||||
require.Equal(t, 1, len(events))
|
||||
@@ -220,7 +219,6 @@ func Test_notifyNewHeadEvent(t *testing.T) {
|
||||
require.DeepSSZEqual(t, wanted, eventHead)
|
||||
})
|
||||
t.Run("epoch transition", func(t *testing.T) {
|
||||
bState, _ := util.DeterministicGenesisState(t, 10)
|
||||
srv := testServiceWithDB(t)
|
||||
srv.SetGenesisTime(time.Now())
|
||||
notifier := srv.cfg.StateNotifier.(*mock.MockStateNotifier)
|
||||
@@ -234,7 +232,7 @@ func Test_notifyNewHeadEvent(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
|
||||
newHeadSlot := params.BeaconConfig().SlotsPerEpoch
|
||||
require.NoError(t, srv.notifyNewHeadEvent(t.Context(), newHeadSlot, bState, newHeadStateRoot[:], newHeadRoot[:]))
|
||||
require.NoError(t, srv.notifyNewHeadEvent(t.Context(), newHeadSlot, newHeadStateRoot[:], newHeadRoot[:]))
|
||||
events := notifier.ReceivedEvents()
|
||||
require.Equal(t, 1, len(events))
|
||||
|
||||
|
||||
@@ -970,7 +970,6 @@ func (s *Service) lateBlockTasks(ctx context.Context) {
|
||||
s.headLock.RUnlock()
|
||||
|
||||
fcuArgs := &fcuConfig{
|
||||
headState: headState,
|
||||
headRoot: headRoot,
|
||||
headBlock: headBlock,
|
||||
attributes: attribute,
|
||||
|
||||
@@ -37,22 +37,24 @@ func (s *Service) CurrentSlot() primitives.Slot {
|
||||
return slots.CurrentSlot(s.genesisTime)
|
||||
}
|
||||
|
||||
// getFCUArgs returns the arguments to call forkchoice update
|
||||
func (s *Service) getFCUArgs(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error {
|
||||
if err := s.getFCUArgsEarlyBlock(cfg, fcuArgs); err != nil {
|
||||
return err
|
||||
// getFCUArgs returns the arguments to call forkchoice update.
|
||||
// It returns the head state separately so it is not pinned by goroutines
|
||||
// that only need the fcuConfig for the engine call.
|
||||
func (s *Service) getFCUArgs(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) (state.BeaconState, error) {
|
||||
headState, err := s.getFCUArgsEarlyBlock(cfg, fcuArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fcuArgs.attributes = s.getPayloadAttribute(cfg.ctx, fcuArgs.headState, fcuArgs.proposingSlot, cfg.headRoot[:])
|
||||
return nil
|
||||
fcuArgs.attributes = s.getPayloadAttribute(cfg.ctx, headState, fcuArgs.proposingSlot, cfg.headRoot[:])
|
||||
return headState, nil
|
||||
}
|
||||
|
||||
func (s *Service) getFCUArgsEarlyBlock(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error {
|
||||
func (s *Service) getFCUArgsEarlyBlock(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) (state.BeaconState, error) {
|
||||
if cfg.roblock.Root() == cfg.headRoot {
|
||||
fcuArgs.headState = cfg.postState
|
||||
fcuArgs.headBlock = cfg.roblock
|
||||
fcuArgs.headRoot = cfg.headRoot
|
||||
fcuArgs.proposingSlot = s.CurrentSlot() + 1
|
||||
return nil
|
||||
return cfg.postState, nil
|
||||
}
|
||||
return s.fcuArgsNonCanonicalBlock(cfg, fcuArgs)
|
||||
}
|
||||
@@ -79,16 +81,15 @@ func (s *Service) logNonCanonicalBlockReceived(blockRoot [32]byte, headRoot [32]
|
||||
|
||||
// fcuArgsNonCanonicalBlock returns the arguments to the FCU call when the
|
||||
// incoming block is non-canonical, that is, based on the head root.
|
||||
func (s *Service) fcuArgsNonCanonicalBlock(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error {
|
||||
func (s *Service) fcuArgsNonCanonicalBlock(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) (state.BeaconState, error) {
|
||||
headState, headBlock, err := s.getStateAndBlock(cfg.ctx, cfg.headRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
fcuArgs.headState = headState
|
||||
fcuArgs.headBlock = headBlock
|
||||
fcuArgs.headRoot = cfg.headRoot
|
||||
fcuArgs.proposingSlot = s.CurrentSlot() + 1
|
||||
return nil
|
||||
return headState, nil
|
||||
}
|
||||
|
||||
// sendStateFeedOnBlock sends an event that a new block has been synced
|
||||
|
||||
@@ -2418,13 +2418,13 @@ func Test_getFCUArgs(t *testing.T) {
|
||||
}
|
||||
// error branch
|
||||
fcuArgs := &fcuConfig{}
|
||||
err = s.getFCUArgs(cfg, fcuArgs)
|
||||
_, err = s.getFCUArgs(cfg, fcuArgs)
|
||||
require.ErrorContains(t, "block does not exist", err)
|
||||
|
||||
// canonical branch
|
||||
cfg.headRoot = cfg.roblock.Root()
|
||||
fcuArgs = &fcuConfig{}
|
||||
err = s.getFCUArgs(cfg, fcuArgs)
|
||||
_, err = s.getFCUArgs(cfg, fcuArgs)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, cfg.roblock.Root(), fcuArgs.headRoot)
|
||||
}
|
||||
|
||||
@@ -150,7 +150,6 @@ func (s *Service) UpdateHead(ctx context.Context, proposingSlot primitives.Slot)
|
||||
}
|
||||
newAttHeadElapsedTime.Observe(float64(time.Since(start).Milliseconds()))
|
||||
fcuArgs := &fcuConfig{
|
||||
headState: headState,
|
||||
headRoot: newHeadRoot,
|
||||
headBlock: headBlock,
|
||||
proposingSlot: proposingSlot,
|
||||
@@ -162,10 +161,10 @@ func (s *Service) UpdateHead(ctx context.Context, proposingSlot primitives.Slot)
|
||||
}
|
||||
go s.forkchoiceUpdateWithExecution(s.ctx, fcuArgs)
|
||||
}
|
||||
if err := s.saveHead(s.ctx, fcuArgs.headRoot, fcuArgs.headBlock, fcuArgs.headState); err != nil {
|
||||
if err := s.saveHead(s.ctx, newHeadRoot, headBlock, headState); err != nil {
|
||||
log.WithError(err).Error("Could not save head")
|
||||
}
|
||||
s.pruneAttsFromPool(s.ctx, fcuArgs.headState, fcuArgs.headBlock)
|
||||
s.pruneAttsFromPool(s.ctx, headState, headBlock)
|
||||
}
|
||||
|
||||
// This processes fork choice attestations from the pool to account for validator votes and fork choice.
|
||||
|
||||
@@ -73,22 +73,23 @@ func PopulateFromSidecar(sidecar blocks.VerifiedRODataColumn) *SidecarReconstruc
|
||||
|
||||
// ValidatorsCustodyRequirement returns the number of custody groups regarding the validator indices attached to the beacon node.
|
||||
// https://github.com/ethereum/consensus-specs/blob/master/specs/fulu/validator.md#validator-custody
|
||||
func ValidatorsCustodyRequirement(st beaconState.ReadOnlyBalances, validatorsIndex map[primitives.ValidatorIndex]bool) (uint64, error) {
|
||||
cfg := params.BeaconConfig()
|
||||
idxs := make([]primitives.ValidatorIndex, 0, len(validatorsIndex))
|
||||
func ValidatorsCustodyRequirement(state beaconState.ReadOnlyBeaconState, validatorsIndex map[primitives.ValidatorIndex]bool) (uint64, error) {
|
||||
totalNodeBalance := uint64(0)
|
||||
for index := range validatorsIndex {
|
||||
idxs = append(idxs, index)
|
||||
}
|
||||
totalBalance, err := st.EffectiveBalanceSum(idxs)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "effective balances")
|
||||
validator, err := state.ValidatorAtIndexReadOnly(index)
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "validator at index %v", index)
|
||||
}
|
||||
|
||||
totalNodeBalance += validator.EffectiveBalance()
|
||||
}
|
||||
|
||||
cfg := params.BeaconConfig()
|
||||
numberOfCustodyGroups := cfg.NumberOfCustodyGroups
|
||||
validatorCustodyRequirement := cfg.ValidatorCustodyRequirement
|
||||
balancePerAdditionalCustodyGroup := cfg.BalancePerAdditionalCustodyGroup
|
||||
|
||||
count := totalBalance / balancePerAdditionalCustodyGroup
|
||||
count := totalNodeBalance / balancePerAdditionalCustodyGroup
|
||||
return min(max(count, validatorCustodyRequirement), numberOfCustodyGroups), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,6 @@ type ReadOnlyBalances interface {
|
||||
Balances() []uint64
|
||||
BalanceAtIndex(idx primitives.ValidatorIndex) (uint64, error)
|
||||
BalancesLength() int
|
||||
EffectiveBalanceSum([]primitives.ValidatorIndex) (uint64, error)
|
||||
}
|
||||
|
||||
// ReadOnlyCheckpoint defines a struct which only has read access to checkpoint methods.
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v7/runtime/version"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Validators participating in consensus on the beacon chain.
|
||||
@@ -81,25 +80,6 @@ func (b *BeaconState) ValidatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Va
|
||||
return b.validatorAtIndex(idx)
|
||||
}
|
||||
|
||||
// EffectiveBalances returns the sum of the effective balances of the given list of validator indices, the eb of each given validator, or an
|
||||
// error if one of the indices is out of bounds, or the state wasn't correctly initialized.
|
||||
func (b *BeaconState) EffectiveBalanceSum(idxs []primitives.ValidatorIndex) (uint64, error) {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
var sum uint64
|
||||
for i := range idxs {
|
||||
if b.validatorsMultiValue == nil {
|
||||
return 0, errors.Wrap(state.ErrNilValidatorsInState, "nil validators multi-value slice")
|
||||
}
|
||||
v, err := b.validatorsMultiValue.At(b, uint64(idxs[i]))
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "validators multi value at index")
|
||||
}
|
||||
sum += v.EffectiveBalance
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) validatorAtIndex(idx primitives.ValidatorIndex) (*ethpb.Validator, error) {
|
||||
if b.validatorsMultiValue == nil {
|
||||
return ðpb.Validator{}, nil
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/stategen"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
)
|
||||
|
||||
@@ -15,8 +14,6 @@ type StateManager struct {
|
||||
StatesBySlot map[primitives.Slot]state.BeaconState
|
||||
}
|
||||
|
||||
var _ stategen.StateManager = (*StateManager)(nil)
|
||||
|
||||
// NewService --
|
||||
func NewService() *StateManager {
|
||||
return &StateManager{
|
||||
@@ -104,8 +101,3 @@ func (m *StateManager) AddStateForSlot(state state.BeaconState, slot primitives.
|
||||
func (m *StateManager) DeleteStateFromCaches(context.Context, [32]byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FinalizedReadOnlyBalances --
|
||||
func (m *StateManager) FinalizedReadOnlyBalances() stategen.NilCheckableReadOnlyBalances {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
@@ -27,13 +27,6 @@ var defaultHotStateDBInterval primitives.Slot = 128
|
||||
|
||||
var populatePubkeyCacheOnce sync.Once
|
||||
|
||||
// NilCheckableReadOnlyBalances adds the IsNil method to ReadOnlyBalances
|
||||
// to allow checking if the underlying state value is nil.
|
||||
type NilCheckableReadOnlyBalances interface {
|
||||
state.ReadOnlyBalances
|
||||
IsNil() bool
|
||||
}
|
||||
|
||||
// StateManager represents a management object that handles the internal
|
||||
// logic of maintaining both hot and cold states in DB.
|
||||
type StateManager interface {
|
||||
@@ -50,7 +43,6 @@ type StateManager interface {
|
||||
ActiveNonSlashedBalancesByRoot(context.Context, [32]byte) ([]uint64, error)
|
||||
StateByRootIfCachedNoCopy(blockRoot [32]byte) state.BeaconState
|
||||
StateByRootInitialSync(ctx context.Context, blockRoot [32]byte) (state.BeaconState, error)
|
||||
FinalizedReadOnlyBalances() NilCheckableReadOnlyBalances
|
||||
}
|
||||
|
||||
// State is a concrete implementation of StateManager.
|
||||
@@ -209,8 +201,3 @@ func (s *State) FinalizedState() state.BeaconState {
|
||||
defer s.finalizedInfo.lock.RUnlock()
|
||||
return s.finalizedInfo.state.Copy()
|
||||
}
|
||||
|
||||
// Returns the finalized state as a ReadOnlyBalances so that it can be used read-only without copying.
|
||||
func (s *State) FinalizedReadOnlyBalances() NilCheckableReadOnlyBalances {
|
||||
return s.finalizedInfo.state
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ go_library(
|
||||
"validate_aggregate_proof.go",
|
||||
"validate_attester_slashing.go",
|
||||
"validate_beacon_attestation.go",
|
||||
"validate_beacon_block_gloas.go",
|
||||
"validate_beacon_blocks.go",
|
||||
"validate_blob.go",
|
||||
"validate_bls_to_execution_change.go",
|
||||
@@ -212,7 +211,6 @@ go_test(
|
||||
"validate_aggregate_proof_test.go",
|
||||
"validate_attester_slashing_test.go",
|
||||
"validate_beacon_attestation_test.go",
|
||||
"validate_beacon_block_gloas_test.go",
|
||||
"validate_beacon_blocks_test.go",
|
||||
"validate_blob_test.go",
|
||||
"validate_bls_to_execution_change_test.go",
|
||||
|
||||
@@ -185,7 +185,7 @@ func (s *Service) validatorsCustodyRequirement() (uint64, error) {
|
||||
}
|
||||
|
||||
// Retrieve the finalized state.
|
||||
finalizedState := s.cfg.stateGen.FinalizedReadOnlyBalances()
|
||||
finalizedState := s.cfg.stateGen.FinalizedState()
|
||||
if finalizedState == nil || finalizedState.IsNil() {
|
||||
return 0, nilFinalizedStateError
|
||||
}
|
||||
|
||||
@@ -268,23 +268,10 @@ func (s *Service) validateCommitteeIndexAndCount(
|
||||
a eth.Att,
|
||||
bs state.ReadOnlyBeaconState,
|
||||
) (primitives.CommitteeIndex, uint64, pubsub.ValidationResult, error) {
|
||||
// Validate committee index based on fork.
|
||||
if a.Version() >= version.Electra {
|
||||
data := a.GetData()
|
||||
attEpoch := slots.ToEpoch(data.Slot)
|
||||
postGloas := attEpoch >= params.BeaconConfig().GloasForkEpoch
|
||||
if postGloas {
|
||||
if result, err := s.validateGloasCommitteeIndex(data); result != pubsub.ValidationAccept {
|
||||
return 0, 0, result, err
|
||||
}
|
||||
} else {
|
||||
// [REJECT] attestation.data.index == 0 (New in Electra, removed in Gloas)
|
||||
if data.CommitteeIndex != 0 {
|
||||
return 0, 0, pubsub.ValidationReject, errors.New("attestation data's committee index must be 0")
|
||||
}
|
||||
}
|
||||
// - [REJECT] attestation.data.index == 0
|
||||
if a.Version() >= version.Electra && a.GetData().CommitteeIndex != 0 {
|
||||
return 0, 0, pubsub.ValidationReject, errors.New("attestation data's committee index must be 0")
|
||||
}
|
||||
|
||||
valCount, err := helpers.ActiveValidatorCount(ctx, bs, slots.ToEpoch(a.GetData().Slot))
|
||||
if err != nil {
|
||||
return 0, 0, pubsub.ValidationIgnore, err
|
||||
@@ -369,29 +356,6 @@ func validateAttestingIndex(
|
||||
return pubsub.ValidationAccept, nil
|
||||
}
|
||||
|
||||
// validateGloasCommitteeIndex validates committee index rules for Gloas fork.
|
||||
// [REJECT] attestation.data.index < 2. (New in Gloas)
|
||||
// [REJECT] attestation.data.index == 0 if block.slot == attestation.data.slot. (New in Gloas)
|
||||
func (s *Service) validateGloasCommitteeIndex(data *eth.AttestationData) (pubsub.ValidationResult, error) {
|
||||
if data.CommitteeIndex >= 2 {
|
||||
return pubsub.ValidationReject, errors.New("attestation data's committee index must be < 2")
|
||||
}
|
||||
|
||||
// Same-slot attestations must use committee index 0
|
||||
if data.CommitteeIndex != 0 {
|
||||
blockRoot := bytesutil.ToBytes32(data.BeaconBlockRoot)
|
||||
slot, err := s.cfg.chain.RecentBlockSlot(blockRoot)
|
||||
if err != nil {
|
||||
return pubsub.ValidationIgnore, err
|
||||
}
|
||||
if slot == data.Slot {
|
||||
return pubsub.ValidationReject, errors.New("same slot attestations must use committee index 0")
|
||||
}
|
||||
}
|
||||
|
||||
return pubsub.ValidationAccept, nil
|
||||
}
|
||||
|
||||
// generateUnaggregatedAttCacheKey generates the cache key for unaggregated attestation tracking.
|
||||
func generateUnaggregatedAttCacheKey(att eth.Att) (string, error) {
|
||||
var attester uint64
|
||||
|
||||
@@ -684,75 +684,3 @@ func Test_validateCommitteeIndexAndCount_Boundary(t *testing.T) {
|
||||
require.ErrorContains(t, "committee index", err)
|
||||
require.Equal(t, pubsub.ValidationReject, res)
|
||||
}
|
||||
|
||||
func Test_validateGloasCommitteeIndex(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
committeeIndex primitives.CommitteeIndex
|
||||
attestationSlot primitives.Slot
|
||||
blockSlot primitives.Slot
|
||||
wantResult pubsub.ValidationResult
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "committee index >= 2 should reject",
|
||||
committeeIndex: 2,
|
||||
attestationSlot: 10,
|
||||
blockSlot: 10,
|
||||
wantResult: pubsub.ValidationReject,
|
||||
wantErr: "committee index must be < 2",
|
||||
},
|
||||
{
|
||||
name: "committee index 0 should accept",
|
||||
committeeIndex: 0,
|
||||
attestationSlot: 10,
|
||||
blockSlot: 10,
|
||||
wantResult: pubsub.ValidationAccept,
|
||||
wantErr: "",
|
||||
},
|
||||
{
|
||||
name: "committee index 1 different-slot should accept",
|
||||
committeeIndex: 1,
|
||||
attestationSlot: 10,
|
||||
blockSlot: 9,
|
||||
wantResult: pubsub.ValidationAccept,
|
||||
wantErr: "",
|
||||
},
|
||||
{
|
||||
name: "committee index 1 same-slot should reject",
|
||||
committeeIndex: 1,
|
||||
attestationSlot: 10,
|
||||
blockSlot: 10,
|
||||
wantResult: pubsub.ValidationReject,
|
||||
wantErr: "same slot attestations must use committee index 0",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockChain := &mockChain.ChainService{
|
||||
BlockSlot: tt.blockSlot,
|
||||
}
|
||||
s := &Service{
|
||||
cfg: &config{
|
||||
chain: mockChain,
|
||||
},
|
||||
}
|
||||
|
||||
data := ðpb.AttestationData{
|
||||
Slot: tt.attestationSlot,
|
||||
CommitteeIndex: tt.committeeIndex,
|
||||
BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot"), 32),
|
||||
}
|
||||
|
||||
result, err := s.validateGloasCommitteeIndex(data)
|
||||
|
||||
require.Equal(t, tt.wantResult, result)
|
||||
if tt.wantErr != "" {
|
||||
require.ErrorContains(t, tt.wantErr, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package sync
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
consensusblocks "github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
|
||||
"github.com/OffchainLabs/prysm/v7/runtime/version"
|
||||
"github.com/OffchainLabs/prysm/v7/time/slots"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// validateExecutionPayloadBid validates execution payload bid gossip rules.
|
||||
// [REJECT] The bid's parent (defined by bid.parent_block_root) equals the block's parent (defined by block.parent_root).
|
||||
// [REJECT] The length of KZG commitments is less than or equal to the limitation defined in the consensus layer --
|
||||
// i.e. validate that len(bid.blob_kzg_commitments) <= get_blob_parameters(get_current_epoch(state)).max_blobs_per_block
|
||||
func (s *Service) validateExecutionPayloadBid(ctx context.Context, blk interfaces.ReadOnlyBeaconBlock) (pubsub.ValidationResult, error) {
|
||||
if blk.Version() < version.Gloas {
|
||||
return pubsub.ValidationAccept, nil
|
||||
}
|
||||
signedBid, err := blk.Body().SignedExecutionPayloadBid()
|
||||
if err != nil {
|
||||
return pubsub.ValidationIgnore, errors.Wrap(err, "unable to read bid from block")
|
||||
}
|
||||
wrappedBid, err := consensusblocks.WrappedROSignedExecutionPayloadBid(signedBid)
|
||||
if err != nil {
|
||||
return pubsub.ValidationIgnore, errors.Wrap(err, "unable to wrap signed execution payload bid")
|
||||
}
|
||||
bid, err := wrappedBid.Bid()
|
||||
if err != nil {
|
||||
return pubsub.ValidationIgnore, errors.Wrap(err, "unable to read bid from signed execution payload bid")
|
||||
}
|
||||
|
||||
if bid.ParentBlockRoot() != blk.ParentRoot() {
|
||||
return pubsub.ValidationReject, errors.New("bid parent block root does not match block parent root")
|
||||
}
|
||||
|
||||
maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlockAtEpoch(slots.ToEpoch(blk.Slot()))
|
||||
if bid.BlobKzgCommitmentCount() > uint64(maxBlobsPerBlock) {
|
||||
return pubsub.ValidationReject, errors.Wrapf(errRejectCommitmentLen, "%d > %d", bid.BlobKzgCommitmentCount(), maxBlobsPerBlock)
|
||||
}
|
||||
return pubsub.ValidationAccept, nil
|
||||
}
|
||||
|
||||
// validateExecutionPayloadBidParentSeen validates parent payload gossip rules.
|
||||
// [IGNORE] The block's parent execution payload (defined by bid.parent_block_hash) has been seen
|
||||
// (via gossip or non-gossip sources) (a client MAY queue blocks for processing once the parent payload is retrieved).
|
||||
func (s *Service) validateExecutionPayloadBidParentSeen(ctx context.Context, blk interfaces.ReadOnlyBeaconBlock) (pubsub.ValidationResult, error) {
|
||||
// TODO: Requires blockchain service changes to expose parent payload seen status
|
||||
return pubsub.ValidationAccept, nil
|
||||
}
|
||||
|
||||
// validateExecutionPayloadBidParentValid validates parent payload verification status.
|
||||
// If execution_payload verification of block's execution payload parent by an execution node is complete:
|
||||
// [REJECT] The block's execution payload parent (defined by bid.parent_block_hash) passes all validation.
|
||||
func (s *Service) validateExecutionPayloadBidParentValid(ctx context.Context, blk interfaces.ReadOnlyBeaconBlock) (pubsub.ValidationResult, error) {
|
||||
// TODO: Requires blockchain service changes to expose execution payload parent validation status.
|
||||
return pubsub.ValidationAccept, nil
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package sync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
||||
"github.com/OffchainLabs/prysm/v7/testing/util"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestValidateExecutionPayloadBid_Accept(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
parentRoot := bytesutil.PadTo([]byte{0x01}, fieldparams.RootLength)
|
||||
block := util.NewBeaconBlockGloas()
|
||||
block.Block.ParentRoot = parentRoot
|
||||
block.Block.Body.SignedExecutionPayloadBid.Message.ParentBlockRoot = parentRoot
|
||||
block.Block.Body.SignedExecutionPayloadBid.Message.BlobKzgCommitments = nil
|
||||
|
||||
wsb, err := blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := &Service{}
|
||||
res, err := s.validateExecutionPayloadBid(ctx, wsb.Block())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, pubsub.ValidationAccept, res)
|
||||
}
|
||||
|
||||
func TestValidateExecutionPayloadBid_RejectParentRootMismatch(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
block := util.NewBeaconBlockGloas()
|
||||
block.Block.ParentRoot = bytesutil.PadTo([]byte{0x01}, fieldparams.RootLength)
|
||||
block.Block.Body.SignedExecutionPayloadBid.Message.ParentBlockRoot = bytesutil.PadTo([]byte{0x02}, fieldparams.RootLength)
|
||||
|
||||
wsb, err := blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := &Service{}
|
||||
res, err := s.validateExecutionPayloadBid(ctx, wsb.Block())
|
||||
require.Error(t, err)
|
||||
require.Equal(t, pubsub.ValidationReject, res)
|
||||
}
|
||||
|
||||
func TestValidateExecutionPayloadBid_RejectTooManyCommitments(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
ctx := context.Background()
|
||||
|
||||
parentRoot := bytesutil.PadTo([]byte{0x01}, fieldparams.RootLength)
|
||||
block := util.NewBeaconBlockGloas()
|
||||
block.Block.ParentRoot = parentRoot
|
||||
block.Block.Body.SignedExecutionPayloadBid.Message.ParentBlockRoot = parentRoot
|
||||
|
||||
maxBlobs := params.BeaconConfig().MaxBlobsPerBlockAtEpoch(0)
|
||||
commitments := make([][]byte, maxBlobs+1)
|
||||
for i := range commitments {
|
||||
commitments[i] = bytesutil.PadTo([]byte{0x02}, fieldparams.BLSPubkeyLength)
|
||||
}
|
||||
block.Block.Body.SignedExecutionPayloadBid.Message.BlobKzgCommitments = commitments
|
||||
|
||||
wsb, err := blocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := &Service{}
|
||||
res, err := s.validateExecutionPayloadBid(ctx, wsb.Block())
|
||||
require.Error(t, err)
|
||||
require.Equal(t, pubsub.ValidationReject, res)
|
||||
}
|
||||
@@ -127,9 +127,6 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
||||
log.WithError(err).WithFields(getBlockFields(blk)).Debug("Received block with an invalid parent")
|
||||
return pubsub.ValidationReject, err
|
||||
}
|
||||
if res, err := s.validateExecutionPayloadBidParentValid(ctx, blk.Block()); err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
s.pendingQueueLock.RLock()
|
||||
if s.seenPendingBlocks[blockRoot] {
|
||||
@@ -201,16 +198,6 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
|
||||
log.WithError(err).WithFields(getBlockFields(blk)).Debug("Could not identify parent for block")
|
||||
return pubsub.ValidationIgnore, err
|
||||
}
|
||||
if res, err := s.validateExecutionPayloadBidParentSeen(ctx, blk.Block()); err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if res, err := s.validateExecutionPayloadBid(ctx, blk.Block()); err != nil {
|
||||
if res == pubsub.ValidationReject {
|
||||
s.setBadBlock(ctx, blockRoot)
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
err = s.validateBeaconBlock(ctx, blk, blockRoot)
|
||||
if err != nil {
|
||||
@@ -378,7 +365,7 @@ func (s *Service) blockVerifyingState(ctx context.Context, blk interfaces.ReadOn
|
||||
}
|
||||
|
||||
func validateDenebBeaconBlock(blk interfaces.ReadOnlyBeaconBlock) error {
|
||||
if blk.Version() < version.Deneb || blk.Version() >= version.Gloas {
|
||||
if blk.Version() < version.Deneb {
|
||||
return nil
|
||||
}
|
||||
commits, err := blk.Body().BlobKzgCommitments()
|
||||
@@ -411,10 +398,6 @@ func validateDenebBeaconBlock(blk interfaces.ReadOnlyBeaconBlock) error {
|
||||
// [IGNORE] The block's parent (defined by block.parent_root) passes all validation (including execution
|
||||
// node verification of the block.body.execution_payload).
|
||||
func (s *Service) validateBellatrixBeaconBlock(ctx context.Context, verifyingState state.ReadOnlyBeaconState, blk interfaces.ReadOnlyBeaconBlock) error {
|
||||
if blk.Version() >= version.Gloas {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Error if block and state are not the same version
|
||||
if verifyingState.Version() != blk.Version() {
|
||||
return errors.New("block and state are not the same version")
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
### Fixed
|
||||
- Avoid copying the full finalized state every time we compute cgc.
|
||||
2
changelog/potuz_remove_headstate.md
Normal file
2
changelog/potuz_remove_headstate.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Changed
|
||||
- Remove headState from fcuArgs.
|
||||
@@ -1,3 +0,0 @@
|
||||
### Added
|
||||
|
||||
- Add gossip beacon attestation validation conditions for Gloas fork
|
||||
@@ -1,3 +0,0 @@
|
||||
### Added
|
||||
|
||||
- Add Gloas beacon block gossip validation for execution payload bids
|
||||
Reference in New Issue
Block a user