From e670a8a0a1c4bcde49c7e535764f9642a7e2b8a4 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Thu, 14 Jul 2022 17:39:29 +0530 Subject: [PATCH 01/10] add : bor_filter_test --- eth/filters/bor_filter.go | 4 +- eth/filters/bor_filter_test.go | 184 +++++++++++++++++++++++++++++++++ params/config.go | 2 +- 3 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 eth/filters/bor_filter_test.go 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_test.go b/eth/filters/bor_filter_test.go new file mode 100644 index 0000000000..3474c6c8a2 --- /dev/null +++ b/eth/filters/bor_filter_test.go @@ -0,0 +1,184 @@ +package filters + +import ( + "context" + "fmt" + "io/ioutil" + "math/big" + "os" + "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/params" +) + +func TestBorFilters(t *testing.T) { + dir, err := ioutil.TempDir("", "filtertest") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + var ( + db, _ = rawdb.NewLevelDBDatabase(dir, 0, 0, "", false) + backend = &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) + + } + + temp := rawdb.ReadBorReceipt(db, block.Hash(), block.NumberU64()) + if temp != nil { + fmt.Printf("temp: %+v\n", temp) + fmt.Printf("temp.Logs: %+v\n", temp.Logs[0]) + } + + } + + filter := 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 = 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 = 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 = 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 = 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 = 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 = 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)) + } +} 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) ) From 38114962808510693f12c57adc2d6cbafa97fbf1 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Thu, 14 Jul 2022 17:41:38 +0530 Subject: [PATCH 02/10] fix : remove debug logs --- eth/filters/bor_filter_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/eth/filters/bor_filter_test.go b/eth/filters/bor_filter_test.go index 3474c6c8a2..9828406599 100644 --- a/eth/filters/bor_filter_test.go +++ b/eth/filters/bor_filter_test.go @@ -119,12 +119,6 @@ func TestBorFilters(t *testing.T) { } - temp := rawdb.ReadBorReceipt(db, block.Hash(), block.NumberU64()) - if temp != nil { - fmt.Printf("temp: %+v\n", temp) - fmt.Printf("temp.Logs: %+v\n", temp.Logs[0]) - } - } filter := NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}}) From e47a2df17b91df5ae4beb99b711eba061d9832dc Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Thu, 14 Jul 2022 17:49:55 +0530 Subject: [PATCH 03/10] fix : lint --- eth/filters/bor_filter_test.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/eth/filters/bor_filter_test.go b/eth/filters/bor_filter_test.go index 9828406599..dda4a3271b 100644 --- a/eth/filters/bor_filter_test.go +++ b/eth/filters/bor_filter_test.go @@ -18,10 +18,13 @@ import ( ) func TestBorFilters(t *testing.T) { + t.Parallel() + dir, err := ioutil.TempDir("", "filtertest") if err != nil { t.Fatal(err) } + defer os.RemoveAll(dir) var ( @@ -35,10 +38,12 @@ func TestBorFilters(t *testing.T) { 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 @@ -86,6 +91,7 @@ func TestBorFilters(t *testing.T) { 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) @@ -93,8 +99,10 @@ func TestBorFilters(t *testing.T) { 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 @@ -106,19 +114,18 @@ func TestBorFilters(t *testing.T) { // 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()) + rawdb.WriteBorTxLookupEntry(blockBatch, block.Hash(), block.NumberU64()) } if err := blockBatch.Write(); err != nil { fmt.Println("Failed to write block into disk", "err", err) - } - } filter := NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}}) @@ -130,18 +137,22 @@ func TestBorFilters(t *testing.T) { filter = 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 = 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]) } From 0610c6a6927c0c1dea914034a57ca5bfc53e0797 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Thu, 14 Jul 2022 18:28:21 +0530 Subject: [PATCH 04/10] chg : use memory db --- eth/filters/bor_filter_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/filters/bor_filter_test.go b/eth/filters/bor_filter_test.go index dda4a3271b..ac3fe88aae 100644 --- a/eth/filters/bor_filter_test.go +++ b/eth/filters/bor_filter_test.go @@ -28,7 +28,7 @@ func TestBorFilters(t *testing.T) { defer os.RemoveAll(dir) var ( - db, _ = rawdb.NewLevelDBDatabase(dir, 0, 0, "", false) + db = rawdb.NewMemoryDatabase() backend = &testBackend{db: db} key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr = crypto.PubkeyToAddress(key1.PublicKey) From 9aad8bf928062dc03f5b9100d16979b5baf760f7 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Fri, 15 Jul 2022 13:12:39 +0530 Subject: [PATCH 05/10] fix : remove temp dir --- eth/filters/bor_filter_test.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/eth/filters/bor_filter_test.go b/eth/filters/bor_filter_test.go index ac3fe88aae..1feb95e52b 100644 --- a/eth/filters/bor_filter_test.go +++ b/eth/filters/bor_filter_test.go @@ -3,9 +3,7 @@ package filters import ( "context" "fmt" - "io/ioutil" "math/big" - "os" "testing" "github.com/ethereum/go-ethereum/common" @@ -20,13 +18,6 @@ import ( func TestBorFilters(t *testing.T) { t.Parallel() - dir, err := ioutil.TempDir("", "filtertest") - if err != nil { - t.Fatal(err) - } - - defer os.RemoveAll(dir) - var ( db = rawdb.NewMemoryDatabase() backend = &testBackend{db: db} From 43b18b70388de8ae72b2176ea4f4a7f7083f7878 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Mon, 18 Jul 2022 13:43:36 +0530 Subject: [PATCH 06/10] chg : moved TestBorFilters to tests/bor --- Makefile | 3 +- eth/filters/IBackend.go | 257 ++++++++++++++++++++++++++ eth/filters/bench_test.go | 6 +- eth/filters/bor_filter_system_test.go | 30 --- eth/filters/bor_filter_test.go | 2 +- eth/filters/filter.go | 1 + eth/filters/filter_system_test.go | 140 +------------- eth/filters/filter_test.go | 4 +- eth/filters/test_backend.go | 157 ++++++++++++++++ tests/bor/bor_filter_test.go | 183 ++++++++++++++++++ 10 files changed, 614 insertions(+), 169 deletions(-) create mode 100644 eth/filters/IBackend.go delete mode 100644 eth/filters/bor_filter_system_test.go create mode 100644 eth/filters/test_backend.go create mode 100644 tests/bor/bor_filter_test.go 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/bench_test.go b/eth/filters/bench_test.go index 9632f4195f..1130df5250 100644 --- a/eth/filters/bench_test.go +++ b/eth/filters/bench_test.go @@ -122,13 +122,13 @@ 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 +173,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_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 index 1feb95e52b..3bbe30b81b 100644 --- a/eth/filters/bor_filter_test.go +++ b/eth/filters/bor_filter_test.go @@ -20,7 +20,7 @@ func TestBorFilters(t *testing.T) { var ( db = rawdb.NewMemoryDatabase() - backend = &testBackend{db: db} + backend = &TestBackend{DB: db} key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") addr = crypto.PubkeyToAddress(key1.PublicKey) 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..eba2ac3f67 --- /dev/null +++ b/eth/filters/test_backend.go @@ -0,0 +1,157 @@ +package filters + +import ( + context "context" + "math/rand" + + 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 { + 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) 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 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 +} + +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) 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) +} diff --git a/tests/bor/bor_filter_test.go b/tests/bor/bor_filter_test.go new file mode 100644 index 0000000000..2b7e03d66d --- /dev/null +++ b/tests/bor/bor_filter_test.go @@ -0,0 +1,183 @@ +//go:build integration + +package filters + +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)) + } +} From 8a6c16dcdefbf0729d75b470481027824475ea3b Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Tue, 19 Jul 2022 14:07:19 +0530 Subject: [PATCH 07/10] add : bor_filter_test.go + mock backend --- eth/filters/bor_filter_test.go | 183 ++++++++++++++------------------- 1 file changed, 80 insertions(+), 103 deletions(-) diff --git a/eth/filters/bor_filter_test.go b/eth/filters/bor_filter_test.go index 3bbe30b81b..2dfbf4ec01 100644 --- a/eth/filters/bor_filter_test.go +++ b/eth/filters/bor_filter_test.go @@ -2,131 +2,93 @@ package filters 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" + 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) + + hash1 = common.BytesToHash([]byte("topic1")) + hash2 = common.BytesToHash([]byte("topic2")) + hash3 = common.BytesToHash([]byte("topic3")) + hash4 = common.BytesToHash([]byte("topic4")) +) + +func newTestHeader(blockNumber uint) *types.Header { + head := types.Header{ + Number: big.NewInt(int64(blockNumber)), + } + return &head +} + +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 i := range hashes { + if hashes[i] == nil { + backend.EXPECT().GetBorBlockReceipt(gomock.Any(), gomock.Any()).Return(nil, nil) + continue + } + backend.EXPECT().GetBorBlockReceipt(gomock.Any(), gomock.Any()).Return(newTestReceipt(addr, *hashes[i]), nil) + } +} + func TestBorFilters(t *testing.T) { t.Parallel() var ( - db = rawdb.NewMemoryDatabase() - backend = &TestBackend{DB: db} - key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - addr = crypto.PubkeyToAddress(key1.PublicKey) + db = rawdb.NewMemoryDatabase() - hash1 = common.BytesToHash([]byte("topic1")) - hash2 = common.BytesToHash([]byte("topic2")) - hash3 = common.BytesToHash([]byte("topic3")) - hash4 = common.BytesToHash([]byte("topic4")) + sprint = params.TestChainConfig.Bor.Sprint ) defer db.Close() - genesis := core.GenesisBlockForTesting(db, addr, big.NewInt(1000000)) - sprint := params.TestChainConfig.Bor.Sprint + ctrl := gomock.NewController(t) + defer ctrl.Finish() - 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)) + backend := NewMockBackend(ctrl) - 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)) + // 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() - 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)) + // Block 1 + backend.expectBorReceiptsFromMock([]*common.Hash{nil, &hash1, &hash2, &hash3, &hash4}) - 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 := 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) } - - filter := 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 = NewBorBlockLogsRangeFilter(backend, sprint, 900, 999, []common.Address{addr}, [][]common.Hash{{hash3}}) + // 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 { @@ -137,7 +99,10 @@ func TestBorFilters(t *testing.T) { t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) } - filter = NewBorBlockLogsRangeFilter(backend, sprint, 992, -1, []common.Address{addr}, [][]common.Hash{{hash3}}) + // 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 { @@ -148,30 +113,42 @@ func TestBorFilters(t *testing.T) { t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) } - filter = NewBorBlockLogsRangeFilter(backend, sprint, 1, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2}}) + // 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, -1, nil, [][]common.Hash{{failHash}}) + 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, -1, []common.Address{failAddr}, nil) + 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)) } - filter = NewBorBlockLogsRangeFilter(backend, sprint, 0, -1, nil, [][]common.Hash{{failHash}, {hash1}}) + // 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 { From 58ef6fdbb7ecc37a3eeebd0c0410917b00268327 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Tue, 19 Jul 2022 14:39:26 +0530 Subject: [PATCH 08/10] fix : lint --- eth/filters/bench_test.go | 1 + eth/filters/bor_filter_test.go | 7 +++++++ eth/filters/test_backend.go | 32 ++++++++++++++++++++++++-------- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/eth/filters/bench_test.go b/eth/filters/bench_test.go index 1130df5250..e0eb972a32 100644 --- a/eth/filters/bench_test.go +++ b/eth/filters/bench_test.go @@ -122,6 +122,7 @@ func benchmarkBloomBits(b *testing.B, sectionSize uint64) { b.Log("Running filter benchmarks...") start = time.Now() + var backend *TestBackend for i := 0; i < benchFilterCnt; i++ { diff --git a/eth/filters/bor_filter_test.go b/eth/filters/bor_filter_test.go index 2dfbf4ec01..68c0df8bbc 100644 --- a/eth/filters/bor_filter_test.go +++ b/eth/filters/bor_filter_test.go @@ -10,6 +10,7 @@ import ( 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" ) @@ -27,6 +28,7 @@ func newTestHeader(blockNumber uint) *types.Header { head := types.Header{ Number: big.NewInt(int64(blockNumber)), } + return &head } @@ -40,6 +42,7 @@ func newTestReceipt(contractAddr common.Address, topicAddress common.Hash) *type } receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) + return receipt } @@ -49,6 +52,7 @@ func (backend *MockBackend) expectBorReceiptsFromMock(hashes []*common.Hash) { backend.EXPECT().GetBorBlockReceipt(gomock.Any(), gomock.Any()).Return(nil, nil) continue } + backend.EXPECT().GetBorBlockReceipt(gomock.Any(), gomock.Any()).Return(newTestReceipt(addr, *hashes[i]), nil) } } @@ -78,9 +82,11 @@ func TestBorFilters(t *testing.T) { 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)) } @@ -119,6 +125,7 @@ func TestBorFilters(t *testing.T) { 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)) } diff --git a/eth/filters/test_backend.go b/eth/filters/test_backend.go index eba2ac3f67..c6496f4a08 100644 --- a/eth/filters/test_backend.go +++ b/eth/filters/test_backend.go @@ -2,7 +2,8 @@ package filters import ( context "context" - "math/rand" + "crypto/rand" + "math/big" common "github.com/ethereum/go-ethereum/common" core "github.com/ethereum/go-ethereum/core" @@ -16,7 +17,6 @@ import ( ) type TestBackend struct { - mux *event.TypeMux DB ethdb.Database sections uint64 txFeed event.Feed @@ -35,21 +35,23 @@ func (b *TestBackend) BloomStatus() (uint64, uint64) { 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 + return &types.Receipt{}, nil } receipt := rawdb.ReadBorReceipt(b.DB, hash, *number) if receipt == nil { - return nil, 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 nil, nil + return []*types.Log{}, nil } + return receipt.Logs, nil } @@ -62,25 +64,30 @@ func (b *TestBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe 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 + 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 nil, nil + return &types.Header{}, nil } + return rawdb.ReadHeader(b.DB, hash, *number), nil } @@ -88,6 +95,7 @@ func (b *TestBackend) GetReceipts(ctx context.Context, hash common.Hash) (types. if number := rawdb.ReadHeaderNumber(b.DB, hash); number != nil { return rawdb.ReadReceipts(b.DB, hash, *number, params.TestChainConfig), nil } + return nil, nil } @@ -96,12 +104,14 @@ func (b *TestBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types 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 } @@ -141,7 +151,13 @@ func (b *TestBackend) ServiceFilter(ctx context.Context, session *bloombits.Matc task.Bitsets = make([][]byte, len(task.Sections)) for i, section := range task.Sections { - if rand.Int()%4 != 0 { // Handle occasional missing deliveries + 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) } From 4e189689b0f570d547233113a18ed3c089eb98f2 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Tue, 19 Jul 2022 17:21:11 +0530 Subject: [PATCH 09/10] add : mock database in eth/filters --- eth/filters/IDatabase.go | 368 +++++++++++++++++++++++++++++++++ eth/filters/bor_filter_test.go | 30 ++- ethdb/database.go | 1 + 3 files changed, 381 insertions(+), 18 deletions(-) create mode 100644 eth/filters/IDatabase.go 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/bor_filter_test.go b/eth/filters/bor_filter_test.go index 68c0df8bbc..a176ce6f5b 100644 --- a/eth/filters/bor_filter_test.go +++ b/eth/filters/bor_filter_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" @@ -17,19 +16,12 @@ import ( var ( 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")) ) func newTestHeader(blockNumber uint) *types.Header { - head := types.Header{ + return &types.Header{ Number: big.NewInt(int64(blockNumber)), } - - return &head } func newTestReceipt(contractAddr common.Address, topicAddress common.Hash) *types.Receipt { @@ -47,30 +39,32 @@ func newTestReceipt(contractAddr common.Address, topicAddress common.Hash) *type } func (backend *MockBackend) expectBorReceiptsFromMock(hashes []*common.Hash) { - for i := range hashes { - if hashes[i] == nil { + 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, *hashes[i]), nil) + 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 ( - db = rawdb.NewMemoryDatabase() + 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 ) - defer db.Close() - - ctrl := gomock.NewController(t) - defer ctrl.Finish() - backend := NewMockBackend(ctrl) // should return the following at all times 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 From 68f440a35f7671787899aebb5a45568928501653 Mon Sep 17 00:00:00 2001 From: Shivam Sharma Date: Wed, 20 Jul 2022 16:58:40 +0530 Subject: [PATCH 10/10] fix : integration test package --- tests/bor/bor_filter_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bor/bor_filter_test.go b/tests/bor/bor_filter_test.go index 2b7e03d66d..c37b4ab001 100644 --- a/tests/bor/bor_filter_test.go +++ b/tests/bor/bor_filter_test.go @@ -1,6 +1,6 @@ //go:build integration -package filters +package bor import ( "context"