RPC: Extend participation and performance to Altair (#9499)

* Add endpoints and tests

* Update beacon-chain/rpc/prysm/v1alpha1/beacon/validators_test.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
terence tsao
2021-09-02 11:42:04 -07:00
committed by GitHub
parent b10964514a
commit 1f48accb0e
3 changed files with 194 additions and 20 deletions

View File

@@ -19,6 +19,7 @@ go_library(
deps = [
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/cache/depositcache:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/epoch/precompute:go_default_library",
"//beacon-chain/core/feed:go_default_library",
@@ -49,6 +50,7 @@ go_library(
"//shared/params:go_default_library",
"//shared/sliceutil:go_default_library",
"//shared/slotutil:go_default_library",
"//shared/version:go_default_library",
"@com_github_patrickmn_go_cache//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",

View File

@@ -7,6 +7,7 @@ import (
"time"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core/altair"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
core "github.com/prysmaticlabs/prysm/beacon-chain/core/state"
@@ -17,6 +18,7 @@ import (
"github.com/prysmaticlabs/prysm/shared/cmd"
"github.com/prysmaticlabs/prysm/shared/pagination"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/version"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
@@ -521,14 +523,29 @@ func (bs *Server) GetValidatorParticipation(
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
}
v, b, err := precompute.New(ctx, beaconState)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not set up pre compute instance: %v", err)
}
_, b, err = precompute.ProcessAttestations(ctx, beaconState, v, b)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not pre compute attestations: %v", err)
var v []*precompute.Validator
var b *precompute.Balance
switch beaconState.Version() {
case version.Phase0:
v, b, err = precompute.New(ctx, beaconState)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not set up pre compute instance: %v", err)
}
_, b, err = precompute.ProcessAttestations(ctx, beaconState, v, b)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not pre compute attestations: %v", err)
}
case version.Altair:
v, b, err = altair.InitializeEpochValidators(ctx, beaconState)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not set up altair pre compute instance: %v", err)
}
_, b, err = altair.ProcessEpochParticipation(ctx, beaconState, b, v)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not pre compute attestations: %v", err)
}
default:
return nil, status.Errorf(codes.Internal, "Invalid state type retrieved with a version of %d", beaconState.Version())
}
p := &ethpb.ValidatorParticipationResponse{
@@ -662,19 +679,41 @@ func (bs *Server) GetValidatorPerformance(
return nil, status.Errorf(codes.Internal, "Could not process slots: %v", err)
}
}
vp, bp, err := precompute.New(ctx, headState)
if err != nil {
return nil, err
validatorSummary := []*precompute.Validator{}
switch headState.Version() {
case version.Phase0:
vp, bp, err := precompute.New(ctx, headState)
if err != nil {
return nil, err
}
vp, bp, err = precompute.ProcessAttestations(ctx, headState, vp, bp)
if err != nil {
return nil, err
}
headState, err = precompute.ProcessRewardsAndPenaltiesPrecompute(headState, bp, vp, precompute.AttestationsDelta, precompute.ProposersDelta)
if err != nil {
return nil, err
}
validatorSummary = vp
case version.Altair:
vp, bp, err := altair.InitializeEpochValidators(ctx, headState)
if err != nil {
return nil, err
}
vp, bp, err = altair.ProcessEpochParticipation(ctx, headState, bp, vp)
if err != nil {
return nil, err
}
headState, vp, err = altair.ProcessInactivityScores(ctx, headState, vp)
if err != nil {
return nil, err
}
headState, err = altair.ProcessRewardsAndPenaltiesPrecompute(headState, bp, vp)
if err != nil {
return nil, err
}
validatorSummary = vp
}
vp, bp, err = precompute.ProcessAttestations(ctx, headState, vp, bp)
if err != nil {
return nil, err
}
headState, err = precompute.ProcessRewardsAndPenaltiesPrecompute(headState, bp, vp, precompute.AttestationsDelta, precompute.ProposersDelta)
if err != nil {
return nil, err
}
validatorSummary := vp
responseCap := len(req.Indices) + len(req.PublicKeys)
validatorIndices := make([]types.ValidatorIndex, 0, responseCap)

View File

@@ -1677,6 +1677,71 @@ func TestServer_GetValidatorParticipation_OrphanedUntilGenesis(t *testing.T) {
assert.DeepEqual(t, wanted, res.Participation, "Incorrect validator participation respond")
}
func TestServer_GetValidatorParticipation_CurrentAndPrevEpochAltair(t *testing.T) {
helpers.ClearCache()
beaconDB := dbTest.SetupDB(t)
params.UseMainnetConfig()
ctx := context.Background()
validatorCount := uint64(32)
bits := make([]byte, validatorCount)
for i := range bits {
bits[i] = 0xff
}
headState, _ := testutil.DeterministicGenesisStateAltair(t, validatorCount)
require.NoError(t, headState.SetSlot(2*params.BeaconConfig().SlotsPerEpoch-1))
require.NoError(t, headState.SetCurrentParticipationBits(bits))
require.NoError(t, headState.SetPreviousParticipationBits(bits))
b := testutil.NewBeaconBlockAltair()
b.Block.Slot = 16
ab, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
require.NoError(t, beaconDB.SaveBlock(ctx, ab))
bRoot, err := b.Block.HashTreeRoot()
require.NoError(t, beaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Root: bRoot[:]}))
require.NoError(t, beaconDB.SaveStateSummary(ctx, &ethpb.StateSummary{Root: params.BeaconConfig().ZeroHash[:]}))
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, bRoot))
require.NoError(t, err)
require.NoError(t, beaconDB.SaveState(ctx, headState, bRoot))
m := &mock.ChainService{State: headState}
offset := int64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
bs := &Server{
BeaconDB: beaconDB,
HeadFetcher: m,
StateGen: stategen.New(beaconDB),
GenesisTimeFetcher: &mock.ChainService{
Genesis: timeutils.Now().Add(time.Duration(-1*offset) * time.Second),
},
CanonicalFetcher: &mock.ChainService{
CanonicalRoots: map[[32]byte]bool{
bRoot: true,
},
},
FinalizationFetcher: &mock.ChainService{FinalizedCheckPoint: &ethpb.Checkpoint{Epoch: 100}},
}
res, err := bs.GetValidatorParticipation(ctx, &ethpb.GetValidatorParticipationRequest{QueryFilter: &ethpb.GetValidatorParticipationRequest_Epoch{Epoch: 1}})
require.NoError(t, err)
wanted := &ethpb.ValidatorParticipation{
GlobalParticipationRate: 1,
VotedEther: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
EligibleEther: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
CurrentEpochActiveGwei: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
CurrentEpochAttestingGwei: params.BeaconConfig().EffectiveBalanceIncrement,
CurrentEpochTargetAttestingGwei: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
PreviousEpochActiveGwei: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
PreviousEpochAttestingGwei: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
PreviousEpochTargetAttestingGwei: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
PreviousEpochHeadAttestingGwei: validatorCount * params.BeaconConfig().MaxEffectiveBalance,
}
assert.DeepEqual(t, true, res.Finalized, "Incorrect validator participation respond")
assert.DeepEqual(t, wanted, res.Participation, "Incorrect validator participation respond")
}
func TestGetValidatorPerformance_Syncing(t *testing.T) {
ctx := context.Background()
@@ -1916,6 +1981,74 @@ func TestGetValidatorPerformance_IndicesPubkeys(t *testing.T) {
}
}
func TestGetValidatorPerformanceAltair_OK(t *testing.T) {
helpers.ClearCache()
params.UseMinimalConfig()
defer params.UseMainnetConfig()
ctx := context.Background()
epoch := types.Epoch(1)
headState, _ := testutil.DeterministicGenesisStateAltair(t, 32)
require.NoError(t, headState.SetSlot(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch+1))))
defaultBal := params.BeaconConfig().MaxEffectiveBalance
extraBal := params.BeaconConfig().MaxEffectiveBalance + params.BeaconConfig().GweiPerEth
balances := []uint64{defaultBal, extraBal, extraBal + params.BeaconConfig().GweiPerEth}
require.NoError(t, headState.SetBalances(balances))
publicKey1 := bytesutil.ToBytes48([]byte{1})
publicKey2 := bytesutil.ToBytes48([]byte{2})
publicKey3 := bytesutil.ToBytes48([]byte{3})
validators := []*ethpb.Validator{
{
PublicKey: publicKey1[:],
ActivationEpoch: 5,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
},
{
PublicKey: publicKey2[:],
EffectiveBalance: defaultBal,
ActivationEpoch: 0,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
},
{
PublicKey: publicKey3[:],
EffectiveBalance: defaultBal,
ActivationEpoch: 0,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
},
}
require.NoError(t, headState.SetValidators(validators))
require.NoError(t, headState.SetBalances([]uint64{100, 101, 102}))
offset := int64(headState.Slot().Mul(params.BeaconConfig().SecondsPerSlot))
bs := &Server{
HeadFetcher: &mock.ChainService{
State: headState,
},
GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)},
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
want := &ethpb.ValidatorPerformanceResponse{
PublicKeys: [][]byte{publicKey2[:], publicKey3[:]},
CurrentEffectiveBalances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance},
InclusionSlots: []types.Slot{0, 0},
InclusionDistances: []types.Slot{0, 0},
CorrectlyVotedSource: []bool{false, false},
CorrectlyVotedTarget: []bool{false, false},
CorrectlyVotedHead: []bool{false, false},
BalancesBeforeEpochTransition: []uint64{101, 102},
BalancesAfterEpochTransition: []uint64{0, 0},
MissingValidators: [][]byte{publicKey1[:]},
}
res, err := bs.GetValidatorPerformance(ctx, &ethpb.ValidatorPerformanceRequest{
PublicKeys: [][]byte{publicKey1[:], publicKey3[:], publicKey2[:]},
})
require.NoError(t, err)
if !proto.Equal(want, res) {
t.Errorf("Wanted %v\nReceived %v", want, res)
}
}
func BenchmarkListValidatorBalances(b *testing.B) {
b.StopTimer()
beaconDB := dbTest.SetupDB(b)