diff --git a/internal/consensus/versioned/selectproposer/mocks/proposer_selector.go b/internal/consensus/versioned/selectproposer/mocks/proposer_selector.go new file mode 100644 index 000000000..e2071d276 --- /dev/null +++ b/internal/consensus/versioned/selectproposer/mocks/proposer_selector.go @@ -0,0 +1,136 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + selectproposer "github.com/dashpay/tenderdash/internal/consensus/versioned/selectproposer" + types "github.com/dashpay/tenderdash/types" + mock "github.com/stretchr/testify/mock" +) + +// ProposerSelector is an autogenerated mock type for the ProposerSelector type +type ProposerSelector struct { + mock.Mock +} + +// Copy provides a mock function with given fields: +func (_m *ProposerSelector) Copy() selectproposer.ProposerSelector { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Copy") + } + + var r0 selectproposer.ProposerSelector + if rf, ok := ret.Get(0).(func() selectproposer.ProposerSelector); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(selectproposer.ProposerSelector) + } + } + + return r0 +} + +// GetProposer provides a mock function with given fields: height, round +func (_m *ProposerSelector) GetProposer(height int64, round int32) (*types.Validator, error) { + ret := _m.Called(height, round) + + if len(ret) == 0 { + panic("no return value specified for GetProposer") + } + + var r0 *types.Validator + var r1 error + if rf, ok := ret.Get(0).(func(int64, int32) (*types.Validator, error)); ok { + return rf(height, round) + } + if rf, ok := ret.Get(0).(func(int64, int32) *types.Validator); ok { + r0 = rf(height, round) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Validator) + } + } + + if rf, ok := ret.Get(1).(func(int64, int32) error); ok { + r1 = rf(height, round) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MustGetProposer provides a mock function with given fields: height, round +func (_m *ProposerSelector) MustGetProposer(height int64, round int32) *types.Validator { + ret := _m.Called(height, round) + + if len(ret) == 0 { + panic("no return value specified for MustGetProposer") + } + + var r0 *types.Validator + if rf, ok := ret.Get(0).(func(int64, int32) *types.Validator); ok { + r0 = rf(height, round) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Validator) + } + } + + return r0 +} + +// UpdateHeightRound provides a mock function with given fields: height, round +func (_m *ProposerSelector) UpdateHeightRound(height int64, round int32) error { + ret := _m.Called(height, round) + + if len(ret) == 0 { + panic("no return value specified for UpdateHeightRound") + } + + var r0 error + if rf, ok := ret.Get(0).(func(int64, int32) error); ok { + r0 = rf(height, round) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ValidatorSet provides a mock function with given fields: +func (_m *ProposerSelector) ValidatorSet() *types.ValidatorSet { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for ValidatorSet") + } + + var r0 *types.ValidatorSet + if rf, ok := ret.Get(0).(func() *types.ValidatorSet); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ValidatorSet) + } + } + + return r0 +} + +// NewProposerSelector creates a new instance of ProposerSelector. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewProposerSelector(t interface { + mock.TestingT + Cleanup(func()) +}) *ProposerSelector { + mock := &ProposerSelector{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/consensus/versioned/selectproposer/proposer_selector.go b/internal/consensus/versioned/selectproposer/proposer_selector.go index 792df302f..9895dfd46 100644 --- a/internal/consensus/versioned/selectproposer/proposer_selector.go +++ b/internal/consensus/versioned/selectproposer/proposer_selector.go @@ -8,6 +8,8 @@ import ( "github.com/dashpay/tenderdash/types" ) +//go:generate ../../../../scripts/mockery_generate.sh ProposerSelector + type ProposerSelector interface { // GetProposer returns the proposer for the given height and round. It calls Update if necessary. GetProposer(height int64, round int32) (*types.Validator, error) diff --git a/internal/evidence/pool_test.go b/internal/evidence/pool_test.go index 4d8f263a2..036f1df60 100644 --- a/internal/evidence/pool_test.go +++ b/internal/evidence/pool_test.go @@ -12,6 +12,8 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/dashpay/tenderdash/crypto" + "github.com/dashpay/tenderdash/internal/consensus/versioned/selectproposer" + psmocks "github.com/dashpay/tenderdash/internal/consensus/versioned/selectproposer/mocks" "github.com/dashpay/tenderdash/internal/eventbus" "github.com/dashpay/tenderdash/internal/evidence" "github.com/dashpay/tenderdash/internal/evidence/mocks" @@ -108,6 +110,17 @@ func TestEvidencePoolBasic(t *testing.T) { require.Equal(t, 1, len(evs)) } +func makeBlockMeta(height int64, time time.Time, vals *types.ValidatorSet) *types.BlockMeta { + return &types.BlockMeta{ + Header: types.Header{ + Height: height, + Time: time, + ProposerProTxHash: vals.Proposer().ProTxHash, + ValidatorsHash: vals.Hash(), + }, + } +} + // Tests inbound evidence for the right time and height func TestAddExpiredEvidence(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) @@ -115,20 +128,23 @@ func TestAddExpiredEvidence(t *testing.T) { var ( quorumHash = crypto.RandQuorumHash() - val = types.NewMockPVForQuorum(quorumHash) + privval = types.NewMockPVForQuorum(quorumHash) + val = privval.ExtractIntoValidator(ctx, quorumHash) + valSet = types.NewValidatorSet([]*types.Validator{val}, val.PubKey, btcjson.LLMQType_5_60, quorumHash, true) height = int64(30) - stateStore = initializeValidatorState(ctx, t, val, height, btcjson.LLMQType_5_60, quorumHash) + stateStore = initializeValidatorState(ctx, t, privval, height, btcjson.LLMQType_5_60, quorumHash) evidenceDB = dbm.NewMemDB() blockStore = &mocks.BlockStore{} expiredEvidenceTime = time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC) expiredHeight = int64(2) ) + blockStore.On("Base").Return(int64(3)) blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(func(h int64) *types.BlockMeta { if h == height || h == expiredHeight { - return &types.BlockMeta{Header: types.Header{Time: defaultEvidenceTime}} + return makeBlockMeta(h, defaultEvidenceTime, valSet) } - return &types.BlockMeta{Header: types.Header{Time: expiredEvidenceTime}} + return makeBlockMeta(h, expiredEvidenceTime, valSet) }) logger := log.NewNopLogger() @@ -160,7 +176,7 @@ func TestAddExpiredEvidence(t *testing.T) { defer cancel() vals := pool.State().Validators - ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx, tc.evHeight, tc.evTime, val, evidenceChainID, vals.QuorumType, vals.QuorumHash) + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx, tc.evHeight, tc.evTime, privval, evidenceChainID, vals.QuorumType, vals.QuorumHash) require.NoError(t, err) err = pool.AddEvidence(ctx, ev) if tc.expErr { @@ -408,7 +424,9 @@ func TestRecoverPendingEvidence(t *testing.T) { state, err := stateStore.Load() require.NoError(t, err) - blockStore, err := initializeBlockStore(dbm.NewMemDB(), state) + propSel := mockProposerSelector(t, val.ExtractIntoValidator(ctx, quorumHash)) + + blockStore, err := initializeBlockStore(dbm.NewMemDB(), state, propSel) require.NoError(t, err) logger := log.NewNopLogger() @@ -535,12 +553,12 @@ func initializeValidatorState( // initializeBlockStore creates a block storage and populates it w/ a dummy // block at +height+. -func initializeBlockStore(db dbm.DB, state sm.State) (*store.BlockStore, error) { +func initializeBlockStore(db dbm.DB, state sm.State, propsel selectproposer.ProposerSelector) (*store.BlockStore, error) { blockStore := store.NewBlockStore(db) for i := int64(1); i <= state.LastBlockHeight; i++ { lastCommit := makeCommit(i-1, state.Validators.QuorumHash) - prop := state.GetProposerFromState(i, 0) + prop := propsel.MustGetProposer(i, 0) block := state.MakeBlock(i, []types.Tx{}, lastCommit, nil, prop.ProTxHash, 0) block.Header.Time = defaultEvidenceTime.Add(time.Duration(i) * time.Minute) @@ -573,16 +591,38 @@ func makeCommit(height int64, quorumHash []byte) *types.Commit { ) } +func mockProposerSelector(t *testing.T, validator *types.Validator) selectproposer.ProposerSelector { + t.Helper() + propSel := psmocks.NewProposerSelector(t) + propSel.On("GetProposer", mock.Anything, mock.Anything). + Return(validator, nil). + Maybe() + propSel.On("MustGetProposer", mock.Anything, mock.Anything). + Return(validator). + Maybe() + propSel.On("UpdateHeightRound", mock.Anything, mock.Anything). + Return(nil). + Maybe() + + return propSel +} + func defaultTestPool(ctx context.Context, t *testing.T, height int64) (*evidence.Pool, *types.MockPV, *eventbus.EventBus) { t.Helper() quorumHash := crypto.RandQuorumHash() - val := types.NewMockPVForQuorum(quorumHash) + privval := types.NewMockPVForQuorum(quorumHash) + val := privval.ExtractIntoValidator(ctx, quorumHash) evidenceDB := dbm.NewMemDB() - stateStore := initializeValidatorState(ctx, t, val, height, btcjson.LLMQType_5_60, quorumHash) + stateStore := initializeValidatorState(ctx, t, privval, height, btcjson.LLMQType_5_60, quorumHash) state, err := stateStore.Load() require.NoError(t, err) - blockStore, err := initializeBlockStore(dbm.NewMemDB(), state) + + propSel := mockProposerSelector(t, val) + + require.NoError(t, err) + + blockStore, err := initializeBlockStore(dbm.NewMemDB(), state, propSel) require.NoError(t, err) logger := log.NewNopLogger() @@ -592,7 +632,7 @@ func defaultTestPool(ctx context.Context, t *testing.T, height int64) (*evidence pool := evidence.NewPool(logger, evidenceDB, stateStore, blockStore, evidence.NopMetrics(), eventBus) startPool(t, pool, stateStore) - return pool, val, eventBus + return pool, privval, eventBus } func createState(height int64, valSet *types.ValidatorSet) sm.State { diff --git a/internal/evidence/reactor_test.go b/internal/evidence/reactor_test.go index 845273d38..615405281 100644 --- a/internal/evidence/reactor_test.go +++ b/internal/evidence/reactor_test.go @@ -77,9 +77,10 @@ func setup(ctx context.Context, t *testing.T, stateStores []sm.Store) *reactorTe evidenceDB := dbm.NewMemDB() blockStore := &mocks.BlockStore{} state, _ := stateStores[idx].Load() + blockStore.On("Base").Return(int64(1)) blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(func(h int64) *types.BlockMeta { if h <= state.LastBlockHeight { - return &types.BlockMeta{Header: types.Header{Time: evidenceTime}} + return makeBlockMeta(h, evidenceTime, state.Validators) } return nil }) diff --git a/internal/evidence/verify_test.go b/internal/evidence/verify_test.go index 18db60a22..023ec9e39 100644 --- a/internal/evidence/verify_test.go +++ b/internal/evidence/verify_test.go @@ -7,6 +7,7 @@ import ( "github.com/dashpay/dashd-go/btcjson" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" dbm "github.com/tendermint/tm-db" @@ -110,7 +111,7 @@ func TestVerifyDuplicateVoteEvidence(t *testing.T) { ConsensusParams: *types.DefaultConsensusParams(), } stateStore := &smmocks.Store{} - stateStore.On("LoadValidators", int64(10)).Return(valSet, nil) + stateStore.On("LoadValidators", int64(10), mock.Anything).Return(valSet, nil) stateStore.On("Load").Return(state, nil) blockStore := &mocks.BlockStore{} blockStore.On("LoadBlockMeta", int64(10)).Return(&types.BlockMeta{Header: types.Header{Time: defaultEvidenceTime}})