2020-12-11 01:26:31 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-01-22 20:21:34 +00:00
|
|
|
"fmt"
|
2020-12-11 01:26:31 +00:00
|
|
|
"testing"
|
2020-12-11 19:55:52 +00:00
|
|
|
"time"
|
2020-12-11 01:26:31 +00:00
|
|
|
|
2022-03-21 18:48:02 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2020-12-11 01:26:31 +00:00
|
|
|
"github.com/golang/mock/gomock"
|
2022-06-06 19:32:41 +00:00
|
|
|
"github.com/golang/protobuf/ptypes/empty"
|
2020-12-11 01:26:31 +00:00
|
|
|
"github.com/pkg/errors"
|
2022-01-06 17:33:08 +00:00
|
|
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
2022-06-27 13:34:38 +00:00
|
|
|
validatorserviceconfig "github.com/prysmaticlabs/prysm/config/validator/service"
|
2022-04-29 14:32:11 +00:00
|
|
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
2021-09-15 22:55:11 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/crypto/bls"
|
2021-09-23 15:23:37 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
2021-07-21 21:34:07 +00:00
|
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
2021-09-23 18:53:46 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
2021-09-17 19:20:50 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/testing/mock"
|
2021-09-23 18:53:46 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/testing/require"
|
2021-09-15 00:09:04 +00:00
|
|
|
slotutilmock "github.com/prysmaticlabs/prysm/time/slots/testing"
|
2021-01-22 20:21:34 +00:00
|
|
|
walletMock "github.com/prysmaticlabs/prysm/validator/accounts/testing"
|
2021-03-16 15:00:05 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/validator/client/testutil"
|
2021-01-22 20:21:34 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/validator/keymanager/derived"
|
2022-01-26 14:48:20 +00:00
|
|
|
remotekeymanagermock "github.com/prysmaticlabs/prysm/validator/keymanager/remote/mock"
|
2021-03-05 18:33:39 +00:00
|
|
|
constant "github.com/prysmaticlabs/prysm/validator/testing"
|
2020-12-11 01:26:31 +00:00
|
|
|
logTest "github.com/sirupsen/logrus/hooks/test"
|
2021-01-22 20:21:34 +00:00
|
|
|
"github.com/tyler-smith/go-bip39"
|
|
|
|
util "github.com/wealdtech/go-eth2-util"
|
2020-12-11 01:26:31 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestWaitActivation_ContextCanceled(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
|
|
|
privKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2020-12-11 01:26:31 +00:00
|
|
|
copy(pubKey[:], privKey.PublicKey().Marshal())
|
|
|
|
km := &mockKeymanager{
|
2022-01-06 17:33:08 +00:00
|
|
|
keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{
|
2020-12-11 01:26:31 +00:00
|
|
|
pubKey: privKey,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
v := validator{
|
|
|
|
validatorClient: client,
|
|
|
|
keyManager: km,
|
|
|
|
}
|
|
|
|
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{pubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(clientStream, nil)
|
|
|
|
clientStream.EXPECT().Recv().Return(
|
|
|
|
ðpb.ValidatorActivationResponse{},
|
|
|
|
nil,
|
|
|
|
)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
cancel()
|
2021-03-12 17:23:56 +00:00
|
|
|
assert.ErrorContains(t, cancelledCtx, v.WaitForActivation(ctx, nil))
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2020-12-11 01:26:31 +00:00
|
|
|
privKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2020-12-11 01:26:31 +00:00
|
|
|
copy(pubKey[:], privKey.PublicKey().Marshal())
|
|
|
|
km := &mockKeymanager{
|
2022-01-06 17:33:08 +00:00
|
|
|
keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{
|
2020-12-11 01:26:31 +00:00
|
|
|
pubKey: privKey,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: km,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[pubKey] = 1
|
2020-12-11 01:26:31 +00:00
|
|
|
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{pubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(clientStream, errors.New("failed stream")).Return(clientStream, nil)
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2020-12-11 01:26:31 +00:00
|
|
|
resp := generateMockStatusResponse([][]byte{pubKey[:]})
|
|
|
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
|
|
|
clientStream.EXPECT().Recv().Return(resp, nil)
|
2022-06-06 19:32:41 +00:00
|
|
|
|
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
|
|
|
).Return(&empty.Empty{}, nil)
|
2021-03-12 17:23:56 +00:00
|
|
|
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2020-12-11 01:26:31 +00:00
|
|
|
privKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2020-12-11 01:26:31 +00:00
|
|
|
copy(pubKey[:], privKey.PublicKey().Marshal())
|
|
|
|
km := &mockKeymanager{
|
2022-01-06 17:33:08 +00:00
|
|
|
keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{
|
2020-12-11 01:26:31 +00:00
|
|
|
pubKey: privKey,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: km,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[pubKey] = 1
|
2020-12-11 01:26:31 +00:00
|
|
|
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{pubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(clientStream, nil)
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2020-12-11 01:26:31 +00:00
|
|
|
// A stream fails the first time, but succeeds the second time.
|
|
|
|
resp := generateMockStatusResponse([][]byte{pubKey[:]})
|
|
|
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
|
|
|
clientStream.EXPECT().Recv().Return(
|
|
|
|
nil,
|
|
|
|
errors.New("fails"),
|
|
|
|
).Return(resp, nil)
|
2022-06-06 19:32:41 +00:00
|
|
|
|
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
|
|
|
).Return(&empty.Empty{}, nil)
|
2021-03-12 17:23:56 +00:00
|
|
|
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
|
|
|
|
hook := logTest.NewGlobal()
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2020-12-11 01:26:31 +00:00
|
|
|
privKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2020-12-11 01:26:31 +00:00
|
|
|
copy(pubKey[:], privKey.PublicKey().Marshal())
|
|
|
|
km := &mockKeymanager{
|
2022-01-06 17:33:08 +00:00
|
|
|
keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{
|
2020-12-11 01:26:31 +00:00
|
|
|
pubKey: privKey,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: km,
|
|
|
|
genesisTime: 1,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[pubKey] = 1
|
2020-12-11 01:26:31 +00:00
|
|
|
resp := generateMockStatusResponse([][]byte{pubKey[:]})
|
|
|
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
|
|
|
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{pubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(clientStream, nil)
|
|
|
|
clientStream.EXPECT().Recv().Return(
|
|
|
|
resp,
|
|
|
|
nil,
|
|
|
|
)
|
2022-06-06 19:32:41 +00:00
|
|
|
|
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
|
|
|
).Return(&empty.Empty{}, nil)
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2021-03-12 17:23:56 +00:00
|
|
|
assert.NoError(t, v.WaitForActivation(context.Background(), nil), "Could not wait for activation")
|
2021-01-22 20:21:34 +00:00
|
|
|
assert.LogsContain(t, hook, "Validator activated")
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestWaitForActivation_Exiting(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2020-12-11 01:26:31 +00:00
|
|
|
privKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2020-12-11 01:26:31 +00:00
|
|
|
copy(pubKey[:], privKey.PublicKey().Marshal())
|
|
|
|
km := &mockKeymanager{
|
2022-01-06 17:33:08 +00:00
|
|
|
keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{
|
2020-12-11 01:26:31 +00:00
|
|
|
pubKey: privKey,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: km,
|
|
|
|
genesisTime: 1,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[pubKey] = 1
|
2020-12-11 01:26:31 +00:00
|
|
|
resp := generateMockStatusResponse([][]byte{pubKey[:]})
|
|
|
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_EXITING
|
|
|
|
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{pubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(clientStream, nil)
|
|
|
|
clientStream.EXPECT().Recv().Return(
|
|
|
|
resp,
|
|
|
|
nil,
|
|
|
|
)
|
2022-06-06 19:32:41 +00:00
|
|
|
|
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
|
|
|
).Return(&empty.Empty{}, nil)
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2021-03-12 17:23:56 +00:00
|
|
|
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
|
2020-12-11 01:26:31 +00:00
|
|
|
}
|
2020-12-11 19:55:52 +00:00
|
|
|
|
|
|
|
func TestWaitForActivation_RefetchKeys(t *testing.T) {
|
|
|
|
originalPeriod := keyRefetchPeriod
|
|
|
|
defer func() {
|
|
|
|
keyRefetchPeriod = originalPeriod
|
|
|
|
}()
|
2021-01-22 20:21:34 +00:00
|
|
|
keyRefetchPeriod = 1 * time.Second
|
2020-12-11 19:55:52 +00:00
|
|
|
|
|
|
|
hook := logTest.NewGlobal()
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2020-12-11 19:55:52 +00:00
|
|
|
privKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
pubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2020-12-11 19:55:52 +00:00
|
|
|
copy(pubKey[:], privKey.PublicKey().Marshal())
|
|
|
|
km := &mockKeymanager{
|
2022-01-06 17:33:08 +00:00
|
|
|
keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{
|
2020-12-11 19:55:52 +00:00
|
|
|
pubKey: privKey,
|
|
|
|
},
|
|
|
|
fetchNoKeys: true,
|
|
|
|
}
|
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: km,
|
|
|
|
genesisTime: 1,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2020-12-11 19:55:52 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[pubKey] = 1
|
2020-12-11 19:55:52 +00:00
|
|
|
resp := generateMockStatusResponse([][]byte{pubKey[:]})
|
|
|
|
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
|
|
|
clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{pubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(clientStream, nil)
|
|
|
|
clientStream.EXPECT().Recv().Return(
|
|
|
|
resp,
|
2022-06-06 19:32:41 +00:00
|
|
|
nil)
|
|
|
|
|
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
|
|
|
).Return(&empty.Empty{}, nil)
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2022-01-06 17:33:08 +00:00
|
|
|
assert.NoError(t, v.waitForActivation(context.Background(), make(chan [][fieldparams.BLSPubkeyLength]byte)), "Could not wait for activation")
|
2020-12-11 19:55:52 +00:00
|
|
|
assert.LogsContain(t, hook, msgNoKeysFetched)
|
|
|
|
assert.LogsContain(t, hook, "Validator activated")
|
|
|
|
}
|
2021-01-22 20:21:34 +00:00
|
|
|
|
|
|
|
// Regression test for a scenario where you start with an inactive key and then import an active key.
|
|
|
|
func TestWaitForActivation_AccountsChanged(t *testing.T) {
|
|
|
|
hook := logTest.NewGlobal()
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
t.Run("Imported keymanager", func(t *testing.T) {
|
|
|
|
inactivePrivKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
inactivePubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2021-01-22 20:21:34 +00:00
|
|
|
copy(inactivePubKey[:], inactivePrivKey.PublicKey().Marshal())
|
|
|
|
activePrivKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
activePubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2021-01-22 20:21:34 +00:00
|
|
|
copy(activePubKey[:], activePrivKey.PublicKey().Marshal())
|
|
|
|
km := &mockKeymanager{
|
2022-01-06 17:33:08 +00:00
|
|
|
keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{
|
2021-01-22 20:21:34 +00:00
|
|
|
inactivePubKey: inactivePrivKey,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2021-01-22 20:21:34 +00:00
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: km,
|
|
|
|
genesisTime: 1,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2021-01-22 20:21:34 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[inactivePubKey] = 1
|
2021-01-22 20:21:34 +00:00
|
|
|
inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]})
|
|
|
|
inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
|
|
|
inactiveClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{inactivePubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(inactiveClientStream, nil)
|
|
|
|
inactiveClientStream.EXPECT().Recv().Return(
|
|
|
|
inactiveResp,
|
|
|
|
nil,
|
|
|
|
).AnyTimes()
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2021-01-22 20:21:34 +00:00
|
|
|
|
|
|
|
activeResp := generateMockStatusResponse([][]byte{inactivePubKey[:], activePubKey[:]})
|
|
|
|
activeResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
|
|
|
activeResp.Statuses[1].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
|
|
|
activeClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{inactivePubKey[:], activePubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(activeClientStream, nil)
|
|
|
|
activeClientStream.EXPECT().Recv().Return(
|
|
|
|
activeResp,
|
|
|
|
nil,
|
|
|
|
)
|
2022-06-06 19:32:41 +00:00
|
|
|
|
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
2022-06-21 18:46:28 +00:00
|
|
|
).Times(1).Return(&empty.Empty{}, nil)
|
2021-01-22 20:21:34 +00:00
|
|
|
|
|
|
|
go func() {
|
|
|
|
// We add the active key into the keymanager and simulate a key refresh.
|
|
|
|
time.Sleep(time.Second * 1)
|
|
|
|
km.keysMap[activePubKey] = activePrivKey
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[activePubKey] = 1
|
2022-01-06 17:33:08 +00:00
|
|
|
km.SimulateAccountChanges(make([][fieldparams.BLSPubkeyLength]byte, 0))
|
2021-01-22 20:21:34 +00:00
|
|
|
}()
|
|
|
|
|
2021-03-12 17:23:56 +00:00
|
|
|
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
|
2021-01-22 20:21:34 +00:00
|
|
|
assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node")
|
|
|
|
assert.LogsContain(t, hook, "Validator activated")
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Derived keymanager", func(t *testing.T) {
|
2021-03-02 11:39:54 +00:00
|
|
|
seed := bip39.NewSeed(constant.TestMnemonic, "")
|
2021-01-22 20:21:34 +00:00
|
|
|
inactivePrivKey, err :=
|
|
|
|
util.PrivateKeyFromSeedAndPath(seed, fmt.Sprintf(derived.ValidatingKeyDerivationPathTemplate, 0))
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
inactivePubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2021-01-22 20:21:34 +00:00
|
|
|
copy(inactivePubKey[:], inactivePrivKey.PublicKey().Marshal())
|
|
|
|
activePrivKey, err :=
|
|
|
|
util.PrivateKeyFromSeedAndPath(seed, fmt.Sprintf(derived.ValidatingKeyDerivationPathTemplate, 1))
|
|
|
|
require.NoError(t, err)
|
2022-01-06 17:33:08 +00:00
|
|
|
activePubKey := [fieldparams.BLSPubkeyLength]byte{}
|
2021-01-22 20:21:34 +00:00
|
|
|
copy(activePubKey[:], activePrivKey.PublicKey().Marshal())
|
|
|
|
wallet := &walletMock.Wallet{
|
|
|
|
Files: make(map[string]map[string][]byte),
|
|
|
|
AccountPasswords: make(map[string]string),
|
|
|
|
WalletPassword: "secretPassw0rd$1999",
|
|
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
km, err := derived.NewKeymanager(ctx, &derived.SetupConfig{
|
2021-02-24 18:05:46 +00:00
|
|
|
Wallet: wallet,
|
|
|
|
ListenForChanges: true,
|
2021-01-22 20:21:34 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
2021-03-02 11:39:54 +00:00
|
|
|
err = km.RecoverAccountsFromMnemonic(ctx, constant.TestMnemonic, "", 1)
|
2021-01-22 20:21:34 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2021-01-22 20:21:34 +00:00
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: km,
|
|
|
|
genesisTime: 1,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2021-01-22 20:21:34 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[inactivePubKey] = 1
|
2021-01-22 20:21:34 +00:00
|
|
|
|
|
|
|
inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]})
|
|
|
|
inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
|
|
|
inactiveClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{inactivePubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(inactiveClientStream, nil)
|
|
|
|
inactiveClientStream.EXPECT().Recv().Return(
|
|
|
|
inactiveResp,
|
|
|
|
nil,
|
|
|
|
).AnyTimes()
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2021-01-22 20:21:34 +00:00
|
|
|
|
|
|
|
activeResp := generateMockStatusResponse([][]byte{inactivePubKey[:], activePubKey[:]})
|
|
|
|
activeResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
|
|
|
activeResp.Statuses[1].Status.Status = ethpb.ValidatorStatus_ACTIVE
|
|
|
|
activeClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.ValidatorActivationRequest{
|
|
|
|
PublicKeys: [][]byte{inactivePubKey[:], activePubKey[:]},
|
|
|
|
},
|
|
|
|
).Return(activeClientStream, nil)
|
|
|
|
activeClientStream.EXPECT().Recv().Return(
|
|
|
|
activeResp,
|
|
|
|
nil,
|
|
|
|
)
|
2022-06-06 19:32:41 +00:00
|
|
|
|
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
2022-06-21 18:46:28 +00:00
|
|
|
).Times(1).Return(&empty.Empty{}, nil)
|
2021-01-22 20:21:34 +00:00
|
|
|
|
2022-01-06 17:33:08 +00:00
|
|
|
channel := make(chan [][fieldparams.BLSPubkeyLength]byte)
|
2021-01-22 20:21:34 +00:00
|
|
|
go func() {
|
|
|
|
// We add the active key into the keymanager and simulate a key refresh.
|
|
|
|
time.Sleep(time.Second * 1)
|
2021-03-02 11:39:54 +00:00
|
|
|
err = km.RecoverAccountsFromMnemonic(ctx, constant.TestMnemonic, "", 2)
|
2021-01-22 20:21:34 +00:00
|
|
|
require.NoError(t, err)
|
2022-03-21 18:48:02 +00:00
|
|
|
keys, err := km.FetchValidatingPublicKeys(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
for _, key := range keys {
|
|
|
|
v.pubkeyToValidatorIndex[key] = 1
|
|
|
|
}
|
2022-01-06 17:33:08 +00:00
|
|
|
channel <- [][fieldparams.BLSPubkeyLength]byte{}
|
2021-01-22 20:21:34 +00:00
|
|
|
}()
|
|
|
|
|
2021-03-05 18:33:39 +00:00
|
|
|
assert.NoError(t, v.waitForActivation(context.Background(), channel))
|
2021-01-22 20:21:34 +00:00
|
|
|
assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node")
|
|
|
|
assert.LogsContain(t, hook, "Validator activated")
|
|
|
|
})
|
|
|
|
}
|
2021-03-16 15:00:05 +00:00
|
|
|
|
|
|
|
func TestWaitForActivation_RemoteKeymanager(t *testing.T) {
|
|
|
|
ctrl := gomock.NewController(t)
|
|
|
|
defer ctrl.Finish()
|
|
|
|
|
|
|
|
client := mock.NewMockBeaconNodeValidatorClient(ctrl)
|
|
|
|
stream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl)
|
|
|
|
client.EXPECT().WaitForActivation(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
|
|
|
).Return(stream, nil /* err */).AnyTimes()
|
|
|
|
|
|
|
|
inactiveKey := bytesutil.ToBytes48([]byte("inactive"))
|
|
|
|
activeKey := bytesutil.ToBytes48([]byte("active"))
|
2022-01-26 14:48:20 +00:00
|
|
|
km := remotekeymanagermock.NewMock()
|
2022-01-06 17:33:08 +00:00
|
|
|
km.PublicKeys = [][fieldparams.BLSPubkeyLength]byte{inactiveKey, activeKey}
|
2021-03-16 15:00:05 +00:00
|
|
|
slot := types.Slot(0)
|
|
|
|
|
|
|
|
t.Run("activated", func(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
hook := logTest.NewGlobal()
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2021-03-16 15:00:05 +00:00
|
|
|
tickerChan := make(chan types.Slot)
|
|
|
|
ticker := &slotutilmock.MockTicker{
|
|
|
|
Channel: tickerChan,
|
|
|
|
}
|
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: &km,
|
|
|
|
ticker: ticker,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2021-03-16 15:00:05 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[activeKey] = 1
|
|
|
|
v.pubkeyToValidatorIndex[inactiveKey] = 2
|
2021-03-16 15:00:05 +00:00
|
|
|
go func() {
|
|
|
|
tickerChan <- slot
|
|
|
|
// Cancel after timeout to avoid waiting on channel forever in case test goes wrong.
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
cancel()
|
|
|
|
}()
|
|
|
|
|
|
|
|
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactiveKey[:], activeKey[:]})
|
|
|
|
resp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
|
|
|
resp.Statuses[1].Status = ethpb.ValidatorStatus_ACTIVE
|
|
|
|
client.EXPECT().MultipleValidatorStatus(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.MultipleValidatorStatusRequest{
|
|
|
|
PublicKeys: [][]byte{inactiveKey[:], activeKey[:]},
|
|
|
|
},
|
|
|
|
).Return(resp, nil /* err */)
|
2022-06-06 19:32:41 +00:00
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
2022-06-27 13:34:38 +00:00
|
|
|
).Times(1).Return(&empty.Empty{}, nil)
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 2},
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2021-03-16 15:00:05 +00:00
|
|
|
|
|
|
|
err := v.waitForActivation(ctx, nil /* accountsChangedChan */)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node")
|
|
|
|
assert.LogsContain(t, hook, "Validator activated")
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("cancelled", func(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
|
|
|
tickerChan := make(chan types.Slot)
|
|
|
|
ticker := &slotutilmock.MockTicker{
|
|
|
|
Channel: tickerChan,
|
|
|
|
}
|
|
|
|
v := validator{
|
|
|
|
validatorClient: client,
|
2021-04-30 15:15:22 +00:00
|
|
|
keyManager: &km,
|
2021-03-16 15:00:05 +00:00
|
|
|
ticker: ticker,
|
|
|
|
}
|
|
|
|
go func() {
|
|
|
|
cancel()
|
|
|
|
tickerChan <- slot
|
|
|
|
}()
|
|
|
|
|
|
|
|
err := v.waitForActivation(ctx, nil /* accountsChangedChan */)
|
|
|
|
assert.ErrorContains(t, "context canceled, not waiting for activation anymore", err)
|
|
|
|
})
|
2021-04-30 15:15:22 +00:00
|
|
|
t.Run("reloaded", func(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
hook := logTest.NewGlobal()
|
2022-01-26 14:48:20 +00:00
|
|
|
remoteKm := remotekeymanagermock.NewMock()
|
2022-01-06 17:33:08 +00:00
|
|
|
remoteKm.PublicKeys = [][fieldparams.BLSPubkeyLength]byte{inactiveKey}
|
2022-06-06 19:32:41 +00:00
|
|
|
nodeClient := mock.NewMockNodeClient(ctrl)
|
2021-04-30 15:15:22 +00:00
|
|
|
tickerChan := make(chan types.Slot)
|
|
|
|
ticker := &slotutilmock.MockTicker{
|
|
|
|
Channel: tickerChan,
|
|
|
|
}
|
|
|
|
v := validator{
|
2022-03-21 18:48:02 +00:00
|
|
|
validatorClient: client,
|
2022-06-06 19:32:41 +00:00
|
|
|
node: nodeClient,
|
2022-03-21 18:48:02 +00:00
|
|
|
keyManager: &remoteKm,
|
|
|
|
ticker: ticker,
|
|
|
|
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
|
2022-06-27 13:34:38 +00:00
|
|
|
ProposerSettings: &validatorserviceconfig.ProposerSettings{
|
2022-03-21 18:48:02 +00:00
|
|
|
ProposeConfig: nil,
|
2022-06-27 13:34:38 +00:00
|
|
|
DefaultConfig: &validatorserviceconfig.ProposerOption{
|
2022-03-21 18:48:02 +00:00
|
|
|
FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
|
|
|
|
},
|
|
|
|
},
|
2021-04-30 15:15:22 +00:00
|
|
|
}
|
2022-03-21 18:48:02 +00:00
|
|
|
v.pubkeyToValidatorIndex[activeKey] = 1
|
|
|
|
v.pubkeyToValidatorIndex[inactiveKey] = 2
|
2021-04-30 15:15:22 +00:00
|
|
|
go func() {
|
|
|
|
tickerChan <- slot
|
|
|
|
time.Sleep(time.Second)
|
2022-01-06 17:33:08 +00:00
|
|
|
remoteKm.PublicKeys = [][fieldparams.BLSPubkeyLength]byte{inactiveKey, activeKey}
|
2021-04-30 15:15:22 +00:00
|
|
|
tickerChan <- slot
|
|
|
|
// Cancel after timeout to avoid waiting on channel forever in case test goes wrong.
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
cancel()
|
|
|
|
}()
|
|
|
|
|
|
|
|
resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactiveKey[:]})
|
|
|
|
resp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
|
|
|
client.EXPECT().MultipleValidatorStatus(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.MultipleValidatorStatusRequest{
|
|
|
|
PublicKeys: [][]byte{inactiveKey[:]},
|
|
|
|
},
|
|
|
|
).Return(resp, nil /* err */)
|
|
|
|
resp2 := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactiveKey[:], activeKey[:]})
|
|
|
|
resp2.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS
|
|
|
|
resp2.Statuses[1].Status = ethpb.ValidatorStatus_ACTIVE
|
|
|
|
client.EXPECT().MultipleValidatorStatus(
|
|
|
|
gomock.Any(),
|
|
|
|
ðpb.MultipleValidatorStatusRequest{
|
|
|
|
PublicKeys: [][]byte{inactiveKey[:], activeKey[:]},
|
|
|
|
},
|
|
|
|
).Return(resp2, nil /* err */)
|
2022-06-06 19:32:41 +00:00
|
|
|
|
2022-06-27 13:34:38 +00:00
|
|
|
client.EXPECT().SubmitValidatorRegistration(
|
|
|
|
gomock.Any(),
|
|
|
|
gomock.Any(),
|
|
|
|
).Times(1).Return(&empty.Empty{}, nil)
|
2022-05-31 16:43:01 +00:00
|
|
|
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{
|
|
|
|
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 2},
|
|
|
|
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
|
|
|
|
},
|
|
|
|
}).Return(nil, nil)
|
2021-04-30 15:15:22 +00:00
|
|
|
|
|
|
|
err := v.waitForActivation(ctx, remoteKm.ReloadPublicKeysChan /* accountsChangedChan */)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node")
|
|
|
|
assert.LogsContain(t, hook, "Validator activated")
|
|
|
|
})
|
2021-03-16 15:00:05 +00:00
|
|
|
}
|