From 67a5da36a1533b832d51f6419b47e96d947f8f98 Mon Sep 17 00:00:00 2001 From: Kirill Pisarev Date: Mon, 22 Jan 2024 12:10:23 +0100 Subject: [PATCH 1/5] fix: fix index out of range undeterministic error in rpc test --- dot/state/block.go | 11 +- dot/state/block_test.go | 31 ++ internal/database/mock/database.go | 678 +++++++++++++++++++++++++++ tests/rpc/system_integration_test.go | 4 +- 4 files changed, 716 insertions(+), 8 deletions(-) create mode 100644 internal/database/mock/database.go diff --git a/dot/state/block.go b/dot/state/block.go index 789cfb7c00..903846fa51 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -706,11 +706,8 @@ func (bs *BlockState) retrieveRangeFromDatabase(startHash common.Hash, lastPosition := blocksInRange - 1 - hashes[0] = startHash - hashes[lastPosition] = endHeader.Hash() - - inLoopHash := endHeader.ParentHash - for currentPosition := lastPosition - 1; currentPosition > 0; currentPosition-- { + inLoopHash := endHeader.Hash() + for currentPosition := int(lastPosition); currentPosition >= 0; currentPosition-- { hashes[currentPosition] = inLoopHash inLoopHeader, err := bs.loadHeaderFromDatabase(inLoopHash) @@ -721,9 +718,9 @@ func (bs *BlockState) retrieveRangeFromDatabase(startHash common.Hash, inLoopHash = inLoopHeader.ParentHash } - // here we ensure that we finished up the loop + // here we ensure that we finished up the loop with the hash we used as start // with the same hash as the startHash - if inLoopHash != startHash { + if hashes[0] != startHash { return nil, fmt.Errorf("%w: expecting %s, found: %s", ErrStartHashMismatch, startHash.Short(), inLoopHash.Short()) } diff --git a/dot/state/block_test.go b/dot/state/block_test.go index ced6cd4263..a453d66887 100644 --- a/dot/state/block_test.go +++ b/dot/state/block_test.go @@ -1099,3 +1099,34 @@ func Test_GetRuntime_StoreRuntime(t *testing.T) { require.NoError(t, err) require.Equal(t, runtimeInstance, sameRuntimeOnDiffHash) } + +const headerHex = "0x276bfa91f70859348285599321ea96afd3ae681f0be47d36196bac8075ea32e804496b5fbd26d7014ba2ef84b588859428e334549d374726263ea894691ff78a0d34aea7c0b7cdadce2f44389a28d4200e522cec26d4eae828183ce40bd57ebeee0c0642414245b50103000000002792f1100000000068ab0948ad2f3194f94c4a584bb8dc118d354316c10a51e04ce4ca7aed4a971c046b5dc4704d9fa43daad797291efa00a1070970f979d4593888dbcb7a628b08667ca7a2850eed67f908d9fce9ec45e6e688341d054d3f074ec102ae3844ca0f044241424529010104d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01000000000000000000000000000000000000000000000000000000000000000000000000000000054241424501016425bfe39b70f23a0de6b4e8159cf513c25cb7e18f52c6ba889f426211bb787dbe0f0a237cc93052f9fa8a68386722299b6c8ba0d8060ad6a1cbdb9688e9a982" + +// This decodes to next Header -> ParentHash=0x276bfa91f70859348285599321ea96afd3ae681f0be47d36196bac8075ea32e8 Number=1 StateRoot=0x496b5fbd26d7014ba2ef84b588859428e334549d374726263ea894691ff78a0d ExtrinsicsRoot=0x34aea7c0b7cdadce2f44389a28d4200e522cec26d4eae828183ce40bd57ebeee Digest=[PreRuntimeDigest ConsensusEngineID=BABE Data=0x03000000002792f1100000000068ab0948ad2f3194f94c4a584bb8dc118d354316c10a51e04ce4ca7aed4a971c046b5dc4704d9fa43daad797291efa00a1070970f979d4593888dbcb7a628b08667ca7a2850eed67f908d9fce9ec45e6e688341d054d3f074ec102ae3844ca0f, ConsensusDigest ConsensusEngineID=BABE Data=0x0104d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01000000000000000000000000000000000000000000000000000000000000000000000000000000, SealDigest ConsensusEngineID=BABE Data=0x6425bfe39b70f23a0de6b4e8159cf513c25cb7e18f52c6ba889f426211bb787dbe0f0a237cc93052f9fa8a68386722299b6c8ba0d8060ad6a1cbdb9688e9a982] Hash=0x885d464b8c8753f88973cfa457d385c8fe9c9d90a6a2f62e013cf81de3666812 + +func Test_retrieveRangeFromDatabaseWithOneBlock(t *testing.T) { + ctrl := gomock.NewController(t) + + telemetryMock := NewMockTelemetry(ctrl) + telemetryMock.EXPECT().SendMessage(gomock.Any()).AnyTimes() + db := NewInMemoryDB(t) + genesisHeader := &types.Header{ + Number: 0, + StateRoot: trie.EmptyHash, + Digest: types.NewDigest(), + } + bs, err := NewBlockStateFromGenesis(db, newTriesEmpty(), genesisHeader, telemetryMock) + + headerBytes, err := common.HexToBytes(headerHex) + require.NoError(t, err) + + headerType := types.NewEmptyHeader() + err = scale.Unmarshal(headerBytes, headerType) + require.NoError(t, err) + err = bs.SetHeader(headerType) + require.NoError(t, err) + + hashes, err := bs.retrieveRangeFromDatabase(headerType.Hash(), headerType) + require.NoError(t, err) + require.Equal(t, len(hashes), 1) +} diff --git a/internal/database/mock/database.go b/internal/database/mock/database.go new file mode 100644 index 0000000000..4415423b46 --- /dev/null +++ b/internal/database/mock/database.go @@ -0,0 +1,678 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/database/database.go +// +// Generated by this command: +// +// mockgen -destination=./internal/database/mock/database.go -source=./internal/database/database.go +// + +// Package mock_database is a generated GoMock package. +package mock_database + +import ( + reflect "reflect" + + database "github.com/ChainSafe/gossamer/internal/database" + gomock "go.uber.org/mock/gomock" +) + +// MockReader is a mock of Reader interface. +type MockReader struct { + ctrl *gomock.Controller + recorder *MockReaderMockRecorder +} + +// MockReaderMockRecorder is the mock recorder for MockReader. +type MockReaderMockRecorder struct { + mock *MockReader +} + +// NewMockReader creates a new mock instance. +func NewMockReader(ctrl *gomock.Controller) *MockReader { + mock := &MockReader{ctrl: ctrl} + mock.recorder = &MockReaderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockReader) EXPECT() *MockReaderMockRecorder { + return m.recorder +} + +// Get mocks base method. +func (m *MockReader) Get(key []byte) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", key) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockReaderMockRecorder) Get(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockReader)(nil).Get), key) +} + +// Has mocks base method. +func (m *MockReader) Has(key []byte) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Has", key) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Has indicates an expected call of Has. +func (mr *MockReaderMockRecorder) Has(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockReader)(nil).Has), key) +} + +// MockWriter is a mock of Writer interface. +type MockWriter struct { + ctrl *gomock.Controller + recorder *MockWriterMockRecorder +} + +// MockWriterMockRecorder is the mock recorder for MockWriter. +type MockWriterMockRecorder struct { + mock *MockWriter +} + +// NewMockWriter creates a new mock instance. +func NewMockWriter(ctrl *gomock.Controller) *MockWriter { + mock := &MockWriter{ctrl: ctrl} + mock.recorder = &MockWriterMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockWriter) EXPECT() *MockWriterMockRecorder { + return m.recorder +} + +// Del mocks base method. +func (m *MockWriter) Del(key []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Del", key) + ret0, _ := ret[0].(error) + return ret0 +} + +// Del indicates an expected call of Del. +func (mr *MockWriterMockRecorder) Del(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockWriter)(nil).Del), key) +} + +// Flush mocks base method. +func (m *MockWriter) Flush() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Flush") + ret0, _ := ret[0].(error) + return ret0 +} + +// Flush indicates an expected call of Flush. +func (mr *MockWriterMockRecorder) Flush() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Flush", reflect.TypeOf((*MockWriter)(nil).Flush)) +} + +// Put mocks base method. +func (m *MockWriter) Put(key, value []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Put", key, value) + ret0, _ := ret[0].(error) + return ret0 +} + +// Put indicates an expected call of Put. +func (mr *MockWriterMockRecorder) Put(key, value any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockWriter)(nil).Put), key, value) +} + +// MockIterator is a mock of Iterator interface. +type MockIterator struct { + ctrl *gomock.Controller + recorder *MockIteratorMockRecorder +} + +// MockIteratorMockRecorder is the mock recorder for MockIterator. +type MockIteratorMockRecorder struct { + mock *MockIterator +} + +// NewMockIterator creates a new mock instance. +func NewMockIterator(ctrl *gomock.Controller) *MockIterator { + mock := &MockIterator{ctrl: ctrl} + mock.recorder = &MockIteratorMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIterator) EXPECT() *MockIteratorMockRecorder { + return m.recorder +} + +// Close mocks base method. +func (m *MockIterator) 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 *MockIteratorMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockIterator)(nil).Close)) +} + +// First mocks base method. +func (m *MockIterator) First() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "First") + ret0, _ := ret[0].(bool) + return ret0 +} + +// First indicates an expected call of First. +func (mr *MockIteratorMockRecorder) First() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "First", reflect.TypeOf((*MockIterator)(nil).First)) +} + +// Key mocks base method. +func (m *MockIterator) Key() []byte { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Key") + ret0, _ := ret[0].([]byte) + return ret0 +} + +// Key indicates an expected call of Key. +func (mr *MockIteratorMockRecorder) Key() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Key", reflect.TypeOf((*MockIterator)(nil).Key)) +} + +// Next mocks base method. +func (m *MockIterator) Next() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Next") + ret0, _ := ret[0].(bool) + return ret0 +} + +// Next indicates an expected call of Next. +func (mr *MockIteratorMockRecorder) Next() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Next", reflect.TypeOf((*MockIterator)(nil).Next)) +} + +// Release mocks base method. +func (m *MockIterator) Release() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Release") +} + +// Release indicates an expected call of Release. +func (mr *MockIteratorMockRecorder) Release() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Release", reflect.TypeOf((*MockIterator)(nil).Release)) +} + +// SeekGE mocks base method. +func (m *MockIterator) SeekGE(key []byte) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SeekGE", key) + ret0, _ := ret[0].(bool) + return ret0 +} + +// SeekGE indicates an expected call of SeekGE. +func (mr *MockIteratorMockRecorder) SeekGE(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SeekGE", reflect.TypeOf((*MockIterator)(nil).SeekGE), key) +} + +// Valid mocks base method. +func (m *MockIterator) Valid() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Valid") + ret0, _ := ret[0].(bool) + return ret0 +} + +// Valid indicates an expected call of Valid. +func (mr *MockIteratorMockRecorder) Valid() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Valid", reflect.TypeOf((*MockIterator)(nil).Valid)) +} + +// Value mocks base method. +func (m *MockIterator) Value() []byte { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Value") + ret0, _ := ret[0].([]byte) + return ret0 +} + +// Value indicates an expected call of Value. +func (mr *MockIteratorMockRecorder) Value() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Value", reflect.TypeOf((*MockIterator)(nil).Value)) +} + +// MockBatch is a mock of Batch interface. +type MockBatch struct { + ctrl *gomock.Controller + recorder *MockBatchMockRecorder +} + +// MockBatchMockRecorder is the mock recorder for MockBatch. +type MockBatchMockRecorder struct { + mock *MockBatch +} + +// NewMockBatch creates a new mock instance. +func NewMockBatch(ctrl *gomock.Controller) *MockBatch { + mock := &MockBatch{ctrl: ctrl} + mock.recorder = &MockBatchMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBatch) EXPECT() *MockBatchMockRecorder { + return m.recorder +} + +// Close mocks base method. +func (m *MockBatch) 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 *MockBatchMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockBatch)(nil).Close)) +} + +// Del mocks base method. +func (m *MockBatch) Del(key []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Del", key) + ret0, _ := ret[0].(error) + return ret0 +} + +// Del indicates an expected call of Del. +func (mr *MockBatchMockRecorder) Del(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockBatch)(nil).Del), key) +} + +// Flush mocks base method. +func (m *MockBatch) Flush() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Flush") + ret0, _ := ret[0].(error) + return ret0 +} + +// Flush indicates an expected call of Flush. +func (mr *MockBatchMockRecorder) Flush() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Flush", reflect.TypeOf((*MockBatch)(nil).Flush)) +} + +// Put mocks base method. +func (m *MockBatch) Put(key, value []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Put", key, value) + ret0, _ := ret[0].(error) + return ret0 +} + +// Put indicates an expected call of Put. +func (mr *MockBatchMockRecorder) Put(key, value any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockBatch)(nil).Put), key, value) +} + +// Reset mocks base method. +func (m *MockBatch) Reset() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Reset") +} + +// Reset indicates an expected call of Reset. +func (mr *MockBatchMockRecorder) Reset() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reset", reflect.TypeOf((*MockBatch)(nil).Reset)) +} + +// ValueSize mocks base method. +func (m *MockBatch) ValueSize() int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValueSize") + ret0, _ := ret[0].(int) + return ret0 +} + +// ValueSize indicates an expected call of ValueSize. +func (mr *MockBatchMockRecorder) ValueSize() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValueSize", reflect.TypeOf((*MockBatch)(nil).ValueSize)) +} + +// 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 +} + +// 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)) +} + +// Del mocks base method. +func (m *MockDatabase) Del(key []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Del", key) + ret0, _ := ret[0].(error) + return ret0 +} + +// Del indicates an expected call of Del. +func (mr *MockDatabaseMockRecorder) Del(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockDatabase)(nil).Del), key) +} + +// Flush mocks base method. +func (m *MockDatabase) Flush() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Flush") + ret0, _ := ret[0].(error) + return ret0 +} + +// Flush indicates an expected call of Flush. +func (mr *MockDatabaseMockRecorder) Flush() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Flush", reflect.TypeOf((*MockDatabase)(nil).Flush)) +} + +// Get mocks base method. +func (m *MockDatabase) Get(key []byte) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", key) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockDatabaseMockRecorder) Get(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDatabase)(nil).Get), key) +} + +// Has mocks base method. +func (m *MockDatabase) Has(key []byte) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Has", key) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Has indicates an expected call of Has. +func (mr *MockDatabaseMockRecorder) Has(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockDatabase)(nil).Has), key) +} + +// NewBatch mocks base method. +func (m *MockDatabase) NewBatch() database.Batch { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewBatch") + ret0, _ := ret[0].(database.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)) +} + +// NewIterator mocks base method. +func (m *MockDatabase) NewIterator() (database.Iterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewIterator") + ret0, _ := ret[0].(database.Iterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NewIterator indicates an expected call of NewIterator. +func (mr *MockDatabaseMockRecorder) NewIterator() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewIterator", reflect.TypeOf((*MockDatabase)(nil).NewIterator)) +} + +// NewPrefixIterator mocks base method. +func (m *MockDatabase) NewPrefixIterator(prefix []byte) (database.Iterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewPrefixIterator", prefix) + ret0, _ := ret[0].(database.Iterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NewPrefixIterator indicates an expected call of NewPrefixIterator. +func (mr *MockDatabaseMockRecorder) NewPrefixIterator(prefix any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewPrefixIterator", reflect.TypeOf((*MockDatabase)(nil).NewPrefixIterator), prefix) +} + +// Path mocks base method. +func (m *MockDatabase) Path() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Path") + ret0, _ := ret[0].(string) + return ret0 +} + +// Path indicates an expected call of Path. +func (mr *MockDatabaseMockRecorder) Path() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Path", reflect.TypeOf((*MockDatabase)(nil).Path)) +} + +// Put mocks base method. +func (m *MockDatabase) Put(key, value []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Put", key, value) + ret0, _ := ret[0].(error) + return ret0 +} + +// Put indicates an expected call of Put. +func (mr *MockDatabaseMockRecorder) Put(key, value any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockDatabase)(nil).Put), key, value) +} + +// MockTable is a mock of Table interface. +type MockTable struct { + ctrl *gomock.Controller + recorder *MockTableMockRecorder +} + +// MockTableMockRecorder is the mock recorder for MockTable. +type MockTableMockRecorder struct { + mock *MockTable +} + +// NewMockTable creates a new mock instance. +func NewMockTable(ctrl *gomock.Controller) *MockTable { + mock := &MockTable{ctrl: ctrl} + mock.recorder = &MockTableMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockTable) EXPECT() *MockTableMockRecorder { + return m.recorder +} + +// Del mocks base method. +func (m *MockTable) Del(key []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Del", key) + ret0, _ := ret[0].(error) + return ret0 +} + +// Del indicates an expected call of Del. +func (mr *MockTableMockRecorder) Del(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Del", reflect.TypeOf((*MockTable)(nil).Del), key) +} + +// Flush mocks base method. +func (m *MockTable) Flush() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Flush") + ret0, _ := ret[0].(error) + return ret0 +} + +// Flush indicates an expected call of Flush. +func (mr *MockTableMockRecorder) Flush() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Flush", reflect.TypeOf((*MockTable)(nil).Flush)) +} + +// Get mocks base method. +func (m *MockTable) Get(key []byte) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", key) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockTableMockRecorder) Get(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockTable)(nil).Get), key) +} + +// Has mocks base method. +func (m *MockTable) Has(key []byte) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Has", key) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Has indicates an expected call of Has. +func (mr *MockTableMockRecorder) Has(key any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockTable)(nil).Has), key) +} + +// NewBatch mocks base method. +func (m *MockTable) NewBatch() database.Batch { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewBatch") + ret0, _ := ret[0].(database.Batch) + return ret0 +} + +// NewBatch indicates an expected call of NewBatch. +func (mr *MockTableMockRecorder) NewBatch() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatch", reflect.TypeOf((*MockTable)(nil).NewBatch)) +} + +// NewIterator mocks base method. +func (m *MockTable) NewIterator() (database.Iterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewIterator") + ret0, _ := ret[0].(database.Iterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NewIterator indicates an expected call of NewIterator. +func (mr *MockTableMockRecorder) NewIterator() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewIterator", reflect.TypeOf((*MockTable)(nil).NewIterator)) +} + +// Path mocks base method. +func (m *MockTable) Path() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Path") + ret0, _ := ret[0].(string) + return ret0 +} + +// Path indicates an expected call of Path. +func (mr *MockTableMockRecorder) Path() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Path", reflect.TypeOf((*MockTable)(nil).Path)) +} + +// Put mocks base method. +func (m *MockTable) Put(key, value []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Put", key, value) + ret0, _ := ret[0].(error) + return ret0 +} + +// Put indicates an expected call of Put. +func (mr *MockTableMockRecorder) Put(key, value any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockTable)(nil).Put), key, value) +} diff --git a/tests/rpc/system_integration_test.go b/tests/rpc/system_integration_test.go index e7230f3700..c9ec5396d2 100644 --- a/tests/rpc/system_integration_test.go +++ b/tests/rpc/system_integration_test.go @@ -68,8 +68,10 @@ func TestStableNetworkRPC(t *testing.T) { //nolint:tparallel err := retry.UntilOK(peerTimeout, 10*time.Second, func() (bool, error) { for _, node := range nodes { endpoint := rpc.NewEndpoint(node.RPCPort()) + t.Logf("starting node %s with port %s", node.String(), endpoint) var response modules.SystemHealthResponse fetchWithTimeoutFromEndpoint(t, endpoint, "system_health", &response) + t.Logf("Reponse: %+v", response) if response.Peers != len(nodes)-1 { return false, nil } @@ -162,8 +164,8 @@ func fetchWithTimeoutFromEndpoint(t *testing.T, endpoint, method string, target t.Helper() ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() body, err := rpc.Post(ctx, endpoint, method, "{}") - cancel() require.NoError(t, err) err = rpc.Decode(body, target) From b19844cd8f59597490f95f931c7faf6cbb10ffb6 Mon Sep 17 00:00:00 2001 From: Kirill Pisarev Date: Mon, 22 Jan 2024 12:31:50 +0100 Subject: [PATCH 2/5] fix: linters --- dot/state/block_test.go | 1 + tests/rpc/system_integration_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dot/state/block_test.go b/dot/state/block_test.go index a453d66887..52afbafcea 100644 --- a/dot/state/block_test.go +++ b/dot/state/block_test.go @@ -1116,6 +1116,7 @@ func Test_retrieveRangeFromDatabaseWithOneBlock(t *testing.T) { Digest: types.NewDigest(), } bs, err := NewBlockStateFromGenesis(db, newTriesEmpty(), genesisHeader, telemetryMock) + require.NoError(t, err) headerBytes, err := common.HexToBytes(headerHex) require.NoError(t, err) diff --git a/tests/rpc/system_integration_test.go b/tests/rpc/system_integration_test.go index c9ec5396d2..c2842736e2 100644 --- a/tests/rpc/system_integration_test.go +++ b/tests/rpc/system_integration_test.go @@ -71,7 +71,7 @@ func TestStableNetworkRPC(t *testing.T) { //nolint:tparallel t.Logf("starting node %s with port %s", node.String(), endpoint) var response modules.SystemHealthResponse fetchWithTimeoutFromEndpoint(t, endpoint, "system_health", &response) - t.Logf("Reponse: %+v", response) + t.Logf("Response: %+v", response) if response.Peers != len(nodes)-1 { return false, nil } From f1eae539913bb64711a4801d0a70e89a469e2346 Mon Sep 17 00:00:00 2001 From: Kirill Pisarev Date: Mon, 22 Jan 2024 13:17:18 +0100 Subject: [PATCH 3/5] fix: linters --- dot/state/block_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dot/state/block_test.go b/dot/state/block_test.go index 52afbafcea..2a44d62c5d 100644 --- a/dot/state/block_test.go +++ b/dot/state/block_test.go @@ -1100,9 +1100,9 @@ func Test_GetRuntime_StoreRuntime(t *testing.T) { require.Equal(t, runtimeInstance, sameRuntimeOnDiffHash) } -const headerHex = "0x276bfa91f70859348285599321ea96afd3ae681f0be47d36196bac8075ea32e804496b5fbd26d7014ba2ef84b588859428e334549d374726263ea894691ff78a0d34aea7c0b7cdadce2f44389a28d4200e522cec26d4eae828183ce40bd57ebeee0c0642414245b50103000000002792f1100000000068ab0948ad2f3194f94c4a584bb8dc118d354316c10a51e04ce4ca7aed4a971c046b5dc4704d9fa43daad797291efa00a1070970f979d4593888dbcb7a628b08667ca7a2850eed67f908d9fce9ec45e6e688341d054d3f074ec102ae3844ca0f044241424529010104d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01000000000000000000000000000000000000000000000000000000000000000000000000000000054241424501016425bfe39b70f23a0de6b4e8159cf513c25cb7e18f52c6ba889f426211bb787dbe0f0a237cc93052f9fa8a68386722299b6c8ba0d8060ad6a1cbdb9688e9a982" - -// This decodes to next Header -> ParentHash=0x276bfa91f70859348285599321ea96afd3ae681f0be47d36196bac8075ea32e8 Number=1 StateRoot=0x496b5fbd26d7014ba2ef84b588859428e334549d374726263ea894691ff78a0d ExtrinsicsRoot=0x34aea7c0b7cdadce2f44389a28d4200e522cec26d4eae828183ce40bd57ebeee Digest=[PreRuntimeDigest ConsensusEngineID=BABE Data=0x03000000002792f1100000000068ab0948ad2f3194f94c4a584bb8dc118d354316c10a51e04ce4ca7aed4a971c046b5dc4704d9fa43daad797291efa00a1070970f979d4593888dbcb7a628b08667ca7a2850eed67f908d9fce9ec45e6e688341d054d3f074ec102ae3844ca0f, ConsensusDigest ConsensusEngineID=BABE Data=0x0104d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01000000000000000000000000000000000000000000000000000000000000000000000000000000, SealDigest ConsensusEngineID=BABE Data=0x6425bfe39b70f23a0de6b4e8159cf513c25cb7e18f52c6ba889f426211bb787dbe0f0a237cc93052f9fa8a68386722299b6c8ba0d8060ad6a1cbdb9688e9a982] Hash=0x885d464b8c8753f88973cfa457d385c8fe9c9d90a6a2f62e013cf81de3666812 +const headerHex = "0x276bfa91f70859348285599321ea96afd3ae681f0be47d36196bac8075ea32e804496b5fbd26d7014ba2ef84b588859428e334549d374726263ea894691ff78a0d34aea7c0b7cdadce2f44389a28d4200e522cec26d4eae828183ce40bd57ebeee0c0642414245b50103000000002792f1100000000068ab0948ad2f3194f94c4a584bb8dc118d354316c10a51e04ce4ca7aed4a971c046b5dc4704d9fa43daad797291efa00a1070970f979d4593888dbcb7a628b08667ca7a2850eed67f908d9fce9ec45e6e688341d054d3f074ec102ae3844ca0f044241424529010104d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01000000000000000000000000000000000000000000000000000000000000000000000000000000054241424501016425bfe39b70f23a0de6b4e8159cf513c25cb7e18f52c6ba889f426211bb787dbe0f0a237cc93052f9fa8a68386722299b6c8ba0d8060ad6a1cbdb9688e9a982" //nolint:lll +//nolint:lll +// This decodes to next Header -> ParentHash=0x276bfa91f70859348285599321ea96afd3ae681f0be47d36196bac8075ea32e8 Number=1 StateRoot=0x496b5fbd26d7014ba2ef84b588859428e334549d374726263ea894691ff78a0d ExtrinsicsRoot=0x34aea7c0b7cdadce2f44389a28d4200e522cec26d4eae828183ce40bd57ebeee Digest=[PreRuntimeDigest ConsensusEngineID=BABE Data=0x03000000002792f1100000000068ab0948ad2f3194f94c4a584bb8dc118d354316c10a51e04ce4ca7aed4a971c046b5dc4704d9fa43daad797291efa00a1070970f979d4593888dbcb7a628b08667ca7a2850eed67f908d9fce9ec45e6e688341d054d3f074ec102ae3844ca0f, ConsensusDigest ConsensusEngineID=BABE Data=0x0104d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01000000000000000000000000000000000000000000000000000000000000000000000000000000, SealDigest ConsensusEngineID=BABE Data=0x6425bfe39b70f23a0de6b4e8159cf513c25cb7e18f52c6ba889f426211bb787dbe0f0a237cc93052f9fa8a68386722299b6c8ba0d8060ad6a1cbdb9688e9a982] Hash=0x885d464b8c8753f88973cfa457d385c8fe9c9d90a6a2f62e013cf81de3666812 //nolint:lll func Test_retrieveRangeFromDatabaseWithOneBlock(t *testing.T) { ctrl := gomock.NewController(t) From de6bf270f5839646ceaae49a493d2d304a0ae0ce Mon Sep 17 00:00:00 2001 From: Kirill Pisarev Date: Mon, 22 Jan 2024 13:49:31 +0100 Subject: [PATCH 4/5] fix: fix publickly available locks for BlockState --- dot/state/block.go | 24 ++++++++++++------------ dot/state/block_finalisation.go | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index 789cfb7c00..2436bcb450 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -51,11 +51,11 @@ var ( // BlockState contains the historical block data of the blockchain, including block headers and bodies. // It wraps the blocktree (which contains unfinalised blocks) and the database (which contains finalised blocks). type BlockState struct { - bt *blocktree.BlockTree - baseState *BaseState - dbPath string - db BlockStateDatabase - sync.RWMutex + bt *blocktree.BlockTree + baseState *BaseState + dbPath string + db BlockStateDatabase + lock sync.RWMutex genesisHash common.Hash lastFinalised common.Hash unfinalisedBlocks *hashToBlockMap @@ -334,7 +334,7 @@ func (bs *BlockState) GetBlockHashesBySlot(slotNum uint64) ([]common.Hash, error return nil, fmt.Errorf("failed to get descendants: %w", err) } - blocksWithGivenSlot := []common.Hash{} + var blocksWithGivenSlot []common.Hash for _, desc := range descendants { descSlot, err := bs.GetSlotForBlock(desc) @@ -380,8 +380,8 @@ func (bs *BlockState) GetBlockByNumber(num uint) (*types.Block, error) { // GetBlockByHash returns a block for a given hash func (bs *BlockState) GetBlockByHash(hash common.Hash) (*types.Block, error) { - bs.RLock() - defer bs.RUnlock() + bs.lock.RLock() + defer bs.lock.RUnlock() block := bs.unfinalisedBlocks.getBlock(hash) if block != nil { @@ -413,8 +413,8 @@ func (bs *BlockState) SetHeader(header *types.Header) error { // HasBlockBody returns true if the db contains the block body func (bs *BlockState) HasBlockBody(hash common.Hash) (bool, error) { - bs.RLock() - defer bs.RUnlock() + bs.lock.RLock() + defer bs.lock.RUnlock() if bs.unfinalisedBlocks.getBlock(hash) != nil { return true, nil @@ -471,8 +471,8 @@ func (bs *BlockState) CompareAndSetBlockData(bd *types.BlockData) error { // AddBlock adds a block to the blocktree and the DB with arrival time as current unix time func (bs *BlockState) AddBlock(block *types.Block) error { - bs.Lock() - defer bs.Unlock() + bs.lock.Lock() + defer bs.lock.Unlock() return bs.AddBlockWithArrivalTime(block, time.Now()) } diff --git a/dot/state/block_finalisation.go b/dot/state/block_finalisation.go index d28e628211..58428e7529 100644 --- a/dot/state/block_finalisation.go +++ b/dot/state/block_finalisation.go @@ -38,8 +38,8 @@ func (bs *BlockState) NumberIsFinalised(num uint) (bool, error) { // GetFinalisedHeader returns the finalised block header by round and setID func (bs *BlockState) GetFinalisedHeader(round, setID uint64) (*types.Header, error) { - bs.Lock() - defer bs.Unlock() + bs.lock.Lock() + defer bs.lock.Unlock() h, err := bs.GetFinalisedHash(round, setID) if err != nil { @@ -116,8 +116,8 @@ func (bs *BlockState) GetHighestFinalisedHeader() (*types.Header, error) { // SetFinalisedHash sets the latest finalised block hash func (bs *BlockState) SetFinalisedHash(hash common.Hash, round, setID uint64) error { - bs.Lock() - defer bs.Unlock() + bs.lock.Lock() + defer bs.lock.Unlock() has, err := bs.HasHeader(hash) if err != nil { From acee2cc16ad96f20fee885e2dfe7edaf9e6b2507 Mon Sep 17 00:00:00 2001 From: Kirill Pisarev Date: Mon, 22 Jan 2024 14:05:15 +0100 Subject: [PATCH 5/5] fix: fix go deepsource warning --- dot/state/block.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dot/state/block.go b/dot/state/block.go index 581d59286b..150dcd0179 100644 --- a/dot/state/block.go +++ b/dot/state/block.go @@ -678,8 +678,7 @@ func (bs *BlockState) retrieveRange(startHash, endHash common.Hash) (hashes []co return nil, fmt.Errorf("retrieving range from database: %w", err) } - hashes = append(inDatabaseHashes, inMemoryHashes...) - return hashes, nil + return append(inDatabaseHashes, inMemoryHashes...), nil } var ErrStartHashMismatch = errors.New("start hash mismatch")