diff --git a/Makefile b/Makefile index a39be25aa7..78bf46cf02 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,8 @@ protoc: generate-mocks: go generate mockgen -destination=./tests/bor/mocks/IHeimdallClient.go -package=mocks ./consensus/bor IHeimdallClient - + go generate mockgen -destination=./eth/filters/IBackend.go -package=filters ./eth/filters Backend + geth: $(GORUN) build/ci.go install ./cmd/geth @echo "Done building." diff --git a/eth/filters/IBackend.go b/eth/filters/IBackend.go new file mode 100644 index 0000000000..df844e82b9 --- /dev/null +++ b/eth/filters/IBackend.go @@ -0,0 +1,257 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ethereum/go-ethereum/eth/filters (interfaces: Backend) + +// Package filters is a generated GoMock package. +package filters + +import ( + context "context" + reflect "reflect" + + common "github.com/ethereum/go-ethereum/common" + core "github.com/ethereum/go-ethereum/core" + bloombits "github.com/ethereum/go-ethereum/core/bloombits" + types "github.com/ethereum/go-ethereum/core/types" + ethdb "github.com/ethereum/go-ethereum/ethdb" + event "github.com/ethereum/go-ethereum/event" + rpc "github.com/ethereum/go-ethereum/rpc" + gomock "github.com/golang/mock/gomock" +) + +// MockBackend is a mock of Backend interface. +type MockBackend struct { + ctrl *gomock.Controller + recorder *MockBackendMockRecorder +} + +// MockBackendMockRecorder is the mock recorder for MockBackend. +type MockBackendMockRecorder struct { + mock *MockBackend +} + +// NewMockBackend creates a new mock instance. +func NewMockBackend(ctrl *gomock.Controller) *MockBackend { + mock := &MockBackend{ctrl: ctrl} + mock.recorder = &MockBackendMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBackend) EXPECT() *MockBackendMockRecorder { + return m.recorder +} + +// BloomStatus mocks base method. +func (m *MockBackend) BloomStatus() (uint64, uint64) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BloomStatus") + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(uint64) + return ret0, ret1 +} + +// BloomStatus indicates an expected call of BloomStatus. +func (mr *MockBackendMockRecorder) BloomStatus() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BloomStatus", reflect.TypeOf((*MockBackend)(nil).BloomStatus)) +} + +// ChainDb mocks base method. +func (m *MockBackend) ChainDb() ethdb.Database { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChainDb") + ret0, _ := ret[0].(ethdb.Database) + return ret0 +} + +// ChainDb indicates an expected call of ChainDb. +func (mr *MockBackendMockRecorder) ChainDb() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainDb", reflect.TypeOf((*MockBackend)(nil).ChainDb)) +} + +// GetBorBlockLogs mocks base method. +func (m *MockBackend) GetBorBlockLogs(arg0 context.Context, arg1 common.Hash) ([]*types.Log, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBorBlockLogs", arg0, arg1) + ret0, _ := ret[0].([]*types.Log) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetBorBlockLogs indicates an expected call of GetBorBlockLogs. +func (mr *MockBackendMockRecorder) GetBorBlockLogs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockLogs", reflect.TypeOf((*MockBackend)(nil).GetBorBlockLogs), arg0, arg1) +} + +// GetBorBlockReceipt mocks base method. +func (m *MockBackend) GetBorBlockReceipt(arg0 context.Context, arg1 common.Hash) (*types.Receipt, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBorBlockReceipt", arg0, arg1) + ret0, _ := ret[0].(*types.Receipt) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetBorBlockReceipt indicates an expected call of GetBorBlockReceipt. +func (mr *MockBackendMockRecorder) GetBorBlockReceipt(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockReceipt", reflect.TypeOf((*MockBackend)(nil).GetBorBlockReceipt), arg0, arg1) +} + +// GetLogs mocks base method. +func (m *MockBackend) GetLogs(arg0 context.Context, arg1 common.Hash) ([][]*types.Log, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLogs", arg0, arg1) + ret0, _ := ret[0].([][]*types.Log) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetLogs indicates an expected call of GetLogs. +func (mr *MockBackendMockRecorder) GetLogs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogs", reflect.TypeOf((*MockBackend)(nil).GetLogs), arg0, arg1) +} + +// GetReceipts mocks base method. +func (m *MockBackend) GetReceipts(arg0 context.Context, arg1 common.Hash) (types.Receipts, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetReceipts", arg0, arg1) + ret0, _ := ret[0].(types.Receipts) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetReceipts indicates an expected call of GetReceipts. +func (mr *MockBackendMockRecorder) GetReceipts(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipts", reflect.TypeOf((*MockBackend)(nil).GetReceipts), arg0, arg1) +} + +// HeaderByHash mocks base method. +func (m *MockBackend) HeaderByHash(arg0 context.Context, arg1 common.Hash) (*types.Header, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HeaderByHash", arg0, arg1) + ret0, _ := ret[0].(*types.Header) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HeaderByHash indicates an expected call of HeaderByHash. +func (mr *MockBackendMockRecorder) HeaderByHash(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByHash", reflect.TypeOf((*MockBackend)(nil).HeaderByHash), arg0, arg1) +} + +// HeaderByNumber mocks base method. +func (m *MockBackend) HeaderByNumber(arg0 context.Context, arg1 rpc.BlockNumber) (*types.Header, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HeaderByNumber", arg0, arg1) + ret0, _ := ret[0].(*types.Header) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HeaderByNumber indicates an expected call of HeaderByNumber. +func (mr *MockBackendMockRecorder) HeaderByNumber(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByNumber", reflect.TypeOf((*MockBackend)(nil).HeaderByNumber), arg0, arg1) +} + +// ServiceFilter mocks base method. +func (m *MockBackend) ServiceFilter(arg0 context.Context, arg1 *bloombits.MatcherSession) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ServiceFilter", arg0, arg1) +} + +// ServiceFilter indicates an expected call of ServiceFilter. +func (mr *MockBackendMockRecorder) ServiceFilter(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServiceFilter", reflect.TypeOf((*MockBackend)(nil).ServiceFilter), arg0, arg1) +} + +// SubscribeChainEvent mocks base method. +func (m *MockBackend) SubscribeChainEvent(arg0 chan<- core.ChainEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeChainEvent", arg0) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeChainEvent indicates an expected call of SubscribeChainEvent. +func (mr *MockBackendMockRecorder) SubscribeChainEvent(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChainEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChainEvent), arg0) +} + +// SubscribeLogsEvent mocks base method. +func (m *MockBackend) SubscribeLogsEvent(arg0 chan<- []*types.Log) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeLogsEvent", arg0) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeLogsEvent indicates an expected call of SubscribeLogsEvent. +func (mr *MockBackendMockRecorder) SubscribeLogsEvent(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeLogsEvent), arg0) +} + +// SubscribeNewTxsEvent mocks base method. +func (m *MockBackend) SubscribeNewTxsEvent(arg0 chan<- core.NewTxsEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeNewTxsEvent", arg0) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeNewTxsEvent indicates an expected call of SubscribeNewTxsEvent. +func (mr *MockBackendMockRecorder) SubscribeNewTxsEvent(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeNewTxsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeNewTxsEvent), arg0) +} + +// SubscribePendingLogsEvent mocks base method. +func (m *MockBackend) SubscribePendingLogsEvent(arg0 chan<- []*types.Log) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribePendingLogsEvent", arg0) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribePendingLogsEvent indicates an expected call of SubscribePendingLogsEvent. +func (mr *MockBackendMockRecorder) SubscribePendingLogsEvent(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribePendingLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribePendingLogsEvent), arg0) +} + +// SubscribeRemovedLogsEvent mocks base method. +func (m *MockBackend) SubscribeRemovedLogsEvent(arg0 chan<- core.RemovedLogsEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeRemovedLogsEvent", arg0) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeRemovedLogsEvent indicates an expected call of SubscribeRemovedLogsEvent. +func (mr *MockBackendMockRecorder) SubscribeRemovedLogsEvent(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeRemovedLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeRemovedLogsEvent), arg0) +} + +// SubscribeStateSyncEvent mocks base method. +func (m *MockBackend) SubscribeStateSyncEvent(arg0 chan<- core.StateSyncEvent) event.Subscription { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubscribeStateSyncEvent", arg0) + ret0, _ := ret[0].(event.Subscription) + return ret0 +} + +// SubscribeStateSyncEvent indicates an expected call of SubscribeStateSyncEvent. +func (mr *MockBackendMockRecorder) SubscribeStateSyncEvent(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeStateSyncEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeStateSyncEvent), arg0) +} diff --git a/eth/filters/IDatabase.go b/eth/filters/IDatabase.go new file mode 100644 index 0000000000..fd0824b60d --- /dev/null +++ b/eth/filters/IDatabase.go @@ -0,0 +1,368 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ethereum/go-ethereum/ethdb (interfaces: Database) + +// Package filters is a generated GoMock package. +package filters + +import ( + reflect "reflect" + + ethdb "github.com/ethereum/go-ethereum/ethdb" + gomock "github.com/golang/mock/gomock" +) + +// MockDatabase is a mock of Database interface. +type MockDatabase struct { + ctrl *gomock.Controller + recorder *MockDatabaseMockRecorder +} + +// MockDatabaseMockRecorder is the mock recorder for MockDatabase. +type MockDatabaseMockRecorder struct { + mock *MockDatabase +} + +// NewMockDatabase creates a new mock instance. +func NewMockDatabase(ctrl *gomock.Controller) *MockDatabase { + mock := &MockDatabase{ctrl: ctrl} + mock.recorder = &MockDatabaseMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDatabase) EXPECT() *MockDatabaseMockRecorder { + return m.recorder +} + +// Ancient mocks base method. +func (m *MockDatabase) Ancient(arg0 string, arg1 uint64) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Ancient", arg0, arg1) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Ancient indicates an expected call of Ancient. +func (mr *MockDatabaseMockRecorder) Ancient(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ancient", reflect.TypeOf((*MockDatabase)(nil).Ancient), arg0, arg1) +} + +// AncientRange mocks base method. +func (m *MockDatabase) AncientRange(arg0 string, arg1, arg2, arg3 uint64) ([][]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AncientRange", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].([][]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AncientRange indicates an expected call of AncientRange. +func (mr *MockDatabaseMockRecorder) AncientRange(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientRange", reflect.TypeOf((*MockDatabase)(nil).AncientRange), arg0, arg1, arg2, arg3) +} + +// AncientSize mocks base method. +func (m *MockDatabase) AncientSize(arg0 string) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AncientSize", arg0) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AncientSize indicates an expected call of AncientSize. +func (mr *MockDatabaseMockRecorder) AncientSize(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientSize", reflect.TypeOf((*MockDatabase)(nil).AncientSize), arg0) +} + +// Ancients mocks base method. +func (m *MockDatabase) Ancients() (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Ancients") + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Ancients indicates an expected call of Ancients. +func (mr *MockDatabaseMockRecorder) Ancients() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ancients", reflect.TypeOf((*MockDatabase)(nil).Ancients)) +} + +// Close mocks base method. +func (m *MockDatabase) Close() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 +} + +// Close indicates an expected call of Close. +func (mr *MockDatabaseMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockDatabase)(nil).Close)) +} + +// Compact mocks base method. +func (m *MockDatabase) Compact(arg0, arg1 []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Compact", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// Compact indicates an expected call of Compact. +func (mr *MockDatabaseMockRecorder) Compact(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Compact", reflect.TypeOf((*MockDatabase)(nil).Compact), arg0, arg1) +} + +// Delete mocks base method. +func (m *MockDatabase) Delete(arg0 []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockDatabaseMockRecorder) Delete(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockDatabase)(nil).Delete), arg0) +} + +// Get mocks base method. +func (m *MockDatabase) Get(arg0 []byte) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockDatabaseMockRecorder) Get(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDatabase)(nil).Get), arg0) +} + +// Has mocks base method. +func (m *MockDatabase) Has(arg0 []byte) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Has", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Has indicates an expected call of Has. +func (mr *MockDatabaseMockRecorder) Has(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockDatabase)(nil).Has), arg0) +} + +// HasAncient mocks base method. +func (m *MockDatabase) HasAncient(arg0 string, arg1 uint64) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasAncient", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HasAncient indicates an expected call of HasAncient. +func (mr *MockDatabaseMockRecorder) HasAncient(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasAncient", reflect.TypeOf((*MockDatabase)(nil).HasAncient), arg0, arg1) +} + +// MigrateTable mocks base method. +func (m *MockDatabase) MigrateTable(arg0 string, arg1 func([]byte) ([]byte, error)) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MigrateTable", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// MigrateTable indicates an expected call of MigrateTable. +func (mr *MockDatabaseMockRecorder) MigrateTable(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MigrateTable", reflect.TypeOf((*MockDatabase)(nil).MigrateTable), arg0, arg1) +} + +// ModifyAncients mocks base method. +func (m *MockDatabase) ModifyAncients(arg0 func(ethdb.AncientWriteOp) error) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ModifyAncients", arg0) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ModifyAncients indicates an expected call of ModifyAncients. +func (mr *MockDatabaseMockRecorder) ModifyAncients(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyAncients", reflect.TypeOf((*MockDatabase)(nil).ModifyAncients), arg0) +} + +// NewBatch mocks base method. +func (m *MockDatabase) NewBatch() ethdb.Batch { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewBatch") + ret0, _ := ret[0].(ethdb.Batch) + return ret0 +} + +// NewBatch indicates an expected call of NewBatch. +func (mr *MockDatabaseMockRecorder) NewBatch() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatch", reflect.TypeOf((*MockDatabase)(nil).NewBatch)) +} + +// NewBatchWithSize mocks base method. +func (m *MockDatabase) NewBatchWithSize(arg0 int) ethdb.Batch { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewBatchWithSize", arg0) + ret0, _ := ret[0].(ethdb.Batch) + return ret0 +} + +// NewBatchWithSize indicates an expected call of NewBatchWithSize. +func (mr *MockDatabaseMockRecorder) NewBatchWithSize(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatchWithSize", reflect.TypeOf((*MockDatabase)(nil).NewBatchWithSize), arg0) +} + +// NewIterator mocks base method. +func (m *MockDatabase) NewIterator(arg0, arg1 []byte) ethdb.Iterator { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewIterator", arg0, arg1) + ret0, _ := ret[0].(ethdb.Iterator) + return ret0 +} + +// NewIterator indicates an expected call of NewIterator. +func (mr *MockDatabaseMockRecorder) NewIterator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewIterator", reflect.TypeOf((*MockDatabase)(nil).NewIterator), arg0, arg1) +} + +// NewSnapshot mocks base method. +func (m *MockDatabase) NewSnapshot() (ethdb.Snapshot, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewSnapshot") + ret0, _ := ret[0].(ethdb.Snapshot) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NewSnapshot indicates an expected call of NewSnapshot. +func (mr *MockDatabaseMockRecorder) NewSnapshot() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewSnapshot", reflect.TypeOf((*MockDatabase)(nil).NewSnapshot)) +} + +// Put mocks base method. +func (m *MockDatabase) Put(arg0, arg1 []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Put", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// Put indicates an expected call of Put. +func (mr *MockDatabaseMockRecorder) Put(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockDatabase)(nil).Put), arg0, arg1) +} + +// ReadAncients mocks base method. +func (m *MockDatabase) ReadAncients(arg0 func(ethdb.AncientReader) error) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadAncients", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// ReadAncients indicates an expected call of ReadAncients. +func (mr *MockDatabaseMockRecorder) ReadAncients(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadAncients", reflect.TypeOf((*MockDatabase)(nil).ReadAncients), arg0) +} + +// Stat mocks base method. +func (m *MockDatabase) Stat(arg0 string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Stat", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Stat indicates an expected call of Stat. +func (mr *MockDatabaseMockRecorder) Stat(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stat", reflect.TypeOf((*MockDatabase)(nil).Stat), arg0) +} + +// Sync mocks base method. +func (m *MockDatabase) Sync() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Sync") + ret0, _ := ret[0].(error) + return ret0 +} + +// Sync indicates an expected call of Sync. +func (mr *MockDatabaseMockRecorder) Sync() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sync", reflect.TypeOf((*MockDatabase)(nil).Sync)) +} + +// Tail mocks base method. +func (m *MockDatabase) Tail() (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Tail") + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Tail indicates an expected call of Tail. +func (mr *MockDatabaseMockRecorder) Tail() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Tail", reflect.TypeOf((*MockDatabase)(nil).Tail)) +} + +// TruncateHead mocks base method. +func (m *MockDatabase) TruncateHead(arg0 uint64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TruncateHead", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// TruncateHead indicates an expected call of TruncateHead. +func (mr *MockDatabaseMockRecorder) TruncateHead(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TruncateHead", reflect.TypeOf((*MockDatabase)(nil).TruncateHead), arg0) +} + +// TruncateTail mocks base method. +func (m *MockDatabase) TruncateTail(arg0 uint64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TruncateTail", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// TruncateTail indicates an expected call of TruncateTail. +func (mr *MockDatabaseMockRecorder) TruncateTail(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TruncateTail", reflect.TypeOf((*MockDatabase)(nil).TruncateTail), arg0) +} diff --git a/eth/filters/bench_test.go b/eth/filters/bench_test.go index 9632f4195f..e0eb972a32 100644 --- a/eth/filters/bench_test.go +++ b/eth/filters/bench_test.go @@ -122,13 +122,14 @@ func benchmarkBloomBits(b *testing.B, sectionSize uint64) { b.Log("Running filter benchmarks...") start = time.Now() - var backend *testBackend + + var backend *TestBackend for i := 0; i < benchFilterCnt; i++ { if i%20 == 0 { db.Close() db, _ = rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) - backend = &testBackend{db: db, sections: cnt} + backend = &TestBackend{DB: db, sections: cnt} } var addr common.Address addr[0] = byte(i) @@ -173,7 +174,7 @@ func BenchmarkNoBloomBits(b *testing.B) { b.Log("Running filter benchmarks...") start := time.Now() - backend := &testBackend{db: db} + backend := &TestBackend{DB: db} filter := NewRangeFilter(backend, 0, int64(*headNum), []common.Address{{}}, nil) filter.Logs(context.Background()) d := time.Since(start) diff --git a/eth/filters/bor_filter.go b/eth/filters/bor_filter.go index 009f6cde2a..88dda78448 100644 --- a/eth/filters/bor_filter.go +++ b/eth/filters/bor_filter.go @@ -110,7 +110,7 @@ func (f *BorBlockLogsFilter) Logs(ctx context.Context) ([]*types.Log, error) { func (f *BorBlockLogsFilter) unindexedLogs(ctx context.Context, end uint64) ([]*types.Log, error) { var logs []*types.Log - for ; f.begin <= int64(end); f.begin = f.begin + 64 { + for ; f.begin <= int64(end); f.begin = f.begin + int64(f.sprint) { header, err := f.backend.HeaderByNumber(ctx, rpc.BlockNumber(f.begin)) if header == nil || err != nil { return logs, err @@ -146,5 +146,5 @@ func currentSprintEnd(sprint uint64, n int64) int64 { return n } - return n + 64 - m + return n + int64(sprint) - m } diff --git a/eth/filters/bor_filter_system_test.go b/eth/filters/bor_filter_system_test.go deleted file mode 100644 index 05f05893d6..0000000000 --- a/eth/filters/bor_filter_system_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package filters - -import ( - "context" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/types" -) - -func (b *testBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) { - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == nil { - return nil, nil - } - - receipt := rawdb.ReadBorReceipt(b.db, hash, *number) - if receipt == nil { - return nil, nil - } - return receipt, nil -} - -func (b *testBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) { - receipt, err := b.GetBorBlockReceipt(ctx, hash) - if receipt == nil || err != nil { - return nil, nil - } - return receipt.Logs, nil -} diff --git a/eth/filters/bor_filter_test.go b/eth/filters/bor_filter_test.go new file mode 100644 index 0000000000..a176ce6f5b --- /dev/null +++ b/eth/filters/bor_filter_test.go @@ -0,0 +1,158 @@ +package filters + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + types "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" + + gomock "github.com/golang/mock/gomock" +) + +var ( + key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + addr = crypto.PubkeyToAddress(key1.PublicKey) +) + +func newTestHeader(blockNumber uint) *types.Header { + return &types.Header{ + Number: big.NewInt(int64(blockNumber)), + } +} + +func newTestReceipt(contractAddr common.Address, topicAddress common.Hash) *types.Receipt { + receipt := types.NewReceipt(nil, false, 0) + receipt.Logs = []*types.Log{ + { + Address: contractAddr, + Topics: []common.Hash{topicAddress}, + }, + } + + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + + return receipt +} + +func (backend *MockBackend) expectBorReceiptsFromMock(hashes []*common.Hash) { + for _, h := range hashes { + if h == nil { + backend.EXPECT().GetBorBlockReceipt(gomock.Any(), gomock.Any()).Return(nil, nil) + continue + } + + backend.EXPECT().GetBorBlockReceipt(gomock.Any(), gomock.Any()).Return(newTestReceipt(addr, *h), nil) + } +} + +func TestBorFilters(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + var ( + hash1 = common.BytesToHash([]byte("topic1")) + hash2 = common.BytesToHash([]byte("topic2")) + hash3 = common.BytesToHash([]byte("topic3")) + hash4 = common.BytesToHash([]byte("topic4")) + db = NewMockDatabase(ctrl) + + sprint = params.TestChainConfig.Bor.Sprint + ) + + backend := NewMockBackend(ctrl) + + // should return the following at all times + backend.EXPECT().ChainDb().Return(db).AnyTimes() + backend.EXPECT().HeaderByNumber(gomock.Any(), gomock.Any()).Return(newTestHeader(1), nil).AnyTimes() + + // Block 1 + backend.expectBorReceiptsFromMock([]*common.Hash{nil, &hash1, &hash2, &hash3, &hash4}) + + filter := NewBorBlockLogsRangeFilter(backend, sprint, 0, 18, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}}) + logs, err := filter.Logs(context.Background()) + + if err != nil { + t.Error(err) + } + + if len(logs) != 4 { + t.Error("expected 4 log, got", len(logs)) + } + + // Block 2 + backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash3}) + + filter = NewBorBlockLogsRangeFilter(backend, sprint, 990, 999, []common.Address{addr}, [][]common.Hash{{hash3}}) + logs, _ = filter.Logs(context.Background()) + + if len(logs) != 1 { + t.Error("expected 1 log, got", len(logs)) + } + + if len(logs) > 0 && logs[0].Topics[0] != hash3 { + t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) + } + + // Block 3 + backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, &hash3}) + + filter = NewBorBlockLogsRangeFilter(backend, sprint, 992, 1000, []common.Address{addr}, [][]common.Hash{{hash3}}) + logs, _ = filter.Logs(context.Background()) + + if len(logs) != 1 { + t.Error("expected 1 log, got", len(logs)) + } + + if len(logs) > 0 && logs[0].Topics[0] != hash3 { + t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) + } + + // Block 4 + backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, nil, &hash3}) + + filter = NewBorBlockLogsRangeFilter(backend, sprint, 1, 16, []common.Address{addr}, [][]common.Hash{{hash1, hash2}}) + + logs, _ = filter.Logs(context.Background()) + + if len(logs) != 2 { + t.Error("expected 2 log, got", len(logs)) + } + + // Block 5 + backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, nil, &hash3, &hash4, nil}) + + failHash := common.BytesToHash([]byte("fail")) + filter = NewBorBlockLogsRangeFilter(backend, sprint, 0, 20, nil, [][]common.Hash{{failHash}}) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 0 { + t.Error("expected 0 log, got", len(logs)) + } + + // Block 6 + backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, nil, &hash3, &hash4, nil}) + + failAddr := common.BytesToAddress([]byte("failmenow")) + filter = NewBorBlockLogsRangeFilter(backend, sprint, 0, 20, []common.Address{failAddr}, nil) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 0 { + t.Error("expected 0 log, got", len(logs)) + } + + // Block 7 + backend.expectBorReceiptsFromMock([]*common.Hash{&hash1, &hash2, nil, &hash3, &hash4, nil}) + + filter = NewBorBlockLogsRangeFilter(backend, sprint, 0, 20, nil, [][]common.Hash{{failHash}, {hash1}}) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 0 { + t.Error("expected 0 log, got", len(logs)) + } +} diff --git a/eth/filters/filter.go b/eth/filters/filter.go index 4af45c7ea6..a99f1e753a 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +//go:generate mockgen -destination=../../eth/filters/IBackend.go -package=filters . Backend type Backend interface { ChainDb() ethdb.Database HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index a49f339f86..67d69bb628 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "math/big" - "math/rand" "reflect" "runtime" "testing" @@ -30,11 +29,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" ) @@ -44,126 +40,6 @@ var ( borLogs bool = true ) -type testBackend struct { - mux *event.TypeMux - db ethdb.Database - sections uint64 - txFeed event.Feed - logsFeed event.Feed - rmLogsFeed event.Feed - pendingLogsFeed event.Feed - chainFeed event.Feed - - stateSyncFeed event.Feed -} - -func (b *testBackend) ChainDb() ethdb.Database { - return b.db -} - -func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { - var ( - hash common.Hash - num uint64 - ) - if blockNr == rpc.LatestBlockNumber { - hash = rawdb.ReadHeadBlockHash(b.db) - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == nil { - return nil, nil - } - num = *number - } else { - num = uint64(blockNr) - hash = rawdb.ReadCanonicalHash(b.db, num) - } - return rawdb.ReadHeader(b.db, hash, num), nil -} - -func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == nil { - return nil, nil - } - return rawdb.ReadHeader(b.db, hash, *number), nil -} - -func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { - if number := rawdb.ReadHeaderNumber(b.db, hash); number != nil { - return rawdb.ReadReceipts(b.db, hash, *number, params.TestChainConfig), nil - } - return nil, nil -} - -func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { - number := rawdb.ReadHeaderNumber(b.db, hash) - if number == nil { - return nil, nil - } - receipts := rawdb.ReadReceipts(b.db, hash, *number, params.TestChainConfig) - - logs := make([][]*types.Log, len(receipts)) - for i, receipt := range receipts { - logs[i] = receipt.Logs - } - return logs, nil -} - -func (b *testBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { - return b.txFeed.Subscribe(ch) -} - -func (b *testBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { - return b.rmLogsFeed.Subscribe(ch) -} - -func (b *testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { - return b.logsFeed.Subscribe(ch) -} - -func (b *testBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { - return b.pendingLogsFeed.Subscribe(ch) -} - -func (b *testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { - return b.chainFeed.Subscribe(ch) -} - -func (b *testBackend) BloomStatus() (uint64, uint64) { - return params.BloomBitsBlocks, b.sections -} - -func (b *testBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { - requests := make(chan chan *bloombits.Retrieval) - - go session.Multiplex(16, 0, requests) - go func() { - for { - // Wait for a service request or a shutdown - select { - case <-ctx.Done(): - return - - case request := <-requests: - task := <-request - - task.Bitsets = make([][]byte, len(task.Sections)) - for i, section := range task.Sections { - if rand.Int()%4 != 0 { // Handle occasional missing deliveries - head := rawdb.ReadCanonicalHash(b.db, (section+1)*params.BloomBitsBlocks-1) - task.Bitsets[i], _ = rawdb.ReadBloomBits(b.db, task.Bit, section, head) - } - } - request <- task - } - } - }() -} - -func (b *testBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription { - return b.stateSyncFeed.Subscribe(ch) -} - // TestBlockSubscription tests if a block subscription returns block hashes for posted chain events. // It creates multiple subscriptions: // - one at the start and should receive all posted chain events and a second (blockHashes) @@ -174,7 +50,7 @@ func TestBlockSubscription(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} api = NewPublicFilterAPI(backend, false, deadline, borLogs) genesis = (&core.Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) chain, _ = core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {}) @@ -226,7 +102,7 @@ func TestPendingTxFilter(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} api = NewPublicFilterAPI(backend, false, deadline, borLogs) transactions = []*types.Transaction{ @@ -281,7 +157,7 @@ func TestPendingTxFilter(t *testing.T) { func TestLogFilterCreation(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} api = NewPublicFilterAPI(backend, false, deadline, borLogs) testCases = []struct { @@ -325,7 +201,7 @@ func TestInvalidLogFilterCreation(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} api = NewPublicFilterAPI(backend, false, deadline, borLogs) ) @@ -347,7 +223,7 @@ func TestInvalidLogFilterCreation(t *testing.T) { func TestInvalidGetLogsRequest(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} api = NewPublicFilterAPI(backend, false, deadline, borLogs) blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") ) @@ -372,7 +248,7 @@ func TestLogFilter(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} api = NewPublicFilterAPI(backend, false, deadline, borLogs) firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111") @@ -486,7 +362,7 @@ func TestPendingLogsSubscription(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} api = NewPublicFilterAPI(backend, false, deadline, borLogs) firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111") @@ -670,7 +546,7 @@ func TestPendingTxFilterDeadlock(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} api = NewPublicFilterAPI(backend, false, timeout, borLogs) done = make(chan struct{}) ) diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 63a48f762d..6a8443b67c 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -50,7 +50,7 @@ func BenchmarkFilters(b *testing.B) { var ( db, _ = rawdb.NewLevelDBDatabase(dir, 0, 0, "", false) - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr1 = crypto.PubkeyToAddress(key1.PublicKey) addr2 = common.BytesToAddress([]byte("jeff")) @@ -108,7 +108,7 @@ func TestFilters(t *testing.T) { var ( db, _ = rawdb.NewLevelDBDatabase(dir, 0, 0, "", false) - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr = crypto.PubkeyToAddress(key1.PublicKey) diff --git a/eth/filters/test_backend.go b/eth/filters/test_backend.go new file mode 100644 index 0000000000..c6496f4a08 --- /dev/null +++ b/eth/filters/test_backend.go @@ -0,0 +1,173 @@ +package filters + +import ( + context "context" + "crypto/rand" + "math/big" + + common "github.com/ethereum/go-ethereum/common" + core "github.com/ethereum/go-ethereum/core" + bloombits "github.com/ethereum/go-ethereum/core/bloombits" + "github.com/ethereum/go-ethereum/core/rawdb" + types "github.com/ethereum/go-ethereum/core/types" + ethdb "github.com/ethereum/go-ethereum/ethdb" + event "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/params" + rpc "github.com/ethereum/go-ethereum/rpc" +) + +type TestBackend struct { + DB ethdb.Database + sections uint64 + txFeed event.Feed + logsFeed event.Feed + rmLogsFeed event.Feed + pendingLogsFeed event.Feed + chainFeed event.Feed + + stateSyncFeed event.Feed +} + +func (b *TestBackend) BloomStatus() (uint64, uint64) { + return params.BloomBitsBlocks, b.sections +} + +func (b *TestBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) { + number := rawdb.ReadHeaderNumber(b.DB, hash) + if number == nil { + return &types.Receipt{}, nil + } + + receipt := rawdb.ReadBorReceipt(b.DB, hash, *number) + if receipt == nil { + return &types.Receipt{}, nil + } + + return receipt, nil +} + +func (b *TestBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) { + receipt, err := b.GetBorBlockReceipt(ctx, hash) + if receipt == nil || err != nil { + return []*types.Log{}, nil + } + + return receipt.Logs, nil +} + +func (b *TestBackend) ChainDb() ethdb.Database { + return b.DB +} + +func (b *TestBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { + var ( + hash common.Hash + num uint64 + ) + + if blockNr == rpc.LatestBlockNumber { + hash = rawdb.ReadHeadBlockHash(b.DB) + number := rawdb.ReadHeaderNumber(b.DB, hash) + + if number == nil { + return &types.Header{}, nil + } + + num = *number + } else { + num = uint64(blockNr) + hash = rawdb.ReadCanonicalHash(b.DB, num) + } + + return rawdb.ReadHeader(b.DB, hash, num), nil +} + +func (b *TestBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + number := rawdb.ReadHeaderNumber(b.DB, hash) + if number == nil { + return &types.Header{}, nil + } + + return rawdb.ReadHeader(b.DB, hash, *number), nil +} + +func (b *TestBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { + if number := rawdb.ReadHeaderNumber(b.DB, hash); number != nil { + return rawdb.ReadReceipts(b.DB, hash, *number, params.TestChainConfig), nil + } + + return nil, nil +} + +func (b *TestBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { + number := rawdb.ReadHeaderNumber(b.DB, hash) + if number == nil { + return nil, nil + } + + receipts := rawdb.ReadReceipts(b.DB, hash, *number, params.TestChainConfig) + + logs := make([][]*types.Log, len(receipts)) + for i, receipt := range receipts { + logs[i] = receipt.Logs + } + + return logs, nil +} + +func (b *TestBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { + return b.txFeed.Subscribe(ch) +} + +func (b *TestBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { + return b.rmLogsFeed.Subscribe(ch) +} + +func (b *TestBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { + return b.logsFeed.Subscribe(ch) +} + +func (b *TestBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { + return b.pendingLogsFeed.Subscribe(ch) +} + +func (b *TestBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { + return b.chainFeed.Subscribe(ch) +} + +func (b *TestBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { + requests := make(chan chan *bloombits.Retrieval) + + go session.Multiplex(16, 0, requests) + go func() { + for { + // Wait for a service request or a shutdown + select { + case <-ctx.Done(): + return + + case request := <-requests: + task := <-request + + task.Bitsets = make([][]byte, len(task.Sections)) + for i, section := range task.Sections { + nBig, err := rand.Int(rand.Reader, big.NewInt(100)) + + if err != nil { + panic(err) + } + + if nBig.Int64()%4 != 0 { // Handle occasional missing deliveries + head := rawdb.ReadCanonicalHash(b.DB, (section+1)*params.BloomBitsBlocks-1) + task.Bitsets[i], _ = rawdb.ReadBloomBits(b.DB, task.Bit, section, head) + } + } + request <- task + } + } + }() +} + +func (b *TestBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription { + return b.stateSyncFeed.Subscribe(ch) +} diff --git a/ethdb/database.go b/ethdb/database.go index b2e7c7228a..88c8de6a16 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -164,6 +164,7 @@ type AncientStore interface { // Database contains all the methods required by the high level database to not // only access the key-value data store but also the chain freezer. +//go:generate mockgen -destination=../eth/filters/IDatabase.go -package=filters . Database type Database interface { Reader Writer diff --git a/params/config.go b/params/config.go index 980250a1ec..8b7fedd58f 100644 --- a/params/config.go +++ b/params/config.go @@ -436,7 +436,7 @@ var ( // adding flags to the config to also have to set these fields. AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, &BorConfig{BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, &BorConfig{BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, &BorConfig{Sprint: 4, BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}}} TestRules = TestChainConfig.Rules(new(big.Int), false) ) diff --git a/tests/bor/bor_filter_test.go b/tests/bor/bor_filter_test.go new file mode 100644 index 0000000000..c37b4ab001 --- /dev/null +++ b/tests/bor/bor_filter_test.go @@ -0,0 +1,183 @@ +//go:build integration + +package bor + +import ( + "context" + "fmt" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/filters" + "github.com/ethereum/go-ethereum/params" +) + +func TestBorFilters(t *testing.T) { + t.Parallel() + + var ( + db = rawdb.NewMemoryDatabase() + backend = &filters.TestBackend{DB: db} + key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + addr = crypto.PubkeyToAddress(key1.PublicKey) + + hash1 = common.BytesToHash([]byte("topic1")) + hash2 = common.BytesToHash([]byte("topic2")) + hash3 = common.BytesToHash([]byte("topic3")) + hash4 = common.BytesToHash([]byte("topic4")) + ) + + defer db.Close() + + genesis := core.GenesisBlockForTesting(db, addr, big.NewInt(1000000)) + sprint := params.TestChainConfig.Bor.Sprint + + chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) { + switch i { + case 7: //state-sync tx at block 8 + receipt := types.NewReceipt(nil, false, 0) + receipt.Logs = []*types.Log{ + { + Address: addr, + Topics: []common.Hash{hash1}, + }, + } + gen.AddUncheckedReceipt(receipt) + gen.AddUncheckedTx(types.NewTransaction(8, common.HexToAddress("0x8"), big.NewInt(8), 8, gen.BaseFee(), nil)) + + case 23: //state-sync tx at block 24 + receipt := types.NewReceipt(nil, false, 0) + receipt.Logs = []*types.Log{ + { + Address: addr, + Topics: []common.Hash{hash2}, + }, + } + gen.AddUncheckedReceipt(receipt) + gen.AddUncheckedTx(types.NewTransaction(24, common.HexToAddress("0x24"), big.NewInt(24), 24, gen.BaseFee(), nil)) + + case 991: //state-sync tx at block 992 + receipt := types.NewReceipt(nil, false, 0) + receipt.Logs = []*types.Log{ + { + Address: addr, + Topics: []common.Hash{hash3}, + }, + } + gen.AddUncheckedReceipt(receipt) + gen.AddUncheckedTx(types.NewTransaction(992, common.HexToAddress("0x992"), big.NewInt(992), 992, gen.BaseFee(), nil)) + + case 999: //state-sync tx at block 1000 + receipt := types.NewReceipt(nil, false, 0) + receipt.Logs = []*types.Log{ + { + Address: addr, + Topics: []common.Hash{hash4}, + }, + } + gen.AddUncheckedReceipt(receipt) + gen.AddUncheckedTx(types.NewTransaction(1000, common.HexToAddress("0x1000"), big.NewInt(1000), 1000, gen.BaseFee(), nil)) + } + }) + + for i, block := range chain { + // write the block to database + rawdb.WriteBlock(db, block) + rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64()) + rawdb.WriteHeadBlockHash(db, block.Hash()) + + blockBatch := db.NewBatch() + + // since all the transactions are state-sync, we will not include them as normal receipts + rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), []*types.Receipt{}) + + // check for blocks with receipts. Since the only receipt is state-sync, we can chack the length of receipts + if len(receipts[i]) > 0 { + // write the state-sync receipts to database + // State sync logs don't have tx index, tx hash and other necessary fields, DeriveFieldsForBorLogs will fill those fields for websocket subscriptions + // DeriveFieldsForBorLogs argurments: + // 1. State-sync logs + // 2. Block Hash + // 3. Block Number + // 4. Transactions in the block(except state-sync) i.e. 0 in our case + // 5. AllLogs - StateSyncLogs ; since we only have state-sync tx, it will be 0 + types.DeriveFieldsForBorLogs(receipts[i][0].Logs, block.Hash(), block.NumberU64(), uint(0), uint(0)) + + rawdb.WriteBorReceipt(blockBatch, block.Hash(), block.NumberU64(), &types.ReceiptForStorage{ + Status: types.ReceiptStatusSuccessful, // make receipt status successful + Logs: receipts[i][0].Logs, + }) + + rawdb.WriteBorTxLookupEntry(blockBatch, block.Hash(), block.NumberU64()) + } + + if err := blockBatch.Write(); err != nil { + fmt.Println("Failed to write block into disk", "err", err) + } + } + + filter := filters.NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}}) + + logs, _ := filter.Logs(context.Background()) + if len(logs) != 4 { + t.Error("expected 4 log, got", len(logs)) + } + + filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 900, 999, []common.Address{addr}, [][]common.Hash{{hash3}}) + logs, _ = filter.Logs(context.Background()) + + if len(logs) != 1 { + t.Error("expected 1 log, got", len(logs)) + } + + if len(logs) > 0 && logs[0].Topics[0] != hash3 { + t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) + } + + filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 992, -1, []common.Address{addr}, [][]common.Hash{{hash3}}) + logs, _ = filter.Logs(context.Background()) + + if len(logs) != 1 { + t.Error("expected 1 log, got", len(logs)) + } + + if len(logs) > 0 && logs[0].Topics[0] != hash3 { + t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) + } + + filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 1, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2}}) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 2 { + t.Error("expected 2 log, got", len(logs)) + } + + failHash := common.BytesToHash([]byte("fail")) + filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, nil, [][]common.Hash{{failHash}}) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 0 { + t.Error("expected 0 log, got", len(logs)) + } + + failAddr := common.BytesToAddress([]byte("failmenow")) + filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, []common.Address{failAddr}, nil) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 0 { + t.Error("expected 0 log, got", len(logs)) + } + + filter = filters.NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, nil, [][]common.Hash{{failHash}, {hash1}}) + + logs, _ = filter.Logs(context.Background()) + if len(logs) != 0 { + t.Error("expected 0 log, got", len(logs)) + } +}