looking at ways to reduce validator registration calls (#14371)

* looking at ways to reduce validator registration calls

* small mistake, should be epoch start

* adding more optimizations for reducing registration calls while covering more edgecases

* linting

* adding change log and force full push override

* fixing bug and adding tests

* changing if statement just to be safe

* potuz feedback for easier readability

* more review feedback for simplicity

* more review suggestions from potuz

* fix unit test

* reduce redundancy

* Update CHANGELOG.md

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* small nitpick

* fixing typo

* updating logs

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
james-prysm
2024-09-09 11:30:41 -05:00
committed by GitHub
parent 62b8e63a0a
commit 4c14bd8be2
17 changed files with 454 additions and 224 deletions

View File

@@ -45,6 +45,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
- Electra: build blocks with blobs.
- E2E: fixed gas limit at genesis
- Light client support: use LightClientHeader instead of BeaconBlockHeader.
- validator registration log changed to debug, and the frequency of validator registration calls are reduced
- Core: Fix process effective balance update to safe copy validator for Electra.
- `== nil` checks before calling `IsNil()` on interfaces to prevent panics.

View File

@@ -278,7 +278,11 @@ func (c *Client) RegisterValidator(ctx context.Context, svr []*ethpb.SignedValid
}
_, err = c.do(ctx, http.MethodPost, postRegisterValidatorPath, bytes.NewBuffer(body))
return err
if err != nil {
return err
}
log.WithField("num_registrations", len(svr)).Info("successfully registered validator(s) on builder")
return nil
}
var errResponseVersionMismatch = errors.New("builder API response uses a different version than requested in " + api.VersionHeader + " header")

View File

@@ -429,7 +429,7 @@ func (vs *Server) PrepareBeaconProposer(
if len(validatorIndices) != 0 {
log.WithFields(logrus.Fields{
"validatorCount": len(validatorIndices),
}).Info("Updated fee recipient addresses for validator indices")
}).Debug("Updated fee recipient addresses for validator indices")
}
return &emptypb.Empty{}, nil
}

View File

@@ -204,7 +204,7 @@ func (*Validator) HasProposerSettings() bool {
}
// PushProposerSettings for mocking
func (_ *Validator) PushProposerSettings(_ context.Context, _ keymanager.IKeymanager, _ primitives.Slot) error {
func (_ *Validator) PushProposerSettings(_ context.Context, _ keymanager.IKeymanager, _ primitives.Slot, _ bool) error {
panic("implement me")
}
@@ -214,7 +214,7 @@ func (_ *Validator) SetPubKeyToValidatorIndexMap(_ context.Context, _ keymanager
}
// SignValidatorRegistrationRequest for mocking
func (_ *Validator) SignValidatorRegistrationRequest(_ context.Context, _ iface2.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) {
func (_ *Validator) SignValidatorRegistrationRequest(_ context.Context, _ iface2.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool, error) {
panic("implement me")
}

View File

@@ -175,9 +175,7 @@ go_test(
"@com_github_wealdtech_go_eth2_util//:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//metadata:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
"@org_uber_go_mock//gomock:go_default_library",
],

View File

@@ -57,8 +57,8 @@ type Validator interface {
Keymanager() (keymanager.IKeymanager, error)
HandleKeyReload(ctx context.Context, currentKeys [][fieldparams.BLSPubkeyLength]byte) (bool, error)
CheckDoppelGanger(ctx context.Context) error
PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot) error
SignValidatorRegistrationRequest(ctx context.Context, signer SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error)
PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot, forceFullPush bool) error
SignValidatorRegistrationRequest(ctx context.Context, signer SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool /* isCached */, error)
StartEventStream(ctx context.Context, topics []string, eventsChan chan<- *event.Event)
EventStreamIsRunning() bool
ProcessEvent(event *event.Event)

View File

@@ -7,34 +7,18 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
validator2 "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
)
// HandleKeyReload makes sure the validator keeps operating correctly after a change to the underlying keys.
// It is also responsible for logging out information about the new state of keys.
func (v *validator) HandleKeyReload(ctx context.Context, currentKeys [][fieldparams.BLSPubkeyLength]byte) (anyActive bool, err error) {
func (v *validator) HandleKeyReload(ctx context.Context, currentKeys [][fieldparams.BLSPubkeyLength]byte) (bool, error) {
ctx, span := trace.StartSpan(ctx, "validator.HandleKeyReload")
defer span.End()
statusRequestKeys := make([][]byte, len(currentKeys))
for i := range currentKeys {
statusRequestKeys[i] = currentKeys[i][:]
}
resp, err := v.validatorClient.MultipleValidatorStatus(ctx, &eth.MultipleValidatorStatusRequest{
PublicKeys: statusRequestKeys,
})
if err != nil {
if err := v.updateValidatorStatusCache(ctx, currentKeys); err != nil {
return false, err
}
statuses := make([]*validatorStatus, len(resp.Statuses))
for i, s := range resp.Statuses {
statuses[i] = &validatorStatus{
publicKey: resp.PublicKeys[i],
status: s,
index: resp.Indices[i],
}
}
// "-1" indicates that validator count endpoint is not supported by the beacon node.
var valCount int64 = -1
@@ -47,5 +31,5 @@ func (v *validator) HandleKeyReload(ctx context.Context, currentKeys [][fieldpar
valCount = int64(valCounts[0].Count)
}
return v.checkAndLogValidatorStatus(statuses, valCount), nil
return v.checkAndLogValidatorStatus(valCount), nil
}

View File

@@ -36,6 +36,7 @@ func TestValidator_HandleKeyReload(t *testing.T) {
genesisTime: 1,
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
}
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:], active.pub[:]})
@@ -73,6 +74,7 @@ func TestValidator_HandleKeyReload(t *testing.T) {
genesisTime: 1,
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
}
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]})
@@ -103,6 +105,7 @@ func TestValidator_HandleKeyReload(t *testing.T) {
validatorClient: client,
km: newMockKeymanager(t, kp),
genesisTime: 1,
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
}
client.EXPECT().MultipleValidatorStatus(

View File

@@ -93,24 +93,24 @@ func signValidatorRegistration(ctx context.Context, signer iface.SigningFunc, re
}
// SignValidatorRegistrationRequest compares and returns either the cached validator registration request or signs a new one.
func (v *validator) SignValidatorRegistrationRequest(ctx context.Context, signer iface.SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) {
func (v *validator) SignValidatorRegistrationRequest(ctx context.Context, signer iface.SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool /* isCached */, error) {
ctx, span := trace.StartSpan(ctx, "validator.SignValidatorRegistrationRequest")
defer span.End()
signedReg, ok := v.signedValidatorRegistrations[bytesutil.ToBytes48(newValidatorRegistration.Pubkey)]
if ok && isValidatorRegistrationSame(signedReg.Message, newValidatorRegistration) {
return signedReg, nil
return signedReg, true, nil
} else {
sig, err := signValidatorRegistration(ctx, signer, newValidatorRegistration)
if err != nil {
return nil, err
return nil, false, err
}
newRequest := &ethpb.SignedValidatorRegistrationV1{
Message: newValidatorRegistration,
Signature: sig,
}
v.signedValidatorRegistrations[bytesutil.ToBytes48(newValidatorRegistration.Pubkey)] = newRequest
return newRequest, nil
return newRequest, false, nil
}
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/require"
@@ -172,7 +171,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) {
},
validatorSetter: func(t *testing.T) *validator {
v := validator{
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
genesisTime: 0,
@@ -200,7 +199,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) {
},
validatorSetter: func(t *testing.T) *validator {
v := validator{
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
genesisTime: 0,
@@ -228,7 +227,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) {
},
validatorSetter: func(t *testing.T) *validator {
v := validator{
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
genesisTime: 0,
@@ -256,7 +255,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) {
},
validatorSetter: func(t *testing.T) *validator {
v := validator{
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
genesisTime: 0,
@@ -272,7 +271,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) {
startingReq, ok := v.signedValidatorRegistrations[bytesutil.ToBytes48(tt.arg.Pubkey)]
got, err := v.SignValidatorRegistrationRequest(ctx, m.signfunc, tt.arg)
got, _, err := v.SignValidatorRegistrationRequest(ctx, m.signfunc, tt.arg)
require.NoError(t, err)
if tt.isCached {
require.DeepEqual(t, got, v.signedValidatorRegistrations[bytesutil.ToBytes48(tt.arg.Pubkey)])

View File

@@ -62,7 +62,7 @@ func run(ctx context.Context, v iface.Validator) {
log.Warn("Validator client started without proposer settings such as fee recipient" +
" and will continue to use settings provided in the beacon node.")
}
if err := v.PushProposerSettings(ctx, km, headSlot); err != nil {
if err := v.PushProposerSettings(ctx, km, headSlot, true); err != nil {
log.WithError(err).Fatal("Failed to update proposer settings")
}
for {
@@ -97,7 +97,7 @@ func run(ctx context.Context, v iface.Validator) {
// call push proposer settings often to account for the following edge cases:
// proposer is activated at the start of epoch and tries to propose immediately
// account has changed in the middle of an epoch
if err := v.PushProposerSettings(ctx, km, slot); err != nil {
if err := v.PushProposerSettings(ctx, km, slot, false); err != nil {
log.WithError(err).Warn("Failed to update proposer settings")
}
@@ -316,7 +316,7 @@ func runHealthCheckRoutine(ctx context.Context, v iface.Validator, eventsChan ch
log.WithError(err).Error("Could not get canonical head slot")
return
}
if err := v.PushProposerSettings(ctx, km, slot); err != nil {
if err := v.PushProposerSettings(ctx, km, slot, true); err != nil {
log.WithError(err).Warn("Failed to update proposer settings")
}
}

View File

@@ -184,7 +184,7 @@ func (v *ValidatorService) Start() {
startBalances: make(map[[fieldparams.BLSPubkeyLength]byte]uint64),
prevEpochBalances: make(map[[fieldparams.BLSPubkeyLength]byte]uint64),
blacklistedPubkeys: slashablePublicKeys,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
wallet: v.wallet,
walletInitializedChan: make(chan *wallet.Wallet, 1),
walletInitializedFeed: v.walletInitializedFeed,

View File

@@ -254,7 +254,7 @@ func (*FakeValidator) HasProposerSettings() bool {
}
// PushProposerSettings for mocking
func (fv *FakeValidator) PushProposerSettings(ctx context.Context, _ keymanager.IKeymanager, _ primitives.Slot) error {
func (fv *FakeValidator) PushProposerSettings(ctx context.Context, _ keymanager.IKeymanager, _ primitives.Slot, _ bool) error {
time.Sleep(fv.ProposerSettingWait)
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
log.Error("deadline exceeded")
@@ -276,8 +276,8 @@ func (*FakeValidator) SetPubKeyToValidatorIndexMap(_ context.Context, _ keymanag
}
// SignValidatorRegistrationRequest for mocking
func (*FakeValidator) SignValidatorRegistrationRequest(_ context.Context, _ iface.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) {
return nil, nil
func (*FakeValidator) SignValidatorRegistrationRequest(_ context.Context, _ iface.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool, error) {
return nil, false, nil
}
// ProposerSettings for mocking

View File

@@ -40,7 +40,6 @@ import (
"github.com/prysmaticlabs/prysm/v5/time/slots"
accountsiface "github.com/prysmaticlabs/prysm/v5/validator/accounts/iface"
"github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet"
beaconapi "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api"
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
"github.com/prysmaticlabs/prysm/v5/validator/db"
dbCommon "github.com/prysmaticlabs/prysm/v5/validator/db/common"
@@ -49,9 +48,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/validator/keymanager/local"
remoteweb3signer "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/emptypb"
)
@@ -77,7 +74,7 @@ type validator struct {
startBalances map[[fieldparams.BLSPubkeyLength]byte]uint64
prevEpochBalances map[[fieldparams.BLSPubkeyLength]byte]uint64
blacklistedPubkeys map[[fieldparams.BLSPubkeyLength]byte]bool
pubkeyToValidatorIndex map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex
pubkeyToStatus map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus
wallet *wallet.Wallet
walletInitializedChan chan *wallet.Wallet
walletInitializedFeed *event.Feed
@@ -352,10 +349,10 @@ func (v *validator) WaitForSync(ctx context.Context) error {
}
}
func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, activeValCount int64) bool {
func (v *validator) checkAndLogValidatorStatus(activeValCount int64) bool {
nonexistentIndex := primitives.ValidatorIndex(^uint64(0))
var validatorActivated bool
for _, s := range statuses {
for _, s := range v.pubkeyToStatus {
fields := logrus.Fields{
"pubkey": fmt.Sprintf("%#x", bytesutil.Trunc(s.publicKey)),
"status": s.status.Status.String(),
@@ -1102,7 +1099,7 @@ func (v *validator) SetProposerSettings(ctx context.Context, settings *proposer.
}
// PushProposerSettings calls the prepareBeaconProposer RPC to set the fee recipient and also the register validator API if using a custom builder.
func (v *validator) PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot) error {
func (v *validator) PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot, forceFullPush bool) error {
ctx, span := trace.StartSpan(ctx, "validator.PushProposerSettings")
defer span.End()
@@ -1143,7 +1140,7 @@ func (v *validator) PushProposerSettings(ctx context.Context, km keymanager.IKey
}); err != nil {
return err
}
signedRegReqs := v.buildSignedRegReqs(ctx, filteredKeys, km.Sign)
signedRegReqs := v.buildSignedRegReqs(ctx, filteredKeys, km.Sign, slot, forceFullPush)
if len(signedRegReqs) > 0 {
go func() {
if err := SubmitValidatorRegistrations(ctx, v.validatorClient, signedRegReqs, v.validatorsRegBatchSize); err != nil {
@@ -1212,44 +1209,31 @@ func (v *validator) ChangeHost() {
func (v *validator) filterAndCacheActiveKeys(ctx context.Context, pubkeys [][fieldparams.BLSPubkeyLength]byte, slot primitives.Slot) ([][fieldparams.BLSPubkeyLength]byte, error) {
ctx, span := trace.StartSpan(ctx, "validator.filterAndCacheActiveKeys")
defer span.End()
isEpochStart := slots.IsEpochStart(slot)
filteredKeys := make([][fieldparams.BLSPubkeyLength]byte, 0)
statusRequestKeys := make([][]byte, 0)
for _, k := range pubkeys {
_, ok := v.pubkeyToValidatorIndex[k]
// Get validator index from RPC server if not found.
if !ok {
i, ok, err := v.validatorIndex(ctx, k)
if err != nil {
return nil, err
}
if !ok { // Nothing we can do if RPC server doesn't have validator index.
continue
}
v.pubkeyToValidatorIndex[k] = i
if len(pubkeys) == 0 {
return filteredKeys, nil
}
var err error
// repopulate the statuses if epoch start or if a new key is added missing the cache
if isEpochStart || len(v.pubkeyToStatus) != len(pubkeys) /* cache not populated or updated correctly */ {
if err = v.updateValidatorStatusCache(ctx, pubkeys); err != nil {
return nil, errors.Wrap(err, "failed to update validator status cache")
}
copiedk := k
statusRequestKeys = append(statusRequestKeys, copiedk[:])
}
resp, err := v.validatorClient.MultipleValidatorStatus(ctx, &ethpb.MultipleValidatorStatusRequest{
PublicKeys: statusRequestKeys,
})
if err != nil {
return nil, err
}
for i, s := range resp.Statuses {
for k, s := range v.pubkeyToStatus {
currEpoch := primitives.Epoch(slot / params.BeaconConfig().SlotsPerEpoch)
currActivating := s.Status == ethpb.ValidatorStatus_PENDING && currEpoch >= s.ActivationEpoch
currActivating := s.status.Status == ethpb.ValidatorStatus_PENDING && currEpoch >= s.status.ActivationEpoch
active := s.Status == ethpb.ValidatorStatus_ACTIVE
exiting := s.Status == ethpb.ValidatorStatus_EXITING
active := s.status.Status == ethpb.ValidatorStatus_ACTIVE
exiting := s.status.Status == ethpb.ValidatorStatus_EXITING
if currActivating || active || exiting {
filteredKeys = append(filteredKeys, bytesutil.ToBytes48(resp.PublicKeys[i]))
filteredKeys = append(filteredKeys, k)
} else {
log.WithFields(logrus.Fields{
"pubkey": hexutil.Encode(resp.PublicKeys[i]),
"status": s.Status.String(),
"pubkey": hexutil.Encode(s.publicKey),
"status": s.status.Status.String(),
}).Debugf("Skipping non-active status key.")
}
}
@@ -1257,11 +1241,47 @@ func (v *validator) filterAndCacheActiveKeys(ctx context.Context, pubkeys [][fie
return filteredKeys, nil
}
// updateValidatorStatusCache updates the validator statuses cache, a map of keys currently used by the validator client
func (v *validator) updateValidatorStatusCache(ctx context.Context, pubkeys [][fieldparams.BLSPubkeyLength]byte) error {
statusRequestKeys := make([][]byte, 0)
for _, k := range pubkeys {
statusRequestKeys = append(statusRequestKeys, k[:])
}
resp, err := v.validatorClient.MultipleValidatorStatus(ctx, &ethpb.MultipleValidatorStatusRequest{
PublicKeys: statusRequestKeys,
})
if err != nil {
return err
}
if resp == nil {
return errors.New("response is nil")
}
if len(resp.Statuses) != len(resp.PublicKeys) {
return fmt.Errorf("expected %d pubkeys in status, received %d", len(resp.Statuses), len(resp.PublicKeys))
}
if len(resp.Statuses) != len(resp.Indices) {
return fmt.Errorf("expected %d indices in status, received %d", len(resp.Statuses), len(resp.Indices))
}
for i, s := range resp.Statuses {
v.pubkeyToStatus[bytesutil.ToBytes48(resp.PublicKeys[i])] = &validatorStatus{
publicKey: resp.PublicKeys[i],
status: s,
index: resp.Indices[i],
}
}
return nil
}
func (v *validator) buildPrepProposerReqs(activePubkeys [][fieldparams.BLSPubkeyLength]byte) ([]*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer, error) {
var prepareProposerReqs []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer
for _, k := range activePubkeys {
s, ok := v.pubkeyToStatus[k]
if !ok {
continue
}
// Default case: Define fee recipient to burn address
var feeRecipient common.Address
feeRecipient := common.HexToAddress(params.BeaconConfig().EthBurnAddressHex)
// If fee recipient is defined in default configuration, use it
if v.ProposerSettings() != nil && v.ProposerSettings().DefaultConfig != nil && v.ProposerSettings().DefaultConfig.FeeRecipientConfig != nil {
@@ -1277,13 +1297,8 @@ func (v *validator) buildPrepProposerReqs(activePubkeys [][fieldparams.BLSPubkey
}
}
validatorIndex, ok := v.pubkeyToValidatorIndex[k]
if !ok {
continue
}
prepareProposerReqs = append(prepareProposerReqs, &ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
ValidatorIndex: validatorIndex,
ValidatorIndex: s.index,
FeeRecipient: feeRecipient[:],
})
}
@@ -1294,19 +1309,27 @@ func (v *validator) buildSignedRegReqs(
ctx context.Context,
activePubkeys [][fieldparams.BLSPubkeyLength]byte,
signer iface.SigningFunc,
slot primitives.Slot,
forceFullPush bool,
) []*ethpb.SignedValidatorRegistrationV1 {
ctx, span := trace.StartSpan(ctx, "validator.buildSignedRegReqs")
defer span.End()
var signedValRegRegs []*ethpb.SignedValidatorRegistrationV1
var signedValRegRequests []*ethpb.SignedValidatorRegistrationV1
if v.ProposerSettings() == nil {
return signedValRegRegs
return signedValRegRequests
}
// if the timestamp is pre-genesis, don't create registrations
if v.genesisTime > uint64(time.Now().UTC().Unix()) {
return signedValRegRegs
return signedValRegRequests
}
for i, k := range activePubkeys {
// map is populated before this function in buildPrepProposerReq
_, ok := v.pubkeyToStatus[k]
if !ok {
continue
}
feeRecipient := common.HexToAddress(params.BeaconConfig().EthBurnAddressHex)
gasLimit := params.BeaconConfig().DefaultBuilderGasLimit
enabled := false
@@ -1346,12 +1369,6 @@ func (v *validator) buildSignedRegReqs(
continue
}
// map is populated before this function in buildPrepProposerReq
_, ok := v.pubkeyToValidatorIndex[k]
if !ok {
continue
}
req := &ethpb.ValidatorRegistrationV1{
FeeRecipient: feeRecipient[:],
GasLimit: gasLimit,
@@ -1359,7 +1376,7 @@ func (v *validator) buildSignedRegReqs(
Pubkey: activePubkeys[i][:],
}
signedReq, err := v.SignValidatorRegistrationRequest(ctx, signer, req)
signedRequest, isCached, err := v.SignValidatorRegistrationRequest(ctx, signer, req)
if err != nil {
log.WithFields(logrus.Fields{
"pubkey": fmt.Sprintf("%#x", req.Pubkey),
@@ -1368,38 +1385,20 @@ func (v *validator) buildSignedRegReqs(
continue
}
signedValRegRegs = append(signedValRegRegs, signedReq)
if hexutil.Encode(feeRecipient.Bytes()) == params.BeaconConfig().EthBurnAddressHex {
log.WithFields(logrus.Fields{
"pubkey": fmt.Sprintf("%#x", req.Pubkey),
"feeRecipient": feeRecipient,
}).Warn("Fee recipient is burn address")
}
}
return signedValRegRegs
}
func (v *validator) validatorIndex(ctx context.Context, pubkey [fieldparams.BLSPubkeyLength]byte) (primitives.ValidatorIndex, bool, error) {
ctx, span := trace.StartSpan(ctx, "validator.validatorIndex")
defer span.End()
resp, err := v.validatorClient.ValidatorIndex(ctx, &ethpb.ValidatorIndexRequest{PublicKey: pubkey[:]})
switch {
case status.Code(err) == codes.NotFound:
log.Debugf("Could not find validator index for public key %#x. "+
"Perhaps the validator is not yet active.", pubkey)
return 0, false, nil
case err != nil:
notFoundErr := &beaconapi.IndexNotFoundError{}
if errors.As(err, &notFoundErr) {
log.Debugf("Could not find validator index for public key %#x. "+
"Perhaps the validator is not yet active.", pubkey)
return 0, false, nil
if slots.IsEpochStart(slot) || forceFullPush || !isCached {
// if epoch start (or forced to) send all validator registrations
// otherwise if slot is not epoch start then only send new non cached values
signedValRegRequests = append(signedValRegRequests, signedRequest)
}
return 0, false, err
}
return resp.Index, true, nil
return signedValRegRequests
}
func (v *validator) aggregatedSelectionProofs(ctx context.Context, duties *ethpb.DutiesResponse) error {

View File

@@ -9,6 +9,7 @@ import (
"math"
"os"
"path/filepath"
"sort"
"strings"
"sync"
"testing"
@@ -45,8 +46,6 @@ import (
logTest "github.com/sirupsen/logrus/hooks/test"
"github.com/urfave/cli/v2"
"go.uber.org/mock/gomock"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
)
@@ -59,6 +58,8 @@ var _ iface.Validator = (*validator)(nil)
const cancelledCtx = "context has been canceled"
var unknownIndex = primitives.ValidatorIndex(^uint64(0))
func genMockKeymanager(t *testing.T, numKeys int) *mockKeymanager {
pairs := make([]keypair, numKeys)
for i := 0; i < numKeys; i++ {
@@ -354,6 +355,7 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
@@ -937,9 +939,10 @@ func TestCheckAndLogValidatorStatus_OK(t *testing.T) {
},
},
},
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
active := v.checkAndLogValidatorStatus([]*validatorStatus{test.status}, 100)
v.pubkeyToStatus[bytesutil.ToBytes48(test.status.publicKey)] = test.status
active := v.checkAndLogValidatorStatus(100)
require.Equal(t, test.active, active)
if test.log != "" {
require.LogsContain(t, hook, test.log)
@@ -1489,7 +1492,7 @@ func TestValidator_PushSettings(t *testing.T) {
validatorClient: client,
nodeClient: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
@@ -1504,14 +1507,23 @@ func TestValidator_PushSettings(t *testing.T) {
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1)
v.pubkeyToValidatorIndex[keys[1]] = primitives.ValidatorIndex(2)
v.pubkeyToStatus[keys[0]] = &validatorStatus{
publicKey: keys[0][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(1),
}
v.pubkeyToStatus[keys[1]] = &validatorStatus{
publicKey: keys[1][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(2),
}
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{keys[0][:], keys[1][:]},
Indices: []primitives.ValidatorIndex{1, 2},
}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
@@ -1571,7 +1583,7 @@ func TestValidator_PushSettings(t *testing.T) {
validatorClient: client,
nodeClient: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
@@ -1586,14 +1598,23 @@ func TestValidator_PushSettings(t *testing.T) {
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1)
v.pubkeyToValidatorIndex[keys[1]] = primitives.ValidatorIndex(2)
v.pubkeyToStatus[keys[0]] = &validatorStatus{
publicKey: keys[0][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(1),
}
v.pubkeyToStatus[keys[1]] = &validatorStatus{
publicKey: keys[1][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(2),
}
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{keys[0][:], keys[1][:]},
Indices: []primitives.ValidatorIndex{1, 2},
}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
@@ -1644,12 +1665,11 @@ func TestValidator_PushSettings(t *testing.T) {
{
name: " Happy Path default doesn't send any validator registrations",
validatorSetter: func(t *testing.T) *validator {
v := validator{
validatorClient: client,
nodeClient: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
@@ -1664,14 +1684,23 @@ func TestValidator_PushSettings(t *testing.T) {
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1)
v.pubkeyToValidatorIndex[keys[1]] = primitives.ValidatorIndex(2)
v.pubkeyToStatus[keys[0]] = &validatorStatus{
publicKey: keys[0][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(1),
}
v.pubkeyToStatus[keys[1]] = &validatorStatus{
publicKey: keys[1][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(2),
}
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{keys[0][:], keys[1][:]},
Indices: []primitives.ValidatorIndex{1, 2},
}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
@@ -1710,7 +1739,7 @@ func TestValidator_PushSettings(t *testing.T) {
validatorClient: client,
nodeClient: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
@@ -1740,13 +1769,18 @@ func TestValidator_PushSettings(t *testing.T) {
},
})
require.NoError(t, err)
v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1)
v.pubkeyToStatus[keys[0]] = &validatorStatus{
publicKey: keys[0][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(1),
}
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{keys[0][:]},
Indices: []primitives.ValidatorIndex{1},
}, nil)
client.EXPECT().SubmitValidatorRegistrations(
@@ -1778,7 +1812,7 @@ func TestValidator_PushSettings(t *testing.T) {
validatorClient: client,
nodeClient: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
@@ -1805,13 +1839,18 @@ func TestValidator_PushSettings(t *testing.T) {
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1)
v.pubkeyToStatus[keys[0]] = &validatorStatus{
publicKey: keys[0][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(1),
}
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{keys[0][:]},
Indices: []primitives.ValidatorIndex{1},
}, nil)
client.EXPECT().SubmitValidatorRegistrations(
gomock.Any(),
@@ -1842,7 +1881,7 @@ func TestValidator_PushSettings(t *testing.T) {
validatorClient: client,
nodeClient: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
@@ -1857,13 +1896,18 @@ func TestValidator_PushSettings(t *testing.T) {
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1)
v.pubkeyToStatus[keys[0]] = &validatorStatus{
publicKey: keys[0][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(1),
}
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{keys[0][:]},
Indices: []primitives.ValidatorIndex{1},
}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
@@ -1894,7 +1938,7 @@ func TestValidator_PushSettings(t *testing.T) {
v := validator{
validatorClient: client,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
@@ -1909,15 +1953,19 @@ func TestValidator_PushSettings(t *testing.T) {
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
client.EXPECT().ValidatorIndex(
gomock.Any(), // ctx
&ethpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
).Return(nil, errors.New("could not find validator index for public key"))
config[keys[0]] = &proposer.Option{
FeeRecipientConfig: &proposer.FeeRecipientConfig{
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
},
}
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}},
PublicKeys: [][]byte{keys[0][:]},
Indices: []primitives.ValidatorIndex{unknownIndex},
}, nil)
err = v.SetProposerSettings(context.Background(), &proposer.Settings{
ProposeConfig: config,
DefaultConfig: &proposer.Option{
@@ -1937,7 +1985,7 @@ func TestValidator_PushSettings(t *testing.T) {
validatorClient: client,
nodeClient: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus),
signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
@@ -1952,13 +2000,18 @@ func TestValidator_PushSettings(t *testing.T) {
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1)
v.pubkeyToStatus[keys[0]] = &validatorStatus{
publicKey: keys[0][:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: primitives.ValidatorIndex(1),
}
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{keys[0][:]},
Indices: []primitives.ValidatorIndex{1},
}, nil)
config[keys[0]] = &proposer.Option{
@@ -2009,7 +2062,7 @@ func TestValidator_PushSettings(t *testing.T) {
if tt.feeRecipientMap != nil {
feeRecipients, err := v.buildPrepProposerReqs(pubkeys)
require.NoError(t, err)
signedRegisterValidatorRequests := v.buildSignedRegReqs(ctx, pubkeys, km.Sign)
signedRegisterValidatorRequests := v.buildSignedRegReqs(ctx, pubkeys, km.Sign, 0, false)
for _, recipient := range feeRecipients {
require.Equal(t, strings.ToLower(tt.feeRecipientMap[recipient.ValidatorIndex]), strings.ToLower(hexutil.Encode(recipient.FeeRecipient)))
}
@@ -2027,7 +2080,7 @@ func TestValidator_PushSettings(t *testing.T) {
require.Equal(t, len(tt.mockExpectedRequests), len(signedRegisterValidatorRequests))
require.Equal(t, len(signedRegisterValidatorRequests), len(v.signedValidatorRegistrations))
}
if err := v.PushProposerSettings(ctx, km, 0); tt.err != "" {
if err := v.PushProposerSettings(ctx, km, 0, false); tt.err != "" {
assert.ErrorContains(t, tt.err, err)
}
if len(tt.logMessages) > 0 {
@@ -2091,28 +2144,14 @@ func TestValidator_buildPrepProposerReqs_WithoutDefaultConfig(t *testing.T) {
ctx := context.Background()
client := validatormock.NewMockValidatorClient(ctrl)
client.EXPECT().ValidatorIndex(
gomock.Any(),
&ethpb.ValidatorIndexRequest{
PublicKey: pubkey2[:],
},
).Return(&ethpb.ValidatorIndexResponse{
Index: 2,
}, nil)
client.EXPECT().ValidatorIndex(
gomock.Any(),
&ethpb.ValidatorIndexRequest{
PublicKey: pubkey3[:],
},
).Return(nil, status.Error(codes.NotFound, "NOT_FOUND"))
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{pubkey1[:], pubkey2[:], pubkey4[:]},
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}, {Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{pubkey1[:], pubkey2[:], pubkey3[:], pubkey4[:]},
Indices: []primitives.ValidatorIndex{1, 2, unknownIndex, 4},
}, nil)
v := validator{
validatorClient: client,
@@ -2141,9 +2180,17 @@ func TestValidator_buildPrepProposerReqs_WithoutDefaultConfig(t *testing.T) {
},
},
},
pubkeyToValidatorIndex: map[[48]byte]primitives.ValidatorIndex{
pubkey1: 1,
pubkey4: 4,
pubkeyToStatus: map[[48]byte]*validatorStatus{
pubkey1: {
publicKey: pubkey1[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 1,
},
pubkey4: {
publicKey: pubkey4[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 4,
},
},
}
@@ -2167,18 +2214,121 @@ func TestValidator_buildPrepProposerReqs_WithoutDefaultConfig(t *testing.T) {
require.NoError(t, err)
actual, err := v.buildPrepProposerReqs(filteredKeys)
require.NoError(t, err)
sort.Slice(actual, func(i, j int) bool {
return actual[i].ValidatorIndex < actual[j].ValidatorIndex
})
assert.DeepEqual(t, expected, actual)
}
func TestValidator_filterAndCacheActiveKeys(t *testing.T) {
// Public keys
pubkey1 := pubkeyFromString(t, "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
pubkey2 := pubkeyFromString(t, "0x222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
pubkey3 := pubkeyFromString(t, "0x333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333")
pubkey4 := pubkeyFromString(t, "0x444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444")
t.Run("refetch all keys at start of epoch", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
client := validatormock.NewMockValidatorClient(ctrl)
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}, {Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{pubkey1[:], pubkey2[:], pubkey3[:], pubkey4[:]},
Indices: []primitives.ValidatorIndex{1, 2, unknownIndex, 4},
}, nil)
v := validator{
validatorClient: client,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
keys, err := v.filterAndCacheActiveKeys(ctx, [][48]byte{pubkey1, pubkey2, pubkey3, pubkey4}, 0)
require.NoError(t, err)
// one key is unknown status
require.Equal(t, 3, len(keys))
})
t.Run("refetch all keys at start of epoch, even with cache", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
client := validatormock.NewMockValidatorClient(ctrl)
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).Return(
&ethpb.MultipleValidatorStatusResponse{
Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}, {Status: ethpb.ValidatorStatus_ACTIVE}},
PublicKeys: [][]byte{pubkey1[:], pubkey2[:], pubkey3[:], pubkey4[:]},
Indices: []primitives.ValidatorIndex{1, 2, unknownIndex, 4},
}, nil)
v := validator{
validatorClient: client,
pubkeyToStatus: map[[48]byte]*validatorStatus{
pubkey1: {
publicKey: pubkey1[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 1,
},
pubkey2: {
publicKey: pubkey2[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 2,
},
pubkey3: {
publicKey: pubkey3[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, // gets overridden
index: 3,
},
pubkey4: {
publicKey: pubkey4[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 4,
},
},
}
keys, err := v.filterAndCacheActiveKeys(ctx, [][48]byte{pubkey1, pubkey2, pubkey3, pubkey4}, 0)
require.NoError(t, err)
// one key is unknown status
require.Equal(t, 3, len(keys))
})
t.Run("cache used mid epoch, no new keys added", func(t *testing.T) {
ctx := context.Background()
v := validator{
pubkeyToStatus: map[[48]byte]*validatorStatus{
pubkey1: {
publicKey: pubkey1[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 1,
},
pubkey4: {
publicKey: pubkey4[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 4,
},
},
}
keys, err := v.filterAndCacheActiveKeys(ctx, [][48]byte{pubkey1, pubkey4}, 5)
require.NoError(t, err)
// one key is unknown status
require.Equal(t, 2, len(keys))
})
}
func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) {
// pubkey1 => feeRecipient1 - Status: active (already in `v.validatorIndex`)
// pubkey2 => feeRecipient2 - Status: active (NOT in `v.validatorIndex`, index found by beacon node)
// pubkey3 => feeRecipient3 - Status: active (NOT in `v.validatorIndex`, index NOT found by beacon node)
// pubkey4 => Nothing - Status: active (already in `v.validatorIndex`)
// pubkey5 => Nothing - Status: unknown (already in `v.validatorIndex`)
// pubkey6 => Nothing - Status: pending (already in `v.validatorIndex`) - ActivationEpoch: 35 (current slot: 641 - current epoch: 20)
// pubkey7 => Nothing - Status: pending (already in `v.validatorIndex`) - ActivationEpoch: 20 (current slot: 641 - current epoch: 20)
// pubkey8 => feeRecipient8 - Status: exiting (already in `v.validatorIndex`)
// pubkey1 => feeRecipient1 - Status: active
// pubkey2 => feeRecipient2 - Status: active
// pubkey3 => feeRecipient3 - Status: unknown
// pubkey4 => Nothing - Status: active
// pubkey5 => Nothing - Status: exited
// pubkey6 => Nothing - Status: pending - ActivationEpoch: 35 (current slot: 641 - current epoch: 20)
// pubkey7 => Nothing - Status: pending - ActivationEpoch: 20 (current slot: 641 - current epoch: 20)
// pubkey8 => feeRecipient8 - Status: exiting
// Public keys
pubkey1 := pubkeyFromString(t, "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
@@ -2201,9 +2351,9 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) {
pubkeyToStatus := map[[fieldparams.BLSPubkeyLength]byte]ethpb.ValidatorStatus{
pubkey1: ethpb.ValidatorStatus_ACTIVE,
pubkey2: ethpb.ValidatorStatus_ACTIVE,
pubkey3: ethpb.ValidatorStatus_ACTIVE,
pubkey3: ethpb.ValidatorStatus_UNKNOWN_STATUS,
pubkey4: ethpb.ValidatorStatus_ACTIVE,
pubkey5: ethpb.ValidatorStatus_UNKNOWN_STATUS,
pubkey5: ethpb.ValidatorStatus_EXITED,
pubkey6: ethpb.ValidatorStatus_PENDING,
pubkey7: ethpb.ValidatorStatus_PENDING,
pubkey8: ethpb.ValidatorStatus_EXITING,
@@ -2220,28 +2370,23 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) {
pubkey8: 0,
}
pubkeyToIndex := map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex{
pubkey1: 1,
pubkey2: 2,
pubkey3: unknownIndex,
pubkey4: 4,
pubkey5: 5,
pubkey6: 6,
pubkey7: 7,
pubkey8: 8,
}
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
client := validatormock.NewMockValidatorClient(ctrl)
client.EXPECT().ValidatorIndex(
gomock.Any(),
&ethpb.ValidatorIndexRequest{
PublicKey: pubkey2[:],
},
).Return(&ethpb.ValidatorIndexResponse{
Index: 2,
}, nil)
client.EXPECT().ValidatorIndex(
gomock.Any(),
&ethpb.ValidatorIndexRequest{
PublicKey: pubkey3[:],
},
).Return(nil, status.Error(codes.NotFound, "NOT_FOUND"))
client.EXPECT().MultipleValidatorStatus(
gomock.Any(),
gomock.Any()).DoAndReturn(func(ctx context.Context, val *ethpb.MultipleValidatorStatusRequest) (*ethpb.MultipleValidatorStatusResponse, error) {
@@ -2253,6 +2398,8 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) {
Status: pubkeyToStatus[bytesutil.ToBytes48(k)],
ActivationEpoch: pubkeyToActivationEpoch[bytesutil.ToBytes48(k)],
})
index := pubkeyToIndex[bytesutil.ToBytes48(k)]
resp.Indices = append(resp.Indices, index)
}
return resp, nil
})
@@ -2288,13 +2435,47 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) {
},
},
},
pubkeyToValidatorIndex: map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex{
pubkey1: 1,
pubkey4: 4,
pubkey5: 5,
pubkey6: 6,
pubkey7: 7,
pubkey8: 8,
pubkeyToStatus: map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus{
pubkey1: {
publicKey: pubkey1[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 1,
},
pubkey2: {
publicKey: pubkey2[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 2,
},
pubkey3: {
publicKey: pubkey3[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_UNKNOWN_STATUS},
index: unknownIndex,
},
pubkey4: {
publicKey: pubkey4[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 4,
},
pubkey5: {
publicKey: pubkey5[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 5,
},
pubkey6: {
publicKey: pubkey6[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 6,
},
pubkey7: {
publicKey: pubkey7[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 7,
},
pubkey8: {
publicKey: pubkey8[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 8,
},
},
}
@@ -2331,10 +2512,13 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) {
FeeRecipient: feeRecipient8[:],
},
}
filteredKeys, err := v.filterAndCacheActiveKeys(ctx, pubkeys, 641)
filteredKeys, err := v.filterAndCacheActiveKeys(ctx, pubkeys, 640)
require.NoError(t, err)
actual, err := v.buildPrepProposerReqs(filteredKeys)
require.NoError(t, err)
sort.Slice(actual, func(i, j int) bool {
return actual[i].ValidatorIndex < actual[j].ValidatorIndex
})
assert.DeepEqual(t, expected, actual)
}
@@ -2404,7 +2588,7 @@ func TestValidator_buildSignedRegReqs_DefaultConfigDisabled(t *testing.T) {
},
},
},
pubkeyToValidatorIndex: make(map[[48]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
pubkeys := [][fieldparams.BLSPubkeyLength]byte{pubkey1, pubkey2, pubkey3}
@@ -2412,26 +2596,41 @@ func TestValidator_buildSignedRegReqs_DefaultConfigDisabled(t *testing.T) {
var signer = func(_ context.Context, _ *validatorpb.SignRequest) (bls.Signature, error) {
return signature, nil
}
v.pubkeyToValidatorIndex[pubkey1] = primitives.ValidatorIndex(1)
v.pubkeyToValidatorIndex[pubkey2] = primitives.ValidatorIndex(2)
v.pubkeyToValidatorIndex[pubkey3] = primitives.ValidatorIndex(3)
actual := v.buildSignedRegReqs(ctx, pubkeys, signer)
v.pubkeyToStatus[pubkey1] = &validatorStatus{
publicKey: pubkey1[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 1,
}
v.pubkeyToStatus[pubkey2] = &validatorStatus{
publicKey: pubkey2[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 2,
}
v.pubkeyToStatus[pubkey3] = &validatorStatus{
publicKey: pubkey3[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 3,
}
actual := v.buildSignedRegReqs(ctx, pubkeys, signer, 0, false)
assert.Equal(t, 1, len(actual))
assert.DeepEqual(t, feeRecipient1[:], actual[0].Message.FeeRecipient)
assert.Equal(t, uint64(1111), actual[0].Message.GasLimit)
assert.DeepEqual(t, pubkey1[:], actual[0].Message.Pubkey)
}
func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) {
// pubkey1 => feeRecipient1, builder enabled
// pubkey2 => feeRecipient2, builder disabled
// pubkey3 => Nothing, builder enabled
// pubkey4 => added after builder requests built once, used in mid epoch test
// Public keys
pubkey1 := pubkeyFromString(t, "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")
pubkey2 := pubkeyFromString(t, "0x222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222")
pubkey3 := pubkeyFromString(t, "0x333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333")
pubkey4 := pubkeyFromString(t, "0x444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444")
// Fee recipients
feeRecipient1 := feeRecipientFromString(t, "0x0000000000000000000000000000000000000000")
@@ -2446,8 +2645,7 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) {
client := validatormock.NewMockValidatorClient(ctrl)
signature := blsmock.NewMockSignature(ctrl)
signature.EXPECT().Marshal().Return([]byte{}).Times(2)
signature.EXPECT().Marshal().Return([]byte{}).AnyTimes()
v := validator{
signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{},
validatorClient: client,
@@ -2489,7 +2687,7 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) {
},
},
},
pubkeyToValidatorIndex: make(map[[48]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
pubkeys := [][fieldparams.BLSPubkeyLength]byte{pubkey1, pubkey2, pubkey3}
@@ -2497,10 +2695,22 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) {
var signer = func(_ context.Context, _ *validatorpb.SignRequest) (bls.Signature, error) {
return signature, nil
}
v.pubkeyToValidatorIndex[pubkey1] = primitives.ValidatorIndex(1)
v.pubkeyToValidatorIndex[pubkey2] = primitives.ValidatorIndex(2)
v.pubkeyToValidatorIndex[pubkey3] = primitives.ValidatorIndex(3)
actual := v.buildSignedRegReqs(ctx, pubkeys, signer)
v.pubkeyToStatus[pubkey1] = &validatorStatus{
publicKey: pubkey1[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 1,
}
v.pubkeyToStatus[pubkey2] = &validatorStatus{
publicKey: pubkey2[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 2,
}
v.pubkeyToStatus[pubkey3] = &validatorStatus{
publicKey: pubkey3[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 3,
}
actual := v.buildSignedRegReqs(ctx, pubkeys, signer, 0, false)
assert.Equal(t, 2, len(actual))
@@ -2511,6 +2721,26 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) {
assert.DeepEqual(t, defaultFeeRecipient[:], actual[1].Message.FeeRecipient)
assert.Equal(t, uint64(9999), actual[1].Message.GasLimit)
assert.DeepEqual(t, pubkey3[:], actual[1].Message.Pubkey)
t.Run("mid epoch only pushes newly added key", func(t *testing.T) {
v.pubkeyToStatus[pubkey4] = &validatorStatus{
publicKey: pubkey4[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 4,
}
pubkeys = append(pubkeys, pubkey4)
actual = v.buildSignedRegReqs(ctx, pubkeys, signer, 5, false)
assert.Equal(t, 1, len(actual))
assert.DeepEqual(t, defaultFeeRecipient[:], actual[0].Message.FeeRecipient)
assert.Equal(t, uint64(9999), actual[0].Message.GasLimit)
assert.DeepEqual(t, pubkey4[:], actual[0].Message.Pubkey)
})
t.Run("force push all keys mid epoch", func(t *testing.T) {
actual = v.buildSignedRegReqs(ctx, pubkeys, signer, 5, true)
assert.Equal(t, 3, len(actual))
})
}
func TestValidator_buildSignedRegReqs_SignerOnError(t *testing.T) {
@@ -2548,7 +2778,7 @@ func TestValidator_buildSignedRegReqs_SignerOnError(t *testing.T) {
return nil, errors.New("custom error")
}
actual := v.buildSignedRegReqs(ctx, pubkeys, signer)
actual := v.buildSignedRegReqs(ctx, pubkeys, signer, 0, false)
assert.Equal(t, 0, len(actual))
}
@@ -2595,7 +2825,7 @@ func TestValidator_buildSignedRegReqs_TimestampBeforeGenesis(t *testing.T) {
},
},
},
pubkeyToValidatorIndex: make(map[[48]byte]primitives.ValidatorIndex),
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
pubkeys := [][fieldparams.BLSPubkeyLength]byte{pubkey1}
@@ -2603,8 +2833,12 @@ func TestValidator_buildSignedRegReqs_TimestampBeforeGenesis(t *testing.T) {
var signer = func(_ context.Context, _ *validatorpb.SignRequest) (bls.Signature, error) {
return signature, nil
}
v.pubkeyToValidatorIndex[pubkey1] = primitives.ValidatorIndex(1)
actual := v.buildSignedRegReqs(ctx, pubkeys, signer)
v.pubkeyToStatus[pubkey1] = &validatorStatus{
publicKey: pubkey1[:],
status: &ethpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE},
index: 1,
}
actual := v.buildSignedRegReqs(ctx, pubkeys, signer, 0, false)
assert.Equal(t, 0, len(actual))
}

View File

@@ -109,9 +109,8 @@ func (v *validator) internalWaitForActivation(ctx context.Context, accountsChang
return v.internalWaitForActivation(incrementRetries(ctx), accountsChangedChan)
}
statuses := make([]*validatorStatus, len(res.Statuses))
for i, s := range res.Statuses {
statuses[i] = &validatorStatus{
for _, s := range res.Statuses {
v.pubkeyToStatus[bytesutil.ToBytes48(s.PublicKey)] = &validatorStatus{
publicKey: s.PublicKey,
status: s.Status,
index: s.Index,
@@ -129,7 +128,7 @@ func (v *validator) internalWaitForActivation(ctx context.Context, accountsChang
valCount = int64(valCounts[0].Count)
}
someAreActive = v.checkAndLogValidatorStatus(statuses, valCount)
someAreActive = v.checkAndLogValidatorStatus(valCount)
}
}

View File

@@ -37,6 +37,7 @@ func TestWaitActivation_ContextCanceled(t *testing.T) {
validatorClient: validatorClient,
km: newMockKeymanager(t, kp),
chainClient: chainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
ctx, cancel := context.WithCancel(context.Background())
@@ -65,6 +66,7 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
@@ -96,6 +98,7 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
validatorClient.EXPECT().WaitForActivation(
@@ -133,6 +136,7 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
genesisTime: 1,
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
@@ -168,6 +172,7 @@ func TestWaitForActivation_Exiting(t *testing.T) {
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_EXITING
@@ -211,6 +216,7 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
km: km,
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
@@ -264,6 +270,7 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
km: km,
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
inactiveResp := generateMockStatusResponse([][]byte{inactive.pub[:]})
inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
@@ -355,6 +362,7 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
genesisTime: 1,
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]})
@@ -423,6 +431,7 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
km: newMockKeymanager(t, kp),
chainClient: chainClient,
prysmChainClient: prysmChainClient,
pubkeyToStatus: make(map[[48]byte]*validatorStatus),
}
resp := generateMockStatusResponse([][]byte{kp.pub[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE