github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/prysm/v1alpha1/beacon/assignments.go (about) 1 package beacon 2 3 import ( 4 "context" 5 "strconv" 6 7 types "github.com/prysmaticlabs/eth2-types" 8 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 9 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 10 "github.com/prysmaticlabs/prysm/shared/bytesutil" 11 "github.com/prysmaticlabs/prysm/shared/cmd" 12 "github.com/prysmaticlabs/prysm/shared/pagination" 13 "google.golang.org/grpc/codes" 14 "google.golang.org/grpc/status" 15 ) 16 17 const errEpoch = "Cannot retrieve information about an epoch in the future, current epoch %d, requesting %d" 18 19 // ListValidatorAssignments retrieves the validator assignments for a given epoch, 20 // optional validator indices or public keys may be included to filter validator assignments. 21 func (bs *Server) ListValidatorAssignments( 22 ctx context.Context, req *ethpb.ListValidatorAssignmentsRequest, 23 ) (*ethpb.ValidatorAssignments, error) { 24 if int(req.PageSize) > cmd.Get().MaxRPCPageSize { 25 return nil, status.Errorf( 26 codes.InvalidArgument, 27 "Requested page size %d can not be greater than max size %d", 28 req.PageSize, 29 cmd.Get().MaxRPCPageSize, 30 ) 31 } 32 33 var res []*ethpb.ValidatorAssignments_CommitteeAssignment 34 filtered := map[types.ValidatorIndex]bool{} // track filtered validators to prevent duplication in the response. 35 filteredIndices := make([]types.ValidatorIndex, 0) 36 var requestedEpoch types.Epoch 37 switch q := req.QueryFilter.(type) { 38 case *ethpb.ListValidatorAssignmentsRequest_Genesis: 39 if q.Genesis { 40 requestedEpoch = 0 41 } 42 case *ethpb.ListValidatorAssignmentsRequest_Epoch: 43 requestedEpoch = q.Epoch 44 } 45 46 currentEpoch := helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) 47 if requestedEpoch > currentEpoch { 48 return nil, status.Errorf( 49 codes.InvalidArgument, 50 errEpoch, 51 currentEpoch, 52 requestedEpoch, 53 ) 54 } 55 56 startSlot, err := helpers.StartSlot(requestedEpoch) 57 if err != nil { 58 return nil, err 59 } 60 requestedState, err := bs.StateGen.StateBySlot(ctx, startSlot) 61 if err != nil { 62 return nil, status.Errorf(codes.Internal, "Could not retrieve archived state for epoch %d: %v", requestedEpoch, err) 63 } 64 65 // Filter out assignments by public keys. 66 for _, pubKey := range req.PublicKeys { 67 index, ok := requestedState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey)) 68 if !ok { 69 return nil, status.Errorf(codes.NotFound, "Could not find validator index for public key %#x", pubKey) 70 } 71 filtered[index] = true 72 filteredIndices = append(filteredIndices, index) 73 } 74 75 // Filter out assignments by validator indices. 76 for _, index := range req.Indices { 77 if !filtered[index] { 78 filteredIndices = append(filteredIndices, index) 79 } 80 } 81 82 activeIndices, err := helpers.ActiveValidatorIndices(requestedState, requestedEpoch) 83 if err != nil { 84 return nil, status.Errorf(codes.Internal, "Could not retrieve active validator indices: %v", err) 85 } 86 if len(filteredIndices) == 0 { 87 if len(activeIndices) == 0 { 88 return ðpb.ValidatorAssignments{ 89 Assignments: make([]*ethpb.ValidatorAssignments_CommitteeAssignment, 0), 90 TotalSize: int32(0), 91 NextPageToken: strconv.Itoa(0), 92 }, nil 93 } 94 // If no filter was specified, return assignments from active validator indices with pagination. 95 filteredIndices = activeIndices 96 } 97 98 start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), len(filteredIndices)) 99 if err != nil { 100 return nil, status.Errorf(codes.Internal, "Could not paginate results: %v", err) 101 } 102 103 // Initialize all committee related data. 104 committeeAssignments, proposerIndexToSlots, err := helpers.CommitteeAssignments(requestedState, requestedEpoch) 105 if err != nil { 106 return nil, status.Errorf(codes.Internal, "Could not compute committee assignments: %v", err) 107 } 108 109 for _, index := range filteredIndices[start:end] { 110 if uint64(index) >= uint64(requestedState.NumValidators()) { 111 return nil, status.Errorf(codes.OutOfRange, "Validator index %d >= validator count %d", 112 index, requestedState.NumValidators()) 113 } 114 comAssignment := committeeAssignments[index] 115 pubkey := requestedState.PubkeyAtIndex(index) 116 assign := ðpb.ValidatorAssignments_CommitteeAssignment{ 117 BeaconCommittees: comAssignment.Committee, 118 CommitteeIndex: comAssignment.CommitteeIndex, 119 AttesterSlot: comAssignment.AttesterSlot, 120 ProposerSlots: proposerIndexToSlots[index], 121 PublicKey: pubkey[:], 122 ValidatorIndex: index, 123 } 124 res = append(res, assign) 125 } 126 127 return ðpb.ValidatorAssignments{ 128 Epoch: requestedEpoch, 129 Assignments: res, 130 NextPageToken: nextPageToken, 131 TotalSize: int32(len(filteredIndices)), 132 }, nil 133 }