mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 23:48:06 -05:00
Optimize GetDuties VC action (#13789)
* wait groups * errgroup * tests * bzl * review
This commit is contained in:
@@ -66,6 +66,7 @@ go_library(
|
|||||||
"@com_github_sirupsen_logrus//:go_default_library",
|
"@com_github_sirupsen_logrus//:go_default_library",
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||||
|
"@org_golang_x_sync//errgroup:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -129,7 +130,6 @@ go_test(
|
|||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
"//testing/assert:go_default_library",
|
"//testing/assert:go_default_library",
|
||||||
"//testing/require:go_default_library",
|
"//testing/require:go_default_library",
|
||||||
"//testing/validator-mock:go_default_library",
|
|
||||||
"//time/slots:go_default_library",
|
"//time/slots:go_default_library",
|
||||||
"//validator/client/beacon-api/mock:go_default_library",
|
"//validator/client/beacon-api/mock:go_default_library",
|
||||||
"//validator/client/beacon-api/test-helpers:go_default_library",
|
"//validator/client/beacon-api/test-helpers:go_default_library",
|
||||||
|
|||||||
@@ -8,11 +8,14 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||||
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dutiesProvider interface {
|
type dutiesProvider interface {
|
||||||
@@ -31,37 +34,42 @@ type committeeIndexSlotPair struct {
|
|||||||
slot primitives.Slot
|
slot primitives.Slot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type validatorForDuty struct {
|
||||||
|
pubkey []byte
|
||||||
|
index primitives.ValidatorIndex
|
||||||
|
status ethpb.ValidatorStatus
|
||||||
|
}
|
||||||
|
|
||||||
func (c beaconApiValidatorClient) getDuties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.DutiesResponse, error) {
|
func (c beaconApiValidatorClient) getDuties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.DutiesResponse, error) {
|
||||||
all, err := c.multipleValidatorStatus(ctx, ðpb.MultipleValidatorStatusRequest{PublicKeys: in.PublicKeys})
|
vals, err := c.getValidatorsForDuties(ctx, in.PublicKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to get validator status")
|
return nil, errors.Wrap(err, "failed to get validators for duties")
|
||||||
}
|
|
||||||
known := ðpb.MultipleValidatorStatusResponse{
|
|
||||||
PublicKeys: make([][]byte, 0, len(all.PublicKeys)),
|
|
||||||
Statuses: make([]*ethpb.ValidatorStatusResponse, 0, len(all.Statuses)),
|
|
||||||
Indices: make([]primitives.ValidatorIndex, 0, len(all.Indices)),
|
|
||||||
}
|
|
||||||
for i, status := range all.Statuses {
|
|
||||||
if status.Status != ethpb.ValidatorStatus_UNKNOWN_STATUS {
|
|
||||||
known.PublicKeys = append(known.PublicKeys, all.PublicKeys[i])
|
|
||||||
known.Statuses = append(known.Statuses, all.Statuses[i])
|
|
||||||
known.Indices = append(known.Indices, all.Indices[i])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync committees are an Altair feature
|
// Sync committees are an Altair feature
|
||||||
fetchSyncDuties := in.Epoch >= params.BeaconConfig().AltairForkEpoch
|
fetchSyncDuties := in.Epoch >= params.BeaconConfig().AltairForkEpoch
|
||||||
|
|
||||||
currentEpochDuties, err := c.getDutiesForEpoch(ctx, in.Epoch, known, fetchSyncDuties)
|
errCh := make(chan error, 1)
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to get duties for current epoch `%d`", in.Epoch)
|
|
||||||
}
|
|
||||||
|
|
||||||
nextEpochDuties, err := c.getDutiesForEpoch(ctx, in.Epoch+1, known, fetchSyncDuties)
|
var currentEpochDuties []*ethpb.DutiesResponse_Duty
|
||||||
|
go func() {
|
||||||
|
currentEpochDuties, err = c.getDutiesForEpoch(ctx, in.Epoch, vals, fetchSyncDuties)
|
||||||
|
if err != nil {
|
||||||
|
errCh <- errors.Wrapf(err, "failed to get duties for current epoch `%d`", in.Epoch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
errCh <- nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
nextEpochDuties, err := c.getDutiesForEpoch(ctx, in.Epoch+1, vals, fetchSyncDuties)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to get duties for next epoch `%d`", in.Epoch+1)
|
return nil, errors.Wrapf(err, "failed to get duties for next epoch `%d`", in.Epoch+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = <-errCh; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return ðpb.DutiesResponse{
|
return ðpb.DutiesResponse{
|
||||||
CurrentEpochDuties: currentEpochDuties,
|
CurrentEpochDuties: currentEpochDuties,
|
||||||
NextEpochDuties: nextEpochDuties,
|
NextEpochDuties: nextEpochDuties,
|
||||||
@@ -71,25 +79,94 @@ func (c beaconApiValidatorClient) getDuties(ctx context.Context, in *ethpb.Dutie
|
|||||||
func (c beaconApiValidatorClient) getDutiesForEpoch(
|
func (c beaconApiValidatorClient) getDutiesForEpoch(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
epoch primitives.Epoch,
|
epoch primitives.Epoch,
|
||||||
multipleValidatorStatus *ethpb.MultipleValidatorStatusResponse,
|
vals []validatorForDuty,
|
||||||
fetchSyncDuties bool,
|
fetchSyncDuties bool,
|
||||||
) ([]*ethpb.DutiesResponse_Duty, error) {
|
) ([]*ethpb.DutiesResponse_Duty, error) {
|
||||||
attesterDuties, err := c.dutiesProvider.GetAttesterDuties(ctx, epoch, multipleValidatorStatus.Indices)
|
indices := make([]primitives.ValidatorIndex, len(vals))
|
||||||
if err != nil {
|
for i, v := range vals {
|
||||||
return nil, errors.Wrapf(err, "failed to get attester duties for epoch `%d`", epoch)
|
indices[i] = v.index
|
||||||
}
|
}
|
||||||
|
|
||||||
var syncDuties []*structs.SyncCommitteeDuty
|
// Below variables MUST NOT be used in the main function before wg.Wait().
|
||||||
if fetchSyncDuties {
|
// This is because they are populated in goroutines and wg.Wait()
|
||||||
if syncDuties, err = c.dutiesProvider.GetSyncDuties(ctx, epoch, multipleValidatorStatus.Indices); err != nil {
|
// will return only once all goroutines finish their execution.
|
||||||
return nil, errors.Wrapf(err, "failed to get sync duties for epoch `%d`", epoch)
|
|
||||||
|
// Mapping from a validator index to its attesting committee's index and slot
|
||||||
|
attesterDutiesMapping := make(map[primitives.ValidatorIndex]committeeIndexSlotPair)
|
||||||
|
// Set containing all validator indices that are part of a sync committee for this epoch
|
||||||
|
syncDutiesMapping := make(map[primitives.ValidatorIndex]bool)
|
||||||
|
// Mapping from a validator index to its proposal slot
|
||||||
|
proposerDutySlots := make(map[primitives.ValidatorIndex][]primitives.Slot)
|
||||||
|
// Mapping from the {committeeIndex, slot} to each of the committee's validator indices
|
||||||
|
committeeMapping := make(map[committeeIndexSlotPair][]primitives.ValidatorIndex)
|
||||||
|
|
||||||
|
var wg errgroup.Group
|
||||||
|
|
||||||
|
wg.Go(func() error {
|
||||||
|
attesterDuties, err := c.dutiesProvider.GetAttesterDuties(ctx, epoch, indices)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to get attester duties for epoch `%d`", epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, attesterDuty := range attesterDuties {
|
||||||
|
validatorIndex, err := strconv.ParseUint(attesterDuty.ValidatorIndex, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to parse attester validator index `%s`", attesterDuty.ValidatorIndex)
|
||||||
|
}
|
||||||
|
slot, err := strconv.ParseUint(attesterDuty.Slot, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to parse attester slot `%s`", attesterDuty.Slot)
|
||||||
|
}
|
||||||
|
committeeIndex, err := strconv.ParseUint(attesterDuty.CommitteeIndex, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to parse attester committee index `%s`", attesterDuty.CommitteeIndex)
|
||||||
|
}
|
||||||
|
attesterDutiesMapping[primitives.ValidatorIndex(validatorIndex)] = committeeIndexSlotPair{
|
||||||
|
slot: primitives.Slot(slot),
|
||||||
|
committeeIndex: primitives.CommitteeIndex(committeeIndex),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if fetchSyncDuties {
|
||||||
|
wg.Go(func() error {
|
||||||
|
syncDuties, err := c.dutiesProvider.GetSyncDuties(ctx, epoch, indices)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to get sync duties for epoch `%d`", epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, syncDuty := range syncDuties {
|
||||||
|
validatorIndex, err := strconv.ParseUint(syncDuty.ValidatorIndex, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to parse sync validator index `%s`", syncDuty.ValidatorIndex)
|
||||||
|
}
|
||||||
|
syncDutiesMapping[primitives.ValidatorIndex(validatorIndex)] = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var proposerDuties []*structs.ProposerDuty
|
wg.Go(func() error {
|
||||||
if proposerDuties, err = c.dutiesProvider.GetProposerDuties(ctx, epoch); err != nil {
|
proposerDuties, err := c.dutiesProvider.GetProposerDuties(ctx, epoch)
|
||||||
return nil, errors.Wrapf(err, "failed to get proposer duties for epoch `%d`", epoch)
|
if err != nil {
|
||||||
}
|
return errors.Wrapf(err, "failed to get proposer duties for epoch `%d`", epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, proposerDuty := range proposerDuties {
|
||||||
|
validatorIndex, err := strconv.ParseUint(proposerDuty.ValidatorIndex, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to parse proposer validator index `%s`", proposerDuty.ValidatorIndex)
|
||||||
|
}
|
||||||
|
slot, err := strconv.ParseUint(proposerDuty.Slot, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to parse proposer slot `%s`", proposerDuty.Slot)
|
||||||
|
}
|
||||||
|
proposerDutySlots[primitives.ValidatorIndex(validatorIndex)] =
|
||||||
|
append(proposerDutySlots[primitives.ValidatorIndex(validatorIndex)], primitives.Slot(slot))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
committees, err := c.dutiesProvider.GetCommittees(ctx, epoch)
|
committees, err := c.dutiesProvider.GetCommittees(ctx, epoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -104,70 +181,15 @@ func (c beaconApiValidatorClient) getDutiesForEpoch(
|
|||||||
slotCommittees[c.Slot] = n + 1
|
slotCommittees[c.Slot] = n + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mapping from a validator index to its attesting committee's index and slot
|
|
||||||
attesterDutiesMapping := make(map[primitives.ValidatorIndex]committeeIndexSlotPair)
|
|
||||||
for _, attesterDuty := range attesterDuties {
|
|
||||||
validatorIndex, err := strconv.ParseUint(attesterDuty.ValidatorIndex, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to parse attester validator index `%s`", attesterDuty.ValidatorIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
slot, err := strconv.ParseUint(attesterDuty.Slot, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to parse attester slot `%s`", attesterDuty.Slot)
|
|
||||||
}
|
|
||||||
|
|
||||||
committeeIndex, err := strconv.ParseUint(attesterDuty.CommitteeIndex, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to parse attester committee index `%s`", attesterDuty.CommitteeIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
attesterDutiesMapping[primitives.ValidatorIndex(validatorIndex)] = committeeIndexSlotPair{
|
|
||||||
slot: primitives.Slot(slot),
|
|
||||||
committeeIndex: primitives.CommitteeIndex(committeeIndex),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mapping from a validator index to its proposal slot
|
|
||||||
proposerDutySlots := make(map[primitives.ValidatorIndex][]primitives.Slot)
|
|
||||||
for _, proposerDuty := range proposerDuties {
|
|
||||||
validatorIndex, err := strconv.ParseUint(proposerDuty.ValidatorIndex, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to parse proposer validator index `%s`", proposerDuty.ValidatorIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
slot, err := strconv.ParseUint(proposerDuty.Slot, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to parse proposer slot `%s`", proposerDuty.Slot)
|
|
||||||
}
|
|
||||||
|
|
||||||
proposerDutySlots[primitives.ValidatorIndex(validatorIndex)] = append(proposerDutySlots[primitives.ValidatorIndex(validatorIndex)], primitives.Slot(slot))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set containing all validator indices that are part of a sync committee for this epoch
|
|
||||||
syncDutiesMapping := make(map[primitives.ValidatorIndex]bool)
|
|
||||||
for _, syncDuty := range syncDuties {
|
|
||||||
validatorIndex, err := strconv.ParseUint(syncDuty.ValidatorIndex, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to parse sync validator index `%s`", syncDuty.ValidatorIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
syncDutiesMapping[primitives.ValidatorIndex(validatorIndex)] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mapping from the {committeeIndex, slot} to each of the committee's validator indices
|
|
||||||
committeeMapping := make(map[committeeIndexSlotPair][]primitives.ValidatorIndex)
|
|
||||||
for _, committee := range committees {
|
for _, committee := range committees {
|
||||||
committeeIndex, err := strconv.ParseUint(committee.Index, 10, 64)
|
committeeIndex, err := strconv.ParseUint(committee.Index, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to parse committee index `%s`", committee.Index)
|
return nil, errors.Wrapf(err, "failed to parse committee index `%s`", committee.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
slot, err := strconv.ParseUint(committee.Slot, 10, 64)
|
slot, err := strconv.ParseUint(committee.Slot, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to parse slot `%s`", committee.Slot)
|
return nil, errors.Wrapf(err, "failed to parse slot `%s`", committee.Slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
validatorIndices := make([]primitives.ValidatorIndex, len(committee.Validators))
|
validatorIndices := make([]primitives.ValidatorIndex, len(committee.Validators))
|
||||||
for index, validatorIndexString := range committee.Validators {
|
for index, validatorIndexString := range committee.Validators {
|
||||||
validatorIndex, err := strconv.ParseUint(validatorIndexString, 10, 64)
|
validatorIndex, err := strconv.ParseUint(validatorIndexString, 10, 64)
|
||||||
@@ -176,7 +198,6 @@ func (c beaconApiValidatorClient) getDutiesForEpoch(
|
|||||||
}
|
}
|
||||||
validatorIndices[index] = primitives.ValidatorIndex(validatorIndex)
|
validatorIndices[index] = primitives.ValidatorIndex(validatorIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
key := committeeIndexSlotPair{
|
key := committeeIndexSlotPair{
|
||||||
committeeIndex: primitives.CommitteeIndex(committeeIndex),
|
committeeIndex: primitives.CommitteeIndex(committeeIndex),
|
||||||
slot: primitives.Slot(slot),
|
slot: primitives.Slot(slot),
|
||||||
@@ -184,16 +205,19 @@ func (c beaconApiValidatorClient) getDutiesForEpoch(
|
|||||||
committeeMapping[key] = validatorIndices
|
committeeMapping[key] = validatorIndices
|
||||||
}
|
}
|
||||||
|
|
||||||
duties := make([]*ethpb.DutiesResponse_Duty, len(multipleValidatorStatus.Statuses))
|
if err = wg.Wait(); err != nil {
|
||||||
for index, validatorStatus := range multipleValidatorStatus.Statuses {
|
return nil, err
|
||||||
validatorIndex := multipleValidatorStatus.Indices[index]
|
}
|
||||||
pubkey := multipleValidatorStatus.PublicKeys[index]
|
|
||||||
|
|
||||||
var attesterSlot primitives.Slot
|
duties := make([]*ethpb.DutiesResponse_Duty, len(vals))
|
||||||
var committeeIndex primitives.CommitteeIndex
|
for i, v := range vals {
|
||||||
var committeeValidatorIndices []primitives.ValidatorIndex
|
var (
|
||||||
|
attesterSlot primitives.Slot
|
||||||
|
committeeIndex primitives.CommitteeIndex
|
||||||
|
committeeValidatorIndices []primitives.ValidatorIndex
|
||||||
|
)
|
||||||
|
|
||||||
if committeeMappingKey, ok := attesterDutiesMapping[validatorIndex]; ok {
|
if committeeMappingKey, ok := attesterDutiesMapping[v.index]; ok {
|
||||||
committeeIndex = committeeMappingKey.committeeIndex
|
committeeIndex = committeeMappingKey.committeeIndex
|
||||||
attesterSlot = committeeMappingKey.slot
|
attesterSlot = committeeMappingKey.slot
|
||||||
|
|
||||||
@@ -202,15 +226,15 @@ func (c beaconApiValidatorClient) getDutiesForEpoch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
duties[index] = ðpb.DutiesResponse_Duty{
|
duties[i] = ðpb.DutiesResponse_Duty{
|
||||||
Committee: committeeValidatorIndices,
|
Committee: committeeValidatorIndices,
|
||||||
CommitteeIndex: committeeIndex,
|
CommitteeIndex: committeeIndex,
|
||||||
AttesterSlot: attesterSlot,
|
AttesterSlot: attesterSlot,
|
||||||
ProposerSlots: proposerDutySlots[validatorIndex],
|
ProposerSlots: proposerDutySlots[v.index],
|
||||||
PublicKey: pubkey,
|
PublicKey: v.pubkey,
|
||||||
Status: validatorStatus.Status,
|
Status: v.status,
|
||||||
ValidatorIndex: validatorIndex,
|
ValidatorIndex: v.index,
|
||||||
IsSyncCommittee: syncDutiesMapping[validatorIndex],
|
IsSyncCommittee: syncDutiesMapping[v.index],
|
||||||
CommitteesAtSlot: slotCommittees[strconv.FormatUint(uint64(attesterSlot), 10)],
|
CommitteesAtSlot: slotCommittees[strconv.FormatUint(uint64(attesterSlot), 10)],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,6 +242,51 @@ func (c beaconApiValidatorClient) getDutiesForEpoch(
|
|||||||
return duties, nil
|
return duties, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *beaconApiValidatorClient) getValidatorsForDuties(ctx context.Context, pubkeys [][]byte) ([]validatorForDuty, error) {
|
||||||
|
vals := make([]validatorForDuty, 0, len(pubkeys))
|
||||||
|
stringPubkeysToPubkeys := make(map[string][]byte, len(pubkeys))
|
||||||
|
stringPubkeys := make([]string, len(pubkeys))
|
||||||
|
|
||||||
|
for i, pk := range pubkeys {
|
||||||
|
stringPk := hexutil.Encode(pk)
|
||||||
|
stringPubkeysToPubkeys[stringPk] = pk
|
||||||
|
stringPubkeys[i] = stringPk
|
||||||
|
}
|
||||||
|
|
||||||
|
statusesWithDuties := []string{validator.ActiveOngoing.String(), validator.ActiveExiting.String()}
|
||||||
|
stateValidatorsResponse, err := c.stateValidatorsProvider.GetStateValidators(ctx, stringPubkeys, nil, statusesWithDuties)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to get state validators")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, validatorContainer := range stateValidatorsResponse.Data {
|
||||||
|
val := validatorForDuty{}
|
||||||
|
|
||||||
|
validatorIndex, err := strconv.ParseUint(validatorContainer.Index, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to parse validator index %s", validatorContainer.Index)
|
||||||
|
}
|
||||||
|
val.index = primitives.ValidatorIndex(validatorIndex)
|
||||||
|
|
||||||
|
stringPubkey := validatorContainer.Validator.Pubkey
|
||||||
|
pubkey, ok := stringPubkeysToPubkeys[stringPubkey]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.Wrapf(err, "returned public key %s not requested", stringPubkey)
|
||||||
|
}
|
||||||
|
val.pubkey = pubkey
|
||||||
|
|
||||||
|
status, ok := beaconAPITogRPCValidatorStatus[validatorContainer.Status]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("invalid validator status " + validatorContainer.Status)
|
||||||
|
}
|
||||||
|
val.status = status
|
||||||
|
|
||||||
|
vals = append(vals, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vals, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetCommittees retrieves the committees for the given epoch
|
// GetCommittees retrieves the committees for the given epoch
|
||||||
func (c beaconApiDutiesProvider) GetCommittees(ctx context.Context, epoch primitives.Epoch) ([]*structs.Committee, error) {
|
func (c beaconApiDutiesProvider) GetCommittees(ctx context.Context, epoch primitives.Epoch) ([]*structs.Committee, error) {
|
||||||
committeeParams := url.Values{}
|
committeeParams := url.Values{}
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
|
||||||
validatormock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock"
|
|
||||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||||
@@ -541,7 +538,6 @@ func TestGetDutiesForEpoch_Error(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "get proposer duties failed",
|
name: "get proposer duties failed",
|
||||||
expectedError: "failed to get proposer duties for epoch `1`: foo error",
|
expectedError: "failed to get proposer duties for epoch `1`: foo error",
|
||||||
fetchAttesterDutiesError: nil,
|
|
||||||
fetchProposerDutiesError: errors.New("foo error"),
|
fetchProposerDutiesError: errors.New("foo error"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -720,28 +716,20 @@ func TestGetDutiesForEpoch_Error(t *testing.T) {
|
|||||||
testCase.fetchCommitteesError,
|
testCase.fetchCommitteesError,
|
||||||
).AnyTimes()
|
).AnyTimes()
|
||||||
|
|
||||||
|
vals := make([]validatorForDuty, len(pubkeys))
|
||||||
|
for i := 0; i < len(pubkeys); i++ {
|
||||||
|
vals[i] = validatorForDuty{
|
||||||
|
pubkey: pubkeys[i],
|
||||||
|
index: validatorIndices[i],
|
||||||
|
status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validatorClient := &beaconApiValidatorClient{dutiesProvider: dutiesProvider}
|
validatorClient := &beaconApiValidatorClient{dutiesProvider: dutiesProvider}
|
||||||
_, err := validatorClient.getDutiesForEpoch(
|
_, err := validatorClient.getDutiesForEpoch(
|
||||||
ctx,
|
ctx,
|
||||||
epoch,
|
epoch,
|
||||||
ðpb.MultipleValidatorStatusResponse{
|
vals,
|
||||||
PublicKeys: pubkeys,
|
|
||||||
Indices: validatorIndices,
|
|
||||||
Statuses: []*ethpb.ValidatorStatusResponse{
|
|
||||||
{Status: ethpb.ValidatorStatus_UNKNOWN_STATUS},
|
|
||||||
{Status: ethpb.ValidatorStatus_DEPOSITED},
|
|
||||||
{Status: ethpb.ValidatorStatus_PENDING},
|
|
||||||
{Status: ethpb.ValidatorStatus_ACTIVE},
|
|
||||||
{Status: ethpb.ValidatorStatus_EXITING},
|
|
||||||
{Status: ethpb.ValidatorStatus_SLASHING},
|
|
||||||
{Status: ethpb.ValidatorStatus_EXITED},
|
|
||||||
{Status: ethpb.ValidatorStatus_INVALID},
|
|
||||||
{Status: ethpb.ValidatorStatus_PARTIALLY_DEPOSITED},
|
|
||||||
{Status: ethpb.ValidatorStatus_UNKNOWN_STATUS},
|
|
||||||
{Status: ethpb.ValidatorStatus_DEPOSITED},
|
|
||||||
{Status: ethpb.ValidatorStatus_PENDING},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
assert.ErrorContains(t, testCase.expectedError, err)
|
assert.ErrorContains(t, testCase.expectedError, err)
|
||||||
@@ -773,40 +761,6 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
committeeSlots := []primitives.Slot{28, 29, 30}
|
committeeSlots := []primitives.Slot{28, 29, 30}
|
||||||
proposerSlots := []primitives.Slot{31, 32, 33, 34, 35, 36, 37, 38}
|
proposerSlots := []primitives.Slot{31, 32, 33, 34, 35, 36, 37, 38}
|
||||||
|
|
||||||
statuses := []ethpb.ValidatorStatus{
|
|
||||||
ethpb.ValidatorStatus_UNKNOWN_STATUS,
|
|
||||||
ethpb.ValidatorStatus_DEPOSITED,
|
|
||||||
ethpb.ValidatorStatus_PENDING,
|
|
||||||
ethpb.ValidatorStatus_ACTIVE,
|
|
||||||
ethpb.ValidatorStatus_EXITING,
|
|
||||||
ethpb.ValidatorStatus_SLASHING,
|
|
||||||
ethpb.ValidatorStatus_EXITED,
|
|
||||||
ethpb.ValidatorStatus_INVALID,
|
|
||||||
ethpb.ValidatorStatus_PARTIALLY_DEPOSITED,
|
|
||||||
ethpb.ValidatorStatus_UNKNOWN_STATUS,
|
|
||||||
ethpb.ValidatorStatus_DEPOSITED,
|
|
||||||
ethpb.ValidatorStatus_PENDING,
|
|
||||||
}
|
|
||||||
|
|
||||||
multipleValidatorStatus := ðpb.MultipleValidatorStatusResponse{
|
|
||||||
PublicKeys: pubkeys,
|
|
||||||
Indices: validatorIndices,
|
|
||||||
Statuses: []*ethpb.ValidatorStatusResponse{
|
|
||||||
{Status: statuses[0]},
|
|
||||||
{Status: statuses[1]},
|
|
||||||
{Status: statuses[2]},
|
|
||||||
{Status: statuses[3]},
|
|
||||||
{Status: statuses[4]},
|
|
||||||
{Status: statuses[5]},
|
|
||||||
{Status: statuses[6]},
|
|
||||||
{Status: statuses[7]},
|
|
||||||
{Status: statuses[8]},
|
|
||||||
{Status: statuses[9]},
|
|
||||||
{Status: statuses[10]},
|
|
||||||
{Status: statuses[11]},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
@@ -824,7 +778,7 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
dutiesProvider.EXPECT().GetAttesterDuties(
|
dutiesProvider.EXPECT().GetAttesterDuties(
|
||||||
ctx,
|
ctx,
|
||||||
epoch,
|
epoch,
|
||||||
multipleValidatorStatus.Indices,
|
validatorIndices,
|
||||||
).Return(
|
).Return(
|
||||||
generateValidAttesterDuties(pubkeys, validatorIndices, committeeIndices, committeeSlots),
|
generateValidAttesterDuties(pubkeys, validatorIndices, committeeIndices, committeeSlots),
|
||||||
nil,
|
nil,
|
||||||
@@ -842,7 +796,7 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
dutiesProvider.EXPECT().GetSyncDuties(
|
dutiesProvider.EXPECT().GetSyncDuties(
|
||||||
ctx,
|
ctx,
|
||||||
epoch,
|
epoch,
|
||||||
multipleValidatorStatus.Indices,
|
validatorIndices,
|
||||||
).Return(
|
).Return(
|
||||||
generateValidSyncDuties(pubkeys, validatorIndices),
|
generateValidSyncDuties(pubkeys, validatorIndices),
|
||||||
nil,
|
nil,
|
||||||
@@ -883,7 +837,7 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
CommitteeIndex: committeeIndices[0],
|
CommitteeIndex: committeeIndices[0],
|
||||||
AttesterSlot: committeeSlots[0],
|
AttesterSlot: committeeSlots[0],
|
||||||
PublicKey: pubkeys[0],
|
PublicKey: pubkeys[0],
|
||||||
Status: statuses[0],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[0],
|
ValidatorIndex: validatorIndices[0],
|
||||||
CommitteesAtSlot: 1,
|
CommitteesAtSlot: 1,
|
||||||
},
|
},
|
||||||
@@ -895,7 +849,7 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
CommitteeIndex: committeeIndices[0],
|
CommitteeIndex: committeeIndices[0],
|
||||||
AttesterSlot: committeeSlots[0],
|
AttesterSlot: committeeSlots[0],
|
||||||
PublicKey: pubkeys[1],
|
PublicKey: pubkeys[1],
|
||||||
Status: statuses[1],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[1],
|
ValidatorIndex: validatorIndices[1],
|
||||||
CommitteesAtSlot: 1,
|
CommitteesAtSlot: 1,
|
||||||
},
|
},
|
||||||
@@ -907,7 +861,7 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
CommitteeIndex: committeeIndices[1],
|
CommitteeIndex: committeeIndices[1],
|
||||||
AttesterSlot: committeeSlots[1],
|
AttesterSlot: committeeSlots[1],
|
||||||
PublicKey: pubkeys[2],
|
PublicKey: pubkeys[2],
|
||||||
Status: statuses[2],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[2],
|
ValidatorIndex: validatorIndices[2],
|
||||||
CommitteesAtSlot: 1,
|
CommitteesAtSlot: 1,
|
||||||
},
|
},
|
||||||
@@ -919,7 +873,7 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
CommitteeIndex: committeeIndices[1],
|
CommitteeIndex: committeeIndices[1],
|
||||||
AttesterSlot: committeeSlots[1],
|
AttesterSlot: committeeSlots[1],
|
||||||
PublicKey: pubkeys[3],
|
PublicKey: pubkeys[3],
|
||||||
Status: statuses[3],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[3],
|
ValidatorIndex: validatorIndices[3],
|
||||||
CommitteesAtSlot: 1,
|
CommitteesAtSlot: 1,
|
||||||
},
|
},
|
||||||
@@ -931,7 +885,7 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
CommitteeIndex: committeeIndices[2],
|
CommitteeIndex: committeeIndices[2],
|
||||||
AttesterSlot: committeeSlots[2],
|
AttesterSlot: committeeSlots[2],
|
||||||
PublicKey: pubkeys[4],
|
PublicKey: pubkeys[4],
|
||||||
Status: statuses[4],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[4],
|
ValidatorIndex: validatorIndices[4],
|
||||||
ProposerSlots: expectedProposerSlots1,
|
ProposerSlots: expectedProposerSlots1,
|
||||||
CommitteesAtSlot: 1,
|
CommitteesAtSlot: 1,
|
||||||
@@ -944,7 +898,7 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
CommitteeIndex: committeeIndices[2],
|
CommitteeIndex: committeeIndices[2],
|
||||||
AttesterSlot: committeeSlots[2],
|
AttesterSlot: committeeSlots[2],
|
||||||
PublicKey: pubkeys[5],
|
PublicKey: pubkeys[5],
|
||||||
Status: statuses[5],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[5],
|
ValidatorIndex: validatorIndices[5],
|
||||||
ProposerSlots: expectedProposerSlots2,
|
ProposerSlots: expectedProposerSlots2,
|
||||||
IsSyncCommittee: testCase.fetchSyncDuties,
|
IsSyncCommittee: testCase.fetchSyncDuties,
|
||||||
@@ -952,47 +906,55 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
PublicKey: pubkeys[6],
|
PublicKey: pubkeys[6],
|
||||||
Status: statuses[6],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[6],
|
ValidatorIndex: validatorIndices[6],
|
||||||
ProposerSlots: expectedProposerSlots3,
|
ProposerSlots: expectedProposerSlots3,
|
||||||
IsSyncCommittee: testCase.fetchSyncDuties,
|
IsSyncCommittee: testCase.fetchSyncDuties,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PublicKey: pubkeys[7],
|
PublicKey: pubkeys[7],
|
||||||
Status: statuses[7],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[7],
|
ValidatorIndex: validatorIndices[7],
|
||||||
ProposerSlots: expectedProposerSlots4,
|
ProposerSlots: expectedProposerSlots4,
|
||||||
IsSyncCommittee: testCase.fetchSyncDuties,
|
IsSyncCommittee: testCase.fetchSyncDuties,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PublicKey: pubkeys[8],
|
PublicKey: pubkeys[8],
|
||||||
Status: statuses[8],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[8],
|
ValidatorIndex: validatorIndices[8],
|
||||||
IsSyncCommittee: testCase.fetchSyncDuties,
|
IsSyncCommittee: testCase.fetchSyncDuties,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PublicKey: pubkeys[9],
|
PublicKey: pubkeys[9],
|
||||||
Status: statuses[9],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[9],
|
ValidatorIndex: validatorIndices[9],
|
||||||
IsSyncCommittee: testCase.fetchSyncDuties,
|
IsSyncCommittee: testCase.fetchSyncDuties,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PublicKey: pubkeys[10],
|
PublicKey: pubkeys[10],
|
||||||
Status: statuses[10],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[10],
|
ValidatorIndex: validatorIndices[10],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PublicKey: pubkeys[11],
|
PublicKey: pubkeys[11],
|
||||||
Status: statuses[11],
|
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
ValidatorIndex: validatorIndices[11],
|
ValidatorIndex: validatorIndices[11],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
validatorClient := &beaconApiValidatorClient{dutiesProvider: dutiesProvider}
|
validatorClient := &beaconApiValidatorClient{dutiesProvider: dutiesProvider}
|
||||||
|
vals := make([]validatorForDuty, len(pubkeys))
|
||||||
|
for i := 0; i < len(pubkeys); i++ {
|
||||||
|
vals[i] = validatorForDuty{
|
||||||
|
pubkey: pubkeys[i],
|
||||||
|
index: validatorIndices[i],
|
||||||
|
status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
|
}
|
||||||
|
}
|
||||||
duties, err := validatorClient.getDutiesForEpoch(
|
duties, err := validatorClient.getDutiesForEpoch(
|
||||||
ctx,
|
ctx,
|
||||||
epoch,
|
epoch,
|
||||||
multipleValidatorStatus,
|
vals,
|
||||||
testCase.fetchSyncDuties,
|
testCase.fetchSyncDuties,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -1018,41 +980,24 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
statuses := []ethpb.ValidatorStatus{
|
valCount := 12
|
||||||
ethpb.ValidatorStatus_DEPOSITED,
|
pubkeys := make([][]byte, valCount)
|
||||||
ethpb.ValidatorStatus_PENDING,
|
validatorIndices := make([]primitives.ValidatorIndex, valCount)
|
||||||
ethpb.ValidatorStatus_ACTIVE,
|
vals := make([]validatorForDuty, valCount)
|
||||||
ethpb.ValidatorStatus_EXITING,
|
for i := 0; i < valCount; i++ {
|
||||||
ethpb.ValidatorStatus_SLASHING,
|
|
||||||
ethpb.ValidatorStatus_EXITED,
|
|
||||||
ethpb.ValidatorStatus_EXITED,
|
|
||||||
ethpb.ValidatorStatus_EXITED,
|
|
||||||
ethpb.ValidatorStatus_EXITED,
|
|
||||||
ethpb.ValidatorStatus_DEPOSITED,
|
|
||||||
ethpb.ValidatorStatus_PENDING,
|
|
||||||
ethpb.ValidatorStatus_ACTIVE,
|
|
||||||
}
|
|
||||||
pubkeys := make([][]byte, len(statuses))
|
|
||||||
validatorIndices := make([]primitives.ValidatorIndex, len(statuses))
|
|
||||||
for i := range statuses {
|
|
||||||
pubkeys[i] = []byte(strconv.Itoa(i))
|
pubkeys[i] = []byte(strconv.Itoa(i))
|
||||||
validatorIndices[i] = primitives.ValidatorIndex(i)
|
validatorIndices[i] = primitives.ValidatorIndex(i)
|
||||||
|
vals[i] = validatorForDuty{
|
||||||
|
pubkey: pubkeys[i],
|
||||||
|
index: validatorIndices[i],
|
||||||
|
status: ethpb.ValidatorStatus_ACTIVE,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
committeeIndices := []primitives.CommitteeIndex{25, 26, 27}
|
committeeIndices := []primitives.CommitteeIndex{25, 26, 27}
|
||||||
committeeSlots := []primitives.Slot{28, 29, 30}
|
committeeSlots := []primitives.Slot{28, 29, 30}
|
||||||
proposerSlots := []primitives.Slot{31, 32, 33, 34, 35, 36, 37, 38}
|
proposerSlots := []primitives.Slot{31, 32, 33, 34, 35, 36, 37, 38}
|
||||||
|
|
||||||
statusResps := make([]*ethpb.ValidatorStatusResponse, len(statuses))
|
|
||||||
for i, s := range statuses {
|
|
||||||
statusResps[i] = ðpb.ValidatorStatusResponse{Status: s}
|
|
||||||
}
|
|
||||||
multipleValidatorStatus := ðpb.MultipleValidatorStatusResponse{
|
|
||||||
PublicKeys: pubkeys,
|
|
||||||
Indices: validatorIndices,
|
|
||||||
Statuses: statusResps,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
@@ -1070,7 +1015,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
dutiesProvider.EXPECT().GetAttesterDuties(
|
dutiesProvider.EXPECT().GetAttesterDuties(
|
||||||
ctx,
|
ctx,
|
||||||
testCase.epoch,
|
testCase.epoch,
|
||||||
multipleValidatorStatus.Indices,
|
validatorIndices,
|
||||||
).Return(
|
).Return(
|
||||||
generateValidAttesterDuties(pubkeys, validatorIndices, committeeIndices, committeeSlots),
|
generateValidAttesterDuties(pubkeys, validatorIndices, committeeIndices, committeeSlots),
|
||||||
nil,
|
nil,
|
||||||
@@ -1089,7 +1034,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
dutiesProvider.EXPECT().GetSyncDuties(
|
dutiesProvider.EXPECT().GetSyncDuties(
|
||||||
ctx,
|
ctx,
|
||||||
testCase.epoch,
|
testCase.epoch,
|
||||||
multipleValidatorStatus.Indices,
|
validatorIndices,
|
||||||
).Return(
|
).Return(
|
||||||
generateValidSyncDuties(pubkeys, validatorIndices),
|
generateValidSyncDuties(pubkeys, validatorIndices),
|
||||||
nil,
|
nil,
|
||||||
@@ -1143,7 +1088,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
Data: []*structs.ValidatorContainer{
|
Data: []*structs.ValidatorContainer{
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[0]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[0]), 10),
|
||||||
Status: "pending_initialized",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[0]),
|
Pubkey: hexutil.Encode(pubkeys[0]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1151,7 +1096,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[1]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[1]), 10),
|
||||||
Status: "pending_queued",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[1]),
|
Pubkey: hexutil.Encode(pubkeys[1]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1167,7 +1112,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[3]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[3]), 10),
|
||||||
Status: "active_exiting",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[3]),
|
Pubkey: hexutil.Encode(pubkeys[3]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1175,7 +1120,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[4]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[4]), 10),
|
||||||
Status: "active_slashed",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[4]),
|
Pubkey: hexutil.Encode(pubkeys[4]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1183,7 +1128,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[5]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[5]), 10),
|
||||||
Status: "exited_unslashed",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[5]),
|
Pubkey: hexutil.Encode(pubkeys[5]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1191,7 +1136,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[6]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[6]), 10),
|
||||||
Status: "exited_slashed",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[6]),
|
Pubkey: hexutil.Encode(pubkeys[6]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1199,7 +1144,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[7]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[7]), 10),
|
||||||
Status: "withdrawal_possible",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[7]),
|
Pubkey: hexutil.Encode(pubkeys[7]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1207,7 +1152,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[8]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[8]), 10),
|
||||||
Status: "withdrawal_done",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[8]),
|
Pubkey: hexutil.Encode(pubkeys[8]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1215,7 +1160,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[9]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[9]), 10),
|
||||||
Status: "pending_initialized",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[9]),
|
Pubkey: hexutil.Encode(pubkeys[9]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1223,7 +1168,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: strconv.FormatUint(uint64(validatorIndices[10]), 10),
|
Index: strconv.FormatUint(uint64(validatorIndices[10]), 10),
|
||||||
Status: "pending_queued",
|
Status: "active_ongoing",
|
||||||
Validator: &structs.Validator{
|
Validator: &structs.Validator{
|
||||||
Pubkey: hexutil.Encode(pubkeys[10]),
|
Pubkey: hexutil.Encode(pubkeys[10]),
|
||||||
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
ActivationEpoch: strconv.FormatUint(uint64(testCase.epoch), 10),
|
||||||
@@ -1242,27 +1187,16 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
).MinTimes(1)
|
).MinTimes(1)
|
||||||
|
|
||||||
prysmBeaconChainClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
|
||||||
prysmBeaconChainClient.EXPECT().GetValidatorCount(
|
|
||||||
ctx,
|
|
||||||
gomock.Any(),
|
|
||||||
gomock.Any(),
|
|
||||||
).Return(
|
|
||||||
nil,
|
|
||||||
iface.ErrNotSupported,
|
|
||||||
).MinTimes(1)
|
|
||||||
|
|
||||||
// Make sure that our values are equal to what would be returned by calling getDutiesForEpoch individually
|
// Make sure that our values are equal to what would be returned by calling getDutiesForEpoch individually
|
||||||
validatorClient := &beaconApiValidatorClient{
|
validatorClient := &beaconApiValidatorClient{
|
||||||
dutiesProvider: dutiesProvider,
|
dutiesProvider: dutiesProvider,
|
||||||
stateValidatorsProvider: stateValidatorsProvider,
|
stateValidatorsProvider: stateValidatorsProvider,
|
||||||
prysmBeaconChainCLient: prysmBeaconChainClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedCurrentEpochDuties, err := validatorClient.getDutiesForEpoch(
|
expectedCurrentEpochDuties, err := validatorClient.getDutiesForEpoch(
|
||||||
ctx,
|
ctx,
|
||||||
testCase.epoch,
|
testCase.epoch,
|
||||||
multipleValidatorStatus,
|
vals,
|
||||||
fetchSyncDuties,
|
fetchSyncDuties,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -1270,7 +1204,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
expectedNextEpochDuties, err := validatorClient.getDutiesForEpoch(
|
expectedNextEpochDuties, err := validatorClient.getDutiesForEpoch(
|
||||||
ctx,
|
ctx,
|
||||||
testCase.epoch+1,
|
testCase.epoch+1,
|
||||||
multipleValidatorStatus,
|
vals,
|
||||||
fetchSyncDuties,
|
fetchSyncDuties,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -1291,7 +1225,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetDuties_GetValidatorStatusFailed(t *testing.T) {
|
func TestGetDuties_GetStateValidatorsFailed(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
@@ -1316,7 +1250,7 @@ func TestGetDuties_GetValidatorStatusFailed(t *testing.T) {
|
|||||||
Epoch: 1,
|
Epoch: 1,
|
||||||
PublicKeys: [][]byte{},
|
PublicKeys: [][]byte{},
|
||||||
})
|
})
|
||||||
assert.ErrorContains(t, "failed to get validator status", err)
|
assert.ErrorContains(t, "failed to get state validators", err)
|
||||||
assert.ErrorContains(t, "foo error", err)
|
assert.ErrorContains(t, "foo error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1325,6 +1259,7 @@ func TestGetDuties_GetDutiesForEpochFailed(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
pubkey := []byte{1, 2, 3}
|
||||||
|
|
||||||
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl)
|
||||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
stateValidatorsProvider.EXPECT().GetStateValidators(
|
||||||
@@ -1334,7 +1269,13 @@ func TestGetDuties_GetDutiesForEpochFailed(t *testing.T) {
|
|||||||
gomock.Any(),
|
gomock.Any(),
|
||||||
).Return(
|
).Return(
|
||||||
&structs.GetValidatorsResponse{
|
&structs.GetValidatorsResponse{
|
||||||
Data: []*structs.ValidatorContainer{},
|
Data: []*structs.ValidatorContainer{{
|
||||||
|
Index: "0",
|
||||||
|
Status: "active_ongoing",
|
||||||
|
Validator: &structs.Validator{
|
||||||
|
Pubkey: hexutil.Encode(pubkey),
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
).Times(1)
|
).Times(1)
|
||||||
@@ -1348,26 +1289,28 @@ func TestGetDuties_GetDutiesForEpochFailed(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
errors.New("foo error"),
|
errors.New("foo error"),
|
||||||
).Times(1)
|
).Times(1)
|
||||||
|
dutiesProvider.EXPECT().GetAttesterDuties(
|
||||||
prysmBeaconChainClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
ctx,
|
||||||
prysmBeaconChainClient.EXPECT().GetValidatorCount(
|
primitives.Epoch(2),
|
||||||
|
gomock.Any(),
|
||||||
|
).Times(1)
|
||||||
|
dutiesProvider.EXPECT().GetProposerDuties(
|
||||||
ctx,
|
ctx,
|
||||||
gomock.Any(),
|
gomock.Any(),
|
||||||
|
).Times(2)
|
||||||
|
dutiesProvider.EXPECT().GetCommittees(
|
||||||
|
ctx,
|
||||||
gomock.Any(),
|
gomock.Any(),
|
||||||
).Return(
|
).Times(2)
|
||||||
nil,
|
|
||||||
iface.ErrNotSupported,
|
|
||||||
).MinTimes(1)
|
|
||||||
|
|
||||||
validatorClient := &beaconApiValidatorClient{
|
validatorClient := &beaconApiValidatorClient{
|
||||||
stateValidatorsProvider: stateValidatorsProvider,
|
stateValidatorsProvider: stateValidatorsProvider,
|
||||||
dutiesProvider: dutiesProvider,
|
dutiesProvider: dutiesProvider,
|
||||||
prysmBeaconChainCLient: prysmBeaconChainClient,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := validatorClient.getDuties(ctx, ðpb.DutiesRequest{
|
_, err := validatorClient.getDuties(ctx, ðpb.DutiesRequest{
|
||||||
Epoch: 1,
|
Epoch: 1,
|
||||||
PublicKeys: [][]byte{},
|
PublicKeys: [][]byte{pubkey},
|
||||||
})
|
})
|
||||||
assert.ErrorContains(t, "failed to get duties for current epoch `1`", err)
|
assert.ErrorContains(t, "failed to get duties for current epoch `1`", err)
|
||||||
assert.ErrorContains(t, "foo error", err)
|
assert.ErrorContains(t, "foo error", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user