diff --git a/Makefile b/Makefile index da0ff87..4058e8f 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,8 @@ test: ./scripts/tests.sh genmocks: - mockgen -source=./chains/evm/listener/events/handlers/deposit.go -destination=./mock/handlers.go -package mock + mockgen -source=./chains/evm/listener/events/handlers/deposit.go -destination=./mock/deposit.go -package mock + mockgen -source=./chains/evm/listener/events/handlers/rotate.go -destination=./mock/rotate.go -package mock mockgen -source=./chains/evm/listener/listener.go -destination=./mock/listener.go -package mock mockgen -source=./chains/evm/executor/executor.go -destination=./mock/executor.go -package mock diff --git a/chains/evm/listener/events/handlers/deposit_test.go b/chains/evm/listener/events/handlers/deposit_test.go index c09e75b..c172fc6 100644 --- a/chains/evm/listener/events/handlers/deposit_test.go +++ b/chains/evm/listener/events/handlers/deposit_test.go @@ -46,7 +46,7 @@ type DepositHandlerTestSuite struct { mockStepProver *mock.MockProver } -func TestRunConfigTestSuite(t *testing.T) { +func TestRunDepositTestSuite(t *testing.T) { suite.Run(t, new(DepositHandlerTestSuite)) } diff --git a/chains/evm/listener/events/handlers/rotate.go b/chains/evm/listener/events/handlers/rotate.go index d6aafce..f6be8ce 100644 --- a/chains/evm/listener/events/handlers/rotate.go +++ b/chains/evm/listener/events/handlers/rotate.go @@ -26,16 +26,17 @@ type RotateHandler struct { prover Prover syncCommitteeFetcher SyncCommitteeFetcher - currentSyncCommittee *api.Response[*apiv1.SyncCommittee] + currentSyncCommittee *apiv1.SyncCommittee } -func NewRotateHandler(domainID uint8, domains []uint8, msgChan chan []*message.Message, syncCommitteeFetcher SyncCommitteeFetcher, prover Prover) *RotateHandler { +func NewRotateHandler(msgChan chan []*message.Message, syncCommitteeFetcher SyncCommitteeFetcher, prover Prover, domainID uint8, domains []uint8) *RotateHandler { return &RotateHandler{ syncCommitteeFetcher: syncCommitteeFetcher, prover: prover, domainID: domainID, domains: domains, msgChan: msgChan, + currentSyncCommittee: &apiv1.SyncCommittee{}, } } @@ -48,7 +49,7 @@ func (h *RotateHandler) HandleEvents(startBlock *big.Int, endBlock *big.Int) err if err != nil { return err } - if syncCommittee.Data.String() == h.currentSyncCommittee.Data.String() { + if syncCommittee.Data.String() == h.currentSyncCommittee.String() { return nil } diff --git a/chains/evm/listener/events/handlers/rotate_test.go b/chains/evm/listener/events/handlers/rotate_test.go new file mode 100644 index 0000000..4b3e443 --- /dev/null +++ b/chains/evm/listener/events/handlers/rotate_test.go @@ -0,0 +1,126 @@ +// The Licensed Work is (c) 2023 Sygma +// SPDX-License-Identifier: LGPL-3.0-only + +package handlers_test + +import ( + "context" + "fmt" + "math/big" + "testing" + + "github.com/attestantio/go-eth2-client/api" + apiv1 "github.com/attestantio/go-eth2-client/api/v1" + "github.com/attestantio/go-eth2-client/spec/phase0" + "github.com/stretchr/testify/suite" + "github.com/sygmaprotocol/spectre-node/chains/evm/listener/events/handlers" + "github.com/sygmaprotocol/spectre-node/mock" + "github.com/sygmaprotocol/sygma-core/relayer/message" + "go.uber.org/mock/gomock" +) + +type RotateHandlerTestSuite struct { + suite.Suite + + handler *handlers.RotateHandler + + msgChan chan []*message.Message + mockProver *mock.MockProver + mockSyncCommitteeFetcher *mock.MockSyncCommitteeFetcher +} + +func TestRunRotateTestSuite(t *testing.T) { + suite.Run(t, new(RotateHandlerTestSuite)) +} + +func (s *RotateHandlerTestSuite) SetupTest() { + ctrl := gomock.NewController(s.T()) + s.mockProver = mock.NewMockProver(ctrl) + s.mockSyncCommitteeFetcher = mock.NewMockSyncCommitteeFetcher(ctrl) + s.msgChan = make(chan []*message.Message, 2) + s.handler = handlers.NewRotateHandler( + s.msgChan, + s.mockSyncCommitteeFetcher, + s.mockProver, + 1, + []uint8{2, 3}, + ) +} + +func (s *RotateHandlerTestSuite) Test_HandleEvents_FetchingCommitteeFails() { + startBlock := big.NewInt(0) + endBlock := big.NewInt(4) + s.mockSyncCommitteeFetcher.EXPECT().SyncCommittee(context.Background(), gomock.Any()).Return(nil, fmt.Errorf("error")) + + err := s.handler.HandleEvents(startBlock, endBlock) + s.NotNil(err) + + _, err = readFromChannel(s.msgChan) + s.NotNil(err) +} + +func (s *RotateHandlerTestSuite) Test_HandleEvents_SyncCommitteeNotChanged() { + startBlock := big.NewInt(0) + endBlock := big.NewInt(4) + s.mockSyncCommitteeFetcher.EXPECT().SyncCommittee(context.Background(), gomock.Any()).Return(&api.Response[*apiv1.SyncCommittee]{ + Data: &apiv1.SyncCommittee{}, + }, nil) + + err := s.handler.HandleEvents(startBlock, endBlock) + s.Nil(err) + + _, err = readFromChannel(s.msgChan) + s.NotNil(err) +} + +func (s *RotateHandlerTestSuite) Test_HandleEvents_NewSyncCommittee_ProofFails() { + startBlock := big.NewInt(0) + endBlock := big.NewInt(4) + s.mockSyncCommitteeFetcher.EXPECT().SyncCommittee(context.Background(), gomock.Any()).Return(&api.Response[*apiv1.SyncCommittee]{ + Data: &apiv1.SyncCommittee{ + Validators: []phase0.ValidatorIndex{128}, + }, + }, nil) + s.mockProver.EXPECT().StepProof(endBlock).Return([32]byte{}, fmt.Errorf("error")) + + err := s.handler.HandleEvents(startBlock, endBlock) + s.NotNil(err) + _, err = readFromChannel(s.msgChan) + s.NotNil(err) + + s.mockSyncCommitteeFetcher.EXPECT().SyncCommittee(context.Background(), gomock.Any()).Return(&api.Response[*apiv1.SyncCommittee]{ + Data: &apiv1.SyncCommittee{ + Validators: []phase0.ValidatorIndex{128}, + }, + }, nil) + s.mockProver.EXPECT().StepProof(endBlock).Return([32]byte{}, nil) + s.mockProver.EXPECT().RotateProof(endBlock).Return([32]byte{}, fmt.Errorf("error")) + + err = s.handler.HandleEvents(startBlock, endBlock) + s.NotNil(err) + _, err = readFromChannel(s.msgChan) + s.NotNil(err) +} + +func (s *RotateHandlerTestSuite) Test_HandleEvents_NewSyncCommittee() { + startBlock := big.NewInt(0) + endBlock := big.NewInt(4) + s.mockSyncCommitteeFetcher.EXPECT().SyncCommittee(context.Background(), gomock.Any()).Return(&api.Response[*apiv1.SyncCommittee]{ + Data: &apiv1.SyncCommittee{ + Validators: []phase0.ValidatorIndex{128}, + }, + }, nil) + s.mockProver.EXPECT().StepProof(endBlock).Return([32]byte{1}, nil) + s.mockProver.EXPECT().RotateProof(endBlock).Return([32]byte{1}, nil) + + err := s.handler.HandleEvents(startBlock, endBlock) + s.Nil(err) + + msgs, err := readFromChannel(s.msgChan) + s.Nil(err) + s.Equal(msgs[0].Destination, uint8(2)) + + msgs, err = readFromChannel(s.msgChan) + s.Nil(err) + s.Equal(msgs[0].Destination, uint8(3)) +} diff --git a/mock/handlers.go b/mock/deposit.go similarity index 98% rename from mock/handlers.go rename to mock/deposit.go index 98418f3..1ed790b 100644 --- a/mock/handlers.go +++ b/mock/deposit.go @@ -3,7 +3,7 @@ // // Generated by this command: // -// mockgen -source=./chains/evm/listener/events/handlers/deposit.go -destination=./mock/handlers.go -package mock +// mockgen -source=./chains/evm/listener/events/handlers/deposit.go -destination=./mock/deposit.go -package mock // // Package mock is a generated GoMock package. package mock diff --git a/mock/rotate.go b/mock/rotate.go new file mode 100644 index 0000000..d74c0ba --- /dev/null +++ b/mock/rotate.go @@ -0,0 +1,56 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./chains/evm/listener/events/handlers/rotate.go +// +// Generated by this command: +// +// mockgen -source=./chains/evm/listener/events/handlers/rotate.go -destination=./mock/rotate.go -package mock +// +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + reflect "reflect" + + api "github.com/attestantio/go-eth2-client/api" + v1 "github.com/attestantio/go-eth2-client/api/v1" + gomock "go.uber.org/mock/gomock" +) + +// MockSyncCommitteeFetcher is a mock of SyncCommitteeFetcher interface. +type MockSyncCommitteeFetcher struct { + ctrl *gomock.Controller + recorder *MockSyncCommitteeFetcherMockRecorder +} + +// MockSyncCommitteeFetcherMockRecorder is the mock recorder for MockSyncCommitteeFetcher. +type MockSyncCommitteeFetcherMockRecorder struct { + mock *MockSyncCommitteeFetcher +} + +// NewMockSyncCommitteeFetcher creates a new mock instance. +func NewMockSyncCommitteeFetcher(ctrl *gomock.Controller) *MockSyncCommitteeFetcher { + mock := &MockSyncCommitteeFetcher{ctrl: ctrl} + mock.recorder = &MockSyncCommitteeFetcherMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSyncCommitteeFetcher) EXPECT() *MockSyncCommitteeFetcherMockRecorder { + return m.recorder +} + +// SyncCommittee mocks base method. +func (m *MockSyncCommitteeFetcher) SyncCommittee(ctx context.Context, opts *api.SyncCommitteeOpts) (*api.Response[*v1.SyncCommittee], error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SyncCommittee", ctx, opts) + ret0, _ := ret[0].(*api.Response[*v1.SyncCommittee]) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SyncCommittee indicates an expected call of SyncCommittee. +func (mr *MockSyncCommitteeFetcherMockRecorder) SyncCommittee(ctx, opts any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncCommittee", reflect.TypeOf((*MockSyncCommitteeFetcher)(nil).SyncCommittee), ctx, opts) +}