mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 04:47:18 +00:00
c21e43e4c5
* Move necessary functions beacon-chain/core/time -> time/slots * Fix fuzz * Fix build * Update slot_epoch.go
135 lines
4.5 KiB
Go
135 lines
4.5 KiB
Go
package beacon
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
|
|
types "github.com/prysmaticlabs/eth2-types"
|
|
"github.com/prysmaticlabs/prysm/api/pagination"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/cmd"
|
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/time/slots"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
const errEpoch = "Cannot retrieve information about an epoch in the future, current epoch %d, requesting %d"
|
|
|
|
// ListValidatorAssignments retrieves the validator assignments for a given epoch,
|
|
// optional validator indices or public keys may be included to filter validator assignments.
|
|
func (bs *Server) ListValidatorAssignments(
|
|
ctx context.Context, req *ethpb.ListValidatorAssignmentsRequest,
|
|
) (*ethpb.ValidatorAssignments, error) {
|
|
if int(req.PageSize) > cmd.Get().MaxRPCPageSize {
|
|
return nil, status.Errorf(
|
|
codes.InvalidArgument,
|
|
"Requested page size %d can not be greater than max size %d",
|
|
req.PageSize,
|
|
cmd.Get().MaxRPCPageSize,
|
|
)
|
|
}
|
|
|
|
var res []*ethpb.ValidatorAssignments_CommitteeAssignment
|
|
filtered := map[types.ValidatorIndex]bool{} // track filtered validators to prevent duplication in the response.
|
|
filteredIndices := make([]types.ValidatorIndex, 0)
|
|
var requestedEpoch types.Epoch
|
|
switch q := req.QueryFilter.(type) {
|
|
case *ethpb.ListValidatorAssignmentsRequest_Genesis:
|
|
if q.Genesis {
|
|
requestedEpoch = 0
|
|
}
|
|
case *ethpb.ListValidatorAssignmentsRequest_Epoch:
|
|
requestedEpoch = q.Epoch
|
|
}
|
|
|
|
currentEpoch := slots.ToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
|
|
if requestedEpoch > currentEpoch {
|
|
return nil, status.Errorf(
|
|
codes.InvalidArgument,
|
|
errEpoch,
|
|
currentEpoch,
|
|
requestedEpoch,
|
|
)
|
|
}
|
|
|
|
startSlot, err := slots.EpochStart(requestedEpoch)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
requestedState, err := bs.StateGen.StateBySlot(ctx, startSlot)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve archived state for epoch %d: %v", requestedEpoch, err)
|
|
}
|
|
|
|
// Filter out assignments by public keys.
|
|
for _, pubKey := range req.PublicKeys {
|
|
index, ok := requestedState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey))
|
|
if !ok {
|
|
return nil, status.Errorf(codes.NotFound, "Could not find validator index for public key %#x", pubKey)
|
|
}
|
|
filtered[index] = true
|
|
filteredIndices = append(filteredIndices, index)
|
|
}
|
|
|
|
// Filter out assignments by validator indices.
|
|
for _, index := range req.Indices {
|
|
if !filtered[index] {
|
|
filteredIndices = append(filteredIndices, index)
|
|
}
|
|
}
|
|
|
|
activeIndices, err := helpers.ActiveValidatorIndices(ctx, requestedState, requestedEpoch)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not retrieve active validator indices: %v", err)
|
|
}
|
|
if len(filteredIndices) == 0 {
|
|
if len(activeIndices) == 0 {
|
|
return ðpb.ValidatorAssignments{
|
|
Assignments: make([]*ethpb.ValidatorAssignments_CommitteeAssignment, 0),
|
|
TotalSize: int32(0),
|
|
NextPageToken: strconv.Itoa(0),
|
|
}, nil
|
|
}
|
|
// If no filter was specified, return assignments from active validator indices with pagination.
|
|
filteredIndices = activeIndices
|
|
}
|
|
|
|
start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(filteredIndices))
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not paginate results: %v", err)
|
|
}
|
|
|
|
// Initialize all committee related data.
|
|
committeeAssignments, proposerIndexToSlots, err := helpers.CommitteeAssignments(ctx, requestedState, requestedEpoch)
|
|
if err != nil {
|
|
return nil, status.Errorf(codes.Internal, "Could not compute committee assignments: %v", err)
|
|
}
|
|
|
|
for _, index := range filteredIndices[start:end] {
|
|
if uint64(index) >= uint64(requestedState.NumValidators()) {
|
|
return nil, status.Errorf(codes.OutOfRange, "Validator index %d >= validator count %d",
|
|
index, requestedState.NumValidators())
|
|
}
|
|
comAssignment := committeeAssignments[index]
|
|
pubkey := requestedState.PubkeyAtIndex(index)
|
|
assign := ðpb.ValidatorAssignments_CommitteeAssignment{
|
|
BeaconCommittees: comAssignment.Committee,
|
|
CommitteeIndex: comAssignment.CommitteeIndex,
|
|
AttesterSlot: comAssignment.AttesterSlot,
|
|
ProposerSlots: proposerIndexToSlots[index],
|
|
PublicKey: pubkey[:],
|
|
ValidatorIndex: index,
|
|
}
|
|
res = append(res, assign)
|
|
}
|
|
|
|
return ðpb.ValidatorAssignments{
|
|
Epoch: requestedEpoch,
|
|
Assignments: res,
|
|
NextPageToken: nextPageToken,
|
|
TotalSize: int32(len(filteredIndices)),
|
|
}, nil
|
|
}
|