diff --git a/validator/client/attest_test.go b/validator/client/attest_test.go index aa53090333..9e536c593b 100644 --- a/validator/client/attest_test.go +++ b/validator/client/attest_test.go @@ -18,7 +18,6 @@ import ( "github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v4/crypto/bls" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/validator-client" @@ -444,9 +443,6 @@ func TestSignAttestation(t *testing.T) { validator, m, _, finish := setup(t) defer finish() - secretKey, err := bls.SecretKeyFromBytes(bytesutil.PadTo([]byte{1}, 32)) - require.NoError(t, err, "Failed to generate key from bytes") - publicKey := secretKey.PublicKey() wantedFork := ðpb.Fork{ PreviousVersion: []byte{'a', 'b', 'c', 'd'}, CurrentVersion: []byte{'d', 'e', 'f', 'f'}, @@ -464,15 +460,10 @@ func TestSignAttestation(t *testing.T) { att.Data.Target.Epoch = 200 att.Data.Slot = 999 att.Data.BeaconBlockRoot = bytesutil.PadTo([]byte("blockRoot"), 32) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], publicKey.Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: secretKey, - }, - } - validator.keyManager = km - sig, sr, err := validator.signAtt(ctx, pubKey, att.Data, att.Data.Slot) + + pk := testKeyFromBytes(t, []byte{1}) + validator.keyManager = newMockKeymanager(t, pk) + sig, sr, err := validator.signAtt(ctx, pk.pub, att.Data, att.Data.Slot) require.NoError(t, err, "%x,%x,%v", sig, sr, err) require.Equal(t, "b6a60f8497bd328908be83634d045"+ "dd7a32f5e246b2c4031fc2f316983f362e36fc27fd3d6d5a2b15"+ diff --git a/validator/client/key_reload_test.go b/validator/client/key_reload_test.go index be5f934aaf..0aba32ab48 100644 --- a/validator/client/key_reload_test.go +++ b/validator/client/key_reload_test.go @@ -7,7 +7,6 @@ import ( "github.com/golang/mock/gomock" "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" - "github.com/prysmaticlabs/prysm/v4/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v4/testing/assert" "github.com/prysmaticlabs/prysm/v4/testing/require" @@ -23,40 +22,30 @@ func TestValidator_HandleKeyReload(t *testing.T) { t.Run("active", func(t *testing.T) { hook := logTest.NewGlobal() - inactivePrivKey, err := bls.RandKey() - require.NoError(t, err) - var inactivePubKey [fieldparams.BLSPubkeyLength]byte - copy(inactivePubKey[:], inactivePrivKey.PublicKey().Marshal()) - activePrivKey, err := bls.RandKey() - require.NoError(t, err) - var activePubKey [fieldparams.BLSPubkeyLength]byte - copy(activePubKey[:], activePrivKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - inactivePubKey: inactivePrivKey, - }, - } + inactive := randKeypair(t) + active := randKeypair(t) + client := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) v := validator{ validatorClient: client, - keyManager: km, + keyManager: newMockKeymanager(t, inactive), genesisTime: 1, beaconClient: beaconClient, } - resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactivePubKey[:], activePubKey[:]}) + resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:], active.pub[:]}) resp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS resp.Statuses[1].Status = ethpb.ValidatorStatus_ACTIVE client.EXPECT().MultipleValidatorStatus( gomock.Any(), ðpb.MultipleValidatorStatusRequest{ - PublicKeys: [][]byte{inactivePubKey[:], activePubKey[:]}, + PublicKeys: [][]byte{inactive.pub[:], active.pub[:]}, }, ).Return(resp, nil) beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil) - anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{inactivePubKey, activePubKey}) + anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{inactive.pub, active.pub}) require.NoError(t, err) assert.Equal(t, true, anyActive) assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node") @@ -66,35 +55,27 @@ func TestValidator_HandleKeyReload(t *testing.T) { t.Run("no active", func(t *testing.T) { hook := logTest.NewGlobal() - inactivePrivKey, err := bls.RandKey() - require.NoError(t, err) - var inactivePubKey [fieldparams.BLSPubkeyLength]byte - copy(inactivePubKey[:], inactivePrivKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - inactivePubKey: inactivePrivKey, - }, - } client := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) + kp := randKeypair(t) v := validator{ validatorClient: client, - keyManager: km, + keyManager: newMockKeymanager(t, kp), genesisTime: 1, beaconClient: beaconClient, } - resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactivePubKey[:]}) + resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]}) resp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS client.EXPECT().MultipleValidatorStatus( gomock.Any(), ðpb.MultipleValidatorStatusRequest{ - PublicKeys: [][]byte{inactivePubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(resp, nil) beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil) - anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{inactivePubKey}) + anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{kp.pub}) require.NoError(t, err) assert.Equal(t, false, anyActive) assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node") @@ -102,30 +83,22 @@ func TestValidator_HandleKeyReload(t *testing.T) { }) t.Run("error when getting status", func(t *testing.T) { - inactivePrivKey, err := bls.RandKey() - require.NoError(t, err) - var inactivePubKey [fieldparams.BLSPubkeyLength]byte - copy(inactivePubKey[:], inactivePrivKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - inactivePubKey: inactivePrivKey, - }, - } + kp := randKeypair(t) client := validatormock.NewMockValidatorClient(ctrl) v := validator{ validatorClient: client, - keyManager: km, + keyManager: newMockKeymanager(t, kp), genesisTime: 1, } client.EXPECT().MultipleValidatorStatus( gomock.Any(), ðpb.MultipleValidatorStatusRequest{ - PublicKeys: [][]byte{inactivePubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(nil, errors.New("error")) - _, err = v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{inactivePubKey}) + _, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{kp.pub}) assert.ErrorContains(t, "error", err) }) } diff --git a/validator/client/propose_test.go b/validator/client/propose_test.go index 183c7d4ae6..59acb9b014 100644 --- a/validator/client/propose_test.go +++ b/validator/client/propose_test.go @@ -59,6 +59,12 @@ func (m mockSignature) Copy() bls.Signature { return m } +func testKeyFromBytes(t *testing.T, b []byte) keypair { + pri, err := bls.SecretKeyFromBytes(bytesutil.PadTo(b, 32)) + require.NoError(t, err, "Failed to generate key from bytes") + return keypair{pub: bytesutil.ToBytes48(pri.PublicKey().Marshal()), pri: pri} +} + func setup(t *testing.T) (*validator, *mocks, bls.SecretKey, func()) { validatorKey, err := bls.RandKey() require.NoError(t, err) @@ -78,17 +84,11 @@ func setupWithKey(t *testing.T, validatorKey bls.SecretKey) (*validator, *mocks, return mockSignature{}, nil }, } - aggregatedSlotCommitteeIDCache := lruwrpr.New(int(params.BeaconConfig().MaxCommitteesPerSlot)) - copy(pubKey[:], validatorKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: validatorKey, - }, - } + validator := &validator{ db: valDB, - keyManager: km, + keyManager: newMockKeymanager(t, keypair{pub: pubKey, pri: validatorKey}), validatorClient: m.validatorClient, slashingProtectionClient: m.slasherClient, graffiti: []byte{}, @@ -823,9 +823,6 @@ func TestSignBlock(t *testing.T) { validator, m, _, finish := setup(t) defer finish() - secretKey, err := bls.SecretKeyFromBytes(bytesutil.PadTo([]byte{1}, 32)) - require.NoError(t, err, "Failed to generate key from bytes") - publicKey := secretKey.PublicKey() proposerDomain := make([]byte, 32) m.validatorClient.EXPECT(). DomainData(gomock.Any(), gomock.Any()). @@ -834,17 +831,13 @@ func TestSignBlock(t *testing.T) { blk := util.NewBeaconBlock() blk.Block.Slot = 1 blk.Block.ProposerIndex = 100 - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], publicKey.Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: secretKey, - }, - } - validator.keyManager = km + + kp := testKeyFromBytes(t, []byte{1}) + + validator.keyManager = newMockKeymanager(t, kp) b, err := blocks.NewBeaconBlock(blk.Block) require.NoError(t, err) - sig, blockRoot, err := validator.signBlock(ctx, pubKey, 0, 0, b) + sig, blockRoot, err := validator.signBlock(ctx, kp.pub, 0, 0, b) require.NoError(t, err, "%x,%v", sig, err) require.Equal(t, "a049e1dc723e5a8b5bd14f292973572dffd53785ddb337"+ "82f20bf762cbe10ee7b9b4f5ae1ad6ff2089d352403750bed402b94b58469c072536"+ @@ -864,9 +857,7 @@ func TestSignAltairBlock(t *testing.T) { validator, m, _, finish := setup(t) defer finish() - secretKey, err := bls.SecretKeyFromBytes(bytesutil.PadTo([]byte{1}, 32)) - require.NoError(t, err, "Failed to generate key from bytes") - publicKey := secretKey.PublicKey() + kp := testKeyFromBytes(t, []byte{1}) proposerDomain := make([]byte, 32) m.validatorClient.EXPECT(). DomainData(gomock.Any(), gomock.Any()). @@ -875,17 +866,10 @@ func TestSignAltairBlock(t *testing.T) { blk := util.NewBeaconBlockAltair() blk.Block.Slot = 1 blk.Block.ProposerIndex = 100 - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], publicKey.Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: secretKey, - }, - } - validator.keyManager = km + validator.keyManager = newMockKeymanager(t, kp) wb, err := blocks.NewBeaconBlock(blk.Block) require.NoError(t, err) - sig, blockRoot, err := validator.signBlock(ctx, pubKey, 0, 0, wb) + sig, blockRoot, err := validator.signBlock(ctx, kp.pub, 0, 0, wb) require.NoError(t, err, "%x,%v", sig, err) // Verify the returned block root matches the expected root using the proposer signature // domain. @@ -900,28 +884,21 @@ func TestSignBellatrixBlock(t *testing.T) { validator, m, _, finish := setup(t) defer finish() - secretKey, err := bls.SecretKeyFromBytes(bytesutil.PadTo([]byte{1}, 32)) - require.NoError(t, err, "Failed to generate key from bytes") - publicKey := secretKey.PublicKey() proposerDomain := make([]byte, 32) m.validatorClient.EXPECT(). DomainData(gomock.Any(), gomock.Any()). Return(ðpb.DomainResponse{SignatureDomain: proposerDomain}, nil) + ctx := context.Background() blk := util.NewBeaconBlockBellatrix() blk.Block.Slot = 1 blk.Block.ProposerIndex = 100 - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], publicKey.Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: secretKey, - }, - } - validator.keyManager = km + + kp := randKeypair(t) + validator.keyManager = newMockKeymanager(t, kp) wb, err := blocks.NewBeaconBlock(blk.Block) require.NoError(t, err) - sig, blockRoot, err := validator.signBlock(ctx, pubKey, 0, 0, wb) + sig, blockRoot, err := validator.signBlock(ctx, kp.pub, 0, 0, wb) require.NoError(t, err, "%x,%v", sig, err) // Verify the returned block root matches the expected root using the proposer signature // domain. diff --git a/validator/client/validator_test.go b/validator/client/validator_test.go index 5c2f811cff..b35b9c81bd 100644 --- a/validator/client/validator_test.go +++ b/validator/client/validator_test.go @@ -54,38 +54,86 @@ var _ iface.Validator = (*validator)(nil) const cancelledCtx = "context has been canceled" -func genMockKeymanager(numKeys int) *mockKeymanager { - km := make(map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey, numKeys) +func genMockKeymanager(t *testing.T, numKeys int) *mockKeymanager { + pairs := make([]keypair, numKeys) for i := 0; i < numKeys; i++ { - k, err := bls.RandKey() - if err != nil { - panic(err) - } - km[bytesutil.ToBytes48(k.PublicKey().Marshal())] = k + pairs[i] = randKeypair(t) } - return &mockKeymanager{keysMap: km} + return newMockKeymanager(t, pairs...) +} + +type keypair struct { + pub [fieldparams.BLSPubkeyLength]byte + pri bls.SecretKey +} + +func randKeypair(t *testing.T) keypair { + pri, err := bls.RandKey() + require.NoError(t, err) + var pub [fieldparams.BLSPubkeyLength]byte + copy(pub[:], pri.PublicKey().Marshal()) + return keypair{pub: pub, pri: pri} +} + +func newMockKeymanager(t *testing.T, pairs ...keypair) *mockKeymanager { + m := &mockKeymanager{keysMap: make(map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey)} + require.NoError(t, m.add(pairs...)) + return m } type mockKeymanager struct { lock sync.RWMutex keysMap map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey + keys [][fieldparams.BLSPubkeyLength]byte fetchNoKeys bool accountsChangedFeed *event.Feed } -func (m *mockKeymanager) FetchValidatingPublicKeys(_ context.Context) ([][fieldparams.BLSPubkeyLength]byte, error) { +var errMockKeyExists = errors.New("key already in mockKeymanager map") + +func (m *mockKeymanager) add(pairs ...keypair) error { + for _, kp := range pairs { + if _, exists := m.keysMap[kp.pub]; exists { + return errMockKeyExists + } + m.keys = append(m.keys, kp.pub) + m.keysMap[kp.pub] = kp.pri + } + return nil +} + +func (m *mockKeymanager) remove(pairs ...keypair) { + for _, kp := range pairs { + if _, exists := m.keysMap[kp.pub]; !exists { + continue + } + m.removeOne(kp) + } +} + +func (m *mockKeymanager) removeOne(kp keypair) { + delete(m.keysMap, kp.pub) + if m.keys[0] == kp.pub { + m.keys = m.keys[1:] + return + } + for i := 1; i < len(m.keys); i++ { + if m.keys[i] == kp.pub { + m.keys = append(m.keys[0:i-1], m.keys[i:]...) + return + } + } +} + +func (m *mockKeymanager) FetchValidatingPublicKeys(ctx context.Context) ([][fieldparams.BLSPubkeyLength]byte, error) { m.lock.RLock() defer m.lock.RUnlock() - keys := make([][fieldparams.BLSPubkeyLength]byte, 0) if m.fetchNoKeys { m.fetchNoKeys = false - return keys, nil + return [][fieldparams.BLSPubkeyLength]byte{}, nil } - for pubKey := range m.keysMap { - keys = append(keys, pubKey) - } - return keys, nil + return m.keys, nil } func (m *mockKeymanager) Sign(_ context.Context, req *validatorpb.SignRequest) (bls.Signature, error) { @@ -308,28 +356,21 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) { defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } + + kp := randKeypair(t) v := validator{ validatorClient: validatorClient, - keyManager: km, + keyManager: newMockKeymanager(t, kp), beaconClient: beaconClient, } - resp := generateMockStatusResponse([][]byte{pubKey[:]}) + resp := generateMockStatusResponse([][]byte{kp.pub[:]}) resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE clientStream := mock2.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) validatorClient.EXPECT().WaitForActivation( gomock.Any(), ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{pubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(clientStream, nil) clientStream.EXPECT().Recv().Return( @@ -346,21 +387,14 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) { defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } + + kp := randKeypair(t) v := validator{ validatorClient: validatorClient, - keyManager: km, + keyManager: newMockKeymanager(t, kp), beaconClient: beaconClient, } - resp := generateMockStatusResponse([][]byte{pubKey[:]}) + resp := generateMockStatusResponse([][]byte{kp.pub[:]}) resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE clientStream := mock2.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) validatorClient.EXPECT().WaitForActivation( @@ -469,18 +503,9 @@ func TestUpdateDuties_ReturnsError(t *testing.T) { defer ctrl.Finish() client := validatormock.NewMockValidatorClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } v := validator{ validatorClient: client, - keyManager: km, + keyManager: newMockKeymanager(t, randKeypair(t)), duties: ðpb.DutiesResponse{ Duties: []*ethpb.DutiesResponse_Duty{ { @@ -507,15 +532,6 @@ func TestUpdateDuties_OK(t *testing.T) { client := validatormock.NewMockValidatorClient(ctrl) slot := params.BeaconConfig().SlotsPerEpoch - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } resp := ðpb.DutiesResponse{ Duties: []*ethpb.DutiesResponse_Duty{ { @@ -529,7 +545,7 @@ func TestUpdateDuties_OK(t *testing.T) { }, } v := validator{ - keyManager: km, + keyManager: newMockKeymanager(t, randKeypair(t)), validatorClient: client, } client.EXPECT().GetDuties( @@ -567,28 +583,20 @@ func TestUpdateDuties_OK_FilterBlacklistedPublicKeys(t *testing.T) { slot := params.BeaconConfig().SlotsPerEpoch numValidators := 10 - keysMap := make(map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey) + km := genMockKeymanager(t, numValidators) blacklistedPublicKeys := make(map[[fieldparams.BLSPubkeyLength]byte]bool) - for i := 0; i < numValidators; i++ { - priv, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], priv.PublicKey().Marshal()) - keysMap[pubKey] = priv - blacklistedPublicKeys[pubKey] = true - } - - km := &mockKeymanager{ - keysMap: keysMap, - } - resp := ðpb.DutiesResponse{ - Duties: []*ethpb.DutiesResponse_Duty{}, + for _, k := range km.keys { + blacklistedPublicKeys[k] = true } v := validator{ keyManager: km, validatorClient: client, eipImportBlacklistedPublicKeys: blacklistedPublicKeys, } + + resp := ðpb.DutiesResponse{ + Duties: []*ethpb.DutiesResponse_Duty{}, + } client.EXPECT().GetDuties( gomock.Any(), gomock.Any(), @@ -854,7 +862,7 @@ func TestAllValidatorsAreExited_AllExited(t *testing.T) { gomock.Any(), // request ).Return(ðpb.MultipleValidatorStatusResponse{Statuses: statuses}, nil /*err*/) - v := validator{keyManager: genMockKeymanager(2), validatorClient: client} + v := validator{keyManager: genMockKeymanager(t, 2), validatorClient: client} exited, err := v.AllValidatorsAreExited(context.Background()) require.NoError(t, err) assert.Equal(t, true, exited) @@ -875,7 +883,7 @@ func TestAllValidatorsAreExited_NotAllExited(t *testing.T) { gomock.Any(), // request ).Return(ðpb.MultipleValidatorStatusResponse{Statuses: statuses}, nil /*err*/) - v := validator{keyManager: genMockKeymanager(2), validatorClient: client} + v := validator{keyManager: genMockKeymanager(t, 2), validatorClient: client} exited, err := v.AllValidatorsAreExited(context.Background()) require.NoError(t, err) assert.Equal(t, false, exited) @@ -895,7 +903,7 @@ func TestAllValidatorsAreExited_PartialResult(t *testing.T) { gomock.Any(), // request ).Return(ðpb.MultipleValidatorStatusResponse{Statuses: statuses}, nil /*err*/) - v := validator{keyManager: genMockKeymanager(2), validatorClient: client} + v := validator{keyManager: genMockKeymanager(t, 2), validatorClient: client} exited, err := v.AllValidatorsAreExited(context.Background()) require.ErrorContains(t, "number of status responses did not match number of requested keys", err) assert.Equal(t, false, exited) @@ -905,7 +913,7 @@ func TestAllValidatorsAreExited_NoKeys(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := validatormock.NewMockValidatorClient(ctrl) - v := validator{keyManager: genMockKeymanager(0), validatorClient: client} + v := validator{keyManager: genMockKeymanager(t, 0), validatorClient: client} exited, err := v.AllValidatorsAreExited(context.Background()) require.NoError(t, err) assert.Equal(t, false, exited) @@ -937,17 +945,9 @@ func TestAllValidatorsAreExited_CorrectRequest(t *testing.T) { request, // request ).Return(ðpb.MultipleValidatorStatusResponse{Statuses: statuses}, nil /*err*/) - keysMap := make(map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey) - // secretKey below is just filler and is used multiple times - secretKeyBytes := [32]byte{1} - secretKey, err := bls.SecretKeyFromBytes(secretKeyBytes[:]) - require.NoError(t, err) - keysMap[pubKey0] = secretKey - keysMap[pubKey1] = secretKey - // If AllValidatorsAreExited does not create the expected request, this test will fail v := validator{ - keyManager: &mockKeymanager{keysMap: keysMap}, + keyManager: newMockKeymanager(t, keypair{pub: pubKey0}, keypair{pub: pubKey1}), validatorClient: client, } exited, err := v.AllValidatorsAreExited(context.Background()) @@ -1047,7 +1047,7 @@ func TestValidator_CheckDoppelGanger(t *testing.T) { name: "no doppelganger", validatorSetter: func(t *testing.T) *validator { client := validatormock.NewMockValidatorClient(ctrl) - km := genMockKeymanager(10) + km := genMockKeymanager(t, 10) keys, err := km.FetchValidatingPublicKeys(context.Background()) assert.NoError(t, err) db := dbTest.SetupDB(t, keys) @@ -1079,7 +1079,7 @@ func TestValidator_CheckDoppelGanger(t *testing.T) { name: "multiple doppelganger exists", validatorSetter: func(t *testing.T) *validator { client := validatormock.NewMockValidatorClient(ctrl) - km := genMockKeymanager(10) + km := genMockKeymanager(t, 10) keys, err := km.FetchValidatingPublicKeys(context.Background()) assert.NoError(t, err) db := dbTest.SetupDB(t, keys) @@ -1113,7 +1113,7 @@ func TestValidator_CheckDoppelGanger(t *testing.T) { name: "single doppelganger exists", validatorSetter: func(t *testing.T) *validator { client := validatormock.NewMockValidatorClient(ctrl) - km := genMockKeymanager(10) + km := genMockKeymanager(t, 10) keys, err := km.FetchValidatingPublicKeys(context.Background()) assert.NoError(t, err) db := dbTest.SetupDB(t, keys) @@ -1147,7 +1147,7 @@ func TestValidator_CheckDoppelGanger(t *testing.T) { name: "multiple attestations saved", validatorSetter: func(t *testing.T) *validator { client := validatormock.NewMockValidatorClient(ctrl) - km := genMockKeymanager(10) + km := genMockKeymanager(t, 10) keys, err := km.FetchValidatingPublicKeys(context.Background()) assert.NoError(t, err) db := dbTest.SetupDB(t, keys) @@ -1187,7 +1187,7 @@ func TestValidator_CheckDoppelGanger(t *testing.T) { validatorSetter: func(t *testing.T) *validator { client := validatormock.NewMockValidatorClient(ctrl) // Use only 1 key for deterministic order. - km := genMockKeymanager(1) + km := genMockKeymanager(t, 1) keys, err := km.FetchValidatingPublicKeys(context.Background()) assert.NoError(t, err) db := dbTest.SetupDB(t, keys) @@ -1222,7 +1222,7 @@ func TestValidator_CheckDoppelGanger(t *testing.T) { } func TestValidatorAttestationsAreOrdered(t *testing.T) { - km := genMockKeymanager(10) + km := genMockKeymanager(t, 10) keys, err := km.FetchValidatingPublicKeys(context.Background()) assert.NoError(t, err) db := dbTest.SetupDB(t, keys) diff --git a/validator/client/wait_for_activation_test.go b/validator/client/wait_for_activation_test.go index 0db086514f..18b64def02 100644 --- a/validator/client/wait_for_activation_test.go +++ b/validator/client/wait_for_activation_test.go @@ -10,7 +10,6 @@ import ( "github.com/golang/mock/gomock" "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" - "github.com/prysmaticlabs/prysm/v4/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v4/testing/assert" "github.com/prysmaticlabs/prysm/v4/testing/mock" @@ -30,18 +29,10 @@ func TestWaitActivation_ContextCanceled(t *testing.T) { defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } + kp := randKeypair(t) v := validator{ validatorClient: validatorClient, - keyManager: km, + keyManager: newMockKeymanager(t, kp), beaconClient: beaconClient, } clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) @@ -49,7 +40,7 @@ func TestWaitActivation_ContextCanceled(t *testing.T) { validatorClient.EXPECT().WaitForActivation( gomock.Any(), ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{pubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(clientStream, nil) clientStream.EXPECT().Recv().Return( @@ -66,29 +57,21 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) { defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } + kp := randKeypair(t) v := validator{ validatorClient: validatorClient, - keyManager: km, + keyManager: newMockKeymanager(t, kp), beaconClient: beaconClient, } clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) validatorClient.EXPECT().WaitForActivation( gomock.Any(), ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{pubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(clientStream, errors.New("failed stream")).Return(clientStream, nil) beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil) - resp := generateMockStatusResponse([][]byte{pubKey[:]}) + resp := generateMockStatusResponse([][]byte{kp.pub[:]}) resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE clientStream.EXPECT().Recv().Return(resp, nil) assert.NoError(t, v.WaitForActivation(context.Background(), nil)) @@ -99,30 +82,22 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } + kp := randKeypair(t) v := validator{ validatorClient: validatorClient, - keyManager: km, + keyManager: newMockKeymanager(t, kp), beaconClient: beaconClient, } clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) validatorClient.EXPECT().WaitForActivation( gomock.Any(), ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{pubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(clientStream, nil) beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil) // A stream fails the first time, but succeeds the second time. - resp := generateMockStatusResponse([][]byte{pubKey[:]}) + resp := generateMockStatusResponse([][]byte{kp.pub[:]}) resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE clientStream.EXPECT().Recv().Return( nil, @@ -137,28 +112,20 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) { defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } + kp := randKeypair(t) v := validator{ validatorClient: validatorClient, - keyManager: km, + keyManager: newMockKeymanager(t, kp), genesisTime: 1, beaconClient: beaconClient, } - resp := generateMockStatusResponse([][]byte{pubKey[:]}) + resp := generateMockStatusResponse([][]byte{kp.pub[:]}) resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) validatorClient.EXPECT().WaitForActivation( gomock.Any(), ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{pubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(clientStream, nil) beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil) @@ -175,27 +142,19 @@ func TestWaitForActivation_Exiting(t *testing.T) { defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - } + kp := randKeypair(t) v := validator{ validatorClient: validatorClient, - keyManager: km, + keyManager: newMockKeymanager(t, kp), beaconClient: beaconClient, } - resp := generateMockStatusResponse([][]byte{pubKey[:]}) + resp := generateMockStatusResponse([][]byte{kp.pub[:]}) resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_EXITING clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) validatorClient.EXPECT().WaitForActivation( gomock.Any(), ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{pubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(clientStream, nil) beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil) @@ -218,28 +177,23 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) { defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) - privKey, err := bls.RandKey() - require.NoError(t, err) - var pubKey [fieldparams.BLSPubkeyLength]byte - copy(pubKey[:], privKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - pubKey: privKey, - }, - fetchNoKeys: true, - } + + kp := randKeypair(t) + km := newMockKeymanager(t, kp) + km.fetchNoKeys = true + v := validator{ validatorClient: validatorClient, keyManager: km, beaconClient: beaconClient, } - resp := generateMockStatusResponse([][]byte{pubKey[:]}) + resp := generateMockStatusResponse([][]byte{kp.pub[:]}) resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) validatorClient.EXPECT().WaitForActivation( gomock.Any(), ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{pubKey[:]}, + PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(clientStream, nil) beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil) @@ -258,19 +212,9 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) { defer ctrl.Finish() t.Run("Imported keymanager", func(t *testing.T) { - inactivePrivKey, err := bls.RandKey() - require.NoError(t, err) - var inactivePubKey [fieldparams.BLSPubkeyLength]byte - copy(inactivePubKey[:], inactivePrivKey.PublicKey().Marshal()) - activePrivKey, err := bls.RandKey() - require.NoError(t, err) - var activePubKey [fieldparams.BLSPubkeyLength]byte - copy(activePubKey[:], activePrivKey.PublicKey().Marshal()) - km := &mockKeymanager{ - keysMap: map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey{ - inactivePubKey: inactivePrivKey, - }, - } + inactive := randKeypair(t) + active := randKeypair(t) + km := newMockKeymanager(t, inactive) validatorClient := validatormock.NewMockValidatorClient(ctrl) beaconClient := validatormock.NewMockBeaconChainClient(ctrl) v := validator{ @@ -278,13 +222,13 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) { keyManager: km, beaconClient: beaconClient, } - inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]}) + inactiveResp := generateMockStatusResponse([][]byte{inactive.pub[:]}) inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS inactiveClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) validatorClient.EXPECT().WaitForActivation( gomock.Any(), ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{inactivePubKey[:]}, + PublicKeys: [][]byte{inactive.pub[:]}, }, ).Return(inactiveClientStream, nil) beaconClient.EXPECT().ListValidators(gomock.Any(), gomock.Any()).Return(ðpb.Validators{}, nil).AnyTimes() @@ -293,7 +237,7 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) { nil, ).AnyTimes() - activeResp := generateMockStatusResponse([][]byte{inactivePubKey[:], activePubKey[:]}) + activeResp := generateMockStatusResponse([][]byte{inactive.pub[:], active.pub[:]}) activeResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS activeResp.Statuses[1].Status.Status = ethpb.ValidatorStatus_ACTIVE activeClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) @@ -302,7 +246,7 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) { mock2.MatchedBy(func(req *ethpb.ValidatorActivationRequest) bool { found := 0 for _, pk := range req.PublicKeys { - if bytes.Equal(pk, activePubKey[:]) || bytes.Equal(pk, inactivePubKey[:]) { + if bytes.Equal(pk, active.pub[:]) || bytes.Equal(pk, inactive.pub[:]) { found++ } } @@ -317,7 +261,7 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) { go func() { // We add the active key into the keymanager and simulate a key refresh. time.Sleep(time.Second * 1) - km.keysMap[activePubKey] = activePrivKey + require.NoError(t, km.add(active)) km.SimulateAccountChanges(make([][fieldparams.BLSPubkeyLength]byte, 0)) }()