github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/rpc/prysm/v1alpha1/beacon/validators.go (about)

     1  package beacon
     2  
     3  import (
     4  	"context"
     5  	"sort"
     6  	"strconv"
     7  	"time"
     8  
     9  	types "github.com/prysmaticlabs/eth2-types"
    10  	"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
    11  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    12  	"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
    13  	"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
    14  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    15  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    16  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    17  	"github.com/prysmaticlabs/prysm/shared/cmd"
    18  	"github.com/prysmaticlabs/prysm/shared/pagination"
    19  	"github.com/prysmaticlabs/prysm/shared/params"
    20  	"google.golang.org/grpc/codes"
    21  	"google.golang.org/grpc/status"
    22  	"google.golang.org/protobuf/types/known/emptypb"
    23  )
    24  
    25  // BalancesTimeout for gRPC requests to ListValidatorBalances.
    26  const BalancesTimeout = time.Second * 30
    27  
    28  // ListValidatorBalances retrieves the validator balances for a given set of public keys.
    29  // An optional Epoch parameter is provided to request historical validator balances from
    30  // archived, persistent data.
    31  func (bs *Server) ListValidatorBalances(
    32  	ctx context.Context,
    33  	req *ethpb.ListValidatorBalancesRequest,
    34  ) (*ethpb.ValidatorBalances, error) {
    35  	ctx, cancel := context.WithTimeout(ctx, BalancesTimeout)
    36  	defer cancel()
    37  	if int(req.PageSize) > cmd.Get().MaxRPCPageSize {
    38  		return nil, status.Errorf(codes.InvalidArgument, "Requested page size %d can not be greater than max size %d",
    39  			req.PageSize, cmd.Get().MaxRPCPageSize)
    40  	}
    41  
    42  	if bs.GenesisTimeFetcher == nil {
    43  		return nil, status.Errorf(codes.Internal, "Nil genesis time fetcher")
    44  	}
    45  	currentEpoch := helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
    46  	requestedEpoch := currentEpoch
    47  	switch q := req.QueryFilter.(type) {
    48  	case *ethpb.ListValidatorBalancesRequest_Epoch:
    49  		requestedEpoch = q.Epoch
    50  	case *ethpb.ListValidatorBalancesRequest_Genesis:
    51  		requestedEpoch = 0
    52  	}
    53  
    54  	if requestedEpoch > currentEpoch {
    55  		return nil, status.Errorf(
    56  			codes.InvalidArgument,
    57  			errEpoch,
    58  			currentEpoch,
    59  			requestedEpoch,
    60  		)
    61  	}
    62  	res := make([]*ethpb.ValidatorBalances_Balance, 0)
    63  	filtered := map[types.ValidatorIndex]bool{} // Track filtered validators to prevent duplication in the response.
    64  
    65  	startSlot, err := helpers.StartSlot(requestedEpoch)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	requestedState, err := bs.StateGen.StateBySlot(ctx, startSlot)
    70  	if err != nil {
    71  		return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
    72  	}
    73  
    74  	vals := requestedState.Validators()
    75  	balances := requestedState.Balances()
    76  	balancesCount := len(balances)
    77  	for _, pubKey := range req.PublicKeys {
    78  		// Skip empty public key.
    79  		if len(pubKey) == 0 {
    80  			continue
    81  		}
    82  		pubkeyBytes := bytesutil.ToBytes48(pubKey)
    83  		index, ok := requestedState.ValidatorIndexByPubkey(pubkeyBytes)
    84  		if !ok {
    85  			// We continue the loop if one validator in the request is not found.
    86  			res = append(res, &ethpb.ValidatorBalances_Balance{
    87  				Status: "UNKNOWN",
    88  			})
    89  			balancesCount = len(res)
    90  			continue
    91  		}
    92  		filtered[index] = true
    93  
    94  		if uint64(index) >= uint64(len(balances)) {
    95  			return nil, status.Errorf(codes.OutOfRange, "Validator index %d >= balance list %d",
    96  				index, len(balances))
    97  		}
    98  
    99  		val := vals[index]
   100  		st := validatorStatus(val, requestedEpoch)
   101  		res = append(res, &ethpb.ValidatorBalances_Balance{
   102  			PublicKey: pubKey,
   103  			Index:     index,
   104  			Balance:   balances[index],
   105  			Status:    st.String(),
   106  		})
   107  		balancesCount = len(res)
   108  	}
   109  
   110  	for _, index := range req.Indices {
   111  		if uint64(index) >= uint64(len(balances)) {
   112  			return nil, status.Errorf(codes.OutOfRange, "Validator index %d >= balance list %d",
   113  				index, len(balances))
   114  		}
   115  
   116  		if !filtered[index] {
   117  			val := vals[index]
   118  			st := validatorStatus(val, requestedEpoch)
   119  			res = append(res, &ethpb.ValidatorBalances_Balance{
   120  				PublicKey: vals[index].PublicKey,
   121  				Index:     index,
   122  				Balance:   balances[index],
   123  				Status:    st.String(),
   124  			})
   125  		}
   126  		balancesCount = len(res)
   127  	}
   128  	// Depending on the indices and public keys given, results might not be sorted.
   129  	sort.Slice(res, func(i, j int) bool {
   130  		return res[i].Index < res[j].Index
   131  	})
   132  
   133  	// If there are no balances, we simply return a response specifying this.
   134  	// Otherwise, attempting to paginate 0 balances below would result in an error.
   135  	if balancesCount == 0 {
   136  		return &ethpb.ValidatorBalances{
   137  			Epoch:         requestedEpoch,
   138  			Balances:      make([]*ethpb.ValidatorBalances_Balance, 0),
   139  			TotalSize:     int32(0),
   140  			NextPageToken: strconv.Itoa(0),
   141  		}, nil
   142  	}
   143  
   144  	start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), balancesCount)
   145  	if err != nil {
   146  		return nil, status.Errorf(
   147  			codes.Internal,
   148  			"Could not paginate results: %v",
   149  			err,
   150  		)
   151  	}
   152  
   153  	if len(req.Indices) == 0 && len(req.PublicKeys) == 0 {
   154  		// Return everything.
   155  		for i := start; i < end; i++ {
   156  			pubkey := requestedState.PubkeyAtIndex(types.ValidatorIndex(i))
   157  			val := vals[i]
   158  			st := validatorStatus(val, requestedEpoch)
   159  			res = append(res, &ethpb.ValidatorBalances_Balance{
   160  				PublicKey: pubkey[:],
   161  				Index:     types.ValidatorIndex(i),
   162  				Balance:   balances[i],
   163  				Status:    st.String(),
   164  			})
   165  		}
   166  		return &ethpb.ValidatorBalances{
   167  			Epoch:         requestedEpoch,
   168  			Balances:      res,
   169  			TotalSize:     int32(balancesCount),
   170  			NextPageToken: nextPageToken,
   171  		}, nil
   172  	}
   173  
   174  	if end > len(res) || end < start {
   175  		return nil, status.Error(codes.OutOfRange, "Request exceeds response length")
   176  	}
   177  
   178  	return &ethpb.ValidatorBalances{
   179  		Epoch:         requestedEpoch,
   180  		Balances:      res[start:end],
   181  		TotalSize:     int32(balancesCount),
   182  		NextPageToken: nextPageToken,
   183  	}, nil
   184  }
   185  
   186  // ListValidators retrieves the current list of active validators with an optional historical epoch flag to
   187  // to retrieve validator set in time.
   188  func (bs *Server) ListValidators(
   189  	ctx context.Context,
   190  	req *ethpb.ListValidatorsRequest,
   191  ) (*ethpb.Validators, error) {
   192  	if int(req.PageSize) > cmd.Get().MaxRPCPageSize {
   193  		return nil, status.Errorf(codes.InvalidArgument, "Requested page size %d can not be greater than max size %d",
   194  			req.PageSize, cmd.Get().MaxRPCPageSize)
   195  	}
   196  
   197  	currentEpoch := helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
   198  	requestedEpoch := currentEpoch
   199  
   200  	switch q := req.QueryFilter.(type) {
   201  	case *ethpb.ListValidatorsRequest_Genesis:
   202  		if q.Genesis {
   203  			requestedEpoch = 0
   204  		}
   205  	case *ethpb.ListValidatorsRequest_Epoch:
   206  		if q.Epoch > currentEpoch {
   207  			return nil, status.Errorf(
   208  				codes.InvalidArgument,
   209  				errEpoch,
   210  				currentEpoch,
   211  				q.Epoch,
   212  			)
   213  		}
   214  		requestedEpoch = q.Epoch
   215  	}
   216  	var reqState iface.BeaconState
   217  	var err error
   218  	if requestedEpoch != currentEpoch {
   219  		var s types.Slot
   220  		s, err = helpers.StartSlot(requestedEpoch)
   221  		if err != nil {
   222  			return nil, err
   223  		}
   224  		reqState, err = bs.StateGen.StateBySlot(ctx, s)
   225  	} else {
   226  		reqState, err = bs.HeadFetcher.HeadState(ctx)
   227  	}
   228  	if err != nil {
   229  		return nil, status.Errorf(codes.Internal, "Could not get requested state: %v", err)
   230  	}
   231  
   232  	s, err := helpers.StartSlot(requestedEpoch)
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  	if s > reqState.Slot() {
   237  		reqState = reqState.Copy()
   238  		reqState, err = state.ProcessSlots(ctx, reqState, s)
   239  		if err != nil {
   240  			return nil, status.Errorf(
   241  				codes.Internal,
   242  				"Could not process slots up to epoch %d: %v",
   243  				requestedEpoch,
   244  				err,
   245  			)
   246  		}
   247  	}
   248  
   249  	validatorList := make([]*ethpb.Validators_ValidatorContainer, 0)
   250  
   251  	for _, index := range req.Indices {
   252  		val, err := reqState.ValidatorAtIndex(index)
   253  		if err != nil {
   254  			return nil, status.Errorf(codes.Internal, "Could not get validator: %v", err)
   255  		}
   256  		validatorList = append(validatorList, &ethpb.Validators_ValidatorContainer{
   257  			Index:     index,
   258  			Validator: val,
   259  		})
   260  	}
   261  
   262  	for _, pubKey := range req.PublicKeys {
   263  		// Skip empty public key.
   264  		if len(pubKey) == 0 {
   265  			continue
   266  		}
   267  		pubkeyBytes := bytesutil.ToBytes48(pubKey)
   268  		index, ok := reqState.ValidatorIndexByPubkey(pubkeyBytes)
   269  		if !ok {
   270  			continue
   271  		}
   272  		val, err := reqState.ValidatorAtIndex(index)
   273  		if err != nil {
   274  			return nil, status.Errorf(codes.Internal, "Could not get validator: %v", err)
   275  		}
   276  		validatorList = append(validatorList, &ethpb.Validators_ValidatorContainer{
   277  			Index:     index,
   278  			Validator: val,
   279  		})
   280  	}
   281  	// Depending on the indices and public keys given, results might not be sorted.
   282  	sort.Slice(validatorList, func(i, j int) bool {
   283  		return validatorList[i].Index < validatorList[j].Index
   284  	})
   285  
   286  	if len(req.PublicKeys) == 0 && len(req.Indices) == 0 {
   287  		for i := types.ValidatorIndex(0); uint64(i) < uint64(reqState.NumValidators()); i++ {
   288  			val, err := reqState.ValidatorAtIndex(i)
   289  			if err != nil {
   290  				return nil, status.Errorf(codes.Internal, "Could not get validator: %v", err)
   291  			}
   292  			validatorList = append(validatorList, &ethpb.Validators_ValidatorContainer{
   293  				Index:     i,
   294  				Validator: val,
   295  			})
   296  		}
   297  	}
   298  
   299  	// Filter active validators if the request specifies it.
   300  	res := validatorList
   301  	if req.Active {
   302  		filteredValidators := make([]*ethpb.Validators_ValidatorContainer, 0)
   303  		for _, item := range validatorList {
   304  			if helpers.IsActiveValidator(item.Validator, requestedEpoch) {
   305  				filteredValidators = append(filteredValidators, item)
   306  			}
   307  		}
   308  		res = filteredValidators
   309  	}
   310  
   311  	validatorCount := len(res)
   312  	// If there are no items, we simply return a response specifying this.
   313  	// Otherwise, attempting to paginate 0 validators below would result in an error.
   314  	if validatorCount == 0 {
   315  		return &ethpb.Validators{
   316  			ValidatorList: make([]*ethpb.Validators_ValidatorContainer, 0),
   317  			TotalSize:     int32(0),
   318  			NextPageToken: strconv.Itoa(0),
   319  		}, nil
   320  	}
   321  
   322  	start, end, nextPageToken, err := pagination.StartAndEndPage(req.PageToken, int(req.PageSize), validatorCount)
   323  	if err != nil {
   324  		return nil, status.Errorf(
   325  			codes.Internal,
   326  			"Could not paginate results: %v",
   327  			err,
   328  		)
   329  	}
   330  
   331  	return &ethpb.Validators{
   332  		ValidatorList: res[start:end],
   333  		TotalSize:     int32(validatorCount),
   334  		NextPageToken: nextPageToken,
   335  	}, nil
   336  }
   337  
   338  // GetValidator information from any validator in the registry by index or public key.
   339  func (bs *Server) GetValidator(
   340  	ctx context.Context, req *ethpb.GetValidatorRequest,
   341  ) (*ethpb.Validator, error) {
   342  	var requestingIndex bool
   343  	var index types.ValidatorIndex
   344  	var pubKey []byte
   345  	switch q := req.QueryFilter.(type) {
   346  	case *ethpb.GetValidatorRequest_Index:
   347  		index = q.Index
   348  		requestingIndex = true
   349  	case *ethpb.GetValidatorRequest_PublicKey:
   350  		pubKey = q.PublicKey
   351  	default:
   352  		return nil, status.Error(
   353  			codes.InvalidArgument,
   354  			"Need to specify either validator index or public key in request",
   355  		)
   356  	}
   357  	headState, err := bs.HeadFetcher.HeadState(ctx)
   358  	if err != nil {
   359  		return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
   360  	}
   361  	if requestingIndex {
   362  		if uint64(index) >= uint64(headState.NumValidators()) {
   363  			return nil, status.Errorf(
   364  				codes.OutOfRange,
   365  				"Requesting index %d, but there are only %d validators",
   366  				index,
   367  				headState.NumValidators(),
   368  			)
   369  		}
   370  		return headState.ValidatorAtIndex(index)
   371  	}
   372  	pk48 := bytesutil.ToBytes48(pubKey)
   373  	for i := types.ValidatorIndex(0); uint64(i) < uint64(headState.NumValidators()); i++ {
   374  		keyFromState := headState.PubkeyAtIndex(i)
   375  		if keyFromState == pk48 {
   376  			return headState.ValidatorAtIndex(i)
   377  		}
   378  	}
   379  	return nil, status.Error(codes.NotFound, "No validator matched filter criteria")
   380  }
   381  
   382  // GetValidatorActiveSetChanges retrieves the active set changes for a given epoch.
   383  //
   384  // This data includes any activations, voluntary exits, and involuntary
   385  // ejections.
   386  func (bs *Server) GetValidatorActiveSetChanges(
   387  	ctx context.Context, req *ethpb.GetValidatorActiveSetChangesRequest,
   388  ) (*ethpb.ActiveSetChanges, error) {
   389  	currentEpoch := helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
   390  
   391  	var requestedEpoch types.Epoch
   392  	switch q := req.QueryFilter.(type) {
   393  	case *ethpb.GetValidatorActiveSetChangesRequest_Genesis:
   394  		requestedEpoch = 0
   395  	case *ethpb.GetValidatorActiveSetChangesRequest_Epoch:
   396  		requestedEpoch = q.Epoch
   397  	default:
   398  		requestedEpoch = currentEpoch
   399  	}
   400  	if requestedEpoch > currentEpoch {
   401  		return nil, status.Errorf(
   402  			codes.InvalidArgument,
   403  			errEpoch,
   404  			currentEpoch,
   405  			requestedEpoch,
   406  		)
   407  	}
   408  
   409  	s, err := helpers.StartSlot(requestedEpoch)
   410  	if err != nil {
   411  		return nil, err
   412  	}
   413  	requestedState, err := bs.StateGen.StateBySlot(ctx, s)
   414  	if err != nil {
   415  		return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
   416  	}
   417  
   418  	activeValidatorCount, err := helpers.ActiveValidatorCount(requestedState, helpers.CurrentEpoch(requestedState))
   419  	if err != nil {
   420  		return nil, status.Errorf(codes.Internal, "Could not get active validator count: %v", err)
   421  	}
   422  	vs := requestedState.Validators()
   423  	activatedIndices := validators.ActivatedValidatorIndices(helpers.CurrentEpoch(requestedState), vs)
   424  	exitedIndices, err := validators.ExitedValidatorIndices(helpers.CurrentEpoch(requestedState), vs, activeValidatorCount)
   425  	if err != nil {
   426  		return nil, status.Errorf(codes.Internal, "Could not determine exited validator indices: %v", err)
   427  	}
   428  	slashedIndices := validators.SlashedValidatorIndices(helpers.CurrentEpoch(requestedState), vs)
   429  	ejectedIndices, err := validators.EjectedValidatorIndices(helpers.CurrentEpoch(requestedState), vs, activeValidatorCount)
   430  	if err != nil {
   431  		return nil, status.Errorf(codes.Internal, "Could not determine ejected validator indices: %v", err)
   432  	}
   433  
   434  	// Retrieve public keys for the indices.
   435  	activatedKeys := make([][]byte, len(activatedIndices))
   436  	exitedKeys := make([][]byte, len(exitedIndices))
   437  	slashedKeys := make([][]byte, len(slashedIndices))
   438  	ejectedKeys := make([][]byte, len(ejectedIndices))
   439  	for i, idx := range activatedIndices {
   440  		pubkey := requestedState.PubkeyAtIndex(idx)
   441  		activatedKeys[i] = pubkey[:]
   442  	}
   443  	for i, idx := range exitedIndices {
   444  		pubkey := requestedState.PubkeyAtIndex(idx)
   445  		exitedKeys[i] = pubkey[:]
   446  	}
   447  	for i, idx := range slashedIndices {
   448  		pubkey := requestedState.PubkeyAtIndex(idx)
   449  		slashedKeys[i] = pubkey[:]
   450  	}
   451  	for i, idx := range ejectedIndices {
   452  		pubkey := requestedState.PubkeyAtIndex(idx)
   453  		ejectedKeys[i] = pubkey[:]
   454  	}
   455  	return &ethpb.ActiveSetChanges{
   456  		Epoch:               requestedEpoch,
   457  		ActivatedPublicKeys: activatedKeys,
   458  		ActivatedIndices:    activatedIndices,
   459  		ExitedPublicKeys:    exitedKeys,
   460  		ExitedIndices:       exitedIndices,
   461  		SlashedPublicKeys:   slashedKeys,
   462  		SlashedIndices:      slashedIndices,
   463  		EjectedPublicKeys:   ejectedKeys,
   464  		EjectedIndices:      ejectedIndices,
   465  	}, nil
   466  }
   467  
   468  // GetValidatorParticipation retrieves the validator participation information for a given epoch,
   469  // it returns the information about validator's participation rate in voting on the proof of stake
   470  // rules based on their balance compared to the total active validator balance.
   471  func (bs *Server) GetValidatorParticipation(
   472  	ctx context.Context, req *ethpb.GetValidatorParticipationRequest,
   473  ) (*ethpb.ValidatorParticipationResponse, error) {
   474  	currentSlot := bs.GenesisTimeFetcher.CurrentSlot()
   475  	currentEpoch := helpers.SlotToEpoch(currentSlot)
   476  
   477  	var requestedEpoch types.Epoch
   478  	switch q := req.QueryFilter.(type) {
   479  	case *ethpb.GetValidatorParticipationRequest_Genesis:
   480  		requestedEpoch = 0
   481  	case *ethpb.GetValidatorParticipationRequest_Epoch:
   482  		requestedEpoch = q.Epoch
   483  	default:
   484  		requestedEpoch = currentEpoch
   485  	}
   486  
   487  	if requestedEpoch > currentEpoch {
   488  		return nil, status.Errorf(
   489  			codes.InvalidArgument,
   490  			"Cannot retrieve information about an epoch greater than current epoch, current epoch %d, requesting %d",
   491  			currentEpoch,
   492  			requestedEpoch,
   493  		)
   494  	}
   495  
   496  	// Get current slot state for current epoch attestations.
   497  	startSlot, err := helpers.StartSlot(requestedEpoch)
   498  	if err != nil {
   499  		return nil, err
   500  	}
   501  	// Use the last slot of requested epoch to obtain current and previous epoch attestations.
   502  	// This ensures that we don't miss previous attestations when input requested epochs.
   503  	startSlot += params.BeaconConfig().SlotsPerEpoch - 1
   504  	// The start slot should be a canonical slot.
   505  	canonical, err := bs.isSlotCanonical(ctx, startSlot)
   506  	if err != nil {
   507  		return nil, err
   508  	}
   509  	// Keep looking back until there's a canonical slot.
   510  	for i := int(startSlot - 1); !canonical && i >= 0; i-- {
   511  		canonical, err = bs.isSlotCanonical(ctx, types.Slot(i))
   512  		if err != nil {
   513  			return nil, err
   514  		}
   515  		startSlot = types.Slot(i)
   516  	}
   517  	beaconState, err := bs.StateGen.StateBySlot(ctx, startSlot)
   518  	if err != nil {
   519  		return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
   520  	}
   521  
   522  	v, b, err := precompute.New(ctx, beaconState)
   523  	if err != nil {
   524  		return nil, status.Errorf(codes.Internal, "Could not set up pre compute instance: %v", err)
   525  	}
   526  	_, b, err = precompute.ProcessAttestations(ctx, beaconState, v, b)
   527  	if err != nil {
   528  		return nil, status.Errorf(codes.Internal, "Could not pre compute attestations: %v", err)
   529  	}
   530  
   531  	p := &ethpb.ValidatorParticipationResponse{
   532  		Epoch:     requestedEpoch,
   533  		Finalized: requestedEpoch <= bs.FinalizationFetcher.FinalizedCheckpt().Epoch,
   534  		Participation: &ethpb.ValidatorParticipation{
   535  			// TODO(7130): Remove these three deprecated fields.
   536  			GlobalParticipationRate:          float32(b.PrevEpochTargetAttested) / float32(b.ActivePrevEpoch),
   537  			VotedEther:                       b.PrevEpochTargetAttested,
   538  			EligibleEther:                    b.ActivePrevEpoch,
   539  			CurrentEpochActiveGwei:           b.ActiveCurrentEpoch,
   540  			CurrentEpochAttestingGwei:        b.CurrentEpochAttested,
   541  			CurrentEpochTargetAttestingGwei:  b.CurrentEpochTargetAttested,
   542  			PreviousEpochActiveGwei:          b.ActivePrevEpoch,
   543  			PreviousEpochAttestingGwei:       b.PrevEpochAttested,
   544  			PreviousEpochTargetAttestingGwei: b.PrevEpochTargetAttested,
   545  			PreviousEpochHeadAttestingGwei:   b.PrevEpochHeadAttested,
   546  		},
   547  	}
   548  
   549  	return p, nil
   550  }
   551  
   552  // GetValidatorQueue retrieves the current validator queue information.
   553  func (bs *Server) GetValidatorQueue(
   554  	ctx context.Context, _ *emptypb.Empty,
   555  ) (*ethpb.ValidatorQueue, error) {
   556  	headState, err := bs.HeadFetcher.HeadState(ctx)
   557  	if err != nil {
   558  		return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
   559  	}
   560  	// Queue the validators whose eligible to activate and sort them by activation eligibility epoch number.
   561  	// Additionally, determine those validators queued to exit
   562  	awaitingExit := make([]types.ValidatorIndex, 0)
   563  	exitEpochs := make([]types.Epoch, 0)
   564  	activationQ := make([]types.ValidatorIndex, 0)
   565  	vals := headState.Validators()
   566  	for idx, validator := range vals {
   567  		eligibleActivated := validator.ActivationEligibilityEpoch != params.BeaconConfig().FarFutureEpoch
   568  		canBeActive := validator.ActivationEpoch >= helpers.ActivationExitEpoch(headState.FinalizedCheckpointEpoch())
   569  		if eligibleActivated && canBeActive {
   570  			activationQ = append(activationQ, types.ValidatorIndex(idx))
   571  		}
   572  		if validator.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
   573  			exitEpochs = append(exitEpochs, validator.ExitEpoch)
   574  			awaitingExit = append(awaitingExit, types.ValidatorIndex(idx))
   575  		}
   576  	}
   577  	sort.Slice(activationQ, func(i, j int) bool {
   578  		return vals[i].ActivationEligibilityEpoch < vals[j].ActivationEligibilityEpoch
   579  	})
   580  	sort.Slice(awaitingExit, func(i, j int) bool {
   581  		return vals[i].WithdrawableEpoch < vals[j].WithdrawableEpoch
   582  	})
   583  
   584  	// Only activate just enough validators according to the activation churn limit.
   585  	activeValidatorCount, err := helpers.ActiveValidatorCount(headState, helpers.CurrentEpoch(headState))
   586  	if err != nil {
   587  		return nil, status.Errorf(codes.Internal, "Could not get active validator count: %v", err)
   588  	}
   589  	churnLimit, err := helpers.ValidatorChurnLimit(activeValidatorCount)
   590  	if err != nil {
   591  		return nil, status.Errorf(codes.Internal, "Could not compute churn limit: %v", err)
   592  	}
   593  
   594  	exitQueueEpoch := types.Epoch(0)
   595  	for _, i := range exitEpochs {
   596  		if exitQueueEpoch < i {
   597  			exitQueueEpoch = i
   598  		}
   599  	}
   600  	exitQueueChurn := uint64(0)
   601  	for _, val := range vals {
   602  		if val.ExitEpoch == exitQueueEpoch {
   603  			exitQueueChurn++
   604  		}
   605  	}
   606  	// Prevent churn limit from causing index out of bound issues.
   607  	if churnLimit < exitQueueChurn {
   608  		// If we are above the churn limit, we simply increase the churn by one.
   609  		exitQueueEpoch++
   610  	}
   611  
   612  	// We use the exit queue churn to determine if we have passed a churn limit.
   613  	minEpoch := exitQueueEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay
   614  	exitQueueIndices := make([]types.ValidatorIndex, 0)
   615  	for _, valIdx := range awaitingExit {
   616  		val := vals[valIdx]
   617  		// Ensure the validator has not yet exited before adding its index to the exit queue.
   618  		if val.WithdrawableEpoch < minEpoch && !validatorHasExited(val, helpers.CurrentEpoch(headState)) {
   619  			exitQueueIndices = append(exitQueueIndices, valIdx)
   620  		}
   621  	}
   622  
   623  	// Get the public keys for the validators in the queues up to the allowed churn limits.
   624  	activationQueueKeys := make([][]byte, len(activationQ))
   625  	exitQueueKeys := make([][]byte, len(exitQueueIndices))
   626  	for i, idx := range activationQ {
   627  		activationQueueKeys[i] = vals[idx].PublicKey
   628  	}
   629  	for i, idx := range exitQueueIndices {
   630  		exitQueueKeys[i] = vals[idx].PublicKey
   631  	}
   632  
   633  	return &ethpb.ValidatorQueue{
   634  		ChurnLimit:                 churnLimit,
   635  		ActivationPublicKeys:       activationQueueKeys,
   636  		ExitPublicKeys:             exitQueueKeys,
   637  		ActivationValidatorIndices: activationQ,
   638  		ExitValidatorIndices:       exitQueueIndices,
   639  	}, nil
   640  }
   641  
   642  // GetValidatorPerformance reports the validator's latest balance along with other important metrics on
   643  // rewards and penalties throughout its lifecycle in the beacon chain.
   644  func (bs *Server) GetValidatorPerformance(
   645  	ctx context.Context, req *ethpb.ValidatorPerformanceRequest,
   646  ) (*ethpb.ValidatorPerformanceResponse, error) {
   647  	if bs.SyncChecker.Syncing() {
   648  		return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond")
   649  	}
   650  
   651  	headState, err := bs.HeadFetcher.HeadState(ctx)
   652  	if err != nil {
   653  		return nil, status.Errorf(codes.Internal, "Could not get head state: %v", err)
   654  	}
   655  
   656  	if bs.GenesisTimeFetcher.CurrentSlot() > headState.Slot() {
   657  		headState, err = state.ProcessSlots(ctx, headState, bs.GenesisTimeFetcher.CurrentSlot())
   658  		if err != nil {
   659  			return nil, status.Errorf(codes.Internal, "Could not process slots: %v", err)
   660  		}
   661  	}
   662  	vp, bp, err := precompute.New(ctx, headState)
   663  	if err != nil {
   664  		return nil, err
   665  	}
   666  	vp, bp, err = precompute.ProcessAttestations(ctx, headState, vp, bp)
   667  	if err != nil {
   668  		return nil, err
   669  	}
   670  	headState, err = precompute.ProcessRewardsAndPenaltiesPrecompute(headState, bp, vp, precompute.AttestationsDelta, precompute.ProposersDelta)
   671  	if err != nil {
   672  		return nil, err
   673  	}
   674  	validatorSummary := vp
   675  
   676  	responseCap := len(req.Indices) + len(req.PublicKeys)
   677  	validatorIndices := make([]types.ValidatorIndex, 0, responseCap)
   678  	missingValidators := make([][]byte, 0, responseCap)
   679  
   680  	filtered := map[types.ValidatorIndex]bool{} // Track filtered validators to prevent duplication in the response.
   681  	// Convert the list of validator public keys to validator indices and add to the indices set.
   682  	for _, pubKey := range req.PublicKeys {
   683  		// Skip empty public key.
   684  		if len(pubKey) == 0 {
   685  			continue
   686  		}
   687  		pubkeyBytes := bytesutil.ToBytes48(pubKey)
   688  		idx, ok := headState.ValidatorIndexByPubkey(pubkeyBytes)
   689  		if !ok {
   690  			// Validator index not found, track as missing.
   691  			missingValidators = append(missingValidators, pubKey)
   692  			continue
   693  		}
   694  		if !filtered[idx] {
   695  			validatorIndices = append(validatorIndices, idx)
   696  			filtered[idx] = true
   697  		}
   698  	}
   699  	// Add provided indices to the indices set.
   700  	for _, idx := range req.Indices {
   701  		if !filtered[idx] {
   702  			validatorIndices = append(validatorIndices, idx)
   703  			filtered[idx] = true
   704  		}
   705  	}
   706  	// Depending on the indices and public keys given, results might not be sorted.
   707  	sort.Slice(validatorIndices, func(i, j int) bool {
   708  		return validatorIndices[i] < validatorIndices[j]
   709  	})
   710  
   711  	currentEpoch := helpers.CurrentEpoch(headState)
   712  	responseCap = len(validatorIndices)
   713  	pubKeys := make([][]byte, 0, responseCap)
   714  	beforeTransitionBalances := make([]uint64, 0, responseCap)
   715  	afterTransitionBalances := make([]uint64, 0, responseCap)
   716  	effectiveBalances := make([]uint64, 0, responseCap)
   717  	inclusionSlots := make([]types.Slot, 0, responseCap)
   718  	inclusionDistances := make([]types.Slot, 0, responseCap)
   719  	correctlyVotedSource := make([]bool, 0, responseCap)
   720  	correctlyVotedTarget := make([]bool, 0, responseCap)
   721  	correctlyVotedHead := make([]bool, 0, responseCap)
   722  	// Append performance summaries.
   723  	// Also track missing validators using public keys.
   724  	for _, idx := range validatorIndices {
   725  		val, err := headState.ValidatorAtIndexReadOnly(idx)
   726  		if err != nil {
   727  			return nil, status.Errorf(codes.Internal, "could not get validator: %v", err)
   728  		}
   729  		pubKey := val.PublicKey()
   730  		if uint64(idx) >= uint64(len(validatorSummary)) {
   731  			// Not listed in validator summary yet; treat it as missing.
   732  			missingValidators = append(missingValidators, pubKey[:])
   733  			continue
   734  		}
   735  		if !helpers.IsActiveValidatorUsingTrie(val, currentEpoch) {
   736  			// Inactive validator; treat it as missing.
   737  			missingValidators = append(missingValidators, pubKey[:])
   738  			continue
   739  		}
   740  
   741  		summary := validatorSummary[idx]
   742  		pubKeys = append(pubKeys, pubKey[:])
   743  		effectiveBalances = append(effectiveBalances, summary.CurrentEpochEffectiveBalance)
   744  		beforeTransitionBalances = append(beforeTransitionBalances, summary.BeforeEpochTransitionBalance)
   745  		afterTransitionBalances = append(afterTransitionBalances, summary.AfterEpochTransitionBalance)
   746  		inclusionSlots = append(inclusionSlots, summary.InclusionSlot)
   747  		inclusionDistances = append(inclusionDistances, summary.InclusionDistance)
   748  		correctlyVotedSource = append(correctlyVotedSource, summary.IsPrevEpochAttester)
   749  		correctlyVotedTarget = append(correctlyVotedTarget, summary.IsPrevEpochTargetAttester)
   750  		correctlyVotedHead = append(correctlyVotedHead, summary.IsPrevEpochHeadAttester)
   751  	}
   752  
   753  	return &ethpb.ValidatorPerformanceResponse{
   754  		PublicKeys:                    pubKeys,
   755  		InclusionSlots:                inclusionSlots,
   756  		InclusionDistances:            inclusionDistances,
   757  		CorrectlyVotedSource:          correctlyVotedSource,
   758  		CorrectlyVotedTarget:          correctlyVotedTarget,
   759  		CorrectlyVotedHead:            correctlyVotedHead,
   760  		CurrentEffectiveBalances:      effectiveBalances,
   761  		BalancesBeforeEpochTransition: beforeTransitionBalances,
   762  		BalancesAfterEpochTransition:  afterTransitionBalances,
   763  		MissingValidators:             missingValidators,
   764  	}, nil
   765  }
   766  
   767  // GetIndividualVotes retrieves individual voting status of validators.
   768  func (bs *Server) GetIndividualVotes(
   769  	ctx context.Context,
   770  	req *ethpb.IndividualVotesRequest,
   771  ) (*ethpb.IndividualVotesRespond, error) {
   772  	currentEpoch := helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
   773  	if req.Epoch > currentEpoch {
   774  		return nil, status.Errorf(
   775  			codes.InvalidArgument,
   776  			errEpoch,
   777  			currentEpoch,
   778  			req.Epoch,
   779  		)
   780  	}
   781  
   782  	s, err := helpers.StartSlot(req.Epoch)
   783  	if err != nil {
   784  		return nil, err
   785  	}
   786  	requestedState, err := bs.StateGen.StateBySlot(ctx, s)
   787  	if err != nil {
   788  		return nil, status.Errorf(codes.Internal, "Could not retrieve archived state for epoch %d: %v", req.Epoch, err)
   789  	}
   790  	// Track filtered validators to prevent duplication in the response.
   791  	filtered := map[types.ValidatorIndex]bool{}
   792  	filteredIndices := make([]types.ValidatorIndex, 0)
   793  	votes := make([]*ethpb.IndividualVotesRespond_IndividualVote, 0, len(req.Indices)+len(req.PublicKeys))
   794  	// Filter out assignments by public keys.
   795  	for _, pubKey := range req.PublicKeys {
   796  		index, ok := requestedState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey))
   797  		if !ok {
   798  			votes = append(votes, &ethpb.IndividualVotesRespond_IndividualVote{PublicKey: pubKey, ValidatorIndex: types.ValidatorIndex(^uint64(0))})
   799  			continue
   800  		}
   801  		filtered[index] = true
   802  		filteredIndices = append(filteredIndices, index)
   803  	}
   804  	// Filter out assignments by validator indices.
   805  	for _, index := range req.Indices {
   806  		if !filtered[index] {
   807  			filteredIndices = append(filteredIndices, index)
   808  		}
   809  	}
   810  	sort.Slice(filteredIndices, func(i, j int) bool {
   811  		return filteredIndices[i] < filteredIndices[j]
   812  	})
   813  
   814  	v, bal, err := precompute.New(ctx, requestedState)
   815  	if err != nil {
   816  		return nil, status.Errorf(codes.Internal, "Could not set up pre compute instance: %v", err)
   817  	}
   818  	v, _, err = precompute.ProcessAttestations(ctx, requestedState, v, bal)
   819  	if err != nil {
   820  		return nil, status.Errorf(codes.Internal, "Could not pre compute attestations: %v", err)
   821  	}
   822  	for _, index := range filteredIndices {
   823  		if uint64(index) >= uint64(len(v)) {
   824  			votes = append(votes, &ethpb.IndividualVotesRespond_IndividualVote{ValidatorIndex: index})
   825  			continue
   826  		}
   827  		val, err := requestedState.ValidatorAtIndexReadOnly(index)
   828  		if err != nil {
   829  			return nil, status.Errorf(codes.Internal, "Could not retrieve validator: %v", err)
   830  
   831  		}
   832  		pb := val.PublicKey()
   833  		votes = append(votes, &ethpb.IndividualVotesRespond_IndividualVote{
   834  			Epoch:                            req.Epoch,
   835  			PublicKey:                        pb[:],
   836  			ValidatorIndex:                   index,
   837  			IsSlashed:                        v[index].IsSlashed,
   838  			IsWithdrawableInCurrentEpoch:     v[index].IsWithdrawableCurrentEpoch,
   839  			IsActiveInCurrentEpoch:           v[index].IsActiveCurrentEpoch,
   840  			IsActiveInPreviousEpoch:          v[index].IsActivePrevEpoch,
   841  			IsCurrentEpochAttester:           v[index].IsCurrentEpochAttester,
   842  			IsCurrentEpochTargetAttester:     v[index].IsCurrentEpochTargetAttester,
   843  			IsPreviousEpochAttester:          v[index].IsPrevEpochAttester,
   844  			IsPreviousEpochTargetAttester:    v[index].IsPrevEpochTargetAttester,
   845  			IsPreviousEpochHeadAttester:      v[index].IsPrevEpochHeadAttester,
   846  			CurrentEpochEffectiveBalanceGwei: v[index].CurrentEpochEffectiveBalance,
   847  			InclusionSlot:                    v[index].InclusionSlot,
   848  			InclusionDistance:                v[index].InclusionDistance,
   849  		})
   850  	}
   851  
   852  	return &ethpb.IndividualVotesRespond{
   853  		IndividualVotes: votes,
   854  	}, nil
   855  }
   856  
   857  // isSlotCanonical returns true if the input slot has a canonical block in the chain,
   858  // if the input slot has a skip block, false is returned,
   859  // if the input slot has more than one block, an error is returned.
   860  func (bs *Server) isSlotCanonical(ctx context.Context, slot types.Slot) (bool, error) {
   861  	if slot == 0 {
   862  		return true, nil
   863  	}
   864  
   865  	hasBlockRoots, roots, err := bs.BeaconDB.BlockRootsBySlot(ctx, slot)
   866  	if err != nil {
   867  		return false, err
   868  	}
   869  	if !hasBlockRoots {
   870  		return false, nil
   871  	}
   872  
   873  	// Loop through all roots in slot, and
   874  	// check which one is canonical.
   875  	for _, rt := range roots {
   876  		canonical, err := bs.CanonicalFetcher.IsCanonical(ctx, rt)
   877  		if err != nil {
   878  			return false, err
   879  		}
   880  		if canonical {
   881  			return true, nil
   882  		}
   883  
   884  	}
   885  	return false, nil
   886  }
   887  
   888  // Determines whether a validator has already exited.
   889  func validatorHasExited(validator *ethpb.Validator, currentEpoch types.Epoch) bool {
   890  	farFutureEpoch := params.BeaconConfig().FarFutureEpoch
   891  	if currentEpoch < validator.ActivationEligibilityEpoch {
   892  		return false
   893  	}
   894  	if currentEpoch < validator.ActivationEpoch {
   895  		return false
   896  	}
   897  	if validator.ExitEpoch == farFutureEpoch {
   898  		return false
   899  	}
   900  	if currentEpoch < validator.ExitEpoch {
   901  		if validator.Slashed {
   902  			return false
   903  		}
   904  		return false
   905  	}
   906  	return true
   907  }
   908  
   909  func validatorStatus(validator *ethpb.Validator, epoch types.Epoch) ethpb.ValidatorStatus {
   910  	farFutureEpoch := params.BeaconConfig().FarFutureEpoch
   911  	if validator == nil {
   912  		return ethpb.ValidatorStatus_UNKNOWN_STATUS
   913  	}
   914  	if epoch < validator.ActivationEligibilityEpoch {
   915  		return ethpb.ValidatorStatus_DEPOSITED
   916  	}
   917  	if epoch < validator.ActivationEpoch {
   918  		return ethpb.ValidatorStatus_PENDING
   919  	}
   920  	if validator.ExitEpoch == farFutureEpoch {
   921  		return ethpb.ValidatorStatus_ACTIVE
   922  	}
   923  	if epoch < validator.ExitEpoch {
   924  		if validator.Slashed {
   925  			return ethpb.ValidatorStatus_SLASHING
   926  		}
   927  		return ethpb.ValidatorStatus_EXITING
   928  	}
   929  	return ethpb.ValidatorStatus_EXITED
   930  }