diff --git a/.mockery.yaml b/.mockery.yaml index 5393a82a47..0eb29b64d8 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -41,11 +41,23 @@ packages: filename: store.go github.com/celestiaorg/go-header: interfaces: + Exchange: + config: + dir: ./test/mocks + pkgname: mocks + filename: external/hexchange.go Store: config: dir: ./test/mocks pkgname: mocks filename: external/hstore.go + github.com/evstack/ev-node/pkg/sync: + interfaces: + P2PExchange: + config: + dir: ./test/mocks + pkgname: mocks + filename: external/p2pexchange.go github.com/evstack/ev-node/block/internal/syncing: interfaces: DARetriever: diff --git a/node/full.go b/node/full.go index 6d03a87c04..0353ca8b45 100644 --- a/node/full.go +++ b/node/full.go @@ -87,12 +87,12 @@ func newFullNode( mainKV := newPrefixKV(database, EvPrefix) rktStore := store.New(mainKV) - headerSyncService, err := initHeaderSyncService(mainKV, nodeConfig, genesis, p2pClient, logger) + headerSyncService, err := initHeaderSyncService(mainKV, rktStore, nodeConfig, genesis, p2pClient, logger) if err != nil { return nil, err } - dataSyncService, err := initDataSyncService(mainKV, nodeConfig, genesis, p2pClient, logger) + dataSyncService, err := initDataSyncService(mainKV, rktStore, nodeConfig, genesis, p2pClient, logger) if err != nil { return nil, err } @@ -149,6 +149,7 @@ func newFullNode( func initHeaderSyncService( mainKV ds.Batching, + daStore store.Store, nodeConfig config.Config, genesis genesispkg.Genesis, p2pClient *p2p.Client, @@ -156,7 +157,7 @@ func initHeaderSyncService( ) (*evsync.HeaderSyncService, error) { componentLogger := logger.With().Str("component", "HeaderSyncService").Logger() - headerSyncService, err := evsync.NewHeaderSyncService(mainKV, nodeConfig, genesis, p2pClient, componentLogger) + headerSyncService, err := evsync.NewHeaderSyncService(mainKV, daStore, nodeConfig, genesis, p2pClient, componentLogger) if err != nil { return nil, fmt.Errorf("error while initializing HeaderSyncService: %w", err) } @@ -165,6 +166,7 @@ func initHeaderSyncService( func initDataSyncService( mainKV ds.Batching, + daStore store.Store, nodeConfig config.Config, genesis genesispkg.Genesis, p2pClient *p2p.Client, @@ -172,7 +174,7 @@ func initDataSyncService( ) (*evsync.DataSyncService, error) { componentLogger := logger.With().Str("component", "DataSyncService").Logger() - dataSyncService, err := evsync.NewDataSyncService(mainKV, nodeConfig, genesis, p2pClient, componentLogger) + dataSyncService, err := evsync.NewDataSyncService(mainKV, daStore, nodeConfig, genesis, p2pClient, componentLogger) if err != nil { return nil, fmt.Errorf("error while initializing DataSyncService: %w", err) } diff --git a/node/light.go b/node/light.go index bdc4a92351..2cfdb8f506 100644 --- a/node/light.go +++ b/node/light.go @@ -43,13 +43,13 @@ func newLightNode( logger zerolog.Logger, ) (ln *LightNode, err error) { componentLogger := logger.With().Str("component", "HeaderSyncService").Logger() - headerSyncService, err := sync.NewHeaderSyncService(database, conf, genesis, p2pClient, componentLogger) + store := store.New(database) + + headerSyncService, err := sync.NewHeaderSyncService(database, store, conf, genesis, p2pClient, componentLogger) if err != nil { return nil, fmt.Errorf("error while initializing HeaderSyncService: %w", err) } - store := store.New(database) - node := &LightNode{ P2P: p2pClient, hSyncService: headerSyncService, diff --git a/pkg/da/jsonrpc/README.md b/pkg/da/jsonrpc/README.md index 7440a6d483..80e2968864 100644 --- a/pkg/da/jsonrpc/README.md +++ b/pkg/da/jsonrpc/README.md @@ -7,7 +7,7 @@ This package is a **trimmed copy** of code from `celestia-node` to stay JSON-com - `blob.go` comes from `celestia-node/blob/blob.go` @ tag `v0.28.4` (release v0.28.4), with unused pieces removed (blob v1, proof helpers, share length calc, appconsts dependency, etc.). - `submit_options.go` mirrors the exported JSON fields of `celestia-node/state/tx_config.go` @ the same tag, leaving out functional options, defaults, and Cosmos keyring helpers. -## Why copy instead of import? +## Why copy instead of import - Avoids pulling Cosmos SDK / celestia-app dependencies into ev-node for the small surface we need (blob JSON and commitment for v0). - Keeps binary size and module graph smaller while remaining wire-compatible with celestia-node's blob service. diff --git a/pkg/sync/exchange_wrapper.go b/pkg/sync/exchange_wrapper.go new file mode 100644 index 0000000000..5d2d54bf47 --- /dev/null +++ b/pkg/sync/exchange_wrapper.go @@ -0,0 +1,65 @@ +package sync + +import ( + "context" + + "github.com/celestiaorg/go-header" + "github.com/evstack/ev-node/pkg/store" +) + +type storeGetter[H header.Header[H]] func(context.Context, store.Store, header.Hash) (H, error) +type storeGetterByHeight[H header.Header[H]] func(context.Context, store.Store, uint64) (H, error) + +// P2PExchange defines the interface for the underlying P2P exchange. +type P2PExchange[H header.Header[H]] interface { + header.Exchange[H] + Start(context.Context) error + Stop(context.Context) error +} + +type exchangeWrapper[H header.Header[H]] struct { + p2pExchange P2PExchange[H] + daStore store.Store + getter storeGetter[H] + getterByHeight storeGetterByHeight[H] +} + +func (ew *exchangeWrapper[H]) Get(ctx context.Context, hash header.Hash) (H, error) { + // Check DA store first + if ew.daStore != nil && ew.getter != nil { + if h, err := ew.getter(ctx, ew.daStore, hash); err == nil && !h.IsZero() { + return h, nil + } + } + + // Fallback to network exchange + return ew.p2pExchange.Get(ctx, hash) +} + +func (ew *exchangeWrapper[H]) GetByHeight(ctx context.Context, height uint64) (H, error) { + // Check DA store first + if ew.daStore != nil && ew.getterByHeight != nil { + if h, err := ew.getterByHeight(ctx, ew.daStore, height); err == nil && !h.IsZero() { + return h, nil + } + } + + // Fallback to network exchange + return ew.p2pExchange.GetByHeight(ctx, height) +} + +func (ew *exchangeWrapper[H]) Head(ctx context.Context, opts ...header.HeadOption[H]) (H, error) { + return ew.p2pExchange.Head(ctx, opts...) +} + +func (ew *exchangeWrapper[H]) GetRangeByHeight(ctx context.Context, from H, to uint64) ([]H, error) { + return ew.p2pExchange.GetRangeByHeight(ctx, from, to) +} + +func (ew *exchangeWrapper[H]) Start(ctx context.Context) error { + return ew.p2pExchange.Start(ctx) +} + +func (ew *exchangeWrapper[H]) Stop(ctx context.Context) error { + return ew.p2pExchange.Stop(ctx) +} diff --git a/pkg/sync/exchange_wrapper_test.go b/pkg/sync/exchange_wrapper_test.go new file mode 100644 index 0000000000..fba9a51676 --- /dev/null +++ b/pkg/sync/exchange_wrapper_test.go @@ -0,0 +1,116 @@ +package sync + +import ( + "context" + "errors" + "testing" + + "github.com/celestiaorg/go-header" + "github.com/evstack/ev-node/pkg/store" + "github.com/evstack/ev-node/test/mocks" + extmocks "github.com/evstack/ev-node/test/mocks/external" + "github.com/evstack/ev-node/types" + "github.com/stretchr/testify/assert" +) + +func TestExchangeWrapper_Get(t *testing.T) { + ctx := context.Background() + hash := header.Hash([]byte("test-hash")) + expectedHeader := &types.SignedHeader{} // Just a dummy + + t.Run("Hit in Store", func(t *testing.T) { + mockEx := extmocks.NewMockP2PExchange[*types.SignedHeader](t) + // Exchange should NOT be called + + getter := func(ctx context.Context, s store.Store, h header.Hash) (*types.SignedHeader, error) { + return expectedHeader, nil + } + + ew := &exchangeWrapper[*types.SignedHeader]{ + p2pExchange: mockEx, + daStore: mocks.NewMockStore(t), + getter: getter, + } + + h, err := ew.Get(ctx, hash) + assert.NoError(t, err) + assert.Equal(t, expectedHeader, h) + }) + + t.Run("Miss in Store", func(t *testing.T) { + mockEx := extmocks.NewMockP2PExchange[*types.SignedHeader](t) + mockEx.EXPECT().Get(ctx, hash).Return(expectedHeader, nil) + + getter := func(ctx context.Context, s store.Store, h header.Hash) (*types.SignedHeader, error) { + return nil, errors.New("not found") + } + + ew := &exchangeWrapper[*types.SignedHeader]{ + p2pExchange: mockEx, + daStore: mocks.NewMockStore(t), + getter: getter, + } + + h, err := ew.Get(ctx, hash) + assert.NoError(t, err) + assert.Equal(t, expectedHeader, h) + }) + + t.Run("Store Not Configured", func(t *testing.T) { + mockEx := extmocks.NewMockP2PExchange[*types.SignedHeader](t) + mockEx.EXPECT().Get(ctx, hash).Return(expectedHeader, nil) + + ew := &exchangeWrapper[*types.SignedHeader]{ + p2pExchange: mockEx, + daStore: nil, // No store + getter: nil, + } + + h, err := ew.Get(ctx, hash) + assert.NoError(t, err) + assert.Equal(t, expectedHeader, h) + }) +} + +func TestExchangeWrapper_GetByHeight(t *testing.T) { + ctx := context.Background() + height := uint64(10) + expectedHeader := &types.SignedHeader{} + + t.Run("Hit in Store", func(t *testing.T) { + mockEx := extmocks.NewMockP2PExchange[*types.SignedHeader](t) + + getterByHeight := func(ctx context.Context, s store.Store, h uint64) (*types.SignedHeader, error) { + return expectedHeader, nil + } + + ew := &exchangeWrapper[*types.SignedHeader]{ + p2pExchange: mockEx, + daStore: mocks.NewMockStore(t), + getterByHeight: getterByHeight, + } + + h, err := ew.GetByHeight(ctx, height) + assert.NoError(t, err) + assert.Equal(t, expectedHeader, h) + }) + + t.Run("Miss in Store", func(t *testing.T) { + mockEx := extmocks.NewMockP2PExchange[*types.SignedHeader](t) + mockEx.EXPECT().GetByHeight(ctx, height).Return(expectedHeader, nil) + + getterByHeight := func(ctx context.Context, s store.Store, h uint64) (*types.SignedHeader, error) { + return nil, errors.New("not found") + } + + ew := &exchangeWrapper[*types.SignedHeader]{ + p2pExchange: mockEx, + daStore: mocks.NewMockStore(t), + getterByHeight: getterByHeight, + } + + h, err := ew.GetByHeight(ctx, height) + assert.NoError(t, err) + assert.Equal(t, expectedHeader, h) + }) +} diff --git a/pkg/sync/sync_service.go b/pkg/sync/sync_service.go index 9b018460ed..822a1f661f 100644 --- a/pkg/sync/sync_service.go +++ b/pkg/sync/sync_service.go @@ -23,6 +23,7 @@ import ( "github.com/evstack/ev-node/pkg/config" "github.com/evstack/ev-node/pkg/genesis" "github.com/evstack/ev-node/pkg/p2p" + "github.com/evstack/ev-node/pkg/store" "github.com/evstack/ev-node/types" ) @@ -48,14 +49,18 @@ type SyncService[H header.Header[H]] struct { p2p *p2p.Client - ex *goheaderp2p.Exchange[H] + ex *exchangeWrapper[H] sub *goheaderp2p.Subscriber[H] p2pServer *goheaderp2p.ExchangeServer[H] store *goheaderstore.Store[H] + daStore store.Store syncer *goheadersync.Syncer[H] syncerStatus *SyncerStatus topicSubscription header.Subscription[H] - storeInitialized atomic.Bool + + getter storeGetter[H] + getterByHeight storeGetterByHeight[H] + storeInitialized atomic.Bool } // DataSyncService is the P2P Sync Service for blocks. @@ -66,28 +71,48 @@ type HeaderSyncService = SyncService[*types.SignedHeader] // NewDataSyncService returns a new DataSyncService. func NewDataSyncService( - store ds.Batching, + dsStore ds.Batching, + daStore store.Store, conf config.Config, genesis genesis.Genesis, p2p *p2p.Client, logger zerolog.Logger, ) (*DataSyncService, error) { - return newSyncService[*types.Data](store, dataSync, conf, genesis, p2p, logger) + getter := func(ctx context.Context, s store.Store, hash header.Hash) (*types.Data, error) { + _, d, err := s.GetBlockByHash(ctx, hash) + return d, err + } + getterByHeight := func(ctx context.Context, s store.Store, height uint64) (*types.Data, error) { + _, d, err := s.GetBlockData(ctx, height) + return d, err + } + return newSyncService[*types.Data](dsStore, daStore, getter, getterByHeight, dataSync, conf, genesis, p2p, logger) } // NewHeaderSyncService returns a new HeaderSyncService. func NewHeaderSyncService( - store ds.Batching, + dsStore ds.Batching, + daStore store.Store, conf config.Config, genesis genesis.Genesis, p2p *p2p.Client, logger zerolog.Logger, ) (*HeaderSyncService, error) { - return newSyncService[*types.SignedHeader](store, headerSync, conf, genesis, p2p, logger) + getter := func(ctx context.Context, s store.Store, hash header.Hash) (*types.SignedHeader, error) { + h, _, err := s.GetBlockByHash(ctx, hash) + return h, err + } + getterByHeight := func(ctx context.Context, s store.Store, height uint64) (*types.SignedHeader, error) { + return s.GetHeader(ctx, height) + } + return newSyncService[*types.SignedHeader](dsStore, daStore, getter, getterByHeight, headerSync, conf, genesis, p2p, logger) } func newSyncService[H header.Header[H]]( - store ds.Batching, + dsStore ds.Batching, + daStore store.Store, + getter storeGetter[H], + getterByHeight storeGetterByHeight[H], syncType syncType, conf config.Config, genesis genesis.Genesis, @@ -99,7 +124,7 @@ func newSyncService[H header.Header[H]]( } ss, err := goheaderstore.NewStore[H]( - store, + dsStore, goheaderstore.WithStorePrefix(string(syncType)), goheaderstore.WithMetrics(), ) @@ -108,13 +133,16 @@ func newSyncService[H header.Header[H]]( } svc := &SyncService[H]{ - conf: conf, - genesis: genesis, - p2p: p2p, - store: ss, - syncType: syncType, - logger: logger, - syncerStatus: new(SyncerStatus), + conf: conf, + genesis: genesis, + p2p: p2p, + store: ss, + daStore: daStore, + getter: getter, + getterByHeight: getterByHeight, + syncType: syncType, + logger: logger, + syncerStatus: new(SyncerStatus), } return svc, nil @@ -283,12 +311,22 @@ func (syncService *SyncService[H]) setupP2PInfrastructure(ctx context.Context) ( peerIDs := syncService.getPeerIDs() - if syncService.ex, err = newP2PExchange[H](syncService.p2p.Host(), peerIDs, networkID, syncService.genesis.ChainID, syncService.p2p.ConnectionGater()); err != nil { + p2pExchange, err := newP2PExchange[H](syncService.p2p.Host(), peerIDs, networkID, syncService.genesis.ChainID, syncService.p2p.ConnectionGater()) + if err != nil { return nil, fmt.Errorf("error while creating exchange: %w", err) } + + // Create exchange wrapper with DA store check + syncService.ex = &exchangeWrapper[H]{ + p2pExchange: p2pExchange, + daStore: syncService.daStore, + getter: syncService.getter, + getterByHeight: syncService.getterByHeight, + } if err := syncService.ex.Start(ctx); err != nil { return nil, fmt.Errorf("error while starting exchange: %w", err) } + return peerIDs, nil } diff --git a/pkg/sync/sync_service_test.go b/pkg/sync/sync_service_test.go index 93603752a7..cd434bc7b9 100644 --- a/pkg/sync/sync_service_test.go +++ b/pkg/sync/sync_service_test.go @@ -21,6 +21,8 @@ import ( mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" "github.com/rs/zerolog" "github.com/stretchr/testify/require" + + "github.com/evstack/ev-node/pkg/store" ) func TestHeaderSyncServiceRestart(t *testing.T) { @@ -58,7 +60,8 @@ func TestHeaderSyncServiceRestart(t *testing.T) { defer cancel() require.NoError(t, p2pClient.Start(ctx)) - svc, err := NewHeaderSyncService(mainKV, conf, genesisDoc, p2pClient, logger) + rktStore := store.New(mainKV) + svc, err := NewHeaderSyncService(mainKV, rktStore, conf, genesisDoc, p2pClient, logger) require.NoError(t, err) err = svc.Start(ctx) require.NoError(t, err) @@ -98,7 +101,7 @@ func TestHeaderSyncServiceRestart(t *testing.T) { require.NoError(t, err) t.Cleanup(func() { _ = p2pClient.Close() }) - svc, err = NewHeaderSyncService(mainKV, conf, genesisDoc, p2pClient, logger) + svc, err = NewHeaderSyncService(mainKV, rktStore, conf, genesisDoc, p2pClient, logger) require.NoError(t, err) err = svc.Start(ctx) require.NoError(t, err) @@ -149,7 +152,8 @@ func TestHeaderSyncServiceInitFromHigherHeight(t *testing.T) { require.NoError(t, p2pClient.Start(ctx)) t.Cleanup(func() { _ = p2pClient.Close() }) - svc, err := NewHeaderSyncService(mainKV, conf, genesisDoc, p2pClient, logger) + rktStore := store.New(mainKV) + svc, err := NewHeaderSyncService(mainKV, rktStore, conf, genesisDoc, p2pClient, logger) require.NoError(t, err) require.NoError(t, svc.Start(ctx)) t.Cleanup(func() { _ = svc.Stop(context.Background()) }) diff --git a/sequencers/based/README.md b/sequencers/based/README.md index 9b425b5a96..6b15105474 100644 --- a/sequencers/based/README.md +++ b/sequencers/based/README.md @@ -59,7 +59,7 @@ When at an epoch end, the retriever fetches transactions from **all DA blocks in 3. Fetches forced inclusion blobs from `epochEnd` 4. Returns all transactions as a single `ForcedInclusionEvent` -### Why Epoch-Based? +### Why Epoch-Based - **Efficiency**: Reduces the number of DA queries - **Batching**: Allows processing multiple DA blocks worth of transactions together diff --git a/test/mocks/external/hexchange.go b/test/mocks/external/hexchange.go new file mode 100644 index 0000000000..cfa5729e5d --- /dev/null +++ b/test/mocks/external/hexchange.go @@ -0,0 +1,330 @@ +// Code generated by mockery; DO NOT EDIT. +// github.com/vektra/mockery +// template: testify + +package mocks + +import ( + "context" + + "github.com/celestiaorg/go-header" + mock "github.com/stretchr/testify/mock" +) + +// NewMockExchange creates a new instance of MockExchange. 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 NewMockExchange[H header.Header[H]](t interface { + mock.TestingT + Cleanup(func()) +}) *MockExchange[H] { + mock := &MockExchange[H]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} + +// MockExchange is an autogenerated mock type for the Exchange type +type MockExchange[H header.Header[H]] struct { + mock.Mock +} + +type MockExchange_Expecter[H header.Header[H]] struct { + mock *mock.Mock +} + +func (_m *MockExchange[H]) EXPECT() *MockExchange_Expecter[H] { + return &MockExchange_Expecter[H]{mock: &_m.Mock} +} + +// Get provides a mock function for the type MockExchange +func (_mock *MockExchange[H]) Get(context1 context.Context, hash header.Hash) (H, error) { + ret := _mock.Called(context1, hash) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 H + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, header.Hash) (H, error)); ok { + return returnFunc(context1, hash) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, header.Hash) H); ok { + r0 = returnFunc(context1, hash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, header.Hash) error); ok { + r1 = returnFunc(context1, hash) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockExchange_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type MockExchange_Get_Call[H header.Header[H]] struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - context1 context.Context +// - hash header.Hash +func (_e *MockExchange_Expecter[H]) Get(context1 interface{}, hash interface{}) *MockExchange_Get_Call[H] { + return &MockExchange_Get_Call[H]{Call: _e.mock.On("Get", context1, hash)} +} + +func (_c *MockExchange_Get_Call[H]) Run(run func(context1 context.Context, hash header.Hash)) *MockExchange_Get_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 header.Hash + if args[1] != nil { + arg1 = args[1].(header.Hash) + } + run( + arg0, + arg1, + ) + }) + return _c +} + +func (_c *MockExchange_Get_Call[H]) Return(v H, err error) *MockExchange_Get_Call[H] { + _c.Call.Return(v, err) + return _c +} + +func (_c *MockExchange_Get_Call[H]) RunAndReturn(run func(context1 context.Context, hash header.Hash) (H, error)) *MockExchange_Get_Call[H] { + _c.Call.Return(run) + return _c +} + +// GetByHeight provides a mock function for the type MockExchange +func (_mock *MockExchange[H]) GetByHeight(context1 context.Context, v uint64) (H, error) { + ret := _mock.Called(context1, v) + + if len(ret) == 0 { + panic("no return value specified for GetByHeight") + } + + var r0 H + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, uint64) (H, error)); ok { + return returnFunc(context1, v) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, uint64) H); ok { + r0 = returnFunc(context1, v) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = returnFunc(context1, v) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockExchange_GetByHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetByHeight' +type MockExchange_GetByHeight_Call[H header.Header[H]] struct { + *mock.Call +} + +// GetByHeight is a helper method to define mock.On call +// - context1 context.Context +// - v uint64 +func (_e *MockExchange_Expecter[H]) GetByHeight(context1 interface{}, v interface{}) *MockExchange_GetByHeight_Call[H] { + return &MockExchange_GetByHeight_Call[H]{Call: _e.mock.On("GetByHeight", context1, v)} +} + +func (_c *MockExchange_GetByHeight_Call[H]) Run(run func(context1 context.Context, v uint64)) *MockExchange_GetByHeight_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 uint64 + if args[1] != nil { + arg1 = args[1].(uint64) + } + run( + arg0, + arg1, + ) + }) + return _c +} + +func (_c *MockExchange_GetByHeight_Call[H]) Return(v1 H, err error) *MockExchange_GetByHeight_Call[H] { + _c.Call.Return(v1, err) + return _c +} + +func (_c *MockExchange_GetByHeight_Call[H]) RunAndReturn(run func(context1 context.Context, v uint64) (H, error)) *MockExchange_GetByHeight_Call[H] { + _c.Call.Return(run) + return _c +} + +// GetRangeByHeight provides a mock function for the type MockExchange +func (_mock *MockExchange[H]) GetRangeByHeight(ctx context.Context, from H, to uint64) ([]H, error) { + ret := _mock.Called(ctx, from, to) + + if len(ret) == 0 { + panic("no return value specified for GetRangeByHeight") + } + + var r0 []H + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, H, uint64) ([]H, error)); ok { + return returnFunc(ctx, from, to) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, H, uint64) []H); ok { + r0 = returnFunc(ctx, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]H) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, H, uint64) error); ok { + r1 = returnFunc(ctx, from, to) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockExchange_GetRangeByHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRangeByHeight' +type MockExchange_GetRangeByHeight_Call[H header.Header[H]] struct { + *mock.Call +} + +// GetRangeByHeight is a helper method to define mock.On call +// - ctx context.Context +// - from H +// - to uint64 +func (_e *MockExchange_Expecter[H]) GetRangeByHeight(ctx interface{}, from interface{}, to interface{}) *MockExchange_GetRangeByHeight_Call[H] { + return &MockExchange_GetRangeByHeight_Call[H]{Call: _e.mock.On("GetRangeByHeight", ctx, from, to)} +} + +func (_c *MockExchange_GetRangeByHeight_Call[H]) Run(run func(ctx context.Context, from H, to uint64)) *MockExchange_GetRangeByHeight_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 H + if args[1] != nil { + arg1 = args[1].(H) + } + var arg2 uint64 + if args[2] != nil { + arg2 = args[2].(uint64) + } + run( + arg0, + arg1, + arg2, + ) + }) + return _c +} + +func (_c *MockExchange_GetRangeByHeight_Call[H]) Return(vs []H, err error) *MockExchange_GetRangeByHeight_Call[H] { + _c.Call.Return(vs, err) + return _c +} + +func (_c *MockExchange_GetRangeByHeight_Call[H]) RunAndReturn(run func(ctx context.Context, from H, to uint64) ([]H, error)) *MockExchange_GetRangeByHeight_Call[H] { + _c.Call.Return(run) + return _c +} + +// Head provides a mock function for the type MockExchange +func (_mock *MockExchange[H]) Head(context1 context.Context, headOptions ...header.HeadOption[H]) (H, error) { + // header.HeadOption[H] + _va := make([]interface{}, len(headOptions)) + for _i := range headOptions { + _va[_i] = headOptions[_i] + } + var _ca []interface{} + _ca = append(_ca, context1) + _ca = append(_ca, _va...) + ret := _mock.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Head") + } + + var r0 H + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, ...header.HeadOption[H]) (H, error)); ok { + return returnFunc(context1, headOptions...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, ...header.HeadOption[H]) H); ok { + r0 = returnFunc(context1, headOptions...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, ...header.HeadOption[H]) error); ok { + r1 = returnFunc(context1, headOptions...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockExchange_Head_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Head' +type MockExchange_Head_Call[H header.Header[H]] struct { + *mock.Call +} + +// Head is a helper method to define mock.On call +// - context1 context.Context +// - headOptions ...header.HeadOption[H] +func (_e *MockExchange_Expecter[H]) Head(context1 interface{}, headOptions ...interface{}) *MockExchange_Head_Call[H] { + return &MockExchange_Head_Call[H]{Call: _e.mock.On("Head", + append([]interface{}{context1}, headOptions...)...)} +} + +func (_c *MockExchange_Head_Call[H]) Run(run func(context1 context.Context, headOptions ...header.HeadOption[H])) *MockExchange_Head_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 []header.HeadOption[H] + variadicArgs := make([]header.HeadOption[H], len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(header.HeadOption[H]) + } + } + arg1 = variadicArgs + run( + arg0, + arg1..., + ) + }) + return _c +} + +func (_c *MockExchange_Head_Call[H]) Return(v H, err error) *MockExchange_Head_Call[H] { + _c.Call.Return(v, err) + return _c +} + +func (_c *MockExchange_Head_Call[H]) RunAndReturn(run func(context1 context.Context, headOptions ...header.HeadOption[H]) (H, error)) *MockExchange_Head_Call[H] { + _c.Call.Return(run) + return _c +} diff --git a/test/mocks/external/p2pexchange.go b/test/mocks/external/p2pexchange.go new file mode 100644 index 0000000000..2ed96418cb --- /dev/null +++ b/test/mocks/external/p2pexchange.go @@ -0,0 +1,432 @@ +// Code generated by mockery; DO NOT EDIT. +// github.com/vektra/mockery +// template: testify + +package mocks + +import ( + "context" + + "github.com/celestiaorg/go-header" + mock "github.com/stretchr/testify/mock" +) + +// NewMockP2PExchange creates a new instance of MockP2PExchange. 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 NewMockP2PExchange[H header.Header[H]](t interface { + mock.TestingT + Cleanup(func()) +}) *MockP2PExchange[H] { + mock := &MockP2PExchange[H]{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} + +// MockP2PExchange is an autogenerated mock type for the P2PExchange type +type MockP2PExchange[H header.Header[H]] struct { + mock.Mock +} + +type MockP2PExchange_Expecter[H header.Header[H]] struct { + mock *mock.Mock +} + +func (_m *MockP2PExchange[H]) EXPECT() *MockP2PExchange_Expecter[H] { + return &MockP2PExchange_Expecter[H]{mock: &_m.Mock} +} + +// Get provides a mock function for the type MockP2PExchange +func (_mock *MockP2PExchange[H]) Get(context1 context.Context, hash header.Hash) (H, error) { + ret := _mock.Called(context1, hash) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 H + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, header.Hash) (H, error)); ok { + return returnFunc(context1, hash) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, header.Hash) H); ok { + r0 = returnFunc(context1, hash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, header.Hash) error); ok { + r1 = returnFunc(context1, hash) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockP2PExchange_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type MockP2PExchange_Get_Call[H header.Header[H]] struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - context1 context.Context +// - hash header.Hash +func (_e *MockP2PExchange_Expecter[H]) Get(context1 interface{}, hash interface{}) *MockP2PExchange_Get_Call[H] { + return &MockP2PExchange_Get_Call[H]{Call: _e.mock.On("Get", context1, hash)} +} + +func (_c *MockP2PExchange_Get_Call[H]) Run(run func(context1 context.Context, hash header.Hash)) *MockP2PExchange_Get_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 header.Hash + if args[1] != nil { + arg1 = args[1].(header.Hash) + } + run( + arg0, + arg1, + ) + }) + return _c +} + +func (_c *MockP2PExchange_Get_Call[H]) Return(v H, err error) *MockP2PExchange_Get_Call[H] { + _c.Call.Return(v, err) + return _c +} + +func (_c *MockP2PExchange_Get_Call[H]) RunAndReturn(run func(context1 context.Context, hash header.Hash) (H, error)) *MockP2PExchange_Get_Call[H] { + _c.Call.Return(run) + return _c +} + +// GetByHeight provides a mock function for the type MockP2PExchange +func (_mock *MockP2PExchange[H]) GetByHeight(context1 context.Context, v uint64) (H, error) { + ret := _mock.Called(context1, v) + + if len(ret) == 0 { + panic("no return value specified for GetByHeight") + } + + var r0 H + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, uint64) (H, error)); ok { + return returnFunc(context1, v) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, uint64) H); ok { + r0 = returnFunc(context1, v) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = returnFunc(context1, v) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockP2PExchange_GetByHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetByHeight' +type MockP2PExchange_GetByHeight_Call[H header.Header[H]] struct { + *mock.Call +} + +// GetByHeight is a helper method to define mock.On call +// - context1 context.Context +// - v uint64 +func (_e *MockP2PExchange_Expecter[H]) GetByHeight(context1 interface{}, v interface{}) *MockP2PExchange_GetByHeight_Call[H] { + return &MockP2PExchange_GetByHeight_Call[H]{Call: _e.mock.On("GetByHeight", context1, v)} +} + +func (_c *MockP2PExchange_GetByHeight_Call[H]) Run(run func(context1 context.Context, v uint64)) *MockP2PExchange_GetByHeight_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 uint64 + if args[1] != nil { + arg1 = args[1].(uint64) + } + run( + arg0, + arg1, + ) + }) + return _c +} + +func (_c *MockP2PExchange_GetByHeight_Call[H]) Return(v1 H, err error) *MockP2PExchange_GetByHeight_Call[H] { + _c.Call.Return(v1, err) + return _c +} + +func (_c *MockP2PExchange_GetByHeight_Call[H]) RunAndReturn(run func(context1 context.Context, v uint64) (H, error)) *MockP2PExchange_GetByHeight_Call[H] { + _c.Call.Return(run) + return _c +} + +// GetRangeByHeight provides a mock function for the type MockP2PExchange +func (_mock *MockP2PExchange[H]) GetRangeByHeight(ctx context.Context, from H, to uint64) ([]H, error) { + ret := _mock.Called(ctx, from, to) + + if len(ret) == 0 { + panic("no return value specified for GetRangeByHeight") + } + + var r0 []H + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, H, uint64) ([]H, error)); ok { + return returnFunc(ctx, from, to) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, H, uint64) []H); ok { + r0 = returnFunc(ctx, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]H) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, H, uint64) error); ok { + r1 = returnFunc(ctx, from, to) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockP2PExchange_GetRangeByHeight_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRangeByHeight' +type MockP2PExchange_GetRangeByHeight_Call[H header.Header[H]] struct { + *mock.Call +} + +// GetRangeByHeight is a helper method to define mock.On call +// - ctx context.Context +// - from H +// - to uint64 +func (_e *MockP2PExchange_Expecter[H]) GetRangeByHeight(ctx interface{}, from interface{}, to interface{}) *MockP2PExchange_GetRangeByHeight_Call[H] { + return &MockP2PExchange_GetRangeByHeight_Call[H]{Call: _e.mock.On("GetRangeByHeight", ctx, from, to)} +} + +func (_c *MockP2PExchange_GetRangeByHeight_Call[H]) Run(run func(ctx context.Context, from H, to uint64)) *MockP2PExchange_GetRangeByHeight_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 H + if args[1] != nil { + arg1 = args[1].(H) + } + var arg2 uint64 + if args[2] != nil { + arg2 = args[2].(uint64) + } + run( + arg0, + arg1, + arg2, + ) + }) + return _c +} + +func (_c *MockP2PExchange_GetRangeByHeight_Call[H]) Return(vs []H, err error) *MockP2PExchange_GetRangeByHeight_Call[H] { + _c.Call.Return(vs, err) + return _c +} + +func (_c *MockP2PExchange_GetRangeByHeight_Call[H]) RunAndReturn(run func(ctx context.Context, from H, to uint64) ([]H, error)) *MockP2PExchange_GetRangeByHeight_Call[H] { + _c.Call.Return(run) + return _c +} + +// Head provides a mock function for the type MockP2PExchange +func (_mock *MockP2PExchange[H]) Head(context1 context.Context, headOptions ...header.HeadOption[H]) (H, error) { + // header.HeadOption[H] + _va := make([]interface{}, len(headOptions)) + for _i := range headOptions { + _va[_i] = headOptions[_i] + } + var _ca []interface{} + _ca = append(_ca, context1) + _ca = append(_ca, _va...) + ret := _mock.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Head") + } + + var r0 H + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, ...header.HeadOption[H]) (H, error)); ok { + return returnFunc(context1, headOptions...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, ...header.HeadOption[H]) H); ok { + r0 = returnFunc(context1, headOptions...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(H) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, ...header.HeadOption[H]) error); ok { + r1 = returnFunc(context1, headOptions...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockP2PExchange_Head_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Head' +type MockP2PExchange_Head_Call[H header.Header[H]] struct { + *mock.Call +} + +// Head is a helper method to define mock.On call +// - context1 context.Context +// - headOptions ...header.HeadOption[H] +func (_e *MockP2PExchange_Expecter[H]) Head(context1 interface{}, headOptions ...interface{}) *MockP2PExchange_Head_Call[H] { + return &MockP2PExchange_Head_Call[H]{Call: _e.mock.On("Head", + append([]interface{}{context1}, headOptions...)...)} +} + +func (_c *MockP2PExchange_Head_Call[H]) Run(run func(context1 context.Context, headOptions ...header.HeadOption[H])) *MockP2PExchange_Head_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 []header.HeadOption[H] + variadicArgs := make([]header.HeadOption[H], len(args)-1) + for i, a := range args[1:] { + if a != nil { + variadicArgs[i] = a.(header.HeadOption[H]) + } + } + arg1 = variadicArgs + run( + arg0, + arg1..., + ) + }) + return _c +} + +func (_c *MockP2PExchange_Head_Call[H]) Return(v H, err error) *MockP2PExchange_Head_Call[H] { + _c.Call.Return(v, err) + return _c +} + +func (_c *MockP2PExchange_Head_Call[H]) RunAndReturn(run func(context1 context.Context, headOptions ...header.HeadOption[H]) (H, error)) *MockP2PExchange_Head_Call[H] { + _c.Call.Return(run) + return _c +} + +// Start provides a mock function for the type MockP2PExchange +func (_mock *MockP2PExchange[H]) Start(context1 context.Context) error { + ret := _mock.Called(context1) + + if len(ret) == 0 { + panic("no return value specified for Start") + } + + var r0 error + if returnFunc, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = returnFunc(context1) + } else { + r0 = ret.Error(0) + } + return r0 +} + +// MockP2PExchange_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type MockP2PExchange_Start_Call[H header.Header[H]] struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - context1 context.Context +func (_e *MockP2PExchange_Expecter[H]) Start(context1 interface{}) *MockP2PExchange_Start_Call[H] { + return &MockP2PExchange_Start_Call[H]{Call: _e.mock.On("Start", context1)} +} + +func (_c *MockP2PExchange_Start_Call[H]) Run(run func(context1 context.Context)) *MockP2PExchange_Start_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + run( + arg0, + ) + }) + return _c +} + +func (_c *MockP2PExchange_Start_Call[H]) Return(err error) *MockP2PExchange_Start_Call[H] { + _c.Call.Return(err) + return _c +} + +func (_c *MockP2PExchange_Start_Call[H]) RunAndReturn(run func(context1 context.Context) error) *MockP2PExchange_Start_Call[H] { + _c.Call.Return(run) + return _c +} + +// Stop provides a mock function for the type MockP2PExchange +func (_mock *MockP2PExchange[H]) Stop(context1 context.Context) error { + ret := _mock.Called(context1) + + if len(ret) == 0 { + panic("no return value specified for Stop") + } + + var r0 error + if returnFunc, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = returnFunc(context1) + } else { + r0 = ret.Error(0) + } + return r0 +} + +// MockP2PExchange_Stop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Stop' +type MockP2PExchange_Stop_Call[H header.Header[H]] struct { + *mock.Call +} + +// Stop is a helper method to define mock.On call +// - context1 context.Context +func (_e *MockP2PExchange_Expecter[H]) Stop(context1 interface{}) *MockP2PExchange_Stop_Call[H] { + return &MockP2PExchange_Stop_Call[H]{Call: _e.mock.On("Stop", context1)} +} + +func (_c *MockP2PExchange_Stop_Call[H]) Run(run func(context1 context.Context)) *MockP2PExchange_Stop_Call[H] { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + run( + arg0, + ) + }) + return _c +} + +func (_c *MockP2PExchange_Stop_Call[H]) Return(err error) *MockP2PExchange_Stop_Call[H] { + _c.Call.Return(err) + return _c +} + +func (_c *MockP2PExchange_Stop_Call[H]) RunAndReturn(run func(context1 context.Context) error) *MockP2PExchange_Stop_Call[H] { + _c.Call.Return(run) + return _c +}