Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing pieces of Electra #14227

Merged
merged 2 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion beacon-chain/blockchain/execution_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState,

var attr payloadattribute.Attributer
switch st.Version() {
case version.Deneb:
case version.Deneb, version.Electra:
withdrawals, _, err := st.ExpectedWithdrawals()
if err != nil {
log.WithError(err).Error("Could not get expected withdrawals to get payload attribute")
Expand Down
88 changes: 55 additions & 33 deletions beacon-chain/blockchain/execution_engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -855,41 +855,63 @@ func Test_GetPayloadAttributeV2(t *testing.T) {
require.Equal(t, 0, len(a))
}

func Test_GetPayloadAttributeDeneb(t *testing.T) {
service, tr := minimalTestService(t, WithPayloadIDCache(cache.NewPayloadIDCache()))
ctx := tr.ctx

st, _ := util.DeterministicGenesisStateDeneb(t, 1)
attr := service.getPayloadAttribute(ctx, st, 0, []byte{})
require.Equal(t, true, attr.IsEmpty())

// Cache hit, advance state, no fee recipient
slot := primitives.Slot(1)
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0})
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
require.Equal(t, false, attr.IsEmpty())
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
a, err := attr.Withdrawals()
require.NoError(t, err)
require.Equal(t, 0, len(a))

// Cache hit, advance state, has fee recipient
suggestedAddr := common.HexToAddress("123")
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0})
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
attr = service.getPayloadAttribute(ctx, st, slot, params.BeaconConfig().ZeroHash[:])
require.Equal(t, false, attr.IsEmpty())
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
a, err = attr.Withdrawals()
require.NoError(t, err)
require.Equal(t, 0, len(a))
func Test_GetPayloadAttributeV3(t *testing.T) {
var testCases = []struct {
name string
st bstate.BeaconState
}{
{
name: "deneb",
st: func() bstate.BeaconState {
st, _ := util.DeterministicGenesisStateDeneb(t, 1)
return st
}(),
},
{
name: "electra",
st: func() bstate.BeaconState {
st, _ := util.DeterministicGenesisStateElectra(t, 1)
return st
}(),
},
}

attrV3, err := attr.PbV3()
require.NoError(t, err)
hr := service.headRoot()
require.Equal(t, hr, [32]byte(attrV3.ParentBeaconBlockRoot))
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
service, tr := minimalTestService(t, WithPayloadIDCache(cache.NewPayloadIDCache()))
ctx := tr.ctx

attr := service.getPayloadAttribute(ctx, test.st, 0, []byte{})
require.Equal(t, true, attr.IsEmpty())

// Cache hit, advance state, no fee recipient
slot := primitives.Slot(1)
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, Index: 0})
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
attr = service.getPayloadAttribute(ctx, test.st, slot, params.BeaconConfig().ZeroHash[:])
require.Equal(t, false, attr.IsEmpty())
require.Equal(t, params.BeaconConfig().EthBurnAddressHex, common.BytesToAddress(attr.SuggestedFeeRecipient()).String())
a, err := attr.Withdrawals()
require.NoError(t, err)
require.Equal(t, 0, len(a))

// Cache hit, advance state, has fee recipient
suggestedAddr := common.HexToAddress("123")
service.cfg.TrackedValidatorsCache.Set(cache.TrackedValidator{Active: true, FeeRecipient: primitives.ExecutionAddress(suggestedAddr), Index: 0})
service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{})
attr = service.getPayloadAttribute(ctx, test.st, slot, params.BeaconConfig().ZeroHash[:])
require.Equal(t, false, attr.IsEmpty())
require.Equal(t, suggestedAddr, common.BytesToAddress(attr.SuggestedFeeRecipient()))
a, err = attr.Withdrawals()
require.NoError(t, err)
require.Equal(t, 0, len(a))

attrV3, err := attr.PbV3()
require.NoError(t, err)
hr := service.headRoot()
require.Equal(t, hr, [32]byte(attrV3.ParentBeaconBlockRoot))
})
}
}

func Test_UpdateLastValidatedCheckpoint(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions beacon-chain/db/kv/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ func isSSZStorageFormat(obj interface{}) bool {
return true
case *ethpb.BeaconBlock:
return true
case *ethpb.Attestation:
case *ethpb.Attestation, *ethpb.AttestationElectra:
return true
case *ethpb.Deposit:
return true
case *ethpb.AttesterSlashing:
case *ethpb.AttesterSlashing, *ethpb.AttesterSlashingElectra:
return true
case *ethpb.ProposerSlashing:
return true
Expand Down
11 changes: 8 additions & 3 deletions beacon-chain/rpc/core/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,13 +368,18 @@ func (s *Service) GetAttestationData(
return nil, &RpcError{Reason: BadRequest, Err: errors.Errorf("invalid request: %v", err)}
}

committeeIndex := primitives.CommitteeIndex(0)
if slots.ToEpoch(req.Slot) < params.BeaconConfig().ElectraForkEpoch {
committeeIndex = req.CommitteeIndex
}

s.AttestationCache.RLock()
res := s.AttestationCache.Get()
if res != nil && res.Slot == req.Slot {
s.AttestationCache.RUnlock()
return &ethpb.AttestationData{
Slot: res.Slot,
CommitteeIndex: req.CommitteeIndex,
CommitteeIndex: committeeIndex,
BeaconBlockRoot: res.HeadRoot,
Source: &ethpb.Checkpoint{
Epoch: res.Source.Epoch,
Expand All @@ -398,7 +403,7 @@ func (s *Service) GetAttestationData(
if res != nil && res.Slot == req.Slot {
return &ethpb.AttestationData{
Slot: res.Slot,
CommitteeIndex: req.CommitteeIndex,
CommitteeIndex: committeeIndex,
BeaconBlockRoot: res.HeadRoot,
Source: &ethpb.Checkpoint{
Epoch: res.Source.Epoch,
Expand Down Expand Up @@ -458,7 +463,7 @@ func (s *Service) GetAttestationData(

return &ethpb.AttestationData{
Slot: req.Slot,
CommitteeIndex: req.CommitteeIndex,
CommitteeIndex: committeeIndex,
BeaconBlockRoot: headRoot,
Source: &ethpb.Checkpoint{
Epoch: justifiedCheckpoint.Epoch,
Expand Down
68 changes: 68 additions & 0 deletions beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,74 @@ func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) {
}
}

func TestGetAttestationData_CommitteeIndexIsZeroPostElectra(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
cfg.ElectraForkEpoch = 0
params.OverrideBeaconConfig(cfg)

block := util.NewBeaconBlock()
block.Block.Slot = 3*params.BeaconConfig().SlotsPerEpoch + 1
targetBlock := util.NewBeaconBlock()
targetBlock.Block.Slot = params.BeaconConfig().SlotsPerEpoch
targetRoot, err := targetBlock.Block.HashTreeRoot()
require.NoError(t, err)

justifiedBlock := util.NewBeaconBlock()
justifiedBlock.Block.Slot = 2 * params.BeaconConfig().SlotsPerEpoch
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err)
justifiedRoot, err := justifiedBlock.Block.HashTreeRoot()
require.NoError(t, err)
slot := 3*params.BeaconConfig().SlotsPerEpoch + 1
beaconState, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, beaconState.SetSlot(slot))
justifiedCheckpoint := &ethpb.Checkpoint{
Epoch: 2,
Root: justifiedRoot[:],
}
require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(justifiedCheckpoint))
offset := int64(slot.Mul(params.BeaconConfig().SecondsPerSlot))
attesterServer := &Server{
SyncChecker: &mockSync.Sync{IsSyncing: false},
OptimisticModeFetcher: &mock.ChainService{Optimistic: false},
TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
CoreService: &core.Service{
HeadFetcher: &mock.ChainService{TargetRoot: targetRoot, Root: blockRoot[:], State: beaconState},
GenesisTimeFetcher: &mock.ChainService{
Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second),
},
FinalizedFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: justifiedCheckpoint},
AttestationCache: cache.NewAttestationCache(),
OptimisticModeFetcher: &mock.ChainService{Optimistic: false},
},
}

req := &ethpb.AttestationDataRequest{
CommitteeIndex: 123, // set non-zero committee index
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
}
res, err := attesterServer.GetAttestationData(context.Background(), req)
require.NoError(t, err)

expected := &ethpb.AttestationData{
Slot: 3*params.BeaconConfig().SlotsPerEpoch + 1,
CommitteeIndex: 0,
BeaconBlockRoot: blockRoot[:],
Source: &ethpb.Checkpoint{
Epoch: 2,
Root: justifiedRoot[:],
},
Target: &ethpb.Checkpoint{
Epoch: 3,
Root: targetRoot[:],
},
}

assert.DeepEqual(t, expected, res)
}

func TestServer_SubscribeCommitteeSubnets_NoSlots(t *testing.T) {
attesterServer := &Server{
HeadFetcher: &mock.ChainService{},
Expand Down
14 changes: 7 additions & 7 deletions validator/db/filesystem/attester_protection.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (s *Store) AttestedPublicKeys(_ context.Context) ([][fieldparams.BLSPubkeyL
// If it is not, it updates the database.
func (s *Store) SlashableAttestationCheck(
ctx context.Context,
indexedAtt *ethpb.IndexedAttestation,
indexedAtt ethpb.IndexedAtt,
pubKey [fieldparams.BLSPubkeyLength]byte,
signingRoot32 [32]byte,
_ bool,
Expand Down Expand Up @@ -128,10 +128,10 @@ func (s *Store) SaveAttestationForPubKey(
_ context.Context,
pubkey [fieldparams.BLSPubkeyLength]byte,
_ [32]byte,
att *ethpb.IndexedAttestation,
att ethpb.IndexedAtt,
) error {
// If there is no attestation, return on error.
if att == nil || att.Data == nil || att.Data.Source == nil || att.Data.Target == nil {
if att == nil || att.GetData() == nil || att.GetData().Source == nil || att.GetData().Target == nil {
return errors.New("incoming attestation does not contain source and/or target epoch")
}

Expand All @@ -141,8 +141,8 @@ func (s *Store) SaveAttestationForPubKey(
return errors.Wrap(err, "could not get validator slashing protection")
}

incomingSourceEpochUInt64 := uint64(att.Data.Source.Epoch)
incomingTargetEpochUInt64 := uint64(att.Data.Target.Epoch)
incomingSourceEpochUInt64 := uint64(att.GetData().Source.Epoch)
incomingTargetEpochUInt64 := uint64(att.GetData().Target.Epoch)

if validatorSlashingProtection == nil {
// If there is no validator slashing protection, create one.
Expand All @@ -167,7 +167,7 @@ func (s *Store) SaveAttestationForPubKey(
if incomingSourceEpochUInt64 < savedSourceEpoch {
return errors.Errorf(
"could not sign attestation with source lower than recorded source epoch, %d < %d",
att.Data.Source.Epoch,
att.GetData().Source.Epoch,
validatorSlashingProtection.LastSignedAttestationSourceEpoch,
)
}
Expand All @@ -177,7 +177,7 @@ func (s *Store) SaveAttestationForPubKey(
if savedTargetEpoch != nil && incomingTargetEpochUInt64 <= *savedTargetEpoch {
return errors.Errorf(
"could not sign attestation with target lower than or equal to recorded target epoch, %d <= %d",
att.Data.Target.Epoch,
att.GetData().Target.Epoch,
*savedTargetEpoch,
)
}
Expand Down
4 changes: 2 additions & 2 deletions validator/db/iface/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ type ValidatorDB interface {
LowestSignedSourceEpoch(ctx context.Context, publicKey [fieldparams.BLSPubkeyLength]byte) (primitives.Epoch, bool, error)
AttestedPublicKeys(ctx context.Context) ([][fieldparams.BLSPubkeyLength]byte, error)
SlashableAttestationCheck(
ctx context.Context, indexedAtt *ethpb.IndexedAttestation, pubKey [fieldparams.BLSPubkeyLength]byte,
ctx context.Context, indexedAtt ethpb.IndexedAtt, pubKey [fieldparams.BLSPubkeyLength]byte,
signingRoot32 [32]byte,
emitAccountMetrics bool,
validatorAttestFailVec *prometheus.CounterVec,
) error
SaveAttestationForPubKey(
ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte, signingRoot [fieldparams.RootLength]byte, att *ethpb.IndexedAttestation,
ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte, signingRoot [fieldparams.RootLength]byte, att ethpb.IndexedAtt,
) error
SaveAttestationsForPubKey(
ctx context.Context, pubKey [fieldparams.BLSPubkeyLength]byte, signingRoots [][]byte, atts []*ethpb.IndexedAttestation,
Expand Down
Loading
Loading