From 3d5d022de49ce5bde2dbf43ec725a4ee036ce8bd Mon Sep 17 00:00:00 2001 From: Shota Date: Thu, 24 Oct 2024 23:18:04 +0400 Subject: [PATCH] =?UTF-8?q?optimise=20a.blsToExecutionChangeService.Proces?= =?UTF-8?q?sMessage=20with=20async=20sign=E2=80=A6=20(#12441)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ature verification Co-authored-by: shota.silagadze --- cl/beacon/handler/pool.go | 27 ++++--- cl/beacon/handler/utils_test.go | 4 +- cl/cltypes/bls_to_execution_change.go | 7 ++ cl/phase1/network/gossip_manager.go | 7 +- .../services/batch_signature_verification.go | 23 +++--- .../bls_to_execution_change_service.go | 72 +++++++++++-------- .../bls_to_execution_change_service_test.go | 63 +++++++++------- .../network/services/global_mock_test.go | 8 +++ cl/phase1/network/services/interface.go | 2 +- .../bls_to_execution_change_service_mock.go | 6 +- cmd/caplin/caplin1/run.go | 2 +- 11 files changed, 133 insertions(+), 88 deletions(-) diff --git a/cl/beacon/handler/pool.go b/cl/beacon/handler/pool.go index c43bf96c4c0..f042fff8aea 100644 --- a/cl/beacon/handler/pool.go +++ b/cl/beacon/handler/pool.go @@ -269,24 +269,21 @@ func (a *ApiHandler) PostEthV1BeaconPoolBlsToExecutionChanges(w http.ResponseWri } failures := []poolingFailure{} for _, v := range req { - if err := a.blsToExecutionChangeService.ProcessMessage(r.Context(), nil, v); err != nil && !errors.Is(err, services.ErrIgnore) { - failures = append(failures, poolingFailure{Index: len(failures), Message: err.Error()}) - continue + encodedSSZ, err := v.EncodeSSZ(nil) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } - // Broadcast to gossip - if a.sentinel != nil { - encodedSSZ, err := v.EncodeSSZ(nil) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - if _, err := a.sentinel.PublishGossip(r.Context(), &sentinel.GossipData{ + + if err := a.blsToExecutionChangeService.ProcessMessage(r.Context(), nil, &cltypes.SignedBLSToExecutionChangeWithGossipData{ + SignedBLSToExecutionChange: v, + GossipData: &sentinel.GossipData{ Data: encodedSSZ, Name: gossip.TopicNameBlsToExecutionChange, - }); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } + }, + }); err != nil && !errors.Is(err, services.ErrIgnore) { + failures = append(failures, poolingFailure{Index: len(failures), Message: err.Error()}) + continue } } diff --git a/cl/beacon/handler/utils_test.go b/cl/beacon/handler/utils_test.go index 75b3b6226dc..f480f849b2f 100644 --- a/cl/beacon/handler/utils_test.go +++ b/cl/beacon/handler/utils_test.go @@ -134,8 +134,8 @@ func setupTestingHandler(t *testing.T, v clparams.StateVersion, logger log.Logge opPool.VoluntaryExitsPool.Insert(msg.VoluntaryExit.ValidatorIndex, msg) return nil }).AnyTimes() - blsToExecutionChangeService.EXPECT().ProcessMessage(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, subnetID *uint64, msg *cltypes.SignedBLSToExecutionChange) error { - opPool.BLSToExecutionChangesPool.Insert(msg.Signature, msg) + blsToExecutionChangeService.EXPECT().ProcessMessage(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, subnetID *uint64, msg *cltypes.SignedBLSToExecutionChangeWithGossipData) error { + opPool.BLSToExecutionChangesPool.Insert(msg.SignedBLSToExecutionChange.Signature, msg.SignedBLSToExecutionChange) return nil }).AnyTimes() proposerSlashingService.EXPECT().ProcessMessage(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, subnetID *uint64, msg *cltypes.ProposerSlashing) error { diff --git a/cl/cltypes/bls_to_execution_change.go b/cl/cltypes/bls_to_execution_change.go index 00bd1bb0fe4..fea594a84f3 100644 --- a/cl/cltypes/bls_to_execution_change.go +++ b/cl/cltypes/bls_to_execution_change.go @@ -20,6 +20,7 @@ import ( "fmt" libcommon "github.com/erigontech/erigon-lib/common" + sentinel "github.com/erigontech/erigon-lib/gointerfaces/sentinelproto" "github.com/erigontech/erigon-lib/types/ssz" "github.com/erigontech/erigon/cl/merkle_tree" ssz2 "github.com/erigontech/erigon/cl/ssz" @@ -58,6 +59,12 @@ func (*BLSToExecutionChange) Static() bool { return true } +// SignedBLSToExecutionChangeWithGossipData type represents SignedBLSToExecutionChange with the gossip data where it's coming from. +type SignedBLSToExecutionChangeWithGossipData struct { + SignedBLSToExecutionChange *SignedBLSToExecutionChange + GossipData *sentinel.GossipData +} + type SignedBLSToExecutionChange struct { Message *BLSToExecutionChange `json:"message"` Signature libcommon.Bytes96 `json:"signature"` diff --git a/cl/phase1/network/gossip_manager.go b/cl/phase1/network/gossip_manager.go index fd7d4f0cec1..4576de6dbd2 100644 --- a/cl/phase1/network/gossip_manager.go +++ b/cl/phase1/network/gossip_manager.go @@ -218,8 +218,11 @@ func (g *GossipManager) routeAndProcess(ctx context.Context, data *sentinel.Goss case gossip.TopicNameAttesterSlashing: return operationsContract[*cltypes.AttesterSlashing](ctx, g, data, int(version), "attester slashing", g.forkChoice.OnAttesterSlashing) case gossip.TopicNameBlsToExecutionChange: - obj := &cltypes.SignedBLSToExecutionChange{} - if err := obj.DecodeSSZ(data.Data, int(version)); err != nil { + obj := &cltypes.SignedBLSToExecutionChangeWithGossipData{ + GossipData: copyOfSentinelData(data), + SignedBLSToExecutionChange: &cltypes.SignedBLSToExecutionChange{}, + } + if err := obj.SignedBLSToExecutionChange.DecodeSSZ(data.Data, int(version)); err != nil { return err } return g.blsToExecutionChangeService.ProcessMessage(ctx, data.SubnetId, obj) diff --git a/cl/phase1/network/services/batch_signature_verification.go b/cl/phase1/network/services/batch_signature_verification.go index 3f6d83ae625..9069d1593db 100644 --- a/cl/phase1/network/services/batch_signature_verification.go +++ b/cl/phase1/network/services/batch_signature_verification.go @@ -22,10 +22,11 @@ var ( ) type BatchSignatureVerifier struct { - sentinel sentinel.SentinelClient - attVerifyAndExecute chan *AggregateVerificationData - aggregateProofVerify chan *AggregateVerificationData - ctx context.Context + sentinel sentinel.SentinelClient + attVerifyAndExecute chan *AggregateVerificationData + aggregateProofVerify chan *AggregateVerificationData + blsToExecutionChangeVerify chan *AggregateVerificationData + ctx context.Context } // each AggregateVerification request has sentinel.SentinelClient and *sentinel.GossipData @@ -41,10 +42,11 @@ type AggregateVerificationData struct { func NewBatchSignatureVerifier(ctx context.Context, sentinel sentinel.SentinelClient) *BatchSignatureVerifier { return &BatchSignatureVerifier{ - ctx: ctx, - sentinel: sentinel, - attVerifyAndExecute: make(chan *AggregateVerificationData, 1024), - aggregateProofVerify: make(chan *AggregateVerificationData, 1024), + ctx: ctx, + sentinel: sentinel, + attVerifyAndExecute: make(chan *AggregateVerificationData, 1024), + aggregateProofVerify: make(chan *AggregateVerificationData, 1024), + blsToExecutionChangeVerify: make(chan *AggregateVerificationData, 1024), } } @@ -57,6 +59,10 @@ func (b *BatchSignatureVerifier) AsyncVerifyAggregateProof(data *AggregateVerifi b.aggregateProofVerify <- data } +func (b *BatchSignatureVerifier) AsyncVerifyBlsToExecutionChange(data *AggregateVerificationData) { + b.blsToExecutionChangeVerify <- data +} + func (b *BatchSignatureVerifier) ImmediateVerification(data *AggregateVerificationData) error { return b.processSignatureVerification([]*AggregateVerificationData{data}) } @@ -65,6 +71,7 @@ func (b *BatchSignatureVerifier) Start() { // separate goroutines for each type of verification go b.start(b.attVerifyAndExecute) go b.start(b.aggregateProofVerify) + go b.start(b.blsToExecutionChangeVerify) } // When receiving AggregateVerificationData, we simply collect all the signature verification data diff --git a/cl/phase1/network/services/bls_to_execution_change_service.go b/cl/phase1/network/services/bls_to_execution_change_service.go index 790d7913231..fd12a9dabef 100644 --- a/cl/phase1/network/services/bls_to_execution_change_service.go +++ b/cl/phase1/network/services/bls_to_execution_change_service.go @@ -38,10 +38,11 @@ var ( ) type blsToExecutionChangeService struct { - operationsPool pool.OperationsPool - emitters *beaconevents.EventEmitter - syncedDataManager synced_data.SyncedData - beaconCfg *clparams.BeaconChainConfig + operationsPool pool.OperationsPool + emitters *beaconevents.EventEmitter + syncedDataManager synced_data.SyncedData + beaconCfg *clparams.BeaconChainConfig + batchSignatureVerifier *BatchSignatureVerifier } func NewBLSToExecutionChangeService( @@ -49,23 +50,25 @@ func NewBLSToExecutionChangeService( emitters *beaconevents.EventEmitter, syncedDataManager synced_data.SyncedData, beaconCfg *clparams.BeaconChainConfig, + batchSignatureVerifier *BatchSignatureVerifier, ) BLSToExecutionChangeService { return &blsToExecutionChangeService{ - operationsPool: operationsPool, - emitters: emitters, - syncedDataManager: syncedDataManager, - beaconCfg: beaconCfg, + operationsPool: operationsPool, + emitters: emitters, + syncedDataManager: syncedDataManager, + beaconCfg: beaconCfg, + batchSignatureVerifier: batchSignatureVerifier, } } -func (s *blsToExecutionChangeService) ProcessMessage(ctx context.Context, subnet *uint64, msg *cltypes.SignedBLSToExecutionChange) error { +func (s *blsToExecutionChangeService) ProcessMessage(ctx context.Context, subnet *uint64, msg *cltypes.SignedBLSToExecutionChangeWithGossipData) error { // https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/p2p-interface.md#bls_to_execution_change // [IGNORE] The signed_bls_to_execution_change is the first valid signed bls to execution change received // for the validator with index signed_bls_to_execution_change.message.validator_index. - if s.operationsPool.BLSToExecutionChangesPool.Has(msg.Signature) { + if s.operationsPool.BLSToExecutionChangesPool.Has(msg.SignedBLSToExecutionChange.Signature) { return ErrIgnore } - change := msg.Message + change := msg.SignedBLSToExecutionChange.Message stateReader := s.syncedDataManager.HeadStateReader() if stateReader == nil { return ErrIgnore @@ -110,26 +113,35 @@ func (s *blsToExecutionChangeService) ProcessMessage(ctx context.Context, subnet if err != nil { return err } - valid, err := blsVerify(msg.Signature[:], signedRoot[:], change.From[:]) - if err != nil { - return err - } - if !valid { - return errors.New("invalid signature") + + aggregateVerificationData := &AggregateVerificationData{ + Signatures: [][]byte{msg.SignedBLSToExecutionChange.Signature[:]}, + SignRoots: [][]byte{signedRoot[:]}, + Pks: [][]byte{change.From[:]}, + GossipData: msg.GossipData, + F: func() { + // validator.withdrawal_credentials = ( + // ETH1_ADDRESS_WITHDRAWAL_PREFIX + // + b'\x00' * 11 + // + address_change.to_execution_address + // ) + newWc := libcommon.Hash{} + newWc[0] = byte(s.beaconCfg.ETH1AddressWithdrawalPrefixByte) + copy(newWc[1:], make([]byte, 11)) + copy(newWc[12:], change.To[:]) + stateMutator.SetWithdrawalCredentialForValidatorAtIndex(int(change.ValidatorIndex), newWc) + + s.emitters.Operation().SendBlsToExecution(msg.SignedBLSToExecutionChange) + s.operationsPool.BLSToExecutionChangesPool.Insert(msg.SignedBLSToExecutionChange.Signature, msg.SignedBLSToExecutionChange) + }, } - // validator.withdrawal_credentials = ( - // ETH1_ADDRESS_WITHDRAWAL_PREFIX - // + b'\x00' * 11 - // + address_change.to_execution_address - // ) - newWc := libcommon.Hash{} - newWc[0] = byte(s.beaconCfg.ETH1AddressWithdrawalPrefixByte) - copy(newWc[1:], make([]byte, 11)) - copy(newWc[12:], change.To[:]) - stateMutator.SetWithdrawalCredentialForValidatorAtIndex(int(change.ValidatorIndex), newWc) + // push the signatures to verify asynchronously and run final functions after that. + s.batchSignatureVerifier.AsyncVerifyBlsToExecutionChange(aggregateVerificationData) - s.emitters.Operation().SendBlsToExecution(msg) - s.operationsPool.BLSToExecutionChangesPool.Insert(msg.Signature, msg) - return nil + // As the logic goes, if we return ErrIgnore there will be no peer banning and further publishing + // gossip data into the network by the gossip manager. That's what we want because we will be doing that ourselves + // in BatchSignatureVerifier service. After validating signatures, if they are valid we will publish the + // gossip ourselves or ban the peer which sent that particular invalid signature. + return ErrIgnore } diff --git a/cl/phase1/network/services/bls_to_execution_change_service_test.go b/cl/phase1/network/services/bls_to_execution_change_service_test.go index 7d37978fe56..d6314b44241 100644 --- a/cl/phase1/network/services/bls_to_execution_change_service_test.go +++ b/cl/phase1/network/services/bls_to_execution_change_service_test.go @@ -22,6 +22,7 @@ import ( "fmt" "log" "testing" + "time" "github.com/erigontech/erigon-lib/common" mockState "github.com/erigontech/erigon/cl/abstract/mock_services" @@ -56,13 +57,17 @@ func (t *blsToExecutionChangeTestSuite) SetupTest() { t.syncedData = mockSync.NewMockSyncedData(t.gomockCtrl) t.emitters = beaconevents.NewEventEmitter() t.beaconCfg = &clparams.BeaconChainConfig{} - t.service = NewBLSToExecutionChangeService(*t.operationsPool, t.emitters, t.syncedData, t.beaconCfg) + batchSignatureVerifier := NewBatchSignatureVerifier(context.TODO(), nil) + batchCheckInterval = 1 * time.Millisecond + go batchSignatureVerifier.Start() + t.service = NewBLSToExecutionChangeService(*t.operationsPool, t.emitters, t.syncedData, t.beaconCfg, batchSignatureVerifier) // mock global functions t.mockFuncs = &mockFuncs{ ctrl: t.gomockCtrl, } computeSigningRoot = t.mockFuncs.ComputeSigningRoot blsVerify = t.mockFuncs.BlsVerify + blsVerifyMultipleSignatures = t.mockFuncs.BlsVerifyMultipleSignatures } func (t *blsToExecutionChangeTestSuite) TearDownTest() { @@ -70,26 +75,29 @@ func (t *blsToExecutionChangeTestSuite) TearDownTest() { } func (t *blsToExecutionChangeTestSuite) TestProcessMessage() { - mockMsg := &cltypes.SignedBLSToExecutionChange{ - Message: &cltypes.BLSToExecutionChange{ - ValidatorIndex: 1, - From: common.Bytes48{1, 2, 3, 4, 5, 6}, - To: common.Address{3, 2, 1}, + mockMsg := &cltypes.SignedBLSToExecutionChangeWithGossipData{ + SignedBLSToExecutionChange: &cltypes.SignedBLSToExecutionChange{ + Message: &cltypes.BLSToExecutionChange{ + ValidatorIndex: 1, + From: common.Bytes48{1, 2, 3, 4, 5, 6}, + To: common.Address{3, 2, 1}, + }, + Signature: [96]byte{1, 2, 3}, }, - Signature: [96]byte{1, 2, 3}, + GossipData: nil, } tests := []struct { name string mock func() - msg *cltypes.SignedBLSToExecutionChange + msg *cltypes.SignedBLSToExecutionChangeWithGossipData wantErr bool specificErr error }{ { name: "signature already exists in pool", mock: func() { - t.operationsPool.BLSToExecutionChangesPool.Insert(mockMsg.Signature, mockMsg) + t.operationsPool.BLSToExecutionChangesPool.Insert(mockMsg.SignedBLSToExecutionChange.Signature, mockMsg.SignedBLSToExecutionChange) }, msg: mockMsg, wantErr: true, @@ -113,7 +121,7 @@ func (t *blsToExecutionChangeTestSuite) TestProcessMessage() { mockStateReader := mockState.NewMockBeaconStateReader(t.gomockCtrl) mockStateMutator := mockState.NewMockBeaconStateMutator(t.gomockCtrl) mockStateReader.EXPECT().Version().Return(clparams.CapellaVersion).Times(1) - mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.Message.ValidatorIndex)).Return(nil, errors.New("not found")).Times(1) + mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.SignedBLSToExecutionChange.Message.ValidatorIndex)).Return(nil, errors.New("not found")).Times(1) t.syncedData.EXPECT().HeadStateReader().Return(mockStateReader).Times(1) t.syncedData.EXPECT().HeadStateMutator().Return(mockStateMutator).Times(1) }, @@ -128,7 +136,7 @@ func (t *blsToExecutionChangeTestSuite) TestProcessMessage() { mockValidator := solid.NewValidator() mockValidator.SetWithdrawalCredentials([32]byte{1, 1, 1}) // should be equal to BLS_WITHDRAWAL_PREFIX mockStateReader.EXPECT().Version().Return(clparams.CapellaVersion).Times(1) - mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.Message.ValidatorIndex)).Return(mockValidator, nil).Times(1) + mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.SignedBLSToExecutionChange.Message.ValidatorIndex)).Return(mockValidator, nil).Times(1) t.syncedData.EXPECT().HeadStateReader().Return(mockStateReader).Times(1) t.syncedData.EXPECT().HeadStateMutator().Return(mockStateMutator).Times(1) }, @@ -143,7 +151,7 @@ func (t *blsToExecutionChangeTestSuite) TestProcessMessage() { mockValidator := solid.NewValidator() mockValidator.SetWithdrawalCredentials([32]byte{0}) // first byte is equal to BLS_WITHDRAWAL_PREFIX mockStateReader.EXPECT().Version().Return(clparams.CapellaVersion).Times(1) - mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.Message.ValidatorIndex)).Return(mockValidator, nil).Times(1) + mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.SignedBLSToExecutionChange.Message.ValidatorIndex)).Return(mockValidator, nil).Times(1) t.syncedData.EXPECT().HeadStateReader().Return(mockStateReader).Times(1) t.syncedData.EXPECT().HeadStateMutator().Return(mockStateMutator).Times(1) }, @@ -156,21 +164,22 @@ func (t *blsToExecutionChangeTestSuite) TestProcessMessage() { mockStateReader := mockState.NewMockBeaconStateReader(t.gomockCtrl) mockStateMutator := mockState.NewMockBeaconStateMutator(t.gomockCtrl) mockValidator := solid.NewValidator() - hashedFrom := utils.Sha256(mockMsg.Message.From[:]) + hashedFrom := utils.Sha256(mockMsg.SignedBLSToExecutionChange.Message.From[:]) wc := [32]byte{0} copy(wc[1:], hashedFrom[1:]) mockValidator.SetWithdrawalCredentials(wc) mockStateReader.EXPECT().Version().Return(clparams.CapellaVersion).Times(1) - mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.Message.ValidatorIndex)).Return(mockValidator, nil).Times(1) + mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.SignedBLSToExecutionChange.Message.ValidatorIndex)).Return(mockValidator, nil).Times(1) t.syncedData.EXPECT().HeadStateReader().Return(mockStateReader).Times(1) t.syncedData.EXPECT().HeadStateMutator().Return(mockStateMutator).Times(1) mockStateReader.EXPECT().GenesisValidatorsRoot().Return([32]byte{}).Times(1) // bls verify - t.gomockCtrl.RecordCall(t.mockFuncs, "ComputeSigningRoot", mockMsg.Message, gomock.Any()).Return([32]byte{}, nil).Times(1) - t.gomockCtrl.RecordCall(t.mockFuncs, "BlsVerify", mockMsg.Signature[:], gomock.Any(), mockMsg.Message.From[:]).Return(false, nil).Times(1) + t.gomockCtrl.RecordCall(t.mockFuncs, "ComputeSigningRoot", mockMsg.SignedBLSToExecutionChange.Message, gomock.Any()).Return([32]byte{}, nil).Times(1) + t.gomockCtrl.RecordCall(t.mockFuncs, "BlsVerifyMultipleSignatures", gomock.Any(), gomock.Any(), gomock.Any()).Return(false, nil).Times(2) }, - msg: mockMsg, - wantErr: true, + msg: mockMsg, + specificErr: ErrIgnore, + wantErr: true, }, { name: "pass", @@ -178,26 +187,27 @@ func (t *blsToExecutionChangeTestSuite) TestProcessMessage() { mockStateReader := mockState.NewMockBeaconStateReader(t.gomockCtrl) mockStateMutator := mockState.NewMockBeaconStateMutator(t.gomockCtrl) mockValidator := solid.NewValidator() - hashedFrom := utils.Sha256(mockMsg.Message.From[:]) + hashedFrom := utils.Sha256(mockMsg.SignedBLSToExecutionChange.Message.From[:]) wc := [32]byte{0} copy(wc[1:], hashedFrom[1:]) mockValidator.SetWithdrawalCredentials(wc) mockStateReader.EXPECT().Version().Return(clparams.CapellaVersion).Times(1) - mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.Message.ValidatorIndex)).Return(mockValidator, nil).Times(1) + mockStateReader.EXPECT().ValidatorForValidatorIndex(int(mockMsg.SignedBLSToExecutionChange.Message.ValidatorIndex)).Return(mockValidator, nil).Times(1) t.syncedData.EXPECT().HeadStateReader().Return(mockStateReader).Times(1) t.syncedData.EXPECT().HeadStateMutator().Return(mockStateMutator).Times(1) mockStateReader.EXPECT().GenesisValidatorsRoot().Return([32]byte{}).Times(1) // bls verify - t.gomockCtrl.RecordCall(t.mockFuncs, "ComputeSigningRoot", mockMsg.Message, gomock.Any()).Return([32]byte{}, nil).Times(1) - t.gomockCtrl.RecordCall(t.mockFuncs, "BlsVerify", mockMsg.Signature[:], gomock.Any(), mockMsg.Message.From[:]).Return(true, nil).Times(1) + t.gomockCtrl.RecordCall(t.mockFuncs, "ComputeSigningRoot", mockMsg.SignedBLSToExecutionChange.Message, gomock.Any()).Return([32]byte{}, nil).Times(1) // update withdrawal credentials mockNewWc := common.Hash{byte(t.beaconCfg.ETH1AddressWithdrawalPrefixByte)} copy(mockNewWc[1:], make([]byte, 11)) - copy(mockNewWc[12:], mockMsg.Message.To[:]) - mockStateMutator.EXPECT().SetWithdrawalCredentialForValidatorAtIndex(int(mockMsg.Message.ValidatorIndex), mockNewWc).Times(1) + copy(mockNewWc[12:], mockMsg.SignedBLSToExecutionChange.Message.To[:]) + mockStateMutator.EXPECT().SetWithdrawalCredentialForValidatorAtIndex(int(mockMsg.SignedBLSToExecutionChange.Message.ValidatorIndex), mockNewWc).Times(1) + t.gomockCtrl.RecordCall(t.mockFuncs, "BlsVerifyMultipleSignatures", gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil).Times(1) }, - msg: mockMsg, - wantErr: false, + msg: mockMsg, + specificErr: ErrIgnore, + wantErr: true, }, } @@ -206,6 +216,7 @@ func (t *blsToExecutionChangeTestSuite) TestProcessMessage() { t.SetupTest() tt.mock() err := t.service.ProcessMessage(context.Background(), nil, tt.msg) + time.Sleep(10 * time.Millisecond) if tt.wantErr { t.Require().Error(err) fmt.Printf("Error: %v\n", err) diff --git a/cl/phase1/network/services/global_mock_test.go b/cl/phase1/network/services/global_mock_test.go index 83a44eeedbc..f9a6e7bd42c 100644 --- a/cl/phase1/network/services/global_mock_test.go +++ b/cl/phase1/network/services/global_mock_test.go @@ -40,3 +40,11 @@ func (m *mockFuncs) BlsVerify(pubkey, message, signature []byte) (bool, error) { ret1, _ := ret[1].(error) return ret0, ret1 } + +func (m *mockFuncs) BlsVerifyMultipleSignatures(pubkey, message, signature [][]byte) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlsVerifyMultipleSignatures", pubkey, message, signature) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} diff --git a/cl/phase1/network/services/interface.go b/cl/phase1/network/services/interface.go index 175babb414f..03de1eb01c0 100644 --- a/cl/phase1/network/services/interface.go +++ b/cl/phase1/network/services/interface.go @@ -50,7 +50,7 @@ type AttestationService Service[*AttestationWithGossipData] type VoluntaryExitService Service[*cltypes.SignedVoluntaryExit] //go:generate mockgen -typed=true -destination=./mock_services/bls_to_execution_change_service_mock.go -package=mock_services . BLSToExecutionChangeService -type BLSToExecutionChangeService Service[*cltypes.SignedBLSToExecutionChange] +type BLSToExecutionChangeService Service[*cltypes.SignedBLSToExecutionChangeWithGossipData] //go:generate mockgen -typed=true -destination=./mock_services/proposer_slashing_service_mock.go -package=mock_services . ProposerSlashingService type ProposerSlashingService Service[*cltypes.ProposerSlashing] diff --git a/cl/phase1/network/services/mock_services/bls_to_execution_change_service_mock.go b/cl/phase1/network/services/mock_services/bls_to_execution_change_service_mock.go index c64a9e900a9..fd4b3da1f37 100644 --- a/cl/phase1/network/services/mock_services/bls_to_execution_change_service_mock.go +++ b/cl/phase1/network/services/mock_services/bls_to_execution_change_service_mock.go @@ -42,7 +42,7 @@ func (m *MockBLSToExecutionChangeService) EXPECT() *MockBLSToExecutionChangeServ } // ProcessMessage mocks base method. -func (m *MockBLSToExecutionChangeService) ProcessMessage(ctx context.Context, subnet *uint64, msg *cltypes.SignedBLSToExecutionChange) error { +func (m *MockBLSToExecutionChangeService) ProcessMessage(ctx context.Context, subnet *uint64, msg *cltypes.SignedBLSToExecutionChangeWithGossipData) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ProcessMessage", ctx, subnet, msg) ret0, _ := ret[0].(error) @@ -68,13 +68,13 @@ func (c *MockBLSToExecutionChangeServiceProcessMessageCall) Return(arg0 error) * } // Do rewrite *gomock.Call.Do -func (c *MockBLSToExecutionChangeServiceProcessMessageCall) Do(f func(context.Context, *uint64, *cltypes.SignedBLSToExecutionChange) error) *MockBLSToExecutionChangeServiceProcessMessageCall { +func (c *MockBLSToExecutionChangeServiceProcessMessageCall) Do(f func(context.Context, *uint64, *cltypes.SignedBLSToExecutionChangeWithGossipData) error) *MockBLSToExecutionChangeServiceProcessMessageCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockBLSToExecutionChangeServiceProcessMessageCall) DoAndReturn(f func(context.Context, *uint64, *cltypes.SignedBLSToExecutionChange) error) *MockBLSToExecutionChangeServiceProcessMessageCall { +func (c *MockBLSToExecutionChangeServiceProcessMessageCall) DoAndReturn(f func(context.Context, *uint64, *cltypes.SignedBLSToExecutionChangeWithGossipData) error) *MockBLSToExecutionChangeServiceProcessMessageCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/cmd/caplin/caplin1/run.go b/cmd/caplin/caplin1/run.go index 3d02a06de1b..fa3a2a62f66 100644 --- a/cmd/caplin/caplin1/run.go +++ b/cmd/caplin/caplin1/run.go @@ -311,7 +311,7 @@ func RunCaplinService(ctx context.Context, engine execution_client.ExecutionEngi syncContributionService := services.NewSyncContributionService(syncedDataManager, beaconConfig, syncContributionPool, ethClock, emitters, false) aggregateAndProofService := services.NewAggregateAndProofService(ctx, syncedDataManager, forkChoice, beaconConfig, pool, false, batchSignatureVerifier) voluntaryExitService := services.NewVoluntaryExitService(pool, emitters, syncedDataManager, beaconConfig, ethClock) - blsToExecutionChangeService := services.NewBLSToExecutionChangeService(pool, emitters, syncedDataManager, beaconConfig) + blsToExecutionChangeService := services.NewBLSToExecutionChangeService(pool, emitters, syncedDataManager, beaconConfig, batchSignatureVerifier) proposerSlashingService := services.NewProposerSlashingService(pool, syncedDataManager, beaconConfig, ethClock, emitters) {