diff --git a/Makefile b/Makefile index d092a0f3..90da419b 100644 --- a/Makefile +++ b/Makefile @@ -83,7 +83,12 @@ stop: ## Stops all services .PHONY: test test: trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -short -race -p 1 -covermode=atomic -coverprofile=../coverage.out -coverpkg ./... -timeout 200s ./... + +.PHONY: test-seq_sender +test-seq_sender: + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -short -race -p 1 -covermode=atomic -coverprofile=../coverage.out -coverpkg ./sequencesender/... -timeout 200s ./sequencesender/... + .PHONY: install-linter install-linter: ## Installs the linter curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.54.2 diff --git a/dataavailability/mocks_da/batch_data_provider.go b/dataavailability/mocks_da/batch_data_provider.go new file mode 100644 index 00000000..36e782ac --- /dev/null +++ b/dataavailability/mocks_da/batch_data_provider.go @@ -0,0 +1,96 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_da + +import ( + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" +) + +// BatchDataProvider is an autogenerated mock type for the BatchDataProvider type +type BatchDataProvider struct { + mock.Mock +} + +type BatchDataProvider_Expecter struct { + mock *mock.Mock +} + +func (_m *BatchDataProvider) EXPECT() *BatchDataProvider_Expecter { + return &BatchDataProvider_Expecter{mock: &_m.Mock} +} + +// GetBatchL2Data provides a mock function with given fields: batchNum, batchHashes, dataAvailabilityMessage +func (_m *BatchDataProvider) GetBatchL2Data(batchNum []uint64, batchHashes []common.Hash, dataAvailabilityMessage []byte) ([][]byte, error) { + ret := _m.Called(batchNum, batchHashes, dataAvailabilityMessage) + + if len(ret) == 0 { + panic("no return value specified for GetBatchL2Data") + } + + var r0 [][]byte + var r1 error + if rf, ok := ret.Get(0).(func([]uint64, []common.Hash, []byte) ([][]byte, error)); ok { + return rf(batchNum, batchHashes, dataAvailabilityMessage) + } + if rf, ok := ret.Get(0).(func([]uint64, []common.Hash, []byte) [][]byte); ok { + r0 = rf(batchNum, batchHashes, dataAvailabilityMessage) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([][]byte) + } + } + + if rf, ok := ret.Get(1).(func([]uint64, []common.Hash, []byte) error); ok { + r1 = rf(batchNum, batchHashes, dataAvailabilityMessage) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BatchDataProvider_GetBatchL2Data_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBatchL2Data' +type BatchDataProvider_GetBatchL2Data_Call struct { + *mock.Call +} + +// GetBatchL2Data is a helper method to define mock.On call +// - batchNum []uint64 +// - batchHashes []common.Hash +// - dataAvailabilityMessage []byte +func (_e *BatchDataProvider_Expecter) GetBatchL2Data(batchNum interface{}, batchHashes interface{}, dataAvailabilityMessage interface{}) *BatchDataProvider_GetBatchL2Data_Call { + return &BatchDataProvider_GetBatchL2Data_Call{Call: _e.mock.On("GetBatchL2Data", batchNum, batchHashes, dataAvailabilityMessage)} +} + +func (_c *BatchDataProvider_GetBatchL2Data_Call) Run(run func(batchNum []uint64, batchHashes []common.Hash, dataAvailabilityMessage []byte)) *BatchDataProvider_GetBatchL2Data_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]uint64), args[1].([]common.Hash), args[2].([]byte)) + }) + return _c +} + +func (_c *BatchDataProvider_GetBatchL2Data_Call) Return(_a0 [][]byte, _a1 error) *BatchDataProvider_GetBatchL2Data_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *BatchDataProvider_GetBatchL2Data_Call) RunAndReturn(run func([]uint64, []common.Hash, []byte) ([][]byte, error)) *BatchDataProvider_GetBatchL2Data_Call { + _c.Call.Return(run) + return _c +} + +// NewBatchDataProvider creates a new instance of BatchDataProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBatchDataProvider(t interface { + mock.TestingT + Cleanup(func()) +}) *BatchDataProvider { + mock := &BatchDataProvider{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/dataavailability/mocks_da/da_backender.go b/dataavailability/mocks_da/da_backender.go new file mode 100644 index 00000000..398356e5 --- /dev/null +++ b/dataavailability/mocks_da/da_backender.go @@ -0,0 +1,263 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_da + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + etherman "github.com/0xPolygon/cdk/etherman" + + mock "github.com/stretchr/testify/mock" +) + +// DABackender is an autogenerated mock type for the DABackender type +type DABackender struct { + mock.Mock +} + +type DABackender_Expecter struct { + mock *mock.Mock +} + +func (_m *DABackender) EXPECT() *DABackender_Expecter { + return &DABackender_Expecter{mock: &_m.Mock} +} + +// GetSequence provides a mock function with given fields: ctx, batchHashes, dataAvailabilityMessage +func (_m *DABackender) GetSequence(ctx context.Context, batchHashes []common.Hash, dataAvailabilityMessage []byte) ([][]byte, error) { + ret := _m.Called(ctx, batchHashes, dataAvailabilityMessage) + + if len(ret) == 0 { + panic("no return value specified for GetSequence") + } + + var r0 [][]byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash, []byte) ([][]byte, error)); ok { + return rf(ctx, batchHashes, dataAvailabilityMessage) + } + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash, []byte) [][]byte); ok { + r0 = rf(ctx, batchHashes, dataAvailabilityMessage) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([][]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []common.Hash, []byte) error); ok { + r1 = rf(ctx, batchHashes, dataAvailabilityMessage) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DABackender_GetSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSequence' +type DABackender_GetSequence_Call struct { + *mock.Call +} + +// GetSequence is a helper method to define mock.On call +// - ctx context.Context +// - batchHashes []common.Hash +// - dataAvailabilityMessage []byte +func (_e *DABackender_Expecter) GetSequence(ctx interface{}, batchHashes interface{}, dataAvailabilityMessage interface{}) *DABackender_GetSequence_Call { + return &DABackender_GetSequence_Call{Call: _e.mock.On("GetSequence", ctx, batchHashes, dataAvailabilityMessage)} +} + +func (_c *DABackender_GetSequence_Call) Run(run func(ctx context.Context, batchHashes []common.Hash, dataAvailabilityMessage []byte)) *DABackender_GetSequence_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]common.Hash), args[2].([]byte)) + }) + return _c +} + +func (_c *DABackender_GetSequence_Call) Return(_a0 [][]byte, _a1 error) *DABackender_GetSequence_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DABackender_GetSequence_Call) RunAndReturn(run func(context.Context, []common.Hash, []byte) ([][]byte, error)) *DABackender_GetSequence_Call { + _c.Call.Return(run) + return _c +} + +// Init provides a mock function with given fields: +func (_m *DABackender) Init() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Init") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DABackender_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init' +type DABackender_Init_Call struct { + *mock.Call +} + +// Init is a helper method to define mock.On call +func (_e *DABackender_Expecter) Init() *DABackender_Init_Call { + return &DABackender_Init_Call{Call: _e.mock.On("Init")} +} + +func (_c *DABackender_Init_Call) Run(run func()) *DABackender_Init_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *DABackender_Init_Call) Return(_a0 error) *DABackender_Init_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DABackender_Init_Call) RunAndReturn(run func() error) *DABackender_Init_Call { + _c.Call.Return(run) + return _c +} + +// PostSequence provides a mock function with given fields: ctx, sequence +func (_m *DABackender) PostSequence(ctx context.Context, sequence etherman.SequenceBanana) ([]byte, error) { + ret := _m.Called(ctx, sequence) + + if len(ret) == 0 { + panic("no return value specified for PostSequence") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, etherman.SequenceBanana) ([]byte, error)); ok { + return rf(ctx, sequence) + } + if rf, ok := ret.Get(0).(func(context.Context, etherman.SequenceBanana) []byte); ok { + r0 = rf(ctx, sequence) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, etherman.SequenceBanana) error); ok { + r1 = rf(ctx, sequence) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DABackender_PostSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PostSequence' +type DABackender_PostSequence_Call struct { + *mock.Call +} + +// PostSequence is a helper method to define mock.On call +// - ctx context.Context +// - sequence etherman.SequenceBanana +func (_e *DABackender_Expecter) PostSequence(ctx interface{}, sequence interface{}) *DABackender_PostSequence_Call { + return &DABackender_PostSequence_Call{Call: _e.mock.On("PostSequence", ctx, sequence)} +} + +func (_c *DABackender_PostSequence_Call) Run(run func(ctx context.Context, sequence etherman.SequenceBanana)) *DABackender_PostSequence_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(etherman.SequenceBanana)) + }) + return _c +} + +func (_c *DABackender_PostSequence_Call) Return(_a0 []byte, _a1 error) *DABackender_PostSequence_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DABackender_PostSequence_Call) RunAndReturn(run func(context.Context, etherman.SequenceBanana) ([]byte, error)) *DABackender_PostSequence_Call { + _c.Call.Return(run) + return _c +} + +// PostSequenceElderberry provides a mock function with given fields: ctx, batchesData +func (_m *DABackender) PostSequenceElderberry(ctx context.Context, batchesData [][]byte) ([]byte, error) { + ret := _m.Called(ctx, batchesData) + + if len(ret) == 0 { + panic("no return value specified for PostSequenceElderberry") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) ([]byte, error)); ok { + return rf(ctx, batchesData) + } + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) []byte); ok { + r0 = rf(ctx, batchesData) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, [][]byte) error); ok { + r1 = rf(ctx, batchesData) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DABackender_PostSequenceElderberry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PostSequenceElderberry' +type DABackender_PostSequenceElderberry_Call struct { + *mock.Call +} + +// PostSequenceElderberry is a helper method to define mock.On call +// - ctx context.Context +// - batchesData [][]byte +func (_e *DABackender_Expecter) PostSequenceElderberry(ctx interface{}, batchesData interface{}) *DABackender_PostSequenceElderberry_Call { + return &DABackender_PostSequenceElderberry_Call{Call: _e.mock.On("PostSequenceElderberry", ctx, batchesData)} +} + +func (_c *DABackender_PostSequenceElderberry_Call) Run(run func(ctx context.Context, batchesData [][]byte)) *DABackender_PostSequenceElderberry_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([][]byte)) + }) + return _c +} + +func (_c *DABackender_PostSequenceElderberry_Call) Return(_a0 []byte, _a1 error) *DABackender_PostSequenceElderberry_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DABackender_PostSequenceElderberry_Call) RunAndReturn(run func(context.Context, [][]byte) ([]byte, error)) *DABackender_PostSequenceElderberry_Call { + _c.Call.Return(run) + return _c +} + +// NewDABackender creates a new instance of DABackender. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDABackender(t interface { + mock.TestingT + Cleanup(func()) +}) *DABackender { + mock := &DABackender{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/dataavailability/mocks_da/data_manager.go b/dataavailability/mocks_da/data_manager.go new file mode 100644 index 00000000..4b4e300f --- /dev/null +++ b/dataavailability/mocks_da/data_manager.go @@ -0,0 +1,218 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_da + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + etherman "github.com/0xPolygon/cdk/etherman" + + mock "github.com/stretchr/testify/mock" +) + +// DataManager is an autogenerated mock type for the DataManager type +type DataManager struct { + mock.Mock +} + +type DataManager_Expecter struct { + mock *mock.Mock +} + +func (_m *DataManager) EXPECT() *DataManager_Expecter { + return &DataManager_Expecter{mock: &_m.Mock} +} + +// GetBatchL2Data provides a mock function with given fields: batchNum, batchHashes, dataAvailabilityMessage +func (_m *DataManager) GetBatchL2Data(batchNum []uint64, batchHashes []common.Hash, dataAvailabilityMessage []byte) ([][]byte, error) { + ret := _m.Called(batchNum, batchHashes, dataAvailabilityMessage) + + if len(ret) == 0 { + panic("no return value specified for GetBatchL2Data") + } + + var r0 [][]byte + var r1 error + if rf, ok := ret.Get(0).(func([]uint64, []common.Hash, []byte) ([][]byte, error)); ok { + return rf(batchNum, batchHashes, dataAvailabilityMessage) + } + if rf, ok := ret.Get(0).(func([]uint64, []common.Hash, []byte) [][]byte); ok { + r0 = rf(batchNum, batchHashes, dataAvailabilityMessage) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([][]byte) + } + } + + if rf, ok := ret.Get(1).(func([]uint64, []common.Hash, []byte) error); ok { + r1 = rf(batchNum, batchHashes, dataAvailabilityMessage) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DataManager_GetBatchL2Data_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBatchL2Data' +type DataManager_GetBatchL2Data_Call struct { + *mock.Call +} + +// GetBatchL2Data is a helper method to define mock.On call +// - batchNum []uint64 +// - batchHashes []common.Hash +// - dataAvailabilityMessage []byte +func (_e *DataManager_Expecter) GetBatchL2Data(batchNum interface{}, batchHashes interface{}, dataAvailabilityMessage interface{}) *DataManager_GetBatchL2Data_Call { + return &DataManager_GetBatchL2Data_Call{Call: _e.mock.On("GetBatchL2Data", batchNum, batchHashes, dataAvailabilityMessage)} +} + +func (_c *DataManager_GetBatchL2Data_Call) Run(run func(batchNum []uint64, batchHashes []common.Hash, dataAvailabilityMessage []byte)) *DataManager_GetBatchL2Data_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]uint64), args[1].([]common.Hash), args[2].([]byte)) + }) + return _c +} + +func (_c *DataManager_GetBatchL2Data_Call) Return(_a0 [][]byte, _a1 error) *DataManager_GetBatchL2Data_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DataManager_GetBatchL2Data_Call) RunAndReturn(run func([]uint64, []common.Hash, []byte) ([][]byte, error)) *DataManager_GetBatchL2Data_Call { + _c.Call.Return(run) + return _c +} + +// PostSequence provides a mock function with given fields: ctx, sequence +func (_m *DataManager) PostSequence(ctx context.Context, sequence etherman.SequenceBanana) ([]byte, error) { + ret := _m.Called(ctx, sequence) + + if len(ret) == 0 { + panic("no return value specified for PostSequence") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, etherman.SequenceBanana) ([]byte, error)); ok { + return rf(ctx, sequence) + } + if rf, ok := ret.Get(0).(func(context.Context, etherman.SequenceBanana) []byte); ok { + r0 = rf(ctx, sequence) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, etherman.SequenceBanana) error); ok { + r1 = rf(ctx, sequence) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DataManager_PostSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PostSequence' +type DataManager_PostSequence_Call struct { + *mock.Call +} + +// PostSequence is a helper method to define mock.On call +// - ctx context.Context +// - sequence etherman.SequenceBanana +func (_e *DataManager_Expecter) PostSequence(ctx interface{}, sequence interface{}) *DataManager_PostSequence_Call { + return &DataManager_PostSequence_Call{Call: _e.mock.On("PostSequence", ctx, sequence)} +} + +func (_c *DataManager_PostSequence_Call) Run(run func(ctx context.Context, sequence etherman.SequenceBanana)) *DataManager_PostSequence_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(etherman.SequenceBanana)) + }) + return _c +} + +func (_c *DataManager_PostSequence_Call) Return(_a0 []byte, _a1 error) *DataManager_PostSequence_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DataManager_PostSequence_Call) RunAndReturn(run func(context.Context, etherman.SequenceBanana) ([]byte, error)) *DataManager_PostSequence_Call { + _c.Call.Return(run) + return _c +} + +// PostSequenceElderberry provides a mock function with given fields: ctx, batchesData +func (_m *DataManager) PostSequenceElderberry(ctx context.Context, batchesData [][]byte) ([]byte, error) { + ret := _m.Called(ctx, batchesData) + + if len(ret) == 0 { + panic("no return value specified for PostSequenceElderberry") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) ([]byte, error)); ok { + return rf(ctx, batchesData) + } + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) []byte); ok { + r0 = rf(ctx, batchesData) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, [][]byte) error); ok { + r1 = rf(ctx, batchesData) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DataManager_PostSequenceElderberry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PostSequenceElderberry' +type DataManager_PostSequenceElderberry_Call struct { + *mock.Call +} + +// PostSequenceElderberry is a helper method to define mock.On call +// - ctx context.Context +// - batchesData [][]byte +func (_e *DataManager_Expecter) PostSequenceElderberry(ctx interface{}, batchesData interface{}) *DataManager_PostSequenceElderberry_Call { + return &DataManager_PostSequenceElderberry_Call{Call: _e.mock.On("PostSequenceElderberry", ctx, batchesData)} +} + +func (_c *DataManager_PostSequenceElderberry_Call) Run(run func(ctx context.Context, batchesData [][]byte)) *DataManager_PostSequenceElderberry_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([][]byte)) + }) + return _c +} + +func (_c *DataManager_PostSequenceElderberry_Call) Return(_a0 []byte, _a1 error) *DataManager_PostSequenceElderberry_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DataManager_PostSequenceElderberry_Call) RunAndReturn(run func(context.Context, [][]byte) ([]byte, error)) *DataManager_PostSequenceElderberry_Call { + _c.Call.Return(run) + return _c +} + +// NewDataManager creates a new instance of DataManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDataManager(t interface { + mock.TestingT + Cleanup(func()) +}) *DataManager { + mock := &DataManager{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/dataavailability/mocks_da/func_sign_type.go b/dataavailability/mocks_da/func_sign_type.go new file mode 100644 index 00000000..3efa4e42 --- /dev/null +++ b/dataavailability/mocks_da/func_sign_type.go @@ -0,0 +1,94 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_da + +import ( + client "github.com/0xPolygon/cdk-data-availability/client" + + mock "github.com/stretchr/testify/mock" +) + +// funcSignType is an autogenerated mock type for the funcSignType type +type funcSignType struct { + mock.Mock +} + +type funcSignType_Expecter struct { + mock *mock.Mock +} + +func (_m *funcSignType) EXPECT() *funcSignType_Expecter { + return &funcSignType_Expecter{mock: &_m.Mock} +} + +// Execute provides a mock function with given fields: c +func (_m *funcSignType) Execute(c client.Client) ([]byte, error) { + ret := _m.Called(c) + + if len(ret) == 0 { + panic("no return value specified for Execute") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(client.Client) ([]byte, error)); ok { + return rf(c) + } + if rf, ok := ret.Get(0).(func(client.Client) []byte); ok { + r0 = rf(c) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(client.Client) error); ok { + r1 = rf(c) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// funcSignType_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute' +type funcSignType_Execute_Call struct { + *mock.Call +} + +// Execute is a helper method to define mock.On call +// - c client.Client +func (_e *funcSignType_Expecter) Execute(c interface{}) *funcSignType_Execute_Call { + return &funcSignType_Execute_Call{Call: _e.mock.On("Execute", c)} +} + +func (_c *funcSignType_Execute_Call) Run(run func(c client.Client)) *funcSignType_Execute_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(client.Client)) + }) + return _c +} + +func (_c *funcSignType_Execute_Call) Return(_a0 []byte, _a1 error) *funcSignType_Execute_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *funcSignType_Execute_Call) RunAndReturn(run func(client.Client) ([]byte, error)) *funcSignType_Execute_Call { + _c.Call.Return(run) + return _c +} + +// newFuncSignType creates a new instance of funcSignType. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newFuncSignType(t interface { + mock.TestingT + Cleanup(func()) +}) *funcSignType { + mock := &funcSignType{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/dataavailability/mocks_da/sequence_retriever.go b/dataavailability/mocks_da/sequence_retriever.go new file mode 100644 index 00000000..f82d9a70 --- /dev/null +++ b/dataavailability/mocks_da/sequence_retriever.go @@ -0,0 +1,98 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_da + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" +) + +// SequenceRetriever is an autogenerated mock type for the SequenceRetriever type +type SequenceRetriever struct { + mock.Mock +} + +type SequenceRetriever_Expecter struct { + mock *mock.Mock +} + +func (_m *SequenceRetriever) EXPECT() *SequenceRetriever_Expecter { + return &SequenceRetriever_Expecter{mock: &_m.Mock} +} + +// GetSequence provides a mock function with given fields: ctx, batchHashes, dataAvailabilityMessage +func (_m *SequenceRetriever) GetSequence(ctx context.Context, batchHashes []common.Hash, dataAvailabilityMessage []byte) ([][]byte, error) { + ret := _m.Called(ctx, batchHashes, dataAvailabilityMessage) + + if len(ret) == 0 { + panic("no return value specified for GetSequence") + } + + var r0 [][]byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash, []byte) ([][]byte, error)); ok { + return rf(ctx, batchHashes, dataAvailabilityMessage) + } + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash, []byte) [][]byte); ok { + r0 = rf(ctx, batchHashes, dataAvailabilityMessage) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([][]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []common.Hash, []byte) error); ok { + r1 = rf(ctx, batchHashes, dataAvailabilityMessage) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SequenceRetriever_GetSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSequence' +type SequenceRetriever_GetSequence_Call struct { + *mock.Call +} + +// GetSequence is a helper method to define mock.On call +// - ctx context.Context +// - batchHashes []common.Hash +// - dataAvailabilityMessage []byte +func (_e *SequenceRetriever_Expecter) GetSequence(ctx interface{}, batchHashes interface{}, dataAvailabilityMessage interface{}) *SequenceRetriever_GetSequence_Call { + return &SequenceRetriever_GetSequence_Call{Call: _e.mock.On("GetSequence", ctx, batchHashes, dataAvailabilityMessage)} +} + +func (_c *SequenceRetriever_GetSequence_Call) Run(run func(ctx context.Context, batchHashes []common.Hash, dataAvailabilityMessage []byte)) *SequenceRetriever_GetSequence_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]common.Hash), args[2].([]byte)) + }) + return _c +} + +func (_c *SequenceRetriever_GetSequence_Call) Return(_a0 [][]byte, _a1 error) *SequenceRetriever_GetSequence_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SequenceRetriever_GetSequence_Call) RunAndReturn(run func(context.Context, []common.Hash, []byte) ([][]byte, error)) *SequenceRetriever_GetSequence_Call { + _c.Call.Return(run) + return _c +} + +// NewSequenceRetriever creates a new instance of SequenceRetriever. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSequenceRetriever(t interface { + mock.TestingT + Cleanup(func()) +}) *SequenceRetriever { + mock := &SequenceRetriever{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/dataavailability/mocks_da/sequence_sender.go b/dataavailability/mocks_da/sequence_sender.go new file mode 100644 index 00000000..fc05dbfe --- /dev/null +++ b/dataavailability/mocks_da/sequence_sender.go @@ -0,0 +1,156 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_da + +import ( + context "context" + + etherman "github.com/0xPolygon/cdk/etherman" + + mock "github.com/stretchr/testify/mock" +) + +// SequenceSender is an autogenerated mock type for the SequenceSender type +type SequenceSender struct { + mock.Mock +} + +type SequenceSender_Expecter struct { + mock *mock.Mock +} + +func (_m *SequenceSender) EXPECT() *SequenceSender_Expecter { + return &SequenceSender_Expecter{mock: &_m.Mock} +} + +// PostSequence provides a mock function with given fields: ctx, sequence +func (_m *SequenceSender) PostSequence(ctx context.Context, sequence etherman.SequenceBanana) ([]byte, error) { + ret := _m.Called(ctx, sequence) + + if len(ret) == 0 { + panic("no return value specified for PostSequence") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, etherman.SequenceBanana) ([]byte, error)); ok { + return rf(ctx, sequence) + } + if rf, ok := ret.Get(0).(func(context.Context, etherman.SequenceBanana) []byte); ok { + r0 = rf(ctx, sequence) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, etherman.SequenceBanana) error); ok { + r1 = rf(ctx, sequence) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SequenceSender_PostSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PostSequence' +type SequenceSender_PostSequence_Call struct { + *mock.Call +} + +// PostSequence is a helper method to define mock.On call +// - ctx context.Context +// - sequence etherman.SequenceBanana +func (_e *SequenceSender_Expecter) PostSequence(ctx interface{}, sequence interface{}) *SequenceSender_PostSequence_Call { + return &SequenceSender_PostSequence_Call{Call: _e.mock.On("PostSequence", ctx, sequence)} +} + +func (_c *SequenceSender_PostSequence_Call) Run(run func(ctx context.Context, sequence etherman.SequenceBanana)) *SequenceSender_PostSequence_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(etherman.SequenceBanana)) + }) + return _c +} + +func (_c *SequenceSender_PostSequence_Call) Return(_a0 []byte, _a1 error) *SequenceSender_PostSequence_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SequenceSender_PostSequence_Call) RunAndReturn(run func(context.Context, etherman.SequenceBanana) ([]byte, error)) *SequenceSender_PostSequence_Call { + _c.Call.Return(run) + return _c +} + +// PostSequenceElderberry provides a mock function with given fields: ctx, batchesData +func (_m *SequenceSender) PostSequenceElderberry(ctx context.Context, batchesData [][]byte) ([]byte, error) { + ret := _m.Called(ctx, batchesData) + + if len(ret) == 0 { + panic("no return value specified for PostSequenceElderberry") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) ([]byte, error)); ok { + return rf(ctx, batchesData) + } + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) []byte); ok { + r0 = rf(ctx, batchesData) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, [][]byte) error); ok { + r1 = rf(ctx, batchesData) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SequenceSender_PostSequenceElderberry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PostSequenceElderberry' +type SequenceSender_PostSequenceElderberry_Call struct { + *mock.Call +} + +// PostSequenceElderberry is a helper method to define mock.On call +// - ctx context.Context +// - batchesData [][]byte +func (_e *SequenceSender_Expecter) PostSequenceElderberry(ctx interface{}, batchesData interface{}) *SequenceSender_PostSequenceElderberry_Call { + return &SequenceSender_PostSequenceElderberry_Call{Call: _e.mock.On("PostSequenceElderberry", ctx, batchesData)} +} + +func (_c *SequenceSender_PostSequenceElderberry_Call) Run(run func(ctx context.Context, batchesData [][]byte)) *SequenceSender_PostSequenceElderberry_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([][]byte)) + }) + return _c +} + +func (_c *SequenceSender_PostSequenceElderberry_Call) Return(_a0 []byte, _a1 error) *SequenceSender_PostSequenceElderberry_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SequenceSender_PostSequenceElderberry_Call) RunAndReturn(run func(context.Context, [][]byte) ([]byte, error)) *SequenceSender_PostSequenceElderberry_Call { + _c.Call.Return(run) + return _c +} + +// NewSequenceSender creates a new instance of SequenceSender. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSequenceSender(t interface { + mock.TestingT + Cleanup(func()) +}) *SequenceSender { + mock := &SequenceSender{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/dataavailability/mocks_da/sequence_sender_elderberry.go b/dataavailability/mocks_da/sequence_sender_elderberry.go new file mode 100644 index 00000000..3816fa1b --- /dev/null +++ b/dataavailability/mocks_da/sequence_sender_elderberry.go @@ -0,0 +1,95 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_da + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// SequenceSenderElderberry is an autogenerated mock type for the SequenceSenderElderberry type +type SequenceSenderElderberry struct { + mock.Mock +} + +type SequenceSenderElderberry_Expecter struct { + mock *mock.Mock +} + +func (_m *SequenceSenderElderberry) EXPECT() *SequenceSenderElderberry_Expecter { + return &SequenceSenderElderberry_Expecter{mock: &_m.Mock} +} + +// PostSequenceElderberry provides a mock function with given fields: ctx, batchesData +func (_m *SequenceSenderElderberry) PostSequenceElderberry(ctx context.Context, batchesData [][]byte) ([]byte, error) { + ret := _m.Called(ctx, batchesData) + + if len(ret) == 0 { + panic("no return value specified for PostSequenceElderberry") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) ([]byte, error)); ok { + return rf(ctx, batchesData) + } + if rf, ok := ret.Get(0).(func(context.Context, [][]byte) []byte); ok { + r0 = rf(ctx, batchesData) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, [][]byte) error); ok { + r1 = rf(ctx, batchesData) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SequenceSenderElderberry_PostSequenceElderberry_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PostSequenceElderberry' +type SequenceSenderElderberry_PostSequenceElderberry_Call struct { + *mock.Call +} + +// PostSequenceElderberry is a helper method to define mock.On call +// - ctx context.Context +// - batchesData [][]byte +func (_e *SequenceSenderElderberry_Expecter) PostSequenceElderberry(ctx interface{}, batchesData interface{}) *SequenceSenderElderberry_PostSequenceElderberry_Call { + return &SequenceSenderElderberry_PostSequenceElderberry_Call{Call: _e.mock.On("PostSequenceElderberry", ctx, batchesData)} +} + +func (_c *SequenceSenderElderberry_PostSequenceElderberry_Call) Run(run func(ctx context.Context, batchesData [][]byte)) *SequenceSenderElderberry_PostSequenceElderberry_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([][]byte)) + }) + return _c +} + +func (_c *SequenceSenderElderberry_PostSequenceElderberry_Call) Return(_a0 []byte, _a1 error) *SequenceSenderElderberry_PostSequenceElderberry_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SequenceSenderElderberry_PostSequenceElderberry_Call) RunAndReturn(run func(context.Context, [][]byte) ([]byte, error)) *SequenceSenderElderberry_PostSequenceElderberry_Call { + _c.Call.Return(run) + return _c +} + +// NewSequenceSenderElderberry creates a new instance of SequenceSenderElderberry. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSequenceSenderElderberry(t interface { + mock.TestingT + Cleanup(func()) +}) *SequenceSenderElderberry { + mock := &SequenceSenderElderberry{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/localbridgesync/mock_downloader_test.go b/localbridgesync/mock_downloader_test.go index f2df97d0..b3f2ad08 100644 --- a/localbridgesync/mock_downloader_test.go +++ b/localbridgesync/mock_downloader_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package localbridgesync @@ -28,6 +28,10 @@ func (_m *DownloaderMock) download(ctx context.Context, fromBlock uint64, downlo func (_m *DownloaderMock) getBlockHeader(ctx context.Context, blockNum uint64) blockHeader { ret := _m.Called(ctx, blockNum) + if len(ret) == 0 { + panic("no return value specified for getBlockHeader") + } + var r0 blockHeader if rf, ok := ret.Get(0).(func(context.Context, uint64) blockHeader); ok { r0 = rf(ctx, blockNum) @@ -42,6 +46,10 @@ func (_m *DownloaderMock) getBlockHeader(ctx context.Context, blockNum uint64) b func (_m *DownloaderMock) getEventsByBlockRange(ctx context.Context, fromBlock uint64, toBlock uint64) []block { ret := _m.Called(ctx, fromBlock, toBlock) + if len(ret) == 0 { + panic("no return value specified for getEventsByBlockRange") + } + var r0 []block if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64) []block); ok { r0 = rf(ctx, fromBlock, toBlock) @@ -58,6 +66,10 @@ func (_m *DownloaderMock) getEventsByBlockRange(ctx context.Context, fromBlock u func (_m *DownloaderMock) getLogs(ctx context.Context, fromBlock uint64, toBlock uint64) []types.Log { ret := _m.Called(ctx, fromBlock, toBlock) + if len(ret) == 0 { + panic("no return value specified for getLogs") + } + var r0 []types.Log if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64) []types.Log); ok { r0 = rf(ctx, fromBlock, toBlock) @@ -74,6 +86,10 @@ func (_m *DownloaderMock) getLogs(ctx context.Context, fromBlock uint64, toBlock func (_m *DownloaderMock) waitForNewBlocks(ctx context.Context, lastBlockSeen uint64) uint64 { ret := _m.Called(ctx, lastBlockSeen) + if len(ret) == 0 { + panic("no return value specified for waitForNewBlocks") + } + var r0 uint64 if rf, ok := ret.Get(0).(func(context.Context, uint64) uint64); ok { r0 = rf(ctx, lastBlockSeen) @@ -84,13 +100,12 @@ func (_m *DownloaderMock) waitForNewBlocks(ctx context.Context, lastBlockSeen ui return r0 } -type mockConstructorTestingTNewDownloaderMock interface { +// NewDownloaderMock creates a new instance of DownloaderMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDownloaderMock(t interface { mock.TestingT Cleanup(func()) -} - -// NewDownloaderMock creates a new instance of DownloaderMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewDownloaderMock(t mockConstructorTestingTNewDownloaderMock) *DownloaderMock { +}) *DownloaderMock { mock := &DownloaderMock{} mock.Mock.Test(t) diff --git a/localbridgesync/mock_l2_test.go b/localbridgesync/mock_l2_test.go index 78baa614..22432fd1 100644 --- a/localbridgesync/mock_l2_test.go +++ b/localbridgesync/mock_l2_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package localbridgesync @@ -24,6 +24,10 @@ type L2Mock struct { func (_m *L2Mock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { ret := _m.Called(ctx, hash) + if len(ret) == 0 { + panic("no return value specified for BlockByHash") + } + var r0 *types.Block var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Block, error)); ok { @@ -50,6 +54,10 @@ func (_m *L2Mock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo func (_m *L2Mock) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { ret := _m.Called(ctx, number) + if len(ret) == 0 { + panic("no return value specified for BlockByNumber") + } + var r0 *types.Block var r1 error if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Block, error)); ok { @@ -76,6 +84,10 @@ func (_m *L2Mock) BlockByNumber(ctx context.Context, number *big.Int) (*types.Bl func (_m *L2Mock) BlockNumber(ctx context.Context) (uint64, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for BlockNumber") + } + var r0 uint64 var r1 error if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { @@ -100,6 +112,10 @@ func (_m *L2Mock) BlockNumber(ctx context.Context) (uint64, error) { func (_m *L2Mock) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { ret := _m.Called(ctx, call, blockNumber) + if len(ret) == 0 { + panic("no return value specified for CallContract") + } + var r0 []byte var r1 error if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error)); ok { @@ -126,6 +142,10 @@ func (_m *L2Mock) CallContract(ctx context.Context, call ethereum.CallMsg, block func (_m *L2Mock) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { ret := _m.Called(ctx, contract, blockNumber) + if len(ret) == 0 { + panic("no return value specified for CodeAt") + } + var r0 []byte var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) ([]byte, error)); ok { @@ -152,6 +172,10 @@ func (_m *L2Mock) CodeAt(ctx context.Context, contract common.Address, blockNumb func (_m *L2Mock) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { ret := _m.Called(ctx, call) + if len(ret) == 0 { + panic("no return value specified for EstimateGas") + } + var r0 uint64 var r1 error if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg) (uint64, error)); ok { @@ -176,6 +200,10 @@ func (_m *L2Mock) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint6 func (_m *L2Mock) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { ret := _m.Called(ctx, q) + if len(ret) == 0 { + panic("no return value specified for FilterLogs") + } + var r0 []types.Log var r1 error if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery) ([]types.Log, error)); ok { @@ -202,6 +230,10 @@ func (_m *L2Mock) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]typ func (_m *L2Mock) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { ret := _m.Called(ctx, hash) + if len(ret) == 0 { + panic("no return value specified for HeaderByHash") + } + var r0 *types.Header var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Header, error)); ok { @@ -228,6 +260,10 @@ func (_m *L2Mock) HeaderByHash(ctx context.Context, hash common.Hash) (*types.He func (_m *L2Mock) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { ret := _m.Called(ctx, number) + if len(ret) == 0 { + panic("no return value specified for HeaderByNumber") + } + var r0 *types.Header var r1 error if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Header, error)); ok { @@ -254,6 +290,10 @@ func (_m *L2Mock) HeaderByNumber(ctx context.Context, number *big.Int) (*types.H func (_m *L2Mock) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { ret := _m.Called(ctx, account) + if len(ret) == 0 { + panic("no return value specified for PendingCodeAt") + } + var r0 []byte var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Address) ([]byte, error)); ok { @@ -280,6 +320,10 @@ func (_m *L2Mock) PendingCodeAt(ctx context.Context, account common.Address) ([] func (_m *L2Mock) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { ret := _m.Called(ctx, account) + if len(ret) == 0 { + panic("no return value specified for PendingNonceAt") + } + var r0 uint64 var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Address) (uint64, error)); ok { @@ -304,6 +348,10 @@ func (_m *L2Mock) PendingNonceAt(ctx context.Context, account common.Address) (u func (_m *L2Mock) SendTransaction(ctx context.Context, tx *types.Transaction) error { ret := _m.Called(ctx, tx) + if len(ret) == 0 { + panic("no return value specified for SendTransaction") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction) error); ok { r0 = rf(ctx, tx) @@ -318,6 +366,10 @@ func (_m *L2Mock) SendTransaction(ctx context.Context, tx *types.Transaction) er func (_m *L2Mock) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { ret := _m.Called(ctx, q, ch) + if len(ret) == 0 { + panic("no return value specified for SubscribeFilterLogs") + } + var r0 ethereum.Subscription var r1 error if rf, ok := ret.Get(0).(func(context.Context, ethereum.FilterQuery, chan<- types.Log) (ethereum.Subscription, error)); ok { @@ -344,6 +396,10 @@ func (_m *L2Mock) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuer func (_m *L2Mock) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { ret := _m.Called(ctx, ch) + if len(ret) == 0 { + panic("no return value specified for SubscribeNewHead") + } + var r0 ethereum.Subscription var r1 error if rf, ok := ret.Get(0).(func(context.Context, chan<- *types.Header) (ethereum.Subscription, error)); ok { @@ -370,6 +426,10 @@ func (_m *L2Mock) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) func (_m *L2Mock) SuggestGasPrice(ctx context.Context) (*big.Int, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for SuggestGasPrice") + } + var r0 *big.Int var r1 error if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { @@ -396,6 +456,10 @@ func (_m *L2Mock) SuggestGasPrice(ctx context.Context) (*big.Int, error) { func (_m *L2Mock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for SuggestGasTipCap") + } + var r0 *big.Int var r1 error if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { @@ -422,6 +486,10 @@ func (_m *L2Mock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { func (_m *L2Mock) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { ret := _m.Called(ctx, blockHash) + if len(ret) == 0 { + panic("no return value specified for TransactionCount") + } + var r0 uint var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (uint, error)); ok { @@ -446,6 +514,10 @@ func (_m *L2Mock) TransactionCount(ctx context.Context, blockHash common.Hash) ( func (_m *L2Mock) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { ret := _m.Called(ctx, blockHash, index) + if len(ret) == 0 { + panic("no return value specified for TransactionInBlock") + } + var r0 *types.Transaction var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Hash, uint) (*types.Transaction, error)); ok { @@ -468,13 +540,12 @@ func (_m *L2Mock) TransactionInBlock(ctx context.Context, blockHash common.Hash, return r0, r1 } -type mockConstructorTestingTNewL2Mock interface { +// NewL2Mock creates a new instance of L2Mock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewL2Mock(t interface { mock.TestingT Cleanup(func()) -} - -// NewL2Mock creates a new instance of L2Mock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewL2Mock(t mockConstructorTestingTNewL2Mock) *L2Mock { +}) *L2Mock { mock := &L2Mock{} mock.Mock.Test(t) diff --git a/localbridgesync/mock_processor_test.go b/localbridgesync/mock_processor_test.go index 4a629f5c..431c6201 100644 --- a/localbridgesync/mock_processor_test.go +++ b/localbridgesync/mock_processor_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package localbridgesync @@ -17,6 +17,10 @@ type ProcessorMock struct { func (_m *ProcessorMock) getLastProcessedBlock(ctx context.Context) (uint64, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for getLastProcessedBlock") + } + var r0 uint64 var r1 error if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { @@ -41,6 +45,10 @@ func (_m *ProcessorMock) getLastProcessedBlock(ctx context.Context) (uint64, err func (_m *ProcessorMock) reorg(firstReorgedBlock uint64) error { ret := _m.Called(firstReorgedBlock) + if len(ret) == 0 { + panic("no return value specified for reorg") + } + var r0 error if rf, ok := ret.Get(0).(func(uint64) error); ok { r0 = rf(firstReorgedBlock) @@ -55,6 +63,10 @@ func (_m *ProcessorMock) reorg(firstReorgedBlock uint64) error { func (_m *ProcessorMock) storeBridgeEvents(blockNum uint64, events []BridgeEvent) error { ret := _m.Called(blockNum, events) + if len(ret) == 0 { + panic("no return value specified for storeBridgeEvents") + } + var r0 error if rf, ok := ret.Get(0).(func(uint64, []BridgeEvent) error); ok { r0 = rf(blockNum, events) @@ -65,13 +77,12 @@ func (_m *ProcessorMock) storeBridgeEvents(blockNum uint64, events []BridgeEvent return r0 } -type mockConstructorTestingTNewProcessorMock interface { +// NewProcessorMock creates a new instance of ProcessorMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewProcessorMock(t interface { mock.TestingT Cleanup(func()) -} - -// NewProcessorMock creates a new instance of ProcessorMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewProcessorMock(t mockConstructorTestingTNewProcessorMock) *ProcessorMock { +}) *ProcessorMock { mock := &ProcessorMock{} mock.Mock.Test(t) diff --git a/localbridgesync/mock_reorgdetector_test.go b/localbridgesync/mock_reorgdetector_test.go index d11434a1..9d076315 100644 --- a/localbridgesync/mock_reorgdetector_test.go +++ b/localbridgesync/mock_reorgdetector_test.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package localbridgesync @@ -21,6 +21,10 @@ type ReorgDetectorMock struct { func (_m *ReorgDetectorMock) AddBlockToTrack(ctx context.Context, id string, blockNum uint64, blockHash common.Hash) error { ret := _m.Called(ctx, id, blockNum, blockHash) + if len(ret) == 0 { + panic("no return value specified for AddBlockToTrack") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string, uint64, common.Hash) error); ok { r0 = rf(ctx, id, blockNum, blockHash) @@ -35,6 +39,10 @@ func (_m *ReorgDetectorMock) AddBlockToTrack(ctx context.Context, id string, blo func (_m *ReorgDetectorMock) Subscribe(id string) *reorgdetector.Subscription { ret := _m.Called(id) + if len(ret) == 0 { + panic("no return value specified for Subscribe") + } + var r0 *reorgdetector.Subscription if rf, ok := ret.Get(0).(func(string) *reorgdetector.Subscription); ok { r0 = rf(id) @@ -47,13 +55,12 @@ func (_m *ReorgDetectorMock) Subscribe(id string) *reorgdetector.Subscription { return r0 } -type mockConstructorTestingTNewReorgDetectorMock interface { +// NewReorgDetectorMock creates a new instance of ReorgDetectorMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewReorgDetectorMock(t interface { mock.TestingT Cleanup(func()) -} - -// NewReorgDetectorMock creates a new instance of ReorgDetectorMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewReorgDetectorMock(t mockConstructorTestingTNewReorgDetectorMock) *ReorgDetectorMock { +}) *ReorgDetectorMock { mock := &ReorgDetectorMock{} mock.Mock.Test(t) diff --git a/reorgdetector/mock_eth_client.go b/reorgdetector/mock_eth_client.go index add883f6..e0eef607 100644 --- a/reorgdetector/mock_eth_client.go +++ b/reorgdetector/mock_eth_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.39.0. DO NOT EDIT. package reorgdetector diff --git a/sequencesender/txbuilder/banana_validium.go b/sequencesender/txbuilder/banana_validium.go index d926143a..e518d107 100644 --- a/sequencesender/txbuilder/banana_validium.go +++ b/sequencesender/txbuilder/banana_validium.go @@ -28,14 +28,14 @@ func NewTxBuilderBananaValidium(rollupContract contracts.RollupBananaType, return &TxBuilderBananaValidium{ TxBuilderBananaBase: *NewTxBuilderBananaBase(rollupContract, gerContract, opts, sender), da: da, - condNewSeq: &NewSequenceConditionalNumBatches{ + condNewSeq: &ConditionalNewSequenceNumBatches{ maxBatchesForL1: maxBatchesForL1, }, } } func (t *TxBuilderBananaValidium) NewSequenceIfWorthToSend(ctx context.Context, sequenceBatches []seqsendertypes.Batch, l2Coinbase common.Address, batchNumber uint64) (seqsendertypes.Sequence, error) { - return t.condNewSeq.NewSequenceIfWorthToSend(ctx, t, sequenceBatches, t.SenderAddress, l2Coinbase, batchNumber) + return t.condNewSeq.NewSequenceIfWorthToSend(ctx, t, sequenceBatches, t.SenderAddress, l2Coinbase) } func (t *TxBuilderBananaValidium) BuildSequenceBatchesTx(ctx context.Context, sender common.Address, sequences seqsendertypes.Sequence) (*ethtypes.Transaction, error) { diff --git a/sequencesender/txbuilder/banana_zkevm.go b/sequencesender/txbuilder/banana_zkevm.go index dbb679fb..e2a2e1aa 100644 --- a/sequencesender/txbuilder/banana_zkevm.go +++ b/sequencesender/txbuilder/banana_zkevm.go @@ -22,14 +22,14 @@ type TxBuilderBananaZKEVM struct { func NewTxBuilderBananaZKEVM(rollupContract contracts.RollupBananaType, gerContract contracts.GlobalExitRootBananaType, opts bind.TransactOpts, sender common.Address, maxTxSizeForL1 uint64) *TxBuilderBananaZKEVM { return &TxBuilderBananaZKEVM{ TxBuilderBananaBase: *NewTxBuilderBananaBase(rollupContract, gerContract, opts, sender), - condNewSeq: &NewSequenceConditionalMaxSize{ + condNewSeq: &ConditionalNewSequenceMaxSize{ maxTxSizeForL1: maxTxSizeForL1, }, } } func (t *TxBuilderBananaZKEVM) NewSequenceIfWorthToSend(ctx context.Context, sequenceBatches []seqsendertypes.Batch, l2Coinbase common.Address, batchNumber uint64) (seqsendertypes.Sequence, error) { - return t.condNewSeq.NewSequenceIfWorthToSend(ctx, t, sequenceBatches, t.SenderAddress, l2Coinbase, batchNumber) + return t.condNewSeq.NewSequenceIfWorthToSend(ctx, t, sequenceBatches, t.SenderAddress, l2Coinbase) } func (t *TxBuilderBananaZKEVM) BuildSequenceBatchesTx(ctx context.Context, sender common.Address, sequences seqsendertypes.Sequence) (*ethtypes.Transaction, error) { diff --git a/sequencesender/txbuilder/elderberry_base.go b/sequencesender/txbuilder/elderberry_base.go index f643a96c..8343eecf 100644 --- a/sequencesender/txbuilder/elderberry_base.go +++ b/sequencesender/txbuilder/elderberry_base.go @@ -21,6 +21,11 @@ func NewTxBuilderElderberryBase(rollupContract contracts.RollupElderberryType, o } } +// SetAuth sets the auth for the tx builder +func (t *TxBuilderElderberryBase) SetAuth(auth *bind.TransactOpts) { + t.opts = *auth +} + func (t *TxBuilderElderberryBase) NewSequence(batches []seqsendertypes.Batch, coinbase common.Address) (seqsendertypes.Sequence, error) { seq := ElderberrySequence{ l2Coinbase: coinbase, @@ -44,5 +49,8 @@ func getLastSequencedBatchNumber(sequences seqsendertypes.Sequence) uint64 { if sequences.Len() == 0 { return 0 } + if sequences.FirstBatch().BatchNumber() == 0 { + panic("First batch number is 0, that is not allowed!") + } return sequences.FirstBatch().BatchNumber() - 1 } diff --git a/sequencesender/txbuilder/elderberry_base_test.go b/sequencesender/txbuilder/elderberry_base_test.go new file mode 100644 index 00000000..619ce1da --- /dev/null +++ b/sequencesender/txbuilder/elderberry_base_test.go @@ -0,0 +1,101 @@ +package txbuilder + +import ( + "testing" + + "github.com/0xPolygon/cdk/etherman/contracts" + "github.com/0xPolygon/cdk/sequencesender/seqsendertypes" + "github.com/0xPolygon/cdk/state/datastream" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestElderberryBaseNewSequence(t *testing.T) { + zkevmContract := contracts.RollupElderberryType{} + opts := bind.TransactOpts{} + sut := NewTxBuilderElderberryBase(zkevmContract, opts) + require.NotNil(t, sut) + seq, err := sut.NewSequence(nil, common.Address{}) + require.NotNil(t, seq) + require.NoError(t, err) +} + +func TestElderberryBaseNewBatchFromL2Block(t *testing.T) { + sut := newElderberryBaseSUT(t) + l2Block := &datastream.L2Block{ + Timestamp: 1, + BatchNumber: 2, + L1InfotreeIndex: 3, + Coinbase: []byte{1, 2, 3}, + GlobalExitRoot: []byte{4, 5, 6}, + } + batch := sut.NewBatchFromL2Block(l2Block) + require.NotNil(t, batch) + require.Equal(t, l2Block.Timestamp, batch.LastL2BLockTimestamp()) + require.Equal(t, l2Block.BatchNumber, batch.BatchNumber()) + require.Equal(t, l2Block.L1InfotreeIndex, batch.L1InfoTreeIndex()) + require.Equal(t, common.BytesToAddress(l2Block.Coinbase), batch.LastCoinbase()) + require.Equal(t, common.BytesToHash(l2Block.GlobalExitRoot), batch.GlobalExitRoot()) + +} + +func TestElderberryBasegetLastSequencedBatchNumberEmpty(t *testing.T) { + sut := newElderberryBaseSUT(t) + seq, err := sut.NewSequence(nil, common.Address{}) + require.NoError(t, err) + + require.Equal(t, uint64(0), getLastSequencedBatchNumber(seq)) +} + +func TestElderberryBasegetLastSequencedBatch1Batch(t *testing.T) { + sut := newElderberryBaseSUT(t) + l2Block := &datastream.L2Block{ + Timestamp: 1, + BatchNumber: 2, + L1InfotreeIndex: 3, + Coinbase: []byte{1, 2, 3}, + GlobalExitRoot: []byte{4, 5, 6}, + } + batchElder := sut.NewBatchFromL2Block(l2Block) + batches := []seqsendertypes.Batch{ + batchElder, + } + + seq, err := sut.NewSequence(batches, common.Address{}) + require.NoError(t, err) + + require.Equal(t, l2Block.BatchNumber-1, getLastSequencedBatchNumber(seq)) +} + +func TestElderberryBaseGetLastSequencedBatchFirstBatchIsZeroThrowAPanic(t *testing.T) { + sut := newElderberryBaseSUT(t) + l2Block := &datastream.L2Block{ + Timestamp: 1, + BatchNumber: 0, + L1InfotreeIndex: 3, + Coinbase: []byte{1, 2, 3}, + GlobalExitRoot: []byte{4, 5, 6}, + } + batchElder := sut.NewBatchFromL2Block(l2Block) + batches := []seqsendertypes.Batch{ + batchElder, + } + + seq, err := sut.NewSequence(batches, common.Address{}) + require.NoError(t, err) + defer func() { + if r := recover(); r == nil { + t.Errorf("The code did not panic") + } + }() + getLastSequencedBatchNumber(seq) +} + +func newElderberryBaseSUT(t *testing.T) *TxBuilderElderberryBase { + zkevmContract := contracts.RollupElderberryType{} + opts := bind.TransactOpts{} + sut := NewTxBuilderElderberryBase(zkevmContract, opts) + require.NotNil(t, sut) + return sut +} diff --git a/sequencesender/txbuilder/elderberry_types.go b/sequencesender/txbuilder/elderberry_types.go index fc57bc18..bbc7d56a 100644 --- a/sequencesender/txbuilder/elderberry_types.go +++ b/sequencesender/txbuilder/elderberry_types.go @@ -13,6 +13,13 @@ type ElderberrySequence struct { batches []seqsendertypes.Batch } +func NewElderberrySequence(batches []seqsendertypes.Batch, l2Coinbase common.Address) *ElderberrySequence { + return &ElderberrySequence{ + l2Coinbase: l2Coinbase, + batches: batches, + } +} + func (b *ElderberrySequence) IndexL1InfoRoot() uint32 { log.Fatal("Elderberry Sequence does not have IndexL1InfoRoot") return 0 diff --git a/sequencesender/txbuilder/elderberry_validium.go b/sequencesender/txbuilder/elderberry_validium.go index a0369191..2a223878 100644 --- a/sequencesender/txbuilder/elderberry_validium.go +++ b/sequencesender/txbuilder/elderberry_validium.go @@ -3,6 +3,7 @@ package txbuilder import ( "context" "encoding/hex" + "fmt" "math/big" "github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog" @@ -32,23 +33,26 @@ func NewTxBuilderElderberryValidium(zkevm contracts.RollupElderberryType, TxBuilderElderberryBase: *NewTxBuilderElderberryBase( zkevm, opts, ), - condNewSeq: &NewSequenceConditionalNumBatches{ - maxBatchesForL1: maxBatchesForL1, - }, + condNewSeq: NewConditionalNewSequenceNumBatches(maxBatchesForL1), } } func (t *TxBuilderElderberryValidium) NewSequenceIfWorthToSend(ctx context.Context, sequenceBatches []seqsendertypes.Batch, l2Coinbase common.Address, batchNumber uint64) (seqsendertypes.Sequence, error) { - return t.condNewSeq.NewSequenceIfWorthToSend(ctx, t, sequenceBatches, t.opts.From, l2Coinbase, batchNumber) + return t.condNewSeq.NewSequenceIfWorthToSend(ctx, t, sequenceBatches, t.opts.From, l2Coinbase) } func (t *TxBuilderElderberryValidium) BuildSequenceBatchesTx(ctx context.Context, sender common.Address, sequences seqsendertypes.Sequence) (*ethtypes.Transaction, error) { - + if sequences == nil || sequences.Len() == 0 { + return nil, fmt.Errorf("can't sequence an empty sequence") + } batchesData := convertToBatchesData(sequences) dataAvailabilityMessage, err := t.da.PostSequenceElderberry(ctx, batchesData) if err != nil { log.Error("error posting sequences to the data availability protocol: ", err) return nil, err } + if dataAvailabilityMessage == nil { + return nil, fmt.Errorf("data availability message is nil") + } newopts := t.opts newopts.NoSend = true diff --git a/sequencesender/txbuilder/elderberry_validium_test.go b/sequencesender/txbuilder/elderberry_validium_test.go new file mode 100644 index 00000000..68f5e303 --- /dev/null +++ b/sequencesender/txbuilder/elderberry_validium_test.go @@ -0,0 +1,109 @@ +package txbuilder_test + +import ( + "context" + "fmt" + "math/big" + "strings" + "testing" + + "github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog" + "github.com/0xPolygon/cdk/dataavailability/mocks_da" + "github.com/0xPolygon/cdk/etherman/contracts" + "github.com/0xPolygon/cdk/sequencesender/seqsendertypes" + "github.com/0xPolygon/cdk/sequencesender/txbuilder" + "github.com/0xPolygon/cdk/state/datastream" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestElderberryValidiumName(t *testing.T) { + testData := newElderberryValidiumSUT(t) + require.NotNil(t, testData.sut) + require.True(t, strings.Contains(testData.sut.String(), "Elderberry")) + require.True(t, strings.Contains(testData.sut.String(), "Validium")) +} + +func TestElderberryValidiumBuildSequenceBatchesTxEmtpySequence(t *testing.T) { + testData := newElderberryValidiumSUT(t) + ctx := context.TODO() + _, err := testData.sut.BuildSequenceBatchesTx(ctx, common.Address{}, nil) + require.Error(t, err) + + seq, err := testData.sut.NewSequence(nil, common.Address{}) + require.NoError(t, err) + _, err = testData.sut.BuildSequenceBatchesTx(ctx, common.Address{}, seq) + require.Error(t, err) +} + +func TestElderberryValidiumBuildSequenceBatchesTxSequenceErrorsFromDA(t *testing.T) { + testData := newElderberryValidiumSUT(t) + ctx := context.TODO() + l2Block := &datastream.L2Block{ + Timestamp: 1, + BatchNumber: 1, + L1InfotreeIndex: 3, + Coinbase: []byte{1, 2, 3}, + GlobalExitRoot: []byte{4, 5, 6}, + } + batchElder := testData.sut.NewBatchFromL2Block(l2Block) + batches := []seqsendertypes.Batch{ + batchElder, + } + seq, err := testData.sut.NewSequence(batches, common.Address{}) + require.NoError(t, err) + testData.mockDA.EXPECT().PostSequenceElderberry(ctx, mock.Anything).Return(nil, nil) + _, err = testData.sut.BuildSequenceBatchesTx(ctx, common.Address{}, seq) + require.Error(t, err, "data availability message is nil") + testData.mockDA.EXPECT().PostSequenceElderberry(ctx, mock.Anything).Return(nil, fmt.Errorf("test error")) + _, err = testData.sut.BuildSequenceBatchesTx(ctx, common.Address{}, seq) + require.Error(t, err, "error posting sequences to the data availability protocol: test error") +} + +func TestElderberryValidiumBuildSequenceBatchesTxSequenceDAOk(t *testing.T) { + testData := newElderberryValidiumSUT(t) + ctx := context.TODO() + l2Block := &datastream.L2Block{ + Timestamp: 1, + BatchNumber: 1, + L1InfotreeIndex: 3, + Coinbase: []byte{1, 2, 3}, + GlobalExitRoot: []byte{4, 5, 6}, + } + batchElder := testData.sut.NewBatchFromL2Block(l2Block) + batches := []seqsendertypes.Batch{ + batchElder, + } + seq, err := testData.sut.NewSequence(batches, common.Address{}) + require.NoError(t, err) + testData.mockDA.EXPECT().PostSequenceElderberry(ctx, mock.Anything).Return([]byte{1}, nil) + tx, err := testData.sut.BuildSequenceBatchesTx(ctx, common.Address{}, seq) + require.NoError(t, err) + require.NotNil(t, tx) +} + +type testDataElderberryValidium struct { + mockDA *mocks_da.SequenceSenderElderberry + sut *txbuilder.TxBuilderElderberryValidium +} + +func newElderberryValidiumSUT(t *testing.T) *testDataElderberryValidium { + zkevmContract, err := contracts.NewContractBase(polygonvalidiumetrog.NewPolygonvalidiumetrog, common.Address{}, nil, contracts.ContractNameRollup, contracts.VersionElderberry) + require.NoError(t, err) + privateKey, err := crypto.HexToECDSA("64e679029f5032046955d41713dcc4b565de77ab891748d31bcf38864b54c175") + require.NoError(t, err) + opts, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) + require.NoError(t, err) + sender := common.Address{} + da := mocks_da.NewSequenceSenderElderberry(t) + + sut := txbuilder.NewTxBuilderElderberryValidium(*zkevmContract, da, *opts, sender, uint64(100)) + require.NotNil(t, sut) + return &testDataElderberryValidium{ + mockDA: da, + sut: sut, + } +} diff --git a/sequencesender/txbuilder/elderberry_zkevm.go b/sequencesender/txbuilder/elderberry_zkevm.go index 39979375..46df1f57 100644 --- a/sequencesender/txbuilder/elderberry_zkevm.go +++ b/sequencesender/txbuilder/elderberry_zkevm.go @@ -2,6 +2,7 @@ package txbuilder import ( "context" + "fmt" "math/big" "github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog" @@ -25,18 +26,20 @@ func NewTxBuilderElderberryZKEVM(zkevm contracts.RollupElderberryType, opts bind TxBuilderElderberryBase: *NewTxBuilderElderberryBase( zkevm, opts, ), - condNewSeq: &NewSequenceConditionalMaxSize{ - maxTxSizeForL1: maxTxSizeForL1, - }, + condNewSeq: NewConditionalNewSequenceMaxSize(maxTxSizeForL1), } } func (t *TxBuilderElderberryZKEVM) NewSequenceIfWorthToSend(ctx context.Context, sequenceBatches []seqsendertypes.Batch, l2Coinbase common.Address, batchNumber uint64) (seqsendertypes.Sequence, error) { - return t.condNewSeq.NewSequenceIfWorthToSend(ctx, t, sequenceBatches, t.opts.From, l2Coinbase, batchNumber) + return t.condNewSeq.NewSequenceIfWorthToSend(ctx, t, sequenceBatches, t.opts.From, l2Coinbase) } -func (t *TxBuilderElderberryZKEVM) BuildSequenceBatchesTx(ctx context.Context, sender common.Address, sequences seqsendertypes.Sequence) (*ethtypes.Transaction, error) { +// SetCondNewSeq allow to override the default conditional for new sequence +func (t *TxBuilderElderberryZKEVM) SetCondNewSeq(cond CondNewSequence) { + t.condNewSeq = cond +} +func (t *TxBuilderElderberryZKEVM) BuildSequenceBatchesTx(ctx context.Context, sender common.Address, sequences seqsendertypes.Sequence) (*ethtypes.Transaction, error) { newopts := t.opts newopts.NoSend = true @@ -49,6 +52,9 @@ func (t *TxBuilderElderberryZKEVM) BuildSequenceBatchesTx(ctx context.Context, s } func (t *TxBuilderElderberryZKEVM) sequenceBatchesRollup(opts bind.TransactOpts, sequences seqsendertypes.Sequence) (*types.Transaction, error) { + if sequences == nil || sequences.Len() == 0 { + return nil, fmt.Errorf("can't sequence an empty sequence") + } batches := make([]polygonvalidiumetrog.PolygonRollupBaseEtrogBatchData, sequences.Len()) for i, seq := range sequences.Batches() { var ger common.Hash diff --git a/sequencesender/txbuilder/elderberry_zkevm_test.go b/sequencesender/txbuilder/elderberry_zkevm_test.go new file mode 100644 index 00000000..6ae3b6eb --- /dev/null +++ b/sequencesender/txbuilder/elderberry_zkevm_test.go @@ -0,0 +1,119 @@ +package txbuilder_test + +import ( + "context" + "math/big" + "strings" + "testing" + + "github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog" + "github.com/0xPolygon/cdk/etherman/contracts" + "github.com/0xPolygon/cdk/sequencesender/seqsendertypes" + "github.com/0xPolygon/cdk/sequencesender/txbuilder" + "github.com/0xPolygon/cdk/sequencesender/txbuilder/mocks_txbuilder" + "github.com/0xPolygon/cdk/state/datastream" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestElderberryZkevmName(t *testing.T) { + zkevmContract := contracts.RollupElderberryType{} + opts := bind.TransactOpts{} + sender := common.Address{} + sut := txbuilder.NewTxBuilderElderberryZKEVM(zkevmContract, opts, sender, 100) + require.NotNil(t, sut) + require.True(t, strings.Contains(sut.String(), "Elderberry")) + require.True(t, strings.Contains(sut.String(), "ZKEVM")) +} + +func TestElderberryZkevmNewSequence(t *testing.T) { + zkevmContract := contracts.RollupElderberryType{} + opts := bind.TransactOpts{} + sender := common.Address{} + sut := txbuilder.NewTxBuilderElderberryZKEVM(zkevmContract, opts, sender, 100) + require.NotNil(t, sut) + seq, err := sut.NewSequence(nil, common.Address{}) + require.NoError(t, err) + require.NotNil(t, seq) +} + +func TestElderberryZkevmBuildSequenceBatchesTxEmtpySequence(t *testing.T) { + sut := newElderberryZkevmSUT(t) + ctx := context.TODO() + _, err := sut.BuildSequenceBatchesTx(ctx, common.Address{}, nil) + require.Error(t, err) + + seq, err := sut.NewSequence(nil, common.Address{}) + require.NoError(t, err) + _, err = sut.BuildSequenceBatchesTx(ctx, common.Address{}, seq) + require.Error(t, err) +} + +func TestElderberryZkevmBuildSequenceBatchesTxSequence1Batch(t *testing.T) { + sut := newElderberryZkevmSUT(t) + ctx := context.TODO() + l2Block := &datastream.L2Block{ + Timestamp: 1, + BatchNumber: 1, + L1InfotreeIndex: 3, + Coinbase: []byte{1, 2, 3}, + GlobalExitRoot: []byte{4, 5, 6}, + } + batchElder := sut.NewBatchFromL2Block(l2Block) + batches := []seqsendertypes.Batch{ + batchElder, + } + seq, err := sut.NewSequence(batches, common.Address{}) + require.NoError(t, err) + _, err = sut.BuildSequenceBatchesTx(ctx, common.Address{}, seq) + require.NoError(t, err) +} + +// This have to signer so produce an error +func TestElderberryZkevmBuildSequenceBatchesTxSequence1BatchError(t *testing.T) { + sut := newElderberryZkevmSUT(t) + sut.SetAuth(&bind.TransactOpts{}) + ctx := context.TODO() + l2Block := &datastream.L2Block{ + Timestamp: 1, + BatchNumber: 1, + L1InfotreeIndex: 3, + Coinbase: []byte{1, 2, 3}, + GlobalExitRoot: []byte{4, 5, 6}, + } + batchElder := sut.NewBatchFromL2Block(l2Block) + batches := []seqsendertypes.Batch{ + batchElder, + } + seq, err := sut.NewSequence(batches, common.Address{}) + require.NoError(t, err) + _, err = sut.BuildSequenceBatchesTx(ctx, common.Address{}, seq) + require.Error(t, err) +} + +func TestElderberryZkevmNewSequenceIfWorthToSend(t *testing.T) { + sut := newElderberryZkevmSUT(t) + mockCond := mocks_txbuilder.NewCondNewSequence(t) + sut.SetCondNewSeq(mockCond) + // Returns that is not work to be send + mockCond.EXPECT().NewSequenceIfWorthToSend(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) + seq, err := sut.NewSequenceIfWorthToSend(context.TODO(), nil, common.Address{}, 0) + require.NoError(t, err) + require.Nil(t, seq) +} + +func newElderberryZkevmSUT(t *testing.T) *txbuilder.TxBuilderElderberryZKEVM { + zkevmContract, err := contracts.NewContractBase(polygonvalidiumetrog.NewPolygonvalidiumetrog, common.Address{}, nil, contracts.ContractNameRollup, contracts.VersionElderberry) + require.NoError(t, err) + privateKey, err := crypto.HexToECDSA("64e679029f5032046955d41713dcc4b565de77ab891748d31bcf38864b54c175") + require.NoError(t, err) + opts, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) + require.NoError(t, err) + sender := common.Address{} + sut := txbuilder.NewTxBuilderElderberryZKEVM(*zkevmContract, *opts, sender, 100) + require.NotNil(t, sut) + return sut +} diff --git a/sequencesender/txbuilder/interface.go b/sequencesender/txbuilder/interface.go index 8f3b4661..ea6e8770 100644 --- a/sequencesender/txbuilder/interface.go +++ b/sequencesender/txbuilder/interface.go @@ -18,5 +18,6 @@ type TxBuilder interface { } type CondNewSequence interface { - NewSequenceIfWorthToSend(ctx context.Context, txBuilder TxBuilder, sequenceBatches []seqsendertypes.Batch, senderAddress, l2Coinbase common.Address, batchNumber uint64) (seqsendertypes.Sequence, error) + //NewSequenceIfWorthToSend Return nil, nil if the sequence is not worth sending + NewSequenceIfWorthToSend(ctx context.Context, txBuilder TxBuilder, sequenceBatches []seqsendertypes.Batch, senderAddress, l2Coinbase common.Address) (seqsendertypes.Sequence, error) } diff --git a/sequencesender/txbuilder/mocks_txbuilder/cond_new_sequence.go b/sequencesender/txbuilder/mocks_txbuilder/cond_new_sequence.go new file mode 100644 index 00000000..2600af02 --- /dev/null +++ b/sequencesender/txbuilder/mocks_txbuilder/cond_new_sequence.go @@ -0,0 +1,104 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_txbuilder + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" + + seqsendertypes "github.com/0xPolygon/cdk/sequencesender/seqsendertypes" + + txbuilder "github.com/0xPolygon/cdk/sequencesender/txbuilder" +) + +// CondNewSequence is an autogenerated mock type for the CondNewSequence type +type CondNewSequence struct { + mock.Mock +} + +type CondNewSequence_Expecter struct { + mock *mock.Mock +} + +func (_m *CondNewSequence) EXPECT() *CondNewSequence_Expecter { + return &CondNewSequence_Expecter{mock: &_m.Mock} +} + +// NewSequenceIfWorthToSend provides a mock function with given fields: ctx, txBuilder, sequenceBatches, senderAddress, l2Coinbase +func (_m *CondNewSequence) NewSequenceIfWorthToSend(ctx context.Context, txBuilder txbuilder.TxBuilder, sequenceBatches []seqsendertypes.Batch, senderAddress common.Address, l2Coinbase common.Address) (seqsendertypes.Sequence, error) { + ret := _m.Called(ctx, txBuilder, sequenceBatches, senderAddress, l2Coinbase) + + if len(ret) == 0 { + panic("no return value specified for NewSequenceIfWorthToSend") + } + + var r0 seqsendertypes.Sequence + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, txbuilder.TxBuilder, []seqsendertypes.Batch, common.Address, common.Address) (seqsendertypes.Sequence, error)); ok { + return rf(ctx, txBuilder, sequenceBatches, senderAddress, l2Coinbase) + } + if rf, ok := ret.Get(0).(func(context.Context, txbuilder.TxBuilder, []seqsendertypes.Batch, common.Address, common.Address) seqsendertypes.Sequence); ok { + r0 = rf(ctx, txBuilder, sequenceBatches, senderAddress, l2Coinbase) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(seqsendertypes.Sequence) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, txbuilder.TxBuilder, []seqsendertypes.Batch, common.Address, common.Address) error); ok { + r1 = rf(ctx, txBuilder, sequenceBatches, senderAddress, l2Coinbase) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CondNewSequence_NewSequenceIfWorthToSend_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewSequenceIfWorthToSend' +type CondNewSequence_NewSequenceIfWorthToSend_Call struct { + *mock.Call +} + +// NewSequenceIfWorthToSend is a helper method to define mock.On call +// - ctx context.Context +// - txBuilder txbuilder.TxBuilder +// - sequenceBatches []seqsendertypes.Batch +// - senderAddress common.Address +// - l2Coinbase common.Address +func (_e *CondNewSequence_Expecter) NewSequenceIfWorthToSend(ctx interface{}, txBuilder interface{}, sequenceBatches interface{}, senderAddress interface{}, l2Coinbase interface{}) *CondNewSequence_NewSequenceIfWorthToSend_Call { + return &CondNewSequence_NewSequenceIfWorthToSend_Call{Call: _e.mock.On("NewSequenceIfWorthToSend", ctx, txBuilder, sequenceBatches, senderAddress, l2Coinbase)} +} + +func (_c *CondNewSequence_NewSequenceIfWorthToSend_Call) Run(run func(ctx context.Context, txBuilder txbuilder.TxBuilder, sequenceBatches []seqsendertypes.Batch, senderAddress common.Address, l2Coinbase common.Address)) *CondNewSequence_NewSequenceIfWorthToSend_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(txbuilder.TxBuilder), args[2].([]seqsendertypes.Batch), args[3].(common.Address), args[4].(common.Address)) + }) + return _c +} + +func (_c *CondNewSequence_NewSequenceIfWorthToSend_Call) Return(_a0 seqsendertypes.Sequence, _a1 error) *CondNewSequence_NewSequenceIfWorthToSend_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *CondNewSequence_NewSequenceIfWorthToSend_Call) RunAndReturn(run func(context.Context, txbuilder.TxBuilder, []seqsendertypes.Batch, common.Address, common.Address) (seqsendertypes.Sequence, error)) *CondNewSequence_NewSequenceIfWorthToSend_Call { + _c.Call.Return(run) + return _c +} + +// NewCondNewSequence creates a new instance of CondNewSequence. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewCondNewSequence(t interface { + mock.TestingT + Cleanup(func()) +}) *CondNewSequence { + mock := &CondNewSequence{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sequencesender/txbuilder/mocks_txbuilder/tx_builder.go b/sequencesender/txbuilder/mocks_txbuilder/tx_builder.go new file mode 100644 index 00000000..e9aa9127 --- /dev/null +++ b/sequencesender/txbuilder/mocks_txbuilder/tx_builder.go @@ -0,0 +1,317 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks_txbuilder + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + datastream "github.com/0xPolygon/cdk/state/datastream" + + mock "github.com/stretchr/testify/mock" + + seqsendertypes "github.com/0xPolygon/cdk/sequencesender/seqsendertypes" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// TxBuilder is an autogenerated mock type for the TxBuilder type +type TxBuilder struct { + mock.Mock +} + +type TxBuilder_Expecter struct { + mock *mock.Mock +} + +func (_m *TxBuilder) EXPECT() *TxBuilder_Expecter { + return &TxBuilder_Expecter{mock: &_m.Mock} +} + +// BuildSequenceBatchesTx provides a mock function with given fields: ctx, sender, sequences +func (_m *TxBuilder) BuildSequenceBatchesTx(ctx context.Context, sender common.Address, sequences seqsendertypes.Sequence) (*types.Transaction, error) { + ret := _m.Called(ctx, sender, sequences) + + if len(ret) == 0 { + panic("no return value specified for BuildSequenceBatchesTx") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, seqsendertypes.Sequence) (*types.Transaction, error)); ok { + return rf(ctx, sender, sequences) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, seqsendertypes.Sequence) *types.Transaction); ok { + r0 = rf(ctx, sender, sequences) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, seqsendertypes.Sequence) error); ok { + r1 = rf(ctx, sender, sequences) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TxBuilder_BuildSequenceBatchesTx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BuildSequenceBatchesTx' +type TxBuilder_BuildSequenceBatchesTx_Call struct { + *mock.Call +} + +// BuildSequenceBatchesTx is a helper method to define mock.On call +// - ctx context.Context +// - sender common.Address +// - sequences seqsendertypes.Sequence +func (_e *TxBuilder_Expecter) BuildSequenceBatchesTx(ctx interface{}, sender interface{}, sequences interface{}) *TxBuilder_BuildSequenceBatchesTx_Call { + return &TxBuilder_BuildSequenceBatchesTx_Call{Call: _e.mock.On("BuildSequenceBatchesTx", ctx, sender, sequences)} +} + +func (_c *TxBuilder_BuildSequenceBatchesTx_Call) Run(run func(ctx context.Context, sender common.Address, sequences seqsendertypes.Sequence)) *TxBuilder_BuildSequenceBatchesTx_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].(seqsendertypes.Sequence)) + }) + return _c +} + +func (_c *TxBuilder_BuildSequenceBatchesTx_Call) Return(_a0 *types.Transaction, _a1 error) *TxBuilder_BuildSequenceBatchesTx_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TxBuilder_BuildSequenceBatchesTx_Call) RunAndReturn(run func(context.Context, common.Address, seqsendertypes.Sequence) (*types.Transaction, error)) *TxBuilder_BuildSequenceBatchesTx_Call { + _c.Call.Return(run) + return _c +} + +// NewBatchFromL2Block provides a mock function with given fields: l2Block +func (_m *TxBuilder) NewBatchFromL2Block(l2Block *datastream.L2Block) seqsendertypes.Batch { + ret := _m.Called(l2Block) + + if len(ret) == 0 { + panic("no return value specified for NewBatchFromL2Block") + } + + var r0 seqsendertypes.Batch + if rf, ok := ret.Get(0).(func(*datastream.L2Block) seqsendertypes.Batch); ok { + r0 = rf(l2Block) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(seqsendertypes.Batch) + } + } + + return r0 +} + +// TxBuilder_NewBatchFromL2Block_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewBatchFromL2Block' +type TxBuilder_NewBatchFromL2Block_Call struct { + *mock.Call +} + +// NewBatchFromL2Block is a helper method to define mock.On call +// - l2Block *datastream.L2Block +func (_e *TxBuilder_Expecter) NewBatchFromL2Block(l2Block interface{}) *TxBuilder_NewBatchFromL2Block_Call { + return &TxBuilder_NewBatchFromL2Block_Call{Call: _e.mock.On("NewBatchFromL2Block", l2Block)} +} + +func (_c *TxBuilder_NewBatchFromL2Block_Call) Run(run func(l2Block *datastream.L2Block)) *TxBuilder_NewBatchFromL2Block_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*datastream.L2Block)) + }) + return _c +} + +func (_c *TxBuilder_NewBatchFromL2Block_Call) Return(_a0 seqsendertypes.Batch) *TxBuilder_NewBatchFromL2Block_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxBuilder_NewBatchFromL2Block_Call) RunAndReturn(run func(*datastream.L2Block) seqsendertypes.Batch) *TxBuilder_NewBatchFromL2Block_Call { + _c.Call.Return(run) + return _c +} + +// NewSequence provides a mock function with given fields: batches, coinbase +func (_m *TxBuilder) NewSequence(batches []seqsendertypes.Batch, coinbase common.Address) (seqsendertypes.Sequence, error) { + ret := _m.Called(batches, coinbase) + + if len(ret) == 0 { + panic("no return value specified for NewSequence") + } + + var r0 seqsendertypes.Sequence + var r1 error + if rf, ok := ret.Get(0).(func([]seqsendertypes.Batch, common.Address) (seqsendertypes.Sequence, error)); ok { + return rf(batches, coinbase) + } + if rf, ok := ret.Get(0).(func([]seqsendertypes.Batch, common.Address) seqsendertypes.Sequence); ok { + r0 = rf(batches, coinbase) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(seqsendertypes.Sequence) + } + } + + if rf, ok := ret.Get(1).(func([]seqsendertypes.Batch, common.Address) error); ok { + r1 = rf(batches, coinbase) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TxBuilder_NewSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewSequence' +type TxBuilder_NewSequence_Call struct { + *mock.Call +} + +// NewSequence is a helper method to define mock.On call +// - batches []seqsendertypes.Batch +// - coinbase common.Address +func (_e *TxBuilder_Expecter) NewSequence(batches interface{}, coinbase interface{}) *TxBuilder_NewSequence_Call { + return &TxBuilder_NewSequence_Call{Call: _e.mock.On("NewSequence", batches, coinbase)} +} + +func (_c *TxBuilder_NewSequence_Call) Run(run func(batches []seqsendertypes.Batch, coinbase common.Address)) *TxBuilder_NewSequence_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]seqsendertypes.Batch), args[1].(common.Address)) + }) + return _c +} + +func (_c *TxBuilder_NewSequence_Call) Return(_a0 seqsendertypes.Sequence, _a1 error) *TxBuilder_NewSequence_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TxBuilder_NewSequence_Call) RunAndReturn(run func([]seqsendertypes.Batch, common.Address) (seqsendertypes.Sequence, error)) *TxBuilder_NewSequence_Call { + _c.Call.Return(run) + return _c +} + +// NewSequenceIfWorthToSend provides a mock function with given fields: ctx, sequenceBatches, l2Coinbase, batchNumber +func (_m *TxBuilder) NewSequenceIfWorthToSend(ctx context.Context, sequenceBatches []seqsendertypes.Batch, l2Coinbase common.Address, batchNumber uint64) (seqsendertypes.Sequence, error) { + ret := _m.Called(ctx, sequenceBatches, l2Coinbase, batchNumber) + + if len(ret) == 0 { + panic("no return value specified for NewSequenceIfWorthToSend") + } + + var r0 seqsendertypes.Sequence + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []seqsendertypes.Batch, common.Address, uint64) (seqsendertypes.Sequence, error)); ok { + return rf(ctx, sequenceBatches, l2Coinbase, batchNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, []seqsendertypes.Batch, common.Address, uint64) seqsendertypes.Sequence); ok { + r0 = rf(ctx, sequenceBatches, l2Coinbase, batchNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(seqsendertypes.Sequence) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []seqsendertypes.Batch, common.Address, uint64) error); ok { + r1 = rf(ctx, sequenceBatches, l2Coinbase, batchNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TxBuilder_NewSequenceIfWorthToSend_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewSequenceIfWorthToSend' +type TxBuilder_NewSequenceIfWorthToSend_Call struct { + *mock.Call +} + +// NewSequenceIfWorthToSend is a helper method to define mock.On call +// - ctx context.Context +// - sequenceBatches []seqsendertypes.Batch +// - l2Coinbase common.Address +// - batchNumber uint64 +func (_e *TxBuilder_Expecter) NewSequenceIfWorthToSend(ctx interface{}, sequenceBatches interface{}, l2Coinbase interface{}, batchNumber interface{}) *TxBuilder_NewSequenceIfWorthToSend_Call { + return &TxBuilder_NewSequenceIfWorthToSend_Call{Call: _e.mock.On("NewSequenceIfWorthToSend", ctx, sequenceBatches, l2Coinbase, batchNumber)} +} + +func (_c *TxBuilder_NewSequenceIfWorthToSend_Call) Run(run func(ctx context.Context, sequenceBatches []seqsendertypes.Batch, l2Coinbase common.Address, batchNumber uint64)) *TxBuilder_NewSequenceIfWorthToSend_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]seqsendertypes.Batch), args[2].(common.Address), args[3].(uint64)) + }) + return _c +} + +func (_c *TxBuilder_NewSequenceIfWorthToSend_Call) Return(_a0 seqsendertypes.Sequence, _a1 error) *TxBuilder_NewSequenceIfWorthToSend_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *TxBuilder_NewSequenceIfWorthToSend_Call) RunAndReturn(run func(context.Context, []seqsendertypes.Batch, common.Address, uint64) (seqsendertypes.Sequence, error)) *TxBuilder_NewSequenceIfWorthToSend_Call { + _c.Call.Return(run) + return _c +} + +// String provides a mock function with given fields: +func (_m *TxBuilder) String() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for String") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// TxBuilder_String_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'String' +type TxBuilder_String_Call struct { + *mock.Call +} + +// String is a helper method to define mock.On call +func (_e *TxBuilder_Expecter) String() *TxBuilder_String_Call { + return &TxBuilder_String_Call{Call: _e.mock.On("String")} +} + +func (_c *TxBuilder_String_Call) Run(run func()) *TxBuilder_String_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TxBuilder_String_Call) Return(_a0 string) *TxBuilder_String_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxBuilder_String_Call) RunAndReturn(run func() string) *TxBuilder_String_Call { + _c.Call.Return(run) + return _c +} + +// NewTxBuilder creates a new instance of TxBuilder. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewTxBuilder(t interface { + mock.TestingT + Cleanup(func()) +}) *TxBuilder { + mock := &TxBuilder{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sequencesender/txbuilder/validium_cond_num_batches.go b/sequencesender/txbuilder/validium_cond_num_batches.go index da663063..66c7c905 100644 --- a/sequencesender/txbuilder/validium_cond_num_batches.go +++ b/sequencesender/txbuilder/validium_cond_num_batches.go @@ -8,11 +8,17 @@ import ( "github.com/ethereum/go-ethereum/common" ) -type NewSequenceConditionalNumBatches struct { +type ConditionalNewSequenceNumBatches struct { maxBatchesForL1 uint64 // cfg.MaxBatchesForL1 } -func (c *NewSequenceConditionalNumBatches) NewSequenceIfWorthToSend(ctx context.Context, txBuilder TxBuilder, sequenceBatches []seqsendertypes.Batch, senderAddress, l2Coinbase common.Address, batchNumber uint64) (seqsendertypes.Sequence, error) { +func NewConditionalNewSequenceNumBatches(maxBatchesForL1 uint64) *ConditionalNewSequenceNumBatches { + return &ConditionalNewSequenceNumBatches{ + maxBatchesForL1: maxBatchesForL1, + } +} + +func (c *ConditionalNewSequenceNumBatches) NewSequenceIfWorthToSend(ctx context.Context, txBuilder TxBuilder, sequenceBatches []seqsendertypes.Batch, senderAddress, l2Coinbase common.Address) (seqsendertypes.Sequence, error) { if c.maxBatchesForL1 > 0 && len(sequenceBatches) >= int(c.maxBatchesForL1) { log.Infof( "[SeqSender] sequence should be sent to L1, because MaxBatchesForL1 (%d) has been reached", diff --git a/sequencesender/txbuilder/validium_cond_num_batches_test.go b/sequencesender/txbuilder/validium_cond_num_batches_test.go new file mode 100644 index 00000000..5375b4fd --- /dev/null +++ b/sequencesender/txbuilder/validium_cond_num_batches_test.go @@ -0,0 +1,45 @@ +package txbuilder_test + +import ( + "testing" + + "github.com/0xPolygon/cdk/sequencesender/seqsendertypes" + "github.com/0xPolygon/cdk/sequencesender/txbuilder" + "github.com/0xPolygon/cdk/sequencesender/txbuilder/mocks_txbuilder" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestConditionalNumBatchesDisabled(t *testing.T) { + mockTxBuilder := mocks_txbuilder.NewTxBuilder(t) + sut := txbuilder.NewConditionalNewSequenceNumBatches(0) + + tx, err := sut.NewSequenceIfWorthToSend(nil, mockTxBuilder, nil, common.Address{}, common.Address{}) + require.NoError(t, err) + require.Nil(t, tx) +} + +// It have 1 batch and minium are 2, so no new sequence +func TestConditionalNumBatchesDontFulfillCondition(t *testing.T) { + mockTxBuilder := mocks_txbuilder.NewTxBuilder(t) + sut := txbuilder.NewConditionalNewSequenceNumBatches(2) + var sequenceBatches []seqsendertypes.Batch + sequenceBatches = append(sequenceBatches, &txbuilder.BananaBatch{}) + tx, err := sut.NewSequenceIfWorthToSend(nil, mockTxBuilder, sequenceBatches, common.Address{}, common.Address{}) + require.NoError(t, err) + require.Nil(t, tx) +} + +// It have 2 batch and minium are 2, so new sequence +func TestConditionalNumBatchesFulfillCondition(t *testing.T) { + mockTxBuilder := mocks_txbuilder.NewTxBuilder(t) + sut := txbuilder.NewConditionalNewSequenceNumBatches(2) + var sequenceBatches []seqsendertypes.Batch + sequenceBatches = append(sequenceBatches, &txbuilder.BananaBatch{}) + sequenceBatches = append(sequenceBatches, &txbuilder.BananaBatch{}) + mockTxBuilder.EXPECT().NewSequence(mock.Anything, mock.Anything).Return(nil, nil) + tx, err := sut.NewSequenceIfWorthToSend(nil, mockTxBuilder, sequenceBatches, common.Address{}, common.Address{}) + require.NoError(t, err) + require.Nil(t, tx) +} diff --git a/sequencesender/txbuilder/zkevm_cond_max_size.go b/sequencesender/txbuilder/zkevm_cond_max_size.go index 3218d015..5280b71f 100644 --- a/sequencesender/txbuilder/zkevm_cond_max_size.go +++ b/sequencesender/txbuilder/zkevm_cond_max_size.go @@ -3,6 +3,7 @@ package txbuilder import ( "context" "errors" + "fmt" "github.com/0xPolygon/cdk/etherman" "github.com/0xPolygon/cdk/log" @@ -15,26 +16,46 @@ var ( ErrOversizedData = errors.New("oversized data") ) -type NewSequenceConditionalMaxSize struct { +type ConditionalNewSequenceMaxSize struct { maxTxSizeForL1 uint64 // cfg.MaxTxSizeForL1 } -func (c *NewSequenceConditionalMaxSize) NewSequenceIfWorthToSend(ctx context.Context, txBuilder TxBuilder, sequenceBatches []seqsendertypes.Batch, senderAddress, l2Coinbase common.Address, batchNumber uint64) (seqsendertypes.Sequence, error) { +func NewConditionalNewSequenceMaxSize(maxTxSizeForL1 uint64) *ConditionalNewSequenceMaxSize { + return &ConditionalNewSequenceMaxSize{ + maxTxSizeForL1: maxTxSizeForL1, + } +} + +func (c *ConditionalNewSequenceMaxSize) NewSequenceIfWorthToSend(ctx context.Context, txBuilder TxBuilder, sequenceBatches []seqsendertypes.Batch, senderAddress, l2Coinbase common.Address) (seqsendertypes.Sequence, error) { + if c.maxTxSizeForL1 == 0 { + log.Debug("maxTxSizeForL1 is 0, so is disabled") + return nil, nil + } sequence, err := txBuilder.NewSequence(sequenceBatches, l2Coinbase) if err != nil { return nil, err } + if sequence == nil { + err = fmt.Errorf("error txBuilder.NewSequence, returns sequence=nil and err==nil, is not expected") + log.Errorf(err.Error()) + return nil, err + } // Check if can be sent tx, err := txBuilder.BuildSequenceBatchesTx(ctx, senderAddress, sequence) - if err == nil && tx.Size() > c.maxTxSizeForL1 { - log.Infof("[SeqSender] oversized Data on TX oldHash %s (txSize %d > %d)", tx.Hash(), tx.Size(), c.maxTxSizeForL1) + if tx == nil && err == nil { + err = fmt.Errorf("error txBuilder.BuildSequenceBatchesTx, returns tx=nil and err==nil, is not expected") + log.Errorf(err.Error()) + return nil, err + } + if err == nil && tx != nil && tx.Size() > c.maxTxSizeForL1 { + log.Infof("Oversized Data on TX oldHash %s (txSize %d > %d)", tx.Hash(), tx.Size(), c.maxTxSizeForL1) err = ErrOversizedData } if err != nil { - log.Infof("[SeqSender] handling estimate gas send sequence error: %v", err) - sequenceBatches, err = handleEstimateGasSendSequenceErr(sequence.Batches(), batchNumber, err) + log.Debugf("Handling estimate gas send sequence error: %v", err) + sequenceBatches, err = handleEstimateGasSendSequenceErr(sequence.Batches(), err) if sequenceBatches != nil { // Handling the error gracefully, re-processing the sequence as a sanity check //sequence, err = s.newSequenceBanana(sequenceBatches, s.cfg.L2Coinbase) @@ -43,36 +64,42 @@ func (c *NewSequenceConditionalMaxSize) NewSequenceIfWorthToSend(ctx context.Con return nil, err } - _, err = txBuilder.BuildSequenceBatchesTx(ctx, senderAddress, sequence) + txReduced, err := txBuilder.BuildSequenceBatchesTx(ctx, senderAddress, sequence) + log.Debugf("After reducing batches: (txSize %d -> %d)", tx.Size(), txReduced.Size()) + if err == nil && txReduced != nil && txReduced.Size() > c.maxTxSizeForL1 { + log.Warnf("After reducing batches: (txSize %d -> %d) is still too big > %d", tx.Size(), txReduced.Size(), c.maxTxSizeForL1) + } return sequence, err } return sequence, err } - log.Infof("[SeqSender] [MaxSize] current size:%d max_size:%d num_batches: %d", tx.Size(), c.maxTxSizeForL1, sequence.Len()) + log.Debugf("Current size:%d < max_size:%d num_batches: %d, no sequence promoted yet", tx.Size(), c.maxTxSizeForL1, sequence.Len()) return nil, nil } // handleEstimateGasSendSequenceErr handles an error on the estimate gas. Results: (nil,nil)=requires waiting, (nil,error)=no handled gracefully, (seq,nil) handled gracefully -func handleEstimateGasSendSequenceErr(sequenceBatches []seqsendertypes.Batch, currentBatchNumToSequence uint64, err error) ([]seqsendertypes.Batch, error) { +func handleEstimateGasSendSequenceErr(sequenceBatches []seqsendertypes.Batch, err error) ([]seqsendertypes.Batch, error) { // Insufficient allowance if errors.Is(err, etherman.ErrInsufficientAllowance) { return nil, err } + errMsg := fmt.Sprintf("due to unknown error: %v", err) if isDataForEthTxTooBig(err) { - // Remove the latest item and send the sequences - log.Infof("Done building sequences, selected batches to %d. Batch %d caused the L1 tx to be too big: %v", currentBatchNumToSequence-1, currentBatchNumToSequence, err) - } else { - // Remove the latest item and send the sequences - log.Infof("Done building sequences, selected batches to %d. Batch %d excluded due to unknown error: %v", currentBatchNumToSequence, currentBatchNumToSequence+1, err) + errMsg = fmt.Sprintf("caused the L1 tx to be too big: %v", err) } - + adjustMsg := "" if len(sequenceBatches) > 1 { + lastPrevious := sequenceBatches[len(sequenceBatches)-1].BatchNumber() sequenceBatches = sequenceBatches[:len(sequenceBatches)-1] + lastCurrent := sequenceBatches[len(sequenceBatches)-1].BatchNumber() + adjustMsg = fmt.Sprintf("removing last batch: old BatchNumber:%d -> %d, new length: %d", lastPrevious, lastCurrent, len(sequenceBatches)) } else { sequenceBatches = nil + adjustMsg = "removing all batches" + log.Warnf("No more batches to remove, sequence is empty... it could be a deadlock situation") } - + log.Infof("Adjusted sequence, %s, because %s", adjustMsg, errMsg) return sequenceBatches, nil } diff --git a/sequencesender/txbuilder/zkevm_cond_max_size_test.go b/sequencesender/txbuilder/zkevm_cond_max_size_test.go new file mode 100644 index 00000000..0f87e78c --- /dev/null +++ b/sequencesender/txbuilder/zkevm_cond_max_size_test.go @@ -0,0 +1,95 @@ +package txbuilder_test + +import ( + "context" + "testing" + + "github.com/0xPolygon/cdk/etherman" + "github.com/0xPolygon/cdk/sequencesender/seqsendertypes" + "github.com/0xPolygon/cdk/sequencesender/txbuilder" + "github.com/0xPolygon/cdk/sequencesender/txbuilder/mocks_txbuilder" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestConditionalMaxSizeDisabled(t *testing.T) { + mockTxBuilder := mocks_txbuilder.NewTxBuilder(t) + sut := txbuilder.NewConditionalNewSequenceMaxSize(0) + + tx, err := sut.NewSequenceIfWorthToSend(nil, mockTxBuilder, nil, common.Address{}, common.Address{}) + require.NoError(t, err) + require.Nil(t, tx) +} + +func TestConditionalMaxSizeTxBuilderNewSequenceReturnsNil(t *testing.T) { + mockTxBuilder := mocks_txbuilder.NewTxBuilder(t) + sut := txbuilder.NewConditionalNewSequenceMaxSize(1024) + var sequenceBatches []seqsendertypes.Batch + sequenceBatches = append(sequenceBatches, &txbuilder.BananaBatch{}) + mockTxBuilder.EXPECT().NewSequence(sequenceBatches, common.Address{}).Return(nil, nil) + _, err := sut.NewSequenceIfWorthToSend(nil, mockTxBuilder, sequenceBatches, common.Address{}, common.Address{}) + require.Error(t, err) +} + +func TestConditionalMaxSizeTxBuilderBuildSequenceBatchesTxReturnsNil(t *testing.T) { + mockTxBuilder := mocks_txbuilder.NewTxBuilder(t) + sut := txbuilder.NewConditionalNewSequenceMaxSize(1024) + var sequenceBatches []seqsendertypes.Batch + sequenceBatches = append(sequenceBatches, &txbuilder.BananaBatch{}) + seq := &txbuilder.ElderberrySequence{} + mockTxBuilder.EXPECT().NewSequence(sequenceBatches, common.Address{}).Return(seq, nil) + mockTxBuilder.EXPECT().BuildSequenceBatchesTx(mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) + _, err := sut.NewSequenceIfWorthToSend(nil, mockTxBuilder, sequenceBatches, common.Address{}, common.Address{}) + require.Error(t, err) +} + +func TestConditionalMaxSizeTxBuilderDontFulFill(t *testing.T) { + mockTxBuilder := mocks_txbuilder.NewTxBuilder(t) + sut := txbuilder.NewConditionalNewSequenceMaxSize(1024) + var sequenceBatches []seqsendertypes.Batch + sequenceBatches = append(sequenceBatches, &txbuilder.BananaBatch{}) + seq := &txbuilder.ElderberrySequence{} + mockTxBuilder.EXPECT().NewSequence(sequenceBatches, common.Address{}).Return(seq, nil) + inner := ðtypes.LegacyTx{} + tx := ethtypes.NewTx(inner) + mockTxBuilder.EXPECT().BuildSequenceBatchesTx(mock.Anything, mock.Anything, mock.Anything).Return(tx, nil) + + res, err := sut.NewSequenceIfWorthToSend(nil, mockTxBuilder, sequenceBatches, common.Address{}, common.Address{}) + + require.NoError(t, err) + require.Nil(t, res) +} + +func TestConditionalMaxSizeTxBuilderFulFill(t *testing.T) { + mockTxBuilder := mocks_txbuilder.NewTxBuilder(t) + sut := txbuilder.NewConditionalNewSequenceMaxSize(10) + l2coinbase := common.Address{} + ctx := context.TODO() + + newSeq := newTestSeq(3, 100, l2coinbase) + mockTxBuilder.EXPECT().NewSequence(newSeq.Batches(), l2coinbase).Return(newSeq, nil) + inner := ðtypes.LegacyTx{ + Data: []byte{0x01, 0x02, 0x03, 0x04}, + } + tx := ethtypes.NewTx(inner) + mockTxBuilder.EXPECT().BuildSequenceBatchesTx(ctx, mock.Anything, newSeq).Return(tx, nil) + // The size of result Tx is 14 that is > 10, so it reduce 1 batch + newSeqReduced := newTestSeq(2, 100, l2coinbase) + mockTxBuilder.EXPECT().NewSequence(newSeqReduced.Batches(), l2coinbase).Return(newSeqReduced, nil) + mockTxBuilder.EXPECT().BuildSequenceBatchesTx(ctx, mock.Anything, newSeqReduced).Return(tx, nil) + + res, err := sut.NewSequenceIfWorthToSend(ctx, mockTxBuilder, newSeq.Batches(), common.Address{}, l2coinbase) + + require.NoError(t, err) + require.NotNil(t, res) +} + +func newTestSeq(numBatches int, firstBatch uint64, l2coinbase common.Address) *txbuilder.ElderberrySequence { + var sequenceBatches []seqsendertypes.Batch + for i := 0; i < numBatches; i++ { + sequenceBatches = append(sequenceBatches, txbuilder.NewBananaBatch(ðerman.Batch{BatchNumber: firstBatch + uint64(i)})) + } + return txbuilder.NewElderberrySequence(sequenceBatches, l2coinbase) +} diff --git a/test/Makefile b/test/Makefile index 3511b4f7..7a53df8c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,6 @@ .PHONY: generate-mocks -generate-mocks: - $(MAKE) generate-mocks-localbridgesync - $(MAKE) generate-mocks-reorgdetector +generate-mocks: generate-mocks-localbridgesync generate-mocks-reorgdetector generate-mocks-sequencesender generate-mocks-da + .PHONY: generate-mocks-localbridgesync generate-mocks-localbridgesync: ## Generates mocks for localbridgesync, using mockery tool @@ -14,6 +13,18 @@ generate-mocks-localbridgesync: ## Generates mocks for localbridgesync, using mo generate-mocks-reorgdetector: ## Generates mocks for reorgdetector, using mockery tool export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=EthClient --dir=../reorgdetector --output=../reorgdetector --outpkg=reorgdetector --inpackage --structname=EthClientMock --filename=mock_eth_client.go +COMMON_MOCKERY_PARAMS=--disable-version-string --with-expecter +.PHONY: generate-mocks-sequencesender +generate-mocks-sequencesender: ## Generates mocks for sequencesender, using mockery tool + rm -Rf ../sequencesender/txbuilder/mocks_txbuilder + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --all --case snake --dir ../sequencesender/txbuilder --output ../sequencesender/txbuilder/mocks_txbuilder --outpkg mocks_txbuilder ${COMMON_MOCKERY_PARAMS} + +.PHONY: generate-mocks-da +generate-mocks-da: ## Generates mocks for dataavailability, using mockery tool + rm -Rf ../dataavailability/mocks_da + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --all --case snake --dir ../dataavailability --output ../dataavailability/mocks_da --outpkg mocks_da ${COMMON_MOCKERY_PARAMS} + + .PHONY: test-e2e-elderberry-validium test-e2e-elderberry-validium: stop ## Runs e2e tests checking elderberry/validium ./run-e2e-seq_sender.sh cdk-validium