prysm-pulse/validator/client/beacon-api/state_validators.go
2023-11-29 18:53:26 +01:00

108 lines
3.4 KiB
Go

package beacon_api
import (
"bytes"
"context"
"encoding/json"
"fmt"
"strconv"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
)
type StateValidatorsProvider interface {
GetStateValidators(context.Context, []string, []primitives.ValidatorIndex, []string) (*beacon.GetValidatorsResponse, error)
GetStateValidatorsForSlot(context.Context, primitives.Slot, []string, []primitives.ValidatorIndex, []string) (*beacon.GetValidatorsResponse, error)
GetStateValidatorsForHead(context.Context, []string, []primitives.ValidatorIndex, []string) (*beacon.GetValidatorsResponse, error)
}
type beaconApiStateValidatorsProvider struct {
jsonRestHandler JsonRestHandler
}
func (c beaconApiStateValidatorsProvider) GetStateValidators(
ctx context.Context,
stringPubkeys []string,
indexes []primitives.ValidatorIndex,
statuses []string,
) (*beacon.GetValidatorsResponse, error) {
stringIndices := convertValidatorIndicesToStrings(indexes)
return c.getStateValidatorsHelper(ctx, "/eth/v1/beacon/states/head/validators", append(stringIndices, stringPubkeys...), statuses)
}
func (c beaconApiStateValidatorsProvider) GetStateValidatorsForSlot(
ctx context.Context,
slot primitives.Slot,
stringPubkeys []string,
indices []primitives.ValidatorIndex,
statuses []string,
) (*beacon.GetValidatorsResponse, error) {
stringIndices := convertValidatorIndicesToStrings(indices)
url := fmt.Sprintf("/eth/v1/beacon/states/%d/validators", slot)
return c.getStateValidatorsHelper(ctx, url, append(stringIndices, stringPubkeys...), statuses)
}
func (c beaconApiStateValidatorsProvider) GetStateValidatorsForHead(
ctx context.Context,
stringPubkeys []string,
indices []primitives.ValidatorIndex,
statuses []string,
) (*beacon.GetValidatorsResponse, error) {
stringIndices := convertValidatorIndicesToStrings(indices)
return c.getStateValidatorsHelper(ctx, "/eth/v1/beacon/states/head/validators", append(stringIndices, stringPubkeys...), statuses)
}
func convertValidatorIndicesToStrings(indices []primitives.ValidatorIndex) []string {
var result []string
indicesSet := make(map[primitives.ValidatorIndex]struct{}, len(indices))
for _, index := range indices {
if _, ok := indicesSet[index]; !ok {
indicesSet[index] = struct{}{}
result = append(result, strconv.FormatUint(uint64(index), 10))
}
}
return result
}
func (c beaconApiStateValidatorsProvider) getStateValidatorsHelper(
ctx context.Context,
endpoint string,
vals []string,
statuses []string,
) (*beacon.GetValidatorsResponse, error) {
req := beacon.GetValidatorsRequest{
Ids: []string{},
Statuses: []string{},
}
req.Statuses = append(req.Statuses, statuses...)
valSet := make(map[string]struct{}, len(vals))
for _, v := range vals {
if _, ok := valSet[v]; !ok {
valSet[v] = struct{}{}
req.Ids = append(req.Ids, v)
}
}
reqBytes, err := json.Marshal(req)
if err != nil {
return nil, errors.Wrapf(err, "failed to marshal request into JSON")
}
stateValidatorsJson := &beacon.GetValidatorsResponse{}
errJson, err := c.jsonRestHandler.Post(ctx, endpoint, nil, bytes.NewBuffer(reqBytes), stateValidatorsJson)
if err != nil {
return nil, errors.Wrapf(err, msgUnexpectedError)
}
if errJson != nil {
return nil, errJson
}
if stateValidatorsJson.Data == nil {
return nil, errors.New("stateValidatorsJson.Data is nil")
}
return stateValidatorsJson, nil
}