mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
integrate validator count endpoint in validator client (#12912)
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
parent
d7318ea485
commit
2806326155
@ -162,7 +162,7 @@ func validatorCountByStatus(validators []*eth.Validator, statuses []validator.Va
|
||||
var resp []*ValidatorCount
|
||||
for status, count := range countByStatus {
|
||||
resp = append(resp, &ValidatorCount{
|
||||
Status: strings.ToLower(ethpb.ValidatorStatus_name[int32(status)]),
|
||||
Status: status.String(),
|
||||
Count: strconv.FormatUint(count, 10),
|
||||
})
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ done
|
||||
# --------------------------------------------------------
|
||||
iface_mocks=(
|
||||
"$iface_mock_path/beacon_chain_client_mock.go BeaconChainClient"
|
||||
"$iface_mock_path/prysm_beacon_chain_client_mock.go PrysmBeaconChainClient"
|
||||
"$iface_mock_path/node_client_mock.go NodeClient"
|
||||
"$iface_mock_path/slasher_client_mock.go SlasherClient"
|
||||
"$iface_mock_path/validator_client_mock.go ValidatorClient"
|
||||
|
@ -7,13 +7,16 @@ go_library(
|
||||
srcs = [
|
||||
"beacon_chain_client_mock.go",
|
||||
"node_client_mock.go",
|
||||
"prysm_beacon_chain_client_mock.go",
|
||||
"validator_client_mock.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v4/testing/validator-mock",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@com_github_golang_mock//gomock:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
],
|
||||
|
52
testing/validator-mock/prysm_beacon_chain_client_mock.go
generated
Normal file
52
testing/validator-mock/prysm_beacon_chain_client_mock.go
generated
Normal file
@ -0,0 +1,52 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/prysmaticlabs/prysm/v4/validator/client/iface (interfaces: PrysmBeaconChainClient)
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package validator_mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
validator "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
iface "github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
)
|
||||
|
||||
// MockPrysmBeaconChainClient is a mock of PrysmBeaconChainClient interface.
|
||||
type MockPrysmBeaconChainClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockPrysmBeaconChainClientMockRecorder
|
||||
}
|
||||
|
||||
// MockPrysmBeaconChainClientMockRecorder is the mock recorder for MockPrysmBeaconChainClient.
|
||||
type MockPrysmBeaconChainClientMockRecorder struct {
|
||||
mock *MockPrysmBeaconChainClient
|
||||
}
|
||||
|
||||
// NewMockPrysmBeaconChainClient creates a new mock instance.
|
||||
func NewMockPrysmBeaconChainClient(ctrl *gomock.Controller) *MockPrysmBeaconChainClient {
|
||||
mock := &MockPrysmBeaconChainClient{ctrl: ctrl}
|
||||
mock.recorder = &MockPrysmBeaconChainClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockPrysmBeaconChainClient) EXPECT() *MockPrysmBeaconChainClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetValidatorCount mocks base method.
|
||||
func (m *MockPrysmBeaconChainClient) GetValidatorCount(arg0 context.Context, arg1 string, arg2 []validator.ValidatorStatus) ([]iface.ValidatorCount, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetValidatorCount", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].([]iface.ValidatorCount)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetValidatorCount indicates an expected call of GetValidatorCount.
|
||||
func (mr *MockPrysmBeaconChainClientMockRecorder) GetValidatorCount(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorCount", reflect.TypeOf((*MockPrysmBeaconChainClient)(nil).GetValidatorCount), arg0, arg1, arg2)
|
||||
}
|
@ -41,6 +41,7 @@ go_library(
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//crypto/rand:go_default_library",
|
||||
|
@ -24,6 +24,7 @@ go_library(
|
||||
"propose_attestation.go",
|
||||
"propose_beacon_block.go",
|
||||
"propose_exit.go",
|
||||
"prysm_beacon_chain_client.go",
|
||||
"registration.go",
|
||||
"state_validators.go",
|
||||
"status.go",
|
||||
@ -48,6 +49,7 @@ go_library(
|
||||
"//beacon-chain/rpc/prysm/validator:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//network/forks:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
@ -105,6 +107,7 @@ go_test(
|
||||
"submit_signed_contribution_and_proof_test.go",
|
||||
"subscribe_committee_subnets_test.go",
|
||||
"sync_committee_test.go",
|
||||
"validator_count_test.go",
|
||||
"wait_for_chain_start_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
@ -118,14 +121,17 @@ go_test(
|
||||
"//beacon-chain/rpc/prysm/validator:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/validator-mock:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"//validator/client/beacon-api/mock:go_default_library",
|
||||
"//validator/client/beacon-api/test-helpers:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_mock//gomock:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
|
@ -20,6 +20,7 @@ type beaconApiValidatorClient struct {
|
||||
stateValidatorsProvider stateValidatorsProvider
|
||||
jsonRestHandler jsonRestHandler
|
||||
beaconBlockConverter beaconBlockConverter
|
||||
prysmBeaconChainCLient iface.PrysmBeaconChainClient
|
||||
}
|
||||
|
||||
func NewBeaconApiValidatorClient(host string, timeout time.Duration) iface.ValidatorClient {
|
||||
@ -34,6 +35,10 @@ func NewBeaconApiValidatorClient(host string, timeout time.Duration) iface.Valid
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler},
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
beaconBlockConverter: beaconApiBeaconBlockConverter{},
|
||||
prysmBeaconChainCLient: prysmBeaconChainClient{
|
||||
nodeClient: &beaconApiNodeClient{jsonRestHandler: jsonRestHandler},
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,9 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
validatormock "github.com/prysmaticlabs/prysm/v4/testing/validator-mock"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
|
||||
@ -1259,10 +1262,21 @@ func TestGetDuties_Valid(t *testing.T) {
|
||||
nil,
|
||||
).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
|
||||
validatorClient := &beaconApiValidatorClient{
|
||||
dutiesProvider: dutiesProvider,
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
prysmBeaconChainCLient: prysmBeaconChainClient,
|
||||
}
|
||||
|
||||
expectedCurrentEpochDuties, err := validatorClient.getDutiesForEpoch(
|
||||
@ -1356,9 +1370,20 @@ func TestGetDuties_GetDutiesForEpochFailed(t *testing.T) {
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
prysmBeaconChainClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
prysmBeaconChainClient.EXPECT().GetValidatorCount(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
iface.ErrNotSupported,
|
||||
).MinTimes(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
dutiesProvider: dutiesProvider,
|
||||
prysmBeaconChainCLient: prysmBeaconChainClient,
|
||||
}
|
||||
|
||||
_, err := validatorClient.getDuties(ctx, ðpb.DutiesRequest{
|
||||
|
4
validator/client/beacon-api/mock/duties_mock.go
generated
4
validator/client/beacon-api/mock/duties_mock.go
generated
@ -9,8 +9,8 @@ import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator"
|
||||
shared "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
|
||||
validator "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator"
|
||||
primitives "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||
)
|
||||
|
||||
|
2
validator/client/beacon-api/mock/genesis_mock.go
generated
2
validator/client/beacon-api/mock/genesis_mock.go
generated
@ -10,7 +10,7 @@ import (
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
apimiddleware "github.com/prysmaticlabs/prysm/v4/api/gateway/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
|
||||
beacon "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
|
||||
)
|
||||
|
||||
// MockgenesisProvider is a mock of genesisProvider interface.
|
||||
|
81
validator/client/beacon-api/prysm_beacon_chain_client.go
Normal file
81
validator/client/beacon-api/prysm_beacon_chain_client.go
Normal file
@ -0,0 +1,81 @@
|
||||
package beacon_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
neturl "net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/validator"
|
||||
validator2 "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
)
|
||||
|
||||
// NewPrysmBeaconChainClient returns implementation of iface.PrysmBeaconChainClient.
|
||||
func NewPrysmBeaconChainClient(host string, timeout time.Duration, nodeClient iface.NodeClient) iface.PrysmBeaconChainClient {
|
||||
jsonRestHandler := beaconApiJsonRestHandler{
|
||||
httpClient: http.Client{Timeout: timeout},
|
||||
host: host,
|
||||
}
|
||||
|
||||
return prysmBeaconChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
nodeClient: nodeClient,
|
||||
}
|
||||
}
|
||||
|
||||
type prysmBeaconChainClient struct {
|
||||
jsonRestHandler jsonRestHandler
|
||||
nodeClient iface.NodeClient
|
||||
}
|
||||
|
||||
func (c prysmBeaconChainClient) GetValidatorCount(ctx context.Context, stateID string, statuses []validator2.ValidatorStatus) ([]iface.ValidatorCount, error) {
|
||||
// Check node version for prysm beacon node as it is a custom endpoint for prysm beacon node.
|
||||
nodeVersion, err := c.nodeClient.GetVersion(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get node version")
|
||||
}
|
||||
|
||||
if !strings.Contains(strings.ToLower(nodeVersion.Version), "prysm") {
|
||||
return nil, iface.ErrNotSupported
|
||||
}
|
||||
|
||||
queryParams := neturl.Values{}
|
||||
for _, status := range statuses {
|
||||
queryParams.Add("status", status.String())
|
||||
}
|
||||
|
||||
queryUrl := buildURL(fmt.Sprintf("/eth/v1/beacon/states/%s/validator_count", stateID), queryParams)
|
||||
|
||||
var validatorCountResponse validator.ValidatorCountResponse
|
||||
if _, err := c.jsonRestHandler.GetRestJsonResponse(ctx, queryUrl, &validatorCountResponse); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to query GET REST endpoint")
|
||||
}
|
||||
|
||||
if validatorCountResponse.Data == nil {
|
||||
return nil, errors.New("validator count data is nil")
|
||||
}
|
||||
|
||||
if len(statuses) != 0 && len(statuses) != len(validatorCountResponse.Data) {
|
||||
return nil, errors.New("mismatch between validator count data and the number of statuses provided")
|
||||
}
|
||||
|
||||
var resp []iface.ValidatorCount
|
||||
for _, vc := range validatorCountResponse.Data {
|
||||
count, err := strconv.ParseUint(vc.Count, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse validator count %s", vc.Count)
|
||||
}
|
||||
|
||||
resp = append(resp, iface.ValidatorCount{
|
||||
Status: vc.Status,
|
||||
Count: count,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||
@ -73,12 +75,32 @@ func (c *beaconApiValidatorClient) getValidatorsStatusResponse(ctx context.Conte
|
||||
return nil, nil, nil, errors.Wrap(err, "failed to get state validators")
|
||||
}
|
||||
|
||||
isLastActivatedValidatorIndexRetrieved := false
|
||||
var lastActivatedValidatorIndex uint64 = 0
|
||||
validatorsCountResponse, err := c.prysmBeaconChainCLient.GetValidatorCount(ctx, "head", nil)
|
||||
if err != nil && !errors.Is(err, iface.ErrNotSupported) {
|
||||
return nil, nil, nil, errors.Wrap(err, "failed to get total validator count")
|
||||
}
|
||||
|
||||
var total, pending uint64
|
||||
for _, valCount := range validatorsCountResponse {
|
||||
if valCount.Status == "pending" {
|
||||
pending = valCount.Count
|
||||
} else {
|
||||
total += valCount.Count
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate last activated validator's index, it will be -1 whenever all validators are pending.
|
||||
lastActivatedValidatorIndex := int(total - pending - 1)
|
||||
|
||||
for i, validatorContainer := range stateValidatorsResponse.Data {
|
||||
stringPubKey := validatorContainer.Validator.Pubkey
|
||||
validatorIndex, err := strconv.ParseUint(validatorContainer.Index, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrapf(err, "failed to parse validator index %s", validatorContainer.Index)
|
||||
}
|
||||
|
||||
outIndexes[i] = primitives.ValidatorIndex(validatorIndex)
|
||||
|
||||
stringPubKey := validatorContainer.Validator.Pubkey
|
||||
stringRetrievedPubKeys[stringPubKey] = struct{}{}
|
||||
|
||||
pubKey, ok := stringTargetPubKeysToPubKeys[stringPubKey]
|
||||
@ -90,14 +112,7 @@ func (c *beaconApiValidatorClient) getValidatorsStatusResponse(ctx context.Conte
|
||||
}
|
||||
}
|
||||
|
||||
validatorIndex, err := strconv.ParseUint(validatorContainer.Index, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrapf(err, "failed to parse validator index %s", validatorContainer.Index)
|
||||
}
|
||||
|
||||
outPubKeys[i] = pubKey
|
||||
outIndexes[i] = primitives.ValidatorIndex(validatorIndex)
|
||||
|
||||
validatorStatus := ðpb.ValidatorStatusResponse{}
|
||||
|
||||
// Set Status
|
||||
@ -119,28 +134,9 @@ func (c *beaconApiValidatorClient) getValidatorsStatusResponse(ctx context.Conte
|
||||
// Set PositionInActivationQueue
|
||||
switch status {
|
||||
case ethpb.ValidatorStatus_PENDING, ethpb.ValidatorStatus_PARTIALLY_DEPOSITED, ethpb.ValidatorStatus_DEPOSITED:
|
||||
if !isLastActivatedValidatorIndexRetrieved {
|
||||
isLastActivatedValidatorIndexRetrieved = true
|
||||
// TODO: double check this due to potential of PENDING STATE being active..
|
||||
// edge case https://github.com/prysmaticlabs/prysm/blob/0669050ffabe925c3d6e5e5d535a86361ae8522b/validator/client/validator.go#L1068
|
||||
activeStateValidators, err := c.stateValidatorsProvider.GetStateValidators(ctx, nil, nil, []string{"active"})
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrap(err, "failed to get state validators")
|
||||
if lastActivatedValidatorIndex >= 0 {
|
||||
validatorStatus.PositionInActivationQueue = validatorIndex - uint64(lastActivatedValidatorIndex)
|
||||
}
|
||||
|
||||
data := activeStateValidators.Data
|
||||
|
||||
if nbActiveValidators := len(data); nbActiveValidators != 0 {
|
||||
lastValidator := data[nbActiveValidators-1]
|
||||
|
||||
lastActivatedValidatorIndex, err = strconv.ParseUint(lastValidator.Index, 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, nil, errors.Wrapf(err, "failed to parse last validator index %s", lastValidator.Index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
validatorStatus.PositionInActivationQueue = validatorIndex - lastActivatedValidatorIndex
|
||||
}
|
||||
|
||||
outValidatorsStatuses[i] = validatorStatus
|
||||
|
@ -6,6 +6,10 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
|
||||
validator2 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/validator"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
|
||||
@ -50,7 +54,26 @@ func TestValidatorStatus_Nominal(t *testing.T) {
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
prysmBeaconChainCLient: prysmBeaconChainClient{
|
||||
nodeClient: &beaconApiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
nil,
|
||||
iface.ErrNotSupported,
|
||||
).Times(1)
|
||||
|
||||
actualValidatorStatusResponse, err := validatorClient.ValidatorStatus(
|
||||
ctx,
|
||||
@ -147,7 +170,27 @@ func TestMultipleValidatorStatus_Nominal(t *testing.T) {
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
nil,
|
||||
iface.ErrNotSupported,
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
prysmBeaconChainCLient: prysmBeaconChainClient{
|
||||
nodeClient: &beaconApiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expectedValidatorStatusResponse := ethpb.MultipleValidatorStatusResponse{
|
||||
PublicKeys: validatorsPubKey,
|
||||
@ -289,33 +332,44 @@ func TestGetValidatorsStatusResponse_Nominal_SomeActiveValidators(t *testing.T)
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
||||
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
nil,
|
||||
nil,
|
||||
[]string{"active"},
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
&beacon.GetValidatorsResponse{
|
||||
Data: []*beacon.ValidatorContainer{
|
||||
{
|
||||
Index: "35000",
|
||||
Status: "active_ongoing",
|
||||
Validator: &beacon.Validator{
|
||||
Pubkey: "0x8000ab56b051f9d8f31c687528c6e91c9b98e4c3a241e752f9ccfbea7c5a7fbbd272bdf2c0a7e52ce7e0b57693df364d",
|
||||
ActivationEpoch: "56",
|
||||
},
|
||||
},
|
||||
{
|
||||
Index: "39000",
|
||||
Status: "active_ongoing",
|
||||
Validator: &beacon.Validator{
|
||||
Pubkey: "0x8000ab56b051f9d8f31c687528c6e91c9b98e4c3a241e752f9ccfbea7c5a7fbbd272bdf2c0a7e52ce7e0b57693df364e",
|
||||
ActivationEpoch: "56",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
apimiddleware.VersionResponseJson{Data: &apimiddleware.VersionJson{Version: "prysm/v0.0.1"}},
|
||||
).Times(1)
|
||||
|
||||
var validatorCountResponse validator2.ValidatorCountResponse
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
"/eth/v1/beacon/states/head/validator_count?",
|
||||
&validatorCountResponse,
|
||||
).Return(
|
||||
nil,
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
validator2.ValidatorCountResponse{
|
||||
Data: []*validator2.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: "50001",
|
||||
},
|
||||
{
|
||||
Status: "pending",
|
||||
Count: "11000",
|
||||
},
|
||||
},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
wantedStringValidatorsPubkey := []string{
|
||||
@ -379,7 +433,15 @@ func TestGetValidatorsStatusResponse_Nominal_SomeActiveValidators(t *testing.T)
|
||||
},
|
||||
}
|
||||
|
||||
validatorClient := beaconApiValidatorClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
prysmBeaconChainCLient: prysmBeaconChainClient{
|
||||
nodeClient: &beaconApiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
}
|
||||
actualValidatorsPubKey, actualValidatorsIndex, actualValidatorsStatusResponse, err := validatorClient.getValidatorsStatusResponse(ctx, validatorsPubKey, validatorsIndex)
|
||||
|
||||
require.NoError(t, err)
|
||||
@ -420,16 +482,17 @@ func TestGetValidatorsStatusResponse_Nominal_NoActiveValidators(t *testing.T) {
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
||||
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
nil,
|
||||
nil,
|
||||
[]string{"active"},
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
&beacon.GetValidatorsResponse{
|
||||
Data: []*beacon.ValidatorContainer{},
|
||||
},
|
||||
nil,
|
||||
iface.ErrNotSupported,
|
||||
).Times(1)
|
||||
|
||||
wantedValidatorsPubKey := [][]byte{validatorPubKey}
|
||||
@ -438,11 +501,18 @@ func TestGetValidatorsStatusResponse_Nominal_NoActiveValidators(t *testing.T) {
|
||||
{
|
||||
Status: ethpb.ValidatorStatus_PENDING,
|
||||
ActivationEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
PositionInActivationQueue: 40000,
|
||||
},
|
||||
}
|
||||
|
||||
validatorClient := beaconApiValidatorClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
prysmBeaconChainCLient: prysmBeaconChainClient{
|
||||
nodeClient: &beaconApiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
}
|
||||
actualValidatorsPubKey, actualValidatorsIndex, actualValidatorsStatusResponse, err := validatorClient.getValidatorsStatusResponse(ctx, wantedValidatorsPubKey, nil)
|
||||
|
||||
require.NoError(t, err)
|
||||
@ -474,26 +544,21 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
// Inputs
|
||||
inputPubKeys [][]byte
|
||||
inputIndexes []int64
|
||||
inputGetStateValidatorsInterfaces []getStateValidatorsInterface
|
||||
inputGetStateValidatorsInterface getStateValidatorsInterface
|
||||
validatorCountCalled int
|
||||
|
||||
// Outputs
|
||||
outputErrMessage string
|
||||
}{
|
||||
{
|
||||
name: "failed getStateValidators",
|
||||
|
||||
inputPubKeys: [][]byte{pubKey},
|
||||
inputIndexes: nil,
|
||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
||||
{
|
||||
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||
inputStringPubKeys: []string{stringPubKey},
|
||||
inputIndexes: nil,
|
||||
inputStatuses: nil,
|
||||
|
||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{},
|
||||
outputErr: errors.New("a specific error"),
|
||||
},
|
||||
},
|
||||
outputErrMessage: "failed to get state validators",
|
||||
},
|
||||
{
|
||||
@ -501,8 +566,7 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
|
||||
inputPubKeys: [][]byte{pubKey},
|
||||
inputIndexes: nil,
|
||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
||||
{
|
||||
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||
inputStringPubKeys: []string{stringPubKey},
|
||||
inputIndexes: nil,
|
||||
inputStatuses: nil,
|
||||
@ -510,6 +574,7 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||
Data: []*beacon.ValidatorContainer{
|
||||
{
|
||||
Index: "0",
|
||||
Validator: &beacon.Validator{
|
||||
Pubkey: "NotAPublicKey",
|
||||
},
|
||||
@ -518,7 +583,7 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
},
|
||||
outputErr: nil,
|
||||
},
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
outputErrMessage: "failed to parse validator public key",
|
||||
},
|
||||
{
|
||||
@ -526,8 +591,8 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
|
||||
inputPubKeys: [][]byte{pubKey},
|
||||
inputIndexes: nil,
|
||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
||||
{
|
||||
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||
|
||||
inputStringPubKeys: []string{stringPubKey},
|
||||
inputIndexes: nil,
|
||||
inputStatuses: nil,
|
||||
@ -544,7 +609,7 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
},
|
||||
outputErr: nil,
|
||||
},
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
outputErrMessage: "failed to parse validator index",
|
||||
},
|
||||
{
|
||||
@ -552,8 +617,7 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
|
||||
inputPubKeys: [][]byte{pubKey},
|
||||
inputIndexes: nil,
|
||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
||||
{
|
||||
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||
inputStringPubKeys: []string{stringPubKey},
|
||||
inputIndexes: nil,
|
||||
inputStatuses: nil,
|
||||
@ -571,7 +635,7 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
},
|
||||
outputErr: nil,
|
||||
},
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
outputErrMessage: "invalid validator status NotAStatus",
|
||||
},
|
||||
{
|
||||
@ -579,8 +643,7 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
|
||||
inputPubKeys: [][]byte{pubKey},
|
||||
inputIndexes: nil,
|
||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
||||
{
|
||||
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||
inputStringPubKeys: []string{stringPubKey},
|
||||
inputIndexes: nil,
|
||||
inputStatuses: nil,
|
||||
@ -599,7 +662,7 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
},
|
||||
outputErr: nil,
|
||||
},
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
outputErrMessage: "failed to parse activation epoch NotAnEpoch",
|
||||
},
|
||||
{
|
||||
@ -607,35 +670,14 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
|
||||
inputPubKeys: [][]byte{pubKey},
|
||||
inputIndexes: nil,
|
||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
||||
{
|
||||
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||
inputStringPubKeys: []string{stringPubKey},
|
||||
inputIndexes: nil,
|
||||
inputStatuses: nil,
|
||||
|
||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||
Data: []*beacon.ValidatorContainer{
|
||||
{
|
||||
Index: "12345",
|
||||
Status: "pending_queued",
|
||||
Validator: &beacon.Validator{
|
||||
Pubkey: stringPubKey,
|
||||
ActivationEpoch: "10",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
outputErr: nil,
|
||||
},
|
||||
{
|
||||
inputStringPubKeys: nil,
|
||||
inputIndexes: nil,
|
||||
inputStatuses: []string{"active"},
|
||||
|
||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{},
|
||||
outputStateValidatorsResponseJson: nil,
|
||||
outputErr: errors.New("a specific error"),
|
||||
},
|
||||
},
|
||||
outputErrMessage: "failed to get state validators",
|
||||
},
|
||||
{
|
||||
@ -643,31 +685,11 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
|
||||
inputPubKeys: [][]byte{pubKey},
|
||||
inputIndexes: nil,
|
||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
||||
{
|
||||
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||
inputStringPubKeys: []string{stringPubKey},
|
||||
inputIndexes: nil,
|
||||
inputStatuses: nil,
|
||||
|
||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||
Data: []*beacon.ValidatorContainer{
|
||||
{
|
||||
Index: "12345",
|
||||
Status: "pending_queued",
|
||||
Validator: &beacon.Validator{
|
||||
Pubkey: stringPubKey,
|
||||
ActivationEpoch: "10",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
outputErr: nil,
|
||||
},
|
||||
{
|
||||
inputStringPubKeys: nil,
|
||||
inputIndexes: nil,
|
||||
inputStatuses: []string{"active"},
|
||||
|
||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||
Data: []*beacon.ValidatorContainer{
|
||||
{
|
||||
@ -677,8 +699,8 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
},
|
||||
outputErr: nil,
|
||||
},
|
||||
},
|
||||
outputErrMessage: "failed to parse last validator index NotAnIndex",
|
||||
validatorCountCalled: 1,
|
||||
outputErrMessage: "failed to parse validator index NotAnIndex",
|
||||
},
|
||||
}
|
||||
|
||||
@ -690,20 +712,38 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
stateValidatorsProvider := mock.NewMockstateValidatorsProvider(ctrl)
|
||||
|
||||
for _, aa := range testCase.inputGetStateValidatorsInterfaces {
|
||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
||||
ctx,
|
||||
aa.inputStringPubKeys,
|
||||
aa.inputIndexes,
|
||||
aa.inputStatuses,
|
||||
testCase.inputGetStateValidatorsInterface.inputStringPubKeys,
|
||||
testCase.inputGetStateValidatorsInterface.inputIndexes,
|
||||
testCase.inputGetStateValidatorsInterface.inputStatuses,
|
||||
).Return(
|
||||
aa.outputStateValidatorsResponseJson,
|
||||
aa.outputErr,
|
||||
testCase.inputGetStateValidatorsInterface.outputStateValidatorsResponseJson,
|
||||
testCase.inputGetStateValidatorsInterface.outputErr,
|
||||
).Times(1)
|
||||
}
|
||||
|
||||
validatorClient := beaconApiValidatorClient{stateValidatorsProvider: stateValidatorsProvider}
|
||||
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
nil,
|
||||
iface.ErrNotSupported,
|
||||
).Times(testCase.validatorCountCalled)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
prysmBeaconChainCLient: prysmBeaconChainClient{
|
||||
nodeClient: &beaconApiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
}
|
||||
|
||||
_, _, _, err := validatorClient.getValidatorsStatusResponse(
|
||||
ctx,
|
||||
|
163
validator/client/beacon-api/validator_count_test.go
Normal file
163
validator/client/beacon-api/validator_count_test.go
Normal file
@ -0,0 +1,163 @@
|
||||
package beacon_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/apimiddleware"
|
||||
validator2 "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/prysm/validator"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/beacon-api/mock"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
)
|
||||
|
||||
func TestGetValidatorCount(t *testing.T) {
|
||||
const nodeVersion = "prysm/v0.0.1"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
versionEndpointError error
|
||||
validatorCountEndpointError error
|
||||
versionResponse apimiddleware.VersionResponseJson
|
||||
validatorCountResponse validator2.ValidatorCountResponse
|
||||
validatorCountCalled int
|
||||
expectedResponse []iface.ValidatorCount
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
versionResponse: apimiddleware.VersionResponseJson{
|
||||
Data: &apimiddleware.VersionJson{Version: nodeVersion},
|
||||
},
|
||||
validatorCountResponse: validator2.ValidatorCountResponse{
|
||||
ExecutionOptimistic: "false",
|
||||
Finalized: "true",
|
||||
Data: []*validator2.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: "10",
|
||||
},
|
||||
},
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not supported beacon node",
|
||||
versionResponse: apimiddleware.VersionResponseJson{
|
||||
Data: &apimiddleware.VersionJson{Version: "lighthouse/v0.0.1"},
|
||||
},
|
||||
expectedError: "endpoint not supported",
|
||||
},
|
||||
{
|
||||
name: "fails to get version",
|
||||
versionEndpointError: errors.New("foo error"),
|
||||
expectedError: "failed to get node version",
|
||||
},
|
||||
{
|
||||
name: "fails to get validator count",
|
||||
versionResponse: apimiddleware.VersionResponseJson{
|
||||
Data: &apimiddleware.VersionJson{Version: nodeVersion},
|
||||
},
|
||||
validatorCountEndpointError: errors.New("foo error"),
|
||||
validatorCountCalled: 1,
|
||||
expectedError: "foo error",
|
||||
},
|
||||
{
|
||||
name: "nil validator count data",
|
||||
versionResponse: apimiddleware.VersionResponseJson{
|
||||
Data: &apimiddleware.VersionJson{Version: nodeVersion},
|
||||
},
|
||||
validatorCountResponse: validator2.ValidatorCountResponse{
|
||||
ExecutionOptimistic: "false",
|
||||
Finalized: "true",
|
||||
Data: nil,
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
expectedError: "validator count data is nil",
|
||||
},
|
||||
{
|
||||
name: "invalid validator count",
|
||||
versionResponse: apimiddleware.VersionResponseJson{
|
||||
Data: &apimiddleware.VersionJson{Version: nodeVersion},
|
||||
},
|
||||
validatorCountResponse: validator2.ValidatorCountResponse{
|
||||
ExecutionOptimistic: "false",
|
||||
Finalized: "true",
|
||||
Data: []*validator2.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: "10",
|
||||
},
|
||||
{
|
||||
Status: "exited",
|
||||
Count: "10",
|
||||
},
|
||||
},
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
expectedError: "mismatch between validator count data and the number of statuses provided",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
nil,
|
||||
test.versionEndpointError,
|
||||
).SetArg(
|
||||
2,
|
||||
test.versionResponse,
|
||||
)
|
||||
|
||||
var validatorCountResponse validator2.ValidatorCountResponse
|
||||
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||
ctx,
|
||||
"/eth/v1/beacon/states/head/validator_count?status=active",
|
||||
&validatorCountResponse,
|
||||
).Return(
|
||||
nil,
|
||||
test.validatorCountEndpointError,
|
||||
).SetArg(
|
||||
2,
|
||||
test.validatorCountResponse,
|
||||
).Times(test.validatorCountCalled)
|
||||
|
||||
// Type assertion.
|
||||
var client iface.PrysmBeaconChainClient = &prysmBeaconChainClient{
|
||||
nodeClient: &beaconApiNodeClient{jsonRestHandler: jsonRestHandler},
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
countResponse, err := client.GetValidatorCount(ctx, "head", []validator.ValidatorStatus{validator.Active})
|
||||
|
||||
if len(test.expectedResponse) == 0 {
|
||||
require.ErrorContains(t, test.expectedError, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, test.expectedResponse, countResponse)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
@ -10,6 +10,7 @@ go_library(
|
||||
"//validator/client/beacon-api:go_default_library",
|
||||
"//validator/client/grpc-api:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"//validator/client/node-client-factory:go_default_library",
|
||||
"//validator/helpers:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
beaconApi "github.com/prysmaticlabs/prysm/v4/validator/client/beacon-api"
|
||||
grpcApi "github.com/prysmaticlabs/prysm/v4/validator/client/grpc-api"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
nodeClientFactory "github.com/prysmaticlabs/prysm/v4/validator/client/node-client-factory"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v4/validator/helpers"
|
||||
)
|
||||
|
||||
@ -13,8 +14,26 @@ func NewBeaconChainClient(validatorConn validatorHelpers.NodeConnection) iface.B
|
||||
featureFlags := features.Get()
|
||||
|
||||
if featureFlags.EnableBeaconRESTApi {
|
||||
return beaconApi.NewBeaconApiBeaconChainClientWithFallback(validatorConn.GetBeaconApiUrl(), validatorConn.GetBeaconApiTimeout(), grpcClient)
|
||||
return beaconApi.NewBeaconApiBeaconChainClientWithFallback(
|
||||
validatorConn.GetBeaconApiUrl(),
|
||||
validatorConn.GetBeaconApiTimeout(),
|
||||
grpcClient,
|
||||
)
|
||||
} else {
|
||||
return grpcClient
|
||||
}
|
||||
}
|
||||
|
||||
func NewPrysmBeaconClient(validatorConn validatorHelpers.NodeConnection) iface.PrysmBeaconChainClient {
|
||||
featureFlags := features.Get()
|
||||
|
||||
if featureFlags.EnableBeaconRESTApi {
|
||||
return beaconApi.NewPrysmBeaconChainClient(
|
||||
validatorConn.GetBeaconApiUrl(),
|
||||
validatorConn.GetBeaconApiTimeout(),
|
||||
nodeClientFactory.NewNodeClient(validatorConn),
|
||||
)
|
||||
} else {
|
||||
return grpcApi.NewGrpcPrysmBeaconChainClient(validatorConn.GetGrpcClientConn())
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,17 @@ go_library(
|
||||
srcs = [
|
||||
"grpc_beacon_chain_client.go",
|
||||
"grpc_node_client.go",
|
||||
"grpc_prysm_beacon_chain_client.go",
|
||||
"grpc_validator_client.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v4/validator/client/grpc-api",
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
@ -22,11 +27,22 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["grpc_validator_client_test.go"],
|
||||
srcs = [
|
||||
"grpc_prysm_beacon_chain_client_test.go",
|
||||
"grpc_validator_client_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/mock:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//testing/validator-mock:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@com_github_golang_mock//gomock:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
],
|
||||
|
97
validator/client/grpc-api/grpc_prysm_beacon_chain_client.go
Normal file
97
validator/client/grpc-api/grpc_prysm_beacon_chain_client.go
Normal file
@ -0,0 +1,97 @@
|
||||
package grpc_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers"
|
||||
statenative "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
eth "github.com/prysmaticlabs/prysm/v4/proto/eth/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type grpcPrysmBeaconChainClient struct {
|
||||
beaconChainClient iface.BeaconChainClient
|
||||
}
|
||||
|
||||
func (g grpcPrysmBeaconChainClient) GetValidatorCount(ctx context.Context, _ string, statuses []validator.ValidatorStatus) ([]iface.ValidatorCount, error) {
|
||||
resp, err := g.beaconChainClient.ListValidators(ctx, ðpb.ListValidatorsRequest{PageSize: 0})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "list validators failed")
|
||||
}
|
||||
|
||||
var vals []*ethpb.Validator
|
||||
for _, val := range resp.ValidatorList {
|
||||
vals = append(vals, val.Validator)
|
||||
}
|
||||
|
||||
head, err := g.beaconChainClient.GetChainHead(ctx, &empty.Empty{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get chain head")
|
||||
}
|
||||
|
||||
if len(statuses) == 0 {
|
||||
for _, val := range eth.ValidatorStatus_value {
|
||||
statuses = append(statuses, validator.ValidatorStatus(val))
|
||||
}
|
||||
}
|
||||
|
||||
valCount, err := validatorCountByStatus(vals, statuses, head.HeadEpoch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "validator count by status")
|
||||
}
|
||||
|
||||
return valCount, nil
|
||||
}
|
||||
|
||||
// validatorCountByStatus returns a slice of validator count for each status in the given epoch.
|
||||
func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.ValidatorStatus, epoch primitives.Epoch) ([]iface.ValidatorCount, error) {
|
||||
countByStatus := make(map[validator.ValidatorStatus]uint64)
|
||||
for _, val := range validators {
|
||||
readOnlyVal, err := statenative.NewValidator(val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert validator: %v", err)
|
||||
}
|
||||
valStatus, err := helpers.ValidatorStatus(readOnlyVal, epoch)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get validator status: %v", err)
|
||||
}
|
||||
valSubStatus, err := helpers.ValidatorSubStatus(readOnlyVal, epoch)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get validator sub status: %v", err)
|
||||
}
|
||||
|
||||
for _, status := range statuses {
|
||||
if valStatus == status || valSubStatus == status {
|
||||
countByStatus[status]++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var resp []iface.ValidatorCount
|
||||
for status, count := range countByStatus {
|
||||
resp = append(resp, iface.ValidatorCount{
|
||||
Status: status.String(),
|
||||
Count: count,
|
||||
})
|
||||
}
|
||||
|
||||
// Sort the response slice according to status strings for deterministic ordering of validator count response.
|
||||
sort.Slice(resp, func(i, j int) bool {
|
||||
return resp[i].Status < resp[j].Status
|
||||
})
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func NewGrpcPrysmBeaconChainClient(cc grpc.ClientConnInterface) iface.PrysmBeaconChainClient {
|
||||
return &grpcPrysmBeaconChainClient{beaconChainClient: &grpcBeaconChainClient{ethpb.NewBeaconChainClient(cc)}}
|
||||
}
|
326
validator/client/grpc-api/grpc_prysm_beacon_chain_client_test.go
Normal file
326
validator/client/grpc-api/grpc_prysm_beacon_chain_client_test.go
Normal file
@ -0,0 +1,326 @@
|
||||
package grpc_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/util"
|
||||
mock "github.com/prysmaticlabs/prysm/v4/testing/validator-mock"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
)
|
||||
|
||||
func TestGetValidatorCount(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 10)
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
validators := []*ethpb.Validator{
|
||||
// Pending initialized.
|
||||
{
|
||||
ActivationEpoch: farFutureEpoch,
|
||||
ActivationEligibilityEpoch: farFutureEpoch,
|
||||
ExitEpoch: farFutureEpoch,
|
||||
WithdrawableEpoch: farFutureEpoch,
|
||||
},
|
||||
// Pending queued.
|
||||
{
|
||||
ActivationEpoch: 10,
|
||||
ActivationEligibilityEpoch: 4,
|
||||
ExitEpoch: farFutureEpoch,
|
||||
WithdrawableEpoch: farFutureEpoch,
|
||||
},
|
||||
// Active ongoing.
|
||||
{
|
||||
ActivationEpoch: 0,
|
||||
ExitEpoch: farFutureEpoch,
|
||||
},
|
||||
// Active slashed.
|
||||
{
|
||||
ActivationEpoch: 0,
|
||||
ExitEpoch: 30,
|
||||
Slashed: true,
|
||||
WithdrawableEpoch: 50,
|
||||
},
|
||||
// Active exiting.
|
||||
{
|
||||
ActivationEpoch: 0,
|
||||
ExitEpoch: 30,
|
||||
Slashed: false,
|
||||
WithdrawableEpoch: 50,
|
||||
},
|
||||
// Exit slashed (at epoch 35).
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 50,
|
||||
Slashed: true,
|
||||
},
|
||||
// Exit unslashed (at epoch 35).
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 50,
|
||||
Slashed: false,
|
||||
},
|
||||
// Withdrawable (at epoch 45).
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
Slashed: false,
|
||||
},
|
||||
// Withdrawal done (at epoch 45).
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
EffectiveBalance: 0,
|
||||
Slashed: false,
|
||||
},
|
||||
}
|
||||
for _, validator := range validators {
|
||||
require.NoError(t, st.AppendValidator(validator))
|
||||
require.NoError(t, st.AppendBalance(params.BeaconConfig().MaxEffectiveBalance))
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
statuses []string
|
||||
currentEpoch int
|
||||
expectedResponse []iface.ValidatorCount
|
||||
}{
|
||||
{
|
||||
name: "Head count active validators",
|
||||
statuses: []string{"active"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count active ongoing validators",
|
||||
statuses: []string{"active_ongoing"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "active_ongoing",
|
||||
Count: 11,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count active exiting validators",
|
||||
statuses: []string{"active_exiting"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "active_exiting",
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count active slashed validators",
|
||||
statuses: []string{"active_slashed"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "active_slashed",
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count pending validators",
|
||||
statuses: []string{"pending"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "pending",
|
||||
Count: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count pending initialized validators",
|
||||
statuses: []string{"pending_initialized"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "pending_initialized",
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count pending queued validators",
|
||||
statuses: []string{"pending_queued"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "pending_queued",
|
||||
Count: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count exited validators",
|
||||
statuses: []string{"exited"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "exited",
|
||||
Count: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count exited slashed validators",
|
||||
statuses: []string{"exited_slashed"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "exited_slashed",
|
||||
Count: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count exited unslashed validators",
|
||||
statuses: []string{"exited_unslashed"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "exited_unslashed",
|
||||
Count: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count withdrawal validators",
|
||||
statuses: []string{"withdrawal"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal",
|
||||
Count: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count withdrawal possible validators",
|
||||
statuses: []string{"withdrawal_possible"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal_possible",
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count withdrawal done validators",
|
||||
statuses: []string{"withdrawal_done"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal_done",
|
||||
Count: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count active and pending validators",
|
||||
statuses: []string{"active", "pending"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
},
|
||||
{
|
||||
Status: "pending",
|
||||
Count: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Head count of ALL validators",
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
},
|
||||
{
|
||||
Status: "active_exiting",
|
||||
Count: 1,
|
||||
},
|
||||
{
|
||||
Status: "active_ongoing",
|
||||
Count: 11,
|
||||
},
|
||||
{
|
||||
Status: "active_slashed",
|
||||
Count: 1,
|
||||
},
|
||||
{
|
||||
Status: "pending",
|
||||
Count: 6,
|
||||
},
|
||||
{
|
||||
Status: "pending_initialized",
|
||||
Count: 1,
|
||||
},
|
||||
{
|
||||
Status: "pending_queued",
|
||||
Count: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
listValidatorResp := ðpb.Validators{}
|
||||
for _, val := range st.Validators() {
|
||||
listValidatorResp.ValidatorList = append(listValidatorResp.ValidatorList, ðpb.Validators_ValidatorContainer{
|
||||
Validator: val,
|
||||
})
|
||||
}
|
||||
|
||||
beaconChainClient := mock.NewMockBeaconChainClient(ctrl)
|
||||
beaconChainClient.EXPECT().ListValidators(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
listValidatorResp,
|
||||
nil,
|
||||
)
|
||||
|
||||
beaconChainClient.EXPECT().GetChainHead(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
ðpb.ChainHead{HeadEpoch: primitives.Epoch(test.currentEpoch)},
|
||||
nil,
|
||||
)
|
||||
|
||||
prysmBeaconChainClient := &grpcPrysmBeaconChainClient{
|
||||
beaconChainClient: beaconChainClient,
|
||||
}
|
||||
|
||||
var statuses []validator.ValidatorStatus
|
||||
for _, status := range test.statuses {
|
||||
ok, valStatus := validator.ValidatorStatusFromString(status)
|
||||
require.Equal(t, true, ok)
|
||||
statuses = append(statuses, valStatus)
|
||||
}
|
||||
vcCountResp, err := prysmBeaconChainClient.GetValidatorCount(context.Background(), "", statuses)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, test.expectedResponse, vcCountResp)
|
||||
})
|
||||
}
|
||||
}
|
@ -5,19 +5,22 @@ go_library(
|
||||
srcs = [
|
||||
"beacon_chain_client.go",
|
||||
"node_client.go",
|
||||
"prysm_beacon_chain_client.go",
|
||||
"validator.go",
|
||||
"validator_client.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v4/validator/client/iface",
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/validator/service:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/validator-client:go_default_library",
|
||||
"//validator/keymanager:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
20
validator/client/iface/prysm_beacon_chain_client.go
Normal file
20
validator/client/iface/prysm_beacon_chain_client.go
Normal file
@ -0,0 +1,20 @@
|
||||
package iface
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
)
|
||||
|
||||
var ErrNotSupported = errors.New("endpoint not supported")
|
||||
|
||||
type ValidatorCount struct {
|
||||
Status string
|
||||
Count uint64
|
||||
}
|
||||
|
||||
// PrysmBeaconChainClient defines an interface required to implement all the prysm specific custom endpoints.
|
||||
type PrysmBeaconChainClient interface {
|
||||
GetValidatorCount(context.Context, string, []validator.ValidatorStatus) ([]ValidatorCount, error)
|
||||
}
|
@ -4,7 +4,10 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||
validator2 "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@ -33,11 +36,19 @@ func (v *validator) HandleKeyReload(ctx context.Context, currentKeys [][fieldpar
|
||||
index: resp.Indices[i],
|
||||
}
|
||||
}
|
||||
vals, err := v.beaconClient.ListValidators(ctx, ð.ListValidatorsRequest{Active: true, PageSize: 0})
|
||||
if err != nil {
|
||||
|
||||
// "-1" indicates that validator count endpoint is not supported by the beacon node.
|
||||
var valCount int64 = -1
|
||||
valCounts, err := v.prysmBeaconClient.GetValidatorCount(ctx, "head", []validator2.ValidatorStatus{validator2.Active})
|
||||
if err != nil && !errors.Is(err, iface.ErrNotSupported) {
|
||||
return false, errors.Wrap(err, "could not get active validator count")
|
||||
}
|
||||
anyActive = v.checkAndLogValidatorStatus(statuses, uint64(vals.TotalSize))
|
||||
|
||||
if len(valCounts) > 0 {
|
||||
valCount = int64(valCounts[0].Count)
|
||||
}
|
||||
|
||||
anyActive = v.checkAndLogValidatorStatus(statuses, valCount)
|
||||
if anyActive {
|
||||
logActiveValidatorStatus(statuses)
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
validator2 "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/pkg/errors"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||
@ -27,11 +30,13 @@ func TestValidator_HandleKeyReload(t *testing.T) {
|
||||
|
||||
client := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
keyManager: newMockKeymanager(t, inactive),
|
||||
genesisTime: 1,
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
|
||||
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:], active.pub[:]})
|
||||
@ -43,7 +48,11 @@ func TestValidator_HandleKeyReload(t *testing.T) {
|
||||
PublicKeys: [][]byte{inactive.pub[:], active.pub[:]},
|
||||
},
|
||||
).Return(resp, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validator2.ValidatorStatus{validator2.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil)
|
||||
|
||||
anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{inactive.pub, active.pub})
|
||||
require.NoError(t, err)
|
||||
@ -57,12 +66,14 @@ func TestValidator_HandleKeyReload(t *testing.T) {
|
||||
|
||||
client := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
kp := randKeypair(t)
|
||||
v := validator{
|
||||
validatorClient: client,
|
||||
keyManager: newMockKeymanager(t, kp),
|
||||
genesisTime: 1,
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
|
||||
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]})
|
||||
@ -73,7 +84,11 @@ func TestValidator_HandleKeyReload(t *testing.T) {
|
||||
PublicKeys: [][]byte{kp.pub[:]},
|
||||
},
|
||||
).Return(resp, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validator2.ValidatorStatus{validator2.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil)
|
||||
|
||||
anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{kp.pub})
|
||||
require.NoError(t, err)
|
||||
|
@ -189,6 +189,7 @@ func (v *ValidatorService) Start() {
|
||||
|
||||
validatorClient := validatorClientFactory.NewValidatorClient(v.conn)
|
||||
beaconClient := beaconChainClientFactory.NewBeaconChainClient(v.conn)
|
||||
prysmBeaconClient := beaconChainClientFactory.NewPrysmBeaconClient(v.conn)
|
||||
|
||||
valStruct := &validator{
|
||||
db: v.db,
|
||||
@ -218,6 +219,7 @@ func (v *ValidatorService) Start() {
|
||||
Web3SignerConfig: v.Web3SignerConfig,
|
||||
proposerSettings: v.proposerSettings,
|
||||
walletInitializedChannel: make(chan *wallet.Wallet, 1),
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
|
||||
// To resolve a race condition at startup due to the interface
|
||||
|
@ -104,6 +104,7 @@ type validator struct {
|
||||
Web3SignerConfig *remoteweb3signer.SetupConfig
|
||||
proposerSettings *validatorserviceconfig.ProposerSettings
|
||||
walletInitializedChannel chan *wallet.Wallet
|
||||
prysmBeaconClient iface.PrysmBeaconChainClient
|
||||
}
|
||||
|
||||
type validatorStatus struct {
|
||||
@ -369,10 +370,7 @@ func (v *validator) ReceiveBlocks(ctx context.Context, connectionErrorChannel ch
|
||||
}
|
||||
}
|
||||
|
||||
func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, activeValCount uint64) bool {
|
||||
activationsPerEpoch :=
|
||||
uint64(math.Max(float64(params.BeaconConfig().MinPerEpochChurnLimit), float64(activeValCount/params.BeaconConfig().ChurnLimitQuotient)))
|
||||
|
||||
func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, activeValCount int64) bool {
|
||||
nonexistentIndex := primitives.ValidatorIndex(^uint64(0))
|
||||
var validatorActivated bool
|
||||
for _, status := range statuses {
|
||||
@ -398,15 +396,17 @@ func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, acti
|
||||
).Info("Deposit processed, entering activation queue after finalization")
|
||||
}
|
||||
case ethpb.ValidatorStatus_PENDING:
|
||||
if activeValCount >= 0 && status.status.ActivationEpoch == params.BeaconConfig().FarFutureEpoch {
|
||||
activationsPerEpoch :=
|
||||
uint64(math.Max(float64(params.BeaconConfig().MinPerEpochChurnLimit), float64(uint64(activeValCount)/params.BeaconConfig().ChurnLimitQuotient)))
|
||||
secondsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||
expectedWaitingTime :=
|
||||
time.Duration((status.status.PositionInActivationQueue+activationsPerEpoch)/activationsPerEpoch*secondsPerEpoch) * time.Second
|
||||
if status.status.ActivationEpoch == params.BeaconConfig().FarFutureEpoch {
|
||||
log.WithFields(logrus.Fields{
|
||||
"positionInActivationQueue": status.status.PositionInActivationQueue,
|
||||
"expectedWaitingTime": expectedWaitingTime.String(),
|
||||
}).Info("Waiting to be assigned activation epoch")
|
||||
} else {
|
||||
} else if status.status.ActivationEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||
log.WithFields(logrus.Fields{
|
||||
"activationEpoch": status.status.ActivationEpoch,
|
||||
}).Info("Waiting for activation")
|
||||
|
@ -358,12 +358,14 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
|
||||
kp := randKeypair(t)
|
||||
v := validator{
|
||||
validatorClient: validatorClient,
|
||||
keyManager: newMockKeymanager(t, kp),
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
|
||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||
@ -379,7 +381,11 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
resp,
|
||||
nil,
|
||||
)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil)
|
||||
require.NoError(t, v.WaitForActivation(ctx, nil), "Could not wait for activation")
|
||||
require.LogsContain(t, hook, "Validator activated")
|
||||
}
|
||||
@ -389,12 +395,14 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
|
||||
kp := randKeypair(t)
|
||||
v := validator{
|
||||
validatorClient: validatorClient,
|
||||
keyManager: newMockKeymanager(t, kp),
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||
@ -403,7 +411,11 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(clientStream, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil).Times(2)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil).Times(2)
|
||||
clientStream.EXPECT().Recv().Return(
|
||||
ðpb.ValidatorActivationResponse{},
|
||||
nil,
|
||||
|
@ -5,6 +5,9 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
validator2 "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
||||
@ -136,12 +139,18 @@ func (v *validator) handleAccountsChanged(ctx context.Context, accountsChangedCh
|
||||
}
|
||||
}
|
||||
|
||||
vals, err := v.beaconClient.ListValidators(ctx, ðpb.ListValidatorsRequest{Active: true, PageSize: 0})
|
||||
if err != nil {
|
||||
// "-1" indicates that validator count endpoint is not supported by the beacon node.
|
||||
var valCount int64 = -1
|
||||
valCounts, err := v.prysmBeaconClient.GetValidatorCount(ctx, "head", []validator2.ValidatorStatus{validator2.Active})
|
||||
if err != nil && !errors.Is(err, iface.ErrNotSupported) {
|
||||
return errors.Wrap(err, "could not get active validator count")
|
||||
}
|
||||
|
||||
valActivated := v.checkAndLogValidatorStatus(statuses, uint64(vals.TotalSize))
|
||||
if len(valCounts) > 0 {
|
||||
valCount = int64(valCounts[0].Count)
|
||||
}
|
||||
|
||||
valActivated := v.checkAndLogValidatorStatus(statuses, valCount)
|
||||
if valActivated {
|
||||
logActiveValidatorStatus(statuses)
|
||||
} else {
|
||||
|
@ -7,6 +7,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
validatorType "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/pkg/errors"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||
@ -57,11 +60,13 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
kp := randKeypair(t)
|
||||
v := validator{
|
||||
validatorClient: validatorClient,
|
||||
keyManager: newMockKeymanager(t, kp),
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
||||
validatorClient.EXPECT().WaitForActivation(
|
||||
@ -70,7 +75,11 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
|
||||
PublicKeys: [][]byte{kp.pub[:]},
|
||||
},
|
||||
).Return(clientStream, errors.New("failed stream")).Return(clientStream, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil)
|
||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||
clientStream.EXPECT().Recv().Return(resp, nil)
|
||||
@ -82,11 +91,13 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
|
||||
defer ctrl.Finish()
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
kp := randKeypair(t)
|
||||
v := validator{
|
||||
validatorClient: validatorClient,
|
||||
keyManager: newMockKeymanager(t, kp),
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
||||
validatorClient.EXPECT().WaitForActivation(
|
||||
@ -95,7 +106,11 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
|
||||
PublicKeys: [][]byte{kp.pub[:]},
|
||||
},
|
||||
).Return(clientStream, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil)
|
||||
// A stream fails the first time, but succeeds the second time.
|
||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||
@ -112,12 +127,14 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
kp := randKeypair(t)
|
||||
v := validator{
|
||||
validatorClient: validatorClient,
|
||||
keyManager: newMockKeymanager(t, kp),
|
||||
genesisTime: 1,
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||
@ -128,7 +145,11 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
|
||||
PublicKeys: [][]byte{kp.pub[:]},
|
||||
},
|
||||
).Return(clientStream, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil)
|
||||
clientStream.EXPECT().Recv().Return(
|
||||
resp,
|
||||
nil,
|
||||
@ -142,11 +163,13 @@ func TestWaitForActivation_Exiting(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
kp := randKeypair(t)
|
||||
v := validator{
|
||||
validatorClient: validatorClient,
|
||||
keyManager: newMockKeymanager(t, kp),
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_EXITING
|
||||
@ -157,7 +180,11 @@ func TestWaitForActivation_Exiting(t *testing.T) {
|
||||
PublicKeys: [][]byte{kp.pub[:]},
|
||||
},
|
||||
).Return(clientStream, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil)
|
||||
clientStream.EXPECT().Recv().Return(
|
||||
resp,
|
||||
nil,
|
||||
@ -177,6 +204,7 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
||||
defer ctrl.Finish()
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
|
||||
kp := randKeypair(t)
|
||||
km := newMockKeymanager(t, kp)
|
||||
@ -186,6 +214,7 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
||||
validatorClient: validatorClient,
|
||||
keyManager: km,
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||
@ -196,7 +225,11 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
||||
PublicKeys: [][]byte{kp.pub[:]},
|
||||
},
|
||||
).Return(clientStream, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil)
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil)
|
||||
clientStream.EXPECT().Recv().Return(
|
||||
resp,
|
||||
nil)
|
||||
@ -217,10 +250,12 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
||||
km := newMockKeymanager(t, inactive)
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
v := validator{
|
||||
validatorClient: validatorClient,
|
||||
keyManager: km,
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
inactiveResp := generateMockStatusResponse([][]byte{inactive.pub[:]})
|
||||
inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
||||
@ -231,7 +266,11 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
||||
PublicKeys: [][]byte{inactive.pub[:]},
|
||||
},
|
||||
).Return(inactiveClientStream, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil).AnyTimes()
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil).AnyTimes()
|
||||
inactiveClientStream.EXPECT().Recv().Return(
|
||||
inactiveResp,
|
||||
nil,
|
||||
@ -297,11 +336,13 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||
v := validator{
|
||||
validatorClient: validatorClient,
|
||||
keyManager: km,
|
||||
genesisTime: 1,
|
||||
beaconClient: beaconClient,
|
||||
prysmBeaconClient: prysmBeaconClient,
|
||||
}
|
||||
|
||||
inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]})
|
||||
@ -313,7 +354,11 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
||||
PublicKeys: [][]byte{inactivePubKey[:]},
|
||||
},
|
||||
).Return(inactiveClientStream, nil)
|
||||
beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil).AnyTimes()
|
||||
prysmBeaconClient.EXPECT().GetValidatorCount(
|
||||
gomock.Any(),
|
||||
"head",
|
||||
[]validatorType.ValidatorStatus{validatorType.Active},
|
||||
).Return([]iface.ValidatorCount{}, nil).AnyTimes()
|
||||
inactiveClientStream.EXPECT().Recv().Return(
|
||||
inactiveResp,
|
||||
nil,
|
||||
|
Loading…
Reference in New Issue
Block a user