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
|
var resp []*ValidatorCount
|
||||||
for status, count := range countByStatus {
|
for status, count := range countByStatus {
|
||||||
resp = append(resp, &ValidatorCount{
|
resp = append(resp, &ValidatorCount{
|
||||||
Status: strings.ToLower(ethpb.ValidatorStatus_name[int32(status)]),
|
Status: status.String(),
|
||||||
Count: strconv.FormatUint(count, 10),
|
Count: strconv.FormatUint(count, 10),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ done
|
|||||||
# --------------------------------------------------------
|
# --------------------------------------------------------
|
||||||
iface_mocks=(
|
iface_mocks=(
|
||||||
"$iface_mock_path/beacon_chain_client_mock.go BeaconChainClient"
|
"$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/node_client_mock.go NodeClient"
|
||||||
"$iface_mock_path/slasher_client_mock.go SlasherClient"
|
"$iface_mock_path/slasher_client_mock.go SlasherClient"
|
||||||
"$iface_mock_path/validator_client_mock.go ValidatorClient"
|
"$iface_mock_path/validator_client_mock.go ValidatorClient"
|
||||||
|
@ -7,13 +7,16 @@ go_library(
|
|||||||
srcs = [
|
srcs = [
|
||||||
"beacon_chain_client_mock.go",
|
"beacon_chain_client_mock.go",
|
||||||
"node_client_mock.go",
|
"node_client_mock.go",
|
||||||
|
"prysm_beacon_chain_client_mock.go",
|
||||||
"validator_client_mock.go",
|
"validator_client_mock.go",
|
||||||
],
|
],
|
||||||
importpath = "github.com/prysmaticlabs/prysm/v4/testing/validator-mock",
|
importpath = "github.com/prysmaticlabs/prysm/v4/testing/validator-mock",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
|
"//consensus-types/validator:go_default_library",
|
||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
|
"//validator/client/iface:go_default_library",
|
||||||
"@com_github_golang_mock//gomock:go_default_library",
|
"@com_github_golang_mock//gomock:go_default_library",
|
||||||
"@org_golang_google_protobuf//types/known/emptypb: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/blocks:go_default_library",
|
||||||
"//consensus-types/interfaces:go_default_library",
|
"//consensus-types/interfaces:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
|
"//consensus-types/validator:go_default_library",
|
||||||
"//crypto/bls:go_default_library",
|
"//crypto/bls:go_default_library",
|
||||||
"//crypto/hash:go_default_library",
|
"//crypto/hash:go_default_library",
|
||||||
"//crypto/rand:go_default_library",
|
"//crypto/rand:go_default_library",
|
||||||
|
@ -24,6 +24,7 @@ go_library(
|
|||||||
"propose_attestation.go",
|
"propose_attestation.go",
|
||||||
"propose_beacon_block.go",
|
"propose_beacon_block.go",
|
||||||
"propose_exit.go",
|
"propose_exit.go",
|
||||||
|
"prysm_beacon_chain_client.go",
|
||||||
"registration.go",
|
"registration.go",
|
||||||
"state_validators.go",
|
"state_validators.go",
|
||||||
"status.go",
|
"status.go",
|
||||||
@ -48,6 +49,7 @@ go_library(
|
|||||||
"//beacon-chain/rpc/prysm/validator:go_default_library",
|
"//beacon-chain/rpc/prysm/validator:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
|
"//consensus-types/validator:go_default_library",
|
||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//network/forks:go_default_library",
|
"//network/forks:go_default_library",
|
||||||
"//proto/engine/v1:go_default_library",
|
"//proto/engine/v1:go_default_library",
|
||||||
@ -105,6 +107,7 @@ go_test(
|
|||||||
"submit_signed_contribution_and_proof_test.go",
|
"submit_signed_contribution_and_proof_test.go",
|
||||||
"subscribe_committee_subnets_test.go",
|
"subscribe_committee_subnets_test.go",
|
||||||
"sync_committee_test.go",
|
"sync_committee_test.go",
|
||||||
|
"validator_count_test.go",
|
||||||
"wait_for_chain_start_test.go",
|
"wait_for_chain_start_test.go",
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
@ -118,14 +121,17 @@ go_test(
|
|||||||
"//beacon-chain/rpc/prysm/validator:go_default_library",
|
"//beacon-chain/rpc/prysm/validator:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
|
"//consensus-types/validator:go_default_library",
|
||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//proto/engine/v1:go_default_library",
|
"//proto/engine/v1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
"//testing/assert:go_default_library",
|
"//testing/assert:go_default_library",
|
||||||
"//testing/require:go_default_library",
|
"//testing/require:go_default_library",
|
||||||
|
"//testing/validator-mock:go_default_library",
|
||||||
"//time/slots:go_default_library",
|
"//time/slots:go_default_library",
|
||||||
"//validator/client/beacon-api/mock:go_default_library",
|
"//validator/client/beacon-api/mock:go_default_library",
|
||||||
"//validator/client/beacon-api/test-helpers: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_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||||
"@com_github_golang_mock//gomock:go_default_library",
|
"@com_github_golang_mock//gomock:go_default_library",
|
||||||
"@com_github_golang_protobuf//ptypes/empty",
|
"@com_github_golang_protobuf//ptypes/empty",
|
||||||
|
@ -20,6 +20,7 @@ type beaconApiValidatorClient struct {
|
|||||||
stateValidatorsProvider stateValidatorsProvider
|
stateValidatorsProvider stateValidatorsProvider
|
||||||
jsonRestHandler jsonRestHandler
|
jsonRestHandler jsonRestHandler
|
||||||
beaconBlockConverter beaconBlockConverter
|
beaconBlockConverter beaconBlockConverter
|
||||||
|
prysmBeaconChainCLient iface.PrysmBeaconChainClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBeaconApiValidatorClient(host string, timeout time.Duration) iface.ValidatorClient {
|
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},
|
stateValidatorsProvider: beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler},
|
||||||
jsonRestHandler: jsonRestHandler,
|
jsonRestHandler: jsonRestHandler,
|
||||||
beaconBlockConverter: beaconApiBeaconBlockConverter{},
|
beaconBlockConverter: beaconApiBeaconBlockConverter{},
|
||||||
|
prysmBeaconChainCLient: prysmBeaconChainClient{
|
||||||
|
nodeClient: &beaconApiNodeClient{jsonRestHandler: jsonRestHandler},
|
||||||
|
jsonRestHandler: jsonRestHandler,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"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/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
|
||||||
@ -1259,10 +1262,21 @@ func TestGetDuties_Valid(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
).MinTimes(1)
|
).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
|
// Make sure that our values are equal to what would be returned by calling getDutiesForEpoch individually
|
||||||
validatorClient := &beaconApiValidatorClient{
|
validatorClient := &beaconApiValidatorClient{
|
||||||
dutiesProvider: dutiesProvider,
|
dutiesProvider: dutiesProvider,
|
||||||
stateValidatorsProvider: stateValidatorsProvider,
|
stateValidatorsProvider: stateValidatorsProvider,
|
||||||
|
prysmBeaconChainCLient: prysmBeaconChainClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedCurrentEpochDuties, err := validatorClient.getDutiesForEpoch(
|
expectedCurrentEpochDuties, err := validatorClient.getDutiesForEpoch(
|
||||||
@ -1356,9 +1370,20 @@ func TestGetDuties_GetDutiesForEpochFailed(t *testing.T) {
|
|||||||
errors.New("foo error"),
|
errors.New("foo error"),
|
||||||
).Times(1)
|
).Times(1)
|
||||||
|
|
||||||
|
prysmBeaconChainClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconChainClient.EXPECT().GetValidatorCount(
|
||||||
|
ctx,
|
||||||
|
gomock.Any(),
|
||||||
|
gomock.Any(),
|
||||||
|
).Return(
|
||||||
|
nil,
|
||||||
|
iface.ErrNotSupported,
|
||||||
|
).MinTimes(1)
|
||||||
|
|
||||||
validatorClient := &beaconApiValidatorClient{
|
validatorClient := &beaconApiValidatorClient{
|
||||||
stateValidatorsProvider: stateValidatorsProvider,
|
stateValidatorsProvider: stateValidatorsProvider,
|
||||||
dutiesProvider: dutiesProvider,
|
dutiesProvider: dutiesProvider,
|
||||||
|
prysmBeaconChainCLient: prysmBeaconChainClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := validatorClient.getDuties(ctx, ðpb.DutiesRequest{
|
_, 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"
|
reflect "reflect"
|
||||||
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
|
shared "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared"
|
||||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator"
|
validator "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/validator"
|
||||||
primitives "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
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"
|
gomock "github.com/golang/mock/gomock"
|
||||||
apimiddleware "github.com/prysmaticlabs/prysm/v4/api/gateway/apimiddleware"
|
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.
|
// 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"
|
"context"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
"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")
|
return nil, nil, nil, errors.Wrap(err, "failed to get state validators")
|
||||||
}
|
}
|
||||||
|
|
||||||
isLastActivatedValidatorIndexRetrieved := false
|
validatorsCountResponse, err := c.prysmBeaconChainCLient.GetValidatorCount(ctx, "head", nil)
|
||||||
var lastActivatedValidatorIndex uint64 = 0
|
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 {
|
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{}{}
|
stringRetrievedPubKeys[stringPubKey] = struct{}{}
|
||||||
|
|
||||||
pubKey, ok := stringTargetPubKeysToPubKeys[stringPubKey]
|
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
|
outPubKeys[i] = pubKey
|
||||||
outIndexes[i] = primitives.ValidatorIndex(validatorIndex)
|
|
||||||
|
|
||||||
validatorStatus := ðpb.ValidatorStatusResponse{}
|
validatorStatus := ðpb.ValidatorStatusResponse{}
|
||||||
|
|
||||||
// Set Status
|
// Set Status
|
||||||
@ -119,28 +134,9 @@ func (c *beaconApiValidatorClient) getValidatorsStatusResponse(ctx context.Conte
|
|||||||
// Set PositionInActivationQueue
|
// Set PositionInActivationQueue
|
||||||
switch status {
|
switch status {
|
||||||
case ethpb.ValidatorStatus_PENDING, ethpb.ValidatorStatus_PARTIALLY_DEPOSITED, ethpb.ValidatorStatus_DEPOSITED:
|
case ethpb.ValidatorStatus_PENDING, ethpb.ValidatorStatus_PARTIALLY_DEPOSITED, ethpb.ValidatorStatus_DEPOSITED:
|
||||||
if !isLastActivatedValidatorIndexRetrieved {
|
if lastActivatedValidatorIndex >= 0 {
|
||||||
isLastActivatedValidatorIndexRetrieved = true
|
validatorStatus.PositionInActivationQueue = validatorIndex - uint64(lastActivatedValidatorIndex)
|
||||||
// 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")
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
outValidatorsStatuses[i] = validatorStatus
|
||||||
|
@ -6,6 +6,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"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/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/beacon"
|
||||||
@ -50,7 +54,26 @@ func TestValidatorStatus_Nominal(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
).Times(1)
|
).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(
|
actualValidatorStatusResponse, err := validatorClient.ValidatorStatus(
|
||||||
ctx,
|
ctx,
|
||||||
@ -147,7 +170,27 @@ func TestMultipleValidatorStatus_Nominal(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
).Times(1)
|
).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{
|
expectedValidatorStatusResponse := ethpb.MultipleValidatorStatusResponse{
|
||||||
PublicKeys: validatorsPubKey,
|
PublicKeys: validatorsPubKey,
|
||||||
@ -289,33 +332,44 @@ func TestGetValidatorsStatusResponse_Nominal_SomeActiveValidators(t *testing.T)
|
|||||||
nil,
|
nil,
|
||||||
).Times(1)
|
).Times(1)
|
||||||
|
|
||||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||||
|
|
||||||
|
// Expect node version endpoint call.
|
||||||
|
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||||
|
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||||
ctx,
|
ctx,
|
||||||
nil,
|
"/eth/v1/node/version",
|
||||||
nil,
|
&nodeVersionResponse,
|
||||||
[]string{"active"},
|
|
||||||
).Return(
|
).Return(
|
||||||
&beacon.GetValidatorsResponse{
|
nil,
|
||||||
Data: []*beacon.ValidatorContainer{
|
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{
|
||||||
{
|
{
|
||||||
Index: "35000",
|
Status: "active",
|
||||||
Status: "active_ongoing",
|
Count: "50001",
|
||||||
Validator: &beacon.Validator{
|
|
||||||
Pubkey: "0x8000ab56b051f9d8f31c687528c6e91c9b98e4c3a241e752f9ccfbea7c5a7fbbd272bdf2c0a7e52ce7e0b57693df364d",
|
|
||||||
ActivationEpoch: "56",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Index: "39000",
|
Status: "pending",
|
||||||
Status: "active_ongoing",
|
Count: "11000",
|
||||||
Validator: &beacon.Validator{
|
|
||||||
Pubkey: "0x8000ab56b051f9d8f31c687528c6e91c9b98e4c3a241e752f9ccfbea7c5a7fbbd272bdf2c0a7e52ce7e0b57693df364e",
|
|
||||||
ActivationEpoch: "56",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
).Times(1)
|
).Times(1)
|
||||||
|
|
||||||
wantedStringValidatorsPubkey := []string{
|
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)
|
actualValidatorsPubKey, actualValidatorsIndex, actualValidatorsStatusResponse, err := validatorClient.getValidatorsStatusResponse(ctx, validatorsPubKey, validatorsIndex)
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -420,29 +482,37 @@ func TestGetValidatorsStatusResponse_Nominal_NoActiveValidators(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
).Times(1)
|
).Times(1)
|
||||||
|
|
||||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||||
|
|
||||||
|
// Expect node version endpoint call.
|
||||||
|
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||||
|
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||||
ctx,
|
ctx,
|
||||||
nil,
|
"/eth/v1/node/version",
|
||||||
nil,
|
&nodeVersionResponse,
|
||||||
[]string{"active"},
|
|
||||||
).Return(
|
).Return(
|
||||||
&beacon.GetValidatorsResponse{
|
|
||||||
Data: []*beacon.ValidatorContainer{},
|
|
||||||
},
|
|
||||||
nil,
|
nil,
|
||||||
|
iface.ErrNotSupported,
|
||||||
).Times(1)
|
).Times(1)
|
||||||
|
|
||||||
wantedValidatorsPubKey := [][]byte{validatorPubKey}
|
wantedValidatorsPubKey := [][]byte{validatorPubKey}
|
||||||
wantedValidatorsIndex := []primitives.ValidatorIndex{40000}
|
wantedValidatorsIndex := []primitives.ValidatorIndex{40000}
|
||||||
wantedValidatorsStatusResponse := []*ethpb.ValidatorStatusResponse{
|
wantedValidatorsStatusResponse := []*ethpb.ValidatorStatusResponse{
|
||||||
{
|
{
|
||||||
Status: ethpb.ValidatorStatus_PENDING,
|
Status: ethpb.ValidatorStatus_PENDING,
|
||||||
ActivationEpoch: params.BeaconConfig().FarFutureEpoch,
|
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)
|
actualValidatorsPubKey, actualValidatorsIndex, actualValidatorsStatusResponse, err := validatorClient.getValidatorsStatusResponse(ctx, wantedValidatorsPubKey, nil)
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -472,27 +542,22 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
inputPubKeys [][]byte
|
inputPubKeys [][]byte
|
||||||
inputIndexes []int64
|
inputIndexes []int64
|
||||||
inputGetStateValidatorsInterfaces []getStateValidatorsInterface
|
inputGetStateValidatorsInterface getStateValidatorsInterface
|
||||||
|
validatorCountCalled int
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
outputErrMessage string
|
outputErrMessage string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "failed getStateValidators",
|
name: "failed getStateValidators",
|
||||||
|
|
||||||
inputPubKeys: [][]byte{pubKey},
|
inputPubKeys: [][]byte{pubKey},
|
||||||
inputIndexes: nil,
|
inputIndexes: nil,
|
||||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||||
{
|
inputStringPubKeys: []string{stringPubKey},
|
||||||
inputStringPubKeys: []string{stringPubKey},
|
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{},
|
||||||
inputIndexes: nil,
|
outputErr: errors.New("a specific error"),
|
||||||
inputStatuses: nil,
|
|
||||||
|
|
||||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{},
|
|
||||||
outputErr: errors.New("a specific error"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
outputErrMessage: "failed to get state validators",
|
outputErrMessage: "failed to get state validators",
|
||||||
},
|
},
|
||||||
@ -501,140 +566,117 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
|||||||
|
|
||||||
inputPubKeys: [][]byte{pubKey},
|
inputPubKeys: [][]byte{pubKey},
|
||||||
inputIndexes: nil,
|
inputIndexes: nil,
|
||||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||||
{
|
inputStringPubKeys: []string{stringPubKey},
|
||||||
inputStringPubKeys: []string{stringPubKey},
|
inputIndexes: nil,
|
||||||
inputIndexes: nil,
|
inputStatuses: nil,
|
||||||
inputStatuses: nil,
|
|
||||||
|
|
||||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||||
Data: []*beacon.ValidatorContainer{
|
Data: []*beacon.ValidatorContainer{
|
||||||
{
|
{
|
||||||
Validator: &beacon.Validator{
|
Index: "0",
|
||||||
Pubkey: "NotAPublicKey",
|
Validator: &beacon.Validator{
|
||||||
},
|
Pubkey: "NotAPublicKey",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
outputErr: nil,
|
|
||||||
},
|
},
|
||||||
|
outputErr: nil,
|
||||||
},
|
},
|
||||||
outputErrMessage: "failed to parse validator public key",
|
validatorCountCalled: 1,
|
||||||
|
outputErrMessage: "failed to parse validator public key",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "failed to parse validator index NotAnIndex",
|
name: "failed to parse validator index NotAnIndex",
|
||||||
|
|
||||||
inputPubKeys: [][]byte{pubKey},
|
inputPubKeys: [][]byte{pubKey},
|
||||||
inputIndexes: nil,
|
inputIndexes: nil,
|
||||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||||
{
|
|
||||||
inputStringPubKeys: []string{stringPubKey},
|
|
||||||
inputIndexes: nil,
|
|
||||||
inputStatuses: nil,
|
|
||||||
|
|
||||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
inputStringPubKeys: []string{stringPubKey},
|
||||||
Data: []*beacon.ValidatorContainer{
|
inputIndexes: nil,
|
||||||
{
|
inputStatuses: nil,
|
||||||
Index: "NotAnIndex",
|
|
||||||
Validator: &beacon.Validator{
|
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||||
Pubkey: stringPubKey,
|
Data: []*beacon.ValidatorContainer{
|
||||||
},
|
{
|
||||||
|
Index: "NotAnIndex",
|
||||||
|
Validator: &beacon.Validator{
|
||||||
|
Pubkey: stringPubKey,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
outputErr: nil,
|
|
||||||
},
|
},
|
||||||
|
outputErr: nil,
|
||||||
},
|
},
|
||||||
outputErrMessage: "failed to parse validator index",
|
validatorCountCalled: 1,
|
||||||
|
outputErrMessage: "failed to parse validator index",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid validator status",
|
name: "invalid validator status",
|
||||||
|
|
||||||
inputPubKeys: [][]byte{pubKey},
|
inputPubKeys: [][]byte{pubKey},
|
||||||
inputIndexes: nil,
|
inputIndexes: nil,
|
||||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||||
{
|
inputStringPubKeys: []string{stringPubKey},
|
||||||
inputStringPubKeys: []string{stringPubKey},
|
inputIndexes: nil,
|
||||||
inputIndexes: nil,
|
inputStatuses: nil,
|
||||||
inputStatuses: nil,
|
|
||||||
|
|
||||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||||
Data: []*beacon.ValidatorContainer{
|
Data: []*beacon.ValidatorContainer{
|
||||||
{
|
{
|
||||||
Index: "12345",
|
Index: "12345",
|
||||||
Status: "NotAStatus",
|
Status: "NotAStatus",
|
||||||
Validator: &beacon.Validator{
|
Validator: &beacon.Validator{
|
||||||
Pubkey: stringPubKey,
|
Pubkey: stringPubKey,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
outputErr: nil,
|
|
||||||
},
|
},
|
||||||
|
outputErr: nil,
|
||||||
},
|
},
|
||||||
outputErrMessage: "invalid validator status NotAStatus",
|
validatorCountCalled: 1,
|
||||||
|
outputErrMessage: "invalid validator status NotAStatus",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "failed to parse activation epoch",
|
name: "failed to parse activation epoch",
|
||||||
|
|
||||||
inputPubKeys: [][]byte{pubKey},
|
inputPubKeys: [][]byte{pubKey},
|
||||||
inputIndexes: nil,
|
inputIndexes: nil,
|
||||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||||
{
|
inputStringPubKeys: []string{stringPubKey},
|
||||||
inputStringPubKeys: []string{stringPubKey},
|
inputIndexes: nil,
|
||||||
inputIndexes: nil,
|
inputStatuses: nil,
|
||||||
inputStatuses: nil,
|
|
||||||
|
|
||||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||||
Data: []*beacon.ValidatorContainer{
|
Data: []*beacon.ValidatorContainer{
|
||||||
{
|
{
|
||||||
Index: "12345",
|
Index: "12345",
|
||||||
Status: "active_ongoing",
|
Status: "active_ongoing",
|
||||||
Validator: &beacon.Validator{
|
Validator: &beacon.Validator{
|
||||||
Pubkey: stringPubKey,
|
Pubkey: stringPubKey,
|
||||||
ActivationEpoch: "NotAnEpoch",
|
ActivationEpoch: "NotAnEpoch",
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
outputErr: nil,
|
|
||||||
},
|
},
|
||||||
|
outputErr: nil,
|
||||||
},
|
},
|
||||||
outputErrMessage: "failed to parse activation epoch NotAnEpoch",
|
validatorCountCalled: 1,
|
||||||
|
outputErrMessage: "failed to parse activation epoch NotAnEpoch",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "failed to get state validators",
|
name: "failed to get state validators",
|
||||||
|
|
||||||
inputPubKeys: [][]byte{pubKey},
|
inputPubKeys: [][]byte{pubKey},
|
||||||
inputIndexes: nil,
|
inputIndexes: nil,
|
||||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||||
{
|
inputStringPubKeys: []string{stringPubKey},
|
||||||
inputStringPubKeys: []string{stringPubKey},
|
inputIndexes: nil,
|
||||||
inputIndexes: nil,
|
inputStatuses: nil,
|
||||||
inputStatuses: nil,
|
|
||||||
|
|
||||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
outputStateValidatorsResponseJson: nil,
|
||||||
Data: []*beacon.ValidatorContainer{
|
outputErr: errors.New("a specific error"),
|
||||||
{
|
|
||||||
Index: "12345",
|
|
||||||
Status: "pending_queued",
|
|
||||||
Validator: &beacon.Validator{
|
|
||||||
Pubkey: stringPubKey,
|
|
||||||
ActivationEpoch: "10",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
outputErr: nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inputStringPubKeys: nil,
|
|
||||||
inputIndexes: nil,
|
|
||||||
inputStatuses: []string{"active"},
|
|
||||||
|
|
||||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{},
|
|
||||||
outputErr: errors.New("a specific error"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
outputErrMessage: "failed to get state validators",
|
outputErrMessage: "failed to get state validators",
|
||||||
},
|
},
|
||||||
@ -643,42 +685,22 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
|||||||
|
|
||||||
inputPubKeys: [][]byte{pubKey},
|
inputPubKeys: [][]byte{pubKey},
|
||||||
inputIndexes: nil,
|
inputIndexes: nil,
|
||||||
inputGetStateValidatorsInterfaces: []getStateValidatorsInterface{
|
inputGetStateValidatorsInterface: getStateValidatorsInterface{
|
||||||
{
|
inputStringPubKeys: []string{stringPubKey},
|
||||||
inputStringPubKeys: []string{stringPubKey},
|
inputIndexes: nil,
|
||||||
inputIndexes: nil,
|
inputStatuses: nil,
|
||||||
inputStatuses: nil,
|
|
||||||
|
|
||||||
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
outputStateValidatorsResponseJson: &beacon.GetValidatorsResponse{
|
||||||
Data: []*beacon.ValidatorContainer{
|
Data: []*beacon.ValidatorContainer{
|
||||||
{
|
{
|
||||||
Index: "12345",
|
Index: "NotAnIndex",
|
||||||
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{
|
|
||||||
{
|
|
||||||
Index: "NotAnIndex",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
outputErr: nil,
|
|
||||||
},
|
},
|
||||||
|
outputErr: nil,
|
||||||
},
|
},
|
||||||
outputErrMessage: "failed to parse last validator index NotAnIndex",
|
validatorCountCalled: 1,
|
||||||
|
outputErrMessage: "failed to parse validator index NotAnIndex",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,21 +712,39 @@ func TestValidatorStatusResponse_InvalidData(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
stateValidatorsProvider := mock.NewMockstateValidatorsProvider(ctrl)
|
stateValidatorsProvider := mock.NewMockstateValidatorsProvider(ctrl)
|
||||||
|
stateValidatorsProvider.EXPECT().GetStateValidators(
|
||||||
|
ctx,
|
||||||
|
testCase.inputGetStateValidatorsInterface.inputStringPubKeys,
|
||||||
|
testCase.inputGetStateValidatorsInterface.inputIndexes,
|
||||||
|
testCase.inputGetStateValidatorsInterface.inputStatuses,
|
||||||
|
).Return(
|
||||||
|
testCase.inputGetStateValidatorsInterface.outputStateValidatorsResponseJson,
|
||||||
|
testCase.inputGetStateValidatorsInterface.outputErr,
|
||||||
|
).Times(1)
|
||||||
|
|
||||||
for _, aa := range testCase.inputGetStateValidatorsInterfaces {
|
jsonRestHandler := mock.NewMockjsonRestHandler(ctrl)
|
||||||
stateValidatorsProvider.EXPECT().GetStateValidators(
|
|
||||||
ctx,
|
// Expect node version endpoint call.
|
||||||
aa.inputStringPubKeys,
|
var nodeVersionResponse apimiddleware.VersionResponseJson
|
||||||
aa.inputIndexes,
|
jsonRestHandler.EXPECT().GetRestJsonResponse(
|
||||||
aa.inputStatuses,
|
ctx,
|
||||||
).Return(
|
"/eth/v1/node/version",
|
||||||
aa.outputStateValidatorsResponseJson,
|
&nodeVersionResponse,
|
||||||
aa.outputErr,
|
).Return(
|
||||||
).Times(1)
|
nil,
|
||||||
|
iface.ErrNotSupported,
|
||||||
|
).Times(testCase.validatorCountCalled)
|
||||||
|
|
||||||
|
validatorClient := beaconApiValidatorClient{
|
||||||
|
stateValidatorsProvider: stateValidatorsProvider,
|
||||||
|
prysmBeaconChainCLient: prysmBeaconChainClient{
|
||||||
|
nodeClient: &beaconApiNodeClient{
|
||||||
|
jsonRestHandler: jsonRestHandler,
|
||||||
|
},
|
||||||
|
jsonRestHandler: jsonRestHandler,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
validatorClient := beaconApiValidatorClient{stateValidatorsProvider: stateValidatorsProvider}
|
|
||||||
|
|
||||||
_, _, _, err := validatorClient.getValidatorsStatusResponse(
|
_, _, _, err := validatorClient.getValidatorsStatusResponse(
|
||||||
ctx,
|
ctx,
|
||||||
testCase.inputPubKeys,
|
testCase.inputPubKeys,
|
||||||
|
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/beacon-api:go_default_library",
|
||||||
"//validator/client/grpc-api:go_default_library",
|
"//validator/client/grpc-api:go_default_library",
|
||||||
"//validator/client/iface:go_default_library",
|
"//validator/client/iface:go_default_library",
|
||||||
|
"//validator/client/node-client-factory:go_default_library",
|
||||||
"//validator/helpers:go_default_library",
|
"//validator/helpers:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
beaconApi "github.com/prysmaticlabs/prysm/v4/validator/client/beacon-api"
|
beaconApi "github.com/prysmaticlabs/prysm/v4/validator/client/beacon-api"
|
||||||
grpcApi "github.com/prysmaticlabs/prysm/v4/validator/client/grpc-api"
|
grpcApi "github.com/prysmaticlabs/prysm/v4/validator/client/grpc-api"
|
||||||
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
"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"
|
validatorHelpers "github.com/prysmaticlabs/prysm/v4/validator/helpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,8 +14,26 @@ func NewBeaconChainClient(validatorConn validatorHelpers.NodeConnection) iface.B
|
|||||||
featureFlags := features.Get()
|
featureFlags := features.Get()
|
||||||
|
|
||||||
if featureFlags.EnableBeaconRESTApi {
|
if featureFlags.EnableBeaconRESTApi {
|
||||||
return beaconApi.NewBeaconApiBeaconChainClientWithFallback(validatorConn.GetBeaconApiUrl(), validatorConn.GetBeaconApiTimeout(), grpcClient)
|
return beaconApi.NewBeaconApiBeaconChainClientWithFallback(
|
||||||
|
validatorConn.GetBeaconApiUrl(),
|
||||||
|
validatorConn.GetBeaconApiTimeout(),
|
||||||
|
grpcClient,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return grpcClient
|
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 = [
|
srcs = [
|
||||||
"grpc_beacon_chain_client.go",
|
"grpc_beacon_chain_client.go",
|
||||||
"grpc_node_client.go",
|
"grpc_node_client.go",
|
||||||
|
"grpc_prysm_beacon_chain_client.go",
|
||||||
"grpc_validator_client.go",
|
"grpc_validator_client.go",
|
||||||
],
|
],
|
||||||
importpath = "github.com/prysmaticlabs/prysm/v4/validator/client/grpc-api",
|
importpath = "github.com/prysmaticlabs/prysm/v4/validator/client/grpc-api",
|
||||||
visibility = ["//validator:__subpackages__"],
|
visibility = ["//validator:__subpackages__"],
|
||||||
deps = [
|
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/primitives:go_default_library",
|
||||||
|
"//consensus-types/validator:go_default_library",
|
||||||
|
"//proto/eth/v1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
"//validator/client/iface:go_default_library",
|
"//validator/client/iface:go_default_library",
|
||||||
"@com_github_golang_protobuf//ptypes/empty",
|
"@com_github_golang_protobuf//ptypes/empty",
|
||||||
@ -22,11 +27,22 @@ go_library(
|
|||||||
go_test(
|
go_test(
|
||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
size = "small",
|
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"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
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/assert:go_default_library",
|
||||||
"//testing/mock: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",
|
"@com_github_golang_mock//gomock:go_default_library",
|
||||||
"@org_golang_google_protobuf//types/known/emptypb: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 = [
|
srcs = [
|
||||||
"beacon_chain_client.go",
|
"beacon_chain_client.go",
|
||||||
"node_client.go",
|
"node_client.go",
|
||||||
|
"prysm_beacon_chain_client.go",
|
||||||
"validator.go",
|
"validator.go",
|
||||||
"validator_client.go",
|
"validator_client.go",
|
||||||
],
|
],
|
||||||
importpath = "github.com/prysmaticlabs/prysm/v4/validator/client/iface",
|
importpath = "github.com/prysmaticlabs/prysm/v4/validator/client/iface",
|
||||||
visibility = ["//validator:__subpackages__"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//config/fieldparams:go_default_library",
|
"//config/fieldparams:go_default_library",
|
||||||
"//config/validator/service:go_default_library",
|
"//config/validator/service:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
|
"//consensus-types/validator:go_default_library",
|
||||||
"//crypto/bls:go_default_library",
|
"//crypto/bls:go_default_library",
|
||||||
"//proto/prysm/v1alpha1:go_default_library",
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
"//proto/prysm/v1alpha1/validator-client:go_default_library",
|
"//proto/prysm/v1alpha1/validator-client:go_default_library",
|
||||||
"//validator/keymanager:go_default_library",
|
"//validator/keymanager:go_default_library",
|
||||||
"@com_github_golang_protobuf//ptypes/empty",
|
"@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"
|
"context"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||||
|
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
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"
|
eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
)
|
)
|
||||||
@ -33,11 +36,19 @@ func (v *validator) HandleKeyReload(ctx context.Context, currentKeys [][fieldpar
|
|||||||
index: resp.Indices[i],
|
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")
|
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 {
|
if anyActive {
|
||||||
logActiveValidatorStatus(statuses)
|
logActiveValidatorStatus(statuses)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"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/golang/mock/gomock"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||||
@ -27,11 +30,13 @@ func TestValidator_HandleKeyReload(t *testing.T) {
|
|||||||
|
|
||||||
client := validatormock.NewMockValidatorClient(ctrl)
|
client := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: client,
|
validatorClient: client,
|
||||||
keyManager: newMockKeymanager(t, inactive),
|
keyManager: newMockKeymanager(t, inactive),
|
||||||
genesisTime: 1,
|
genesisTime: 1,
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:], active.pub[:]})
|
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:], active.pub[:]})
|
||||||
@ -43,7 +48,11 @@ func TestValidator_HandleKeyReload(t *testing.T) {
|
|||||||
PublicKeys: [][]byte{inactive.pub[:], active.pub[:]},
|
PublicKeys: [][]byte{inactive.pub[:], active.pub[:]},
|
||||||
},
|
},
|
||||||
).Return(resp, nil)
|
).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})
|
anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{inactive.pub, active.pub})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -57,12 +66,14 @@ func TestValidator_HandleKeyReload(t *testing.T) {
|
|||||||
|
|
||||||
client := validatormock.NewMockValidatorClient(ctrl)
|
client := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
kp := randKeypair(t)
|
kp := randKeypair(t)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: client,
|
validatorClient: client,
|
||||||
keyManager: newMockKeymanager(t, kp),
|
keyManager: newMockKeymanager(t, kp),
|
||||||
genesisTime: 1,
|
genesisTime: 1,
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]})
|
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]})
|
||||||
@ -73,7 +84,11 @@ func TestValidator_HandleKeyReload(t *testing.T) {
|
|||||||
PublicKeys: [][]byte{kp.pub[:]},
|
PublicKeys: [][]byte{kp.pub[:]},
|
||||||
},
|
},
|
||||||
).Return(resp, nil)
|
).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})
|
anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{kp.pub})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -189,6 +189,7 @@ func (v *ValidatorService) Start() {
|
|||||||
|
|
||||||
validatorClient := validatorClientFactory.NewValidatorClient(v.conn)
|
validatorClient := validatorClientFactory.NewValidatorClient(v.conn)
|
||||||
beaconClient := beaconChainClientFactory.NewBeaconChainClient(v.conn)
|
beaconClient := beaconChainClientFactory.NewBeaconChainClient(v.conn)
|
||||||
|
prysmBeaconClient := beaconChainClientFactory.NewPrysmBeaconClient(v.conn)
|
||||||
|
|
||||||
valStruct := &validator{
|
valStruct := &validator{
|
||||||
db: v.db,
|
db: v.db,
|
||||||
@ -218,6 +219,7 @@ func (v *ValidatorService) Start() {
|
|||||||
Web3SignerConfig: v.Web3SignerConfig,
|
Web3SignerConfig: v.Web3SignerConfig,
|
||||||
proposerSettings: v.proposerSettings,
|
proposerSettings: v.proposerSettings,
|
||||||
walletInitializedChannel: make(chan *wallet.Wallet, 1),
|
walletInitializedChannel: make(chan *wallet.Wallet, 1),
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
// To resolve a race condition at startup due to the interface
|
// To resolve a race condition at startup due to the interface
|
||||||
|
@ -104,6 +104,7 @@ type validator struct {
|
|||||||
Web3SignerConfig *remoteweb3signer.SetupConfig
|
Web3SignerConfig *remoteweb3signer.SetupConfig
|
||||||
proposerSettings *validatorserviceconfig.ProposerSettings
|
proposerSettings *validatorserviceconfig.ProposerSettings
|
||||||
walletInitializedChannel chan *wallet.Wallet
|
walletInitializedChannel chan *wallet.Wallet
|
||||||
|
prysmBeaconClient iface.PrysmBeaconChainClient
|
||||||
}
|
}
|
||||||
|
|
||||||
type validatorStatus struct {
|
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 {
|
func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, activeValCount int64) bool {
|
||||||
activationsPerEpoch :=
|
|
||||||
uint64(math.Max(float64(params.BeaconConfig().MinPerEpochChurnLimit), float64(activeValCount/params.BeaconConfig().ChurnLimitQuotient)))
|
|
||||||
|
|
||||||
nonexistentIndex := primitives.ValidatorIndex(^uint64(0))
|
nonexistentIndex := primitives.ValidatorIndex(^uint64(0))
|
||||||
var validatorActivated bool
|
var validatorActivated bool
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
@ -398,15 +396,17 @@ func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, acti
|
|||||||
).Info("Deposit processed, entering activation queue after finalization")
|
).Info("Deposit processed, entering activation queue after finalization")
|
||||||
}
|
}
|
||||||
case ethpb.ValidatorStatus_PENDING:
|
case ethpb.ValidatorStatus_PENDING:
|
||||||
secondsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
if activeValCount >= 0 && status.status.ActivationEpoch == params.BeaconConfig().FarFutureEpoch {
|
||||||
expectedWaitingTime :=
|
activationsPerEpoch :=
|
||||||
time.Duration((status.status.PositionInActivationQueue+activationsPerEpoch)/activationsPerEpoch*secondsPerEpoch) * time.Second
|
uint64(math.Max(float64(params.BeaconConfig().MinPerEpochChurnLimit), float64(uint64(activeValCount)/params.BeaconConfig().ChurnLimitQuotient)))
|
||||||
if status.status.ActivationEpoch == params.BeaconConfig().FarFutureEpoch {
|
secondsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot))
|
||||||
|
expectedWaitingTime :=
|
||||||
|
time.Duration((status.status.PositionInActivationQueue+activationsPerEpoch)/activationsPerEpoch*secondsPerEpoch) * time.Second
|
||||||
log.WithFields(logrus.Fields{
|
log.WithFields(logrus.Fields{
|
||||||
"positionInActivationQueue": status.status.PositionInActivationQueue,
|
"positionInActivationQueue": status.status.PositionInActivationQueue,
|
||||||
"expectedWaitingTime": expectedWaitingTime.String(),
|
"expectedWaitingTime": expectedWaitingTime.String(),
|
||||||
}).Info("Waiting to be assigned activation epoch")
|
}).Info("Waiting to be assigned activation epoch")
|
||||||
} else {
|
} else if status.status.ActivationEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||||
log.WithFields(logrus.Fields{
|
log.WithFields(logrus.Fields{
|
||||||
"activationEpoch": status.status.ActivationEpoch,
|
"activationEpoch": status.status.ActivationEpoch,
|
||||||
}).Info("Waiting for activation")
|
}).Info("Waiting for activation")
|
||||||
|
@ -358,12 +358,14 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
|
|
||||||
kp := randKeypair(t)
|
kp := randKeypair(t)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: newMockKeymanager(t, kp),
|
keyManager: newMockKeymanager(t, kp),
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||||
@ -379,7 +381,11 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
|
|||||||
resp,
|
resp,
|
||||||
nil,
|
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.NoError(t, v.WaitForActivation(ctx, nil), "Could not wait for activation")
|
||||||
require.LogsContain(t, hook, "Validator activated")
|
require.LogsContain(t, hook, "Validator activated")
|
||||||
}
|
}
|
||||||
@ -389,12 +395,14 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
|
|
||||||
kp := randKeypair(t)
|
kp := randKeypair(t)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: newMockKeymanager(t, kp),
|
keyManager: newMockKeymanager(t, kp),
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||||
@ -403,7 +411,11 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
|
|||||||
gomock.Any(),
|
gomock.Any(),
|
||||||
gomock.Any(),
|
gomock.Any(),
|
||||||
).Return(clientStream, nil)
|
).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(
|
clientStream.EXPECT().Recv().Return(
|
||||||
ðpb.ValidatorActivationResponse{},
|
ðpb.ValidatorActivationResponse{},
|
||||||
nil,
|
nil,
|
||||||
|
@ -5,6 +5,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
validator2 "github.com/prysmaticlabs/prysm/v4/consensus-types/validator"
|
||||||
|
"github.com/prysmaticlabs/prysm/v4/validator/client/iface"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/v4/config/params"
|
"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})
|
// "-1" indicates that validator count endpoint is not supported by the beacon node.
|
||||||
if err != nil {
|
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")
|
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 {
|
if valActivated {
|
||||||
logActiveValidatorStatus(statuses)
|
logActiveValidatorStatus(statuses)
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,6 +7,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"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/golang/mock/gomock"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
||||||
@ -57,11 +60,13 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
kp := randKeypair(t)
|
kp := randKeypair(t)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: newMockKeymanager(t, kp),
|
keyManager: newMockKeymanager(t, kp),
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
||||||
validatorClient.EXPECT().WaitForActivation(
|
validatorClient.EXPECT().WaitForActivation(
|
||||||
@ -70,7 +75,11 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
|
|||||||
PublicKeys: [][]byte{kp.pub[:]},
|
PublicKeys: [][]byte{kp.pub[:]},
|
||||||
},
|
},
|
||||||
).Return(clientStream, errors.New("failed stream")).Return(clientStream, nil)
|
).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 := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||||
clientStream.EXPECT().Recv().Return(resp, nil)
|
clientStream.EXPECT().Recv().Return(resp, nil)
|
||||||
@ -82,11 +91,13 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
kp := randKeypair(t)
|
kp := randKeypair(t)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: newMockKeymanager(t, kp),
|
keyManager: newMockKeymanager(t, kp),
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
||||||
validatorClient.EXPECT().WaitForActivation(
|
validatorClient.EXPECT().WaitForActivation(
|
||||||
@ -95,7 +106,11 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
|
|||||||
PublicKeys: [][]byte{kp.pub[:]},
|
PublicKeys: [][]byte{kp.pub[:]},
|
||||||
},
|
},
|
||||||
).Return(clientStream, nil)
|
).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.
|
// A stream fails the first time, but succeeds the second time.
|
||||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||||
@ -112,12 +127,14 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
kp := randKeypair(t)
|
kp := randKeypair(t)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: newMockKeymanager(t, kp),
|
keyManager: newMockKeymanager(t, kp),
|
||||||
genesisTime: 1,
|
genesisTime: 1,
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||||
@ -128,7 +145,11 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
|
|||||||
PublicKeys: [][]byte{kp.pub[:]},
|
PublicKeys: [][]byte{kp.pub[:]},
|
||||||
},
|
},
|
||||||
).Return(clientStream, nil)
|
).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(
|
clientStream.EXPECT().Recv().Return(
|
||||||
resp,
|
resp,
|
||||||
nil,
|
nil,
|
||||||
@ -142,11 +163,13 @@ func TestWaitForActivation_Exiting(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
kp := randKeypair(t)
|
kp := randKeypair(t)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: newMockKeymanager(t, kp),
|
keyManager: newMockKeymanager(t, kp),
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_EXITING
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_EXITING
|
||||||
@ -157,7 +180,11 @@ func TestWaitForActivation_Exiting(t *testing.T) {
|
|||||||
PublicKeys: [][]byte{kp.pub[:]},
|
PublicKeys: [][]byte{kp.pub[:]},
|
||||||
},
|
},
|
||||||
).Return(clientStream, nil)
|
).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(
|
clientStream.EXPECT().Recv().Return(
|
||||||
resp,
|
resp,
|
||||||
nil,
|
nil,
|
||||||
@ -177,15 +204,17 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
|||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
|
|
||||||
kp := randKeypair(t)
|
kp := randKeypair(t)
|
||||||
km := newMockKeymanager(t, kp)
|
km := newMockKeymanager(t, kp)
|
||||||
km.fetchNoKeys = true
|
km.fetchNoKeys = true
|
||||||
|
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: km,
|
keyManager: km,
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
|
||||||
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
||||||
@ -196,7 +225,11 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
|||||||
PublicKeys: [][]byte{kp.pub[:]},
|
PublicKeys: [][]byte{kp.pub[:]},
|
||||||
},
|
},
|
||||||
).Return(clientStream, nil)
|
).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(
|
clientStream.EXPECT().Recv().Return(
|
||||||
resp,
|
resp,
|
||||||
nil)
|
nil)
|
||||||
@ -217,10 +250,12 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
|||||||
km := newMockKeymanager(t, inactive)
|
km := newMockKeymanager(t, inactive)
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: km,
|
keyManager: km,
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
inactiveResp := generateMockStatusResponse([][]byte{inactive.pub[:]})
|
inactiveResp := generateMockStatusResponse([][]byte{inactive.pub[:]})
|
||||||
inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
||||||
@ -231,7 +266,11 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
|||||||
PublicKeys: [][]byte{inactive.pub[:]},
|
PublicKeys: [][]byte{inactive.pub[:]},
|
||||||
},
|
},
|
||||||
).Return(inactiveClientStream, nil)
|
).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(
|
inactiveClientStream.EXPECT().Recv().Return(
|
||||||
inactiveResp,
|
inactiveResp,
|
||||||
nil,
|
nil,
|
||||||
@ -297,11 +336,13 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
validatorClient := validatormock.NewMockValidatorClient(ctrl)
|
||||||
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
beaconClient := validatormock.NewMockBeaconChainClient(ctrl)
|
||||||
|
prysmBeaconClient := validatormock.NewMockPrysmBeaconChainClient(ctrl)
|
||||||
v := validator{
|
v := validator{
|
||||||
validatorClient: validatorClient,
|
validatorClient: validatorClient,
|
||||||
keyManager: km,
|
keyManager: km,
|
||||||
genesisTime: 1,
|
genesisTime: 1,
|
||||||
beaconClient: beaconClient,
|
beaconClient: beaconClient,
|
||||||
|
prysmBeaconClient: prysmBeaconClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]})
|
inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]})
|
||||||
@ -313,7 +354,11 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
|||||||
PublicKeys: [][]byte{inactivePubKey[:]},
|
PublicKeys: [][]byte{inactivePubKey[:]},
|
||||||
},
|
},
|
||||||
).Return(inactiveClientStream, nil)
|
).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(
|
inactiveClientStream.EXPECT().Recv().Return(
|
||||||
inactiveResp,
|
inactiveResp,
|
||||||
nil,
|
nil,
|
||||||
|
Loading…
Reference in New Issue
Block a user