mirror of
https://github.com/tendermint/tendermint.git
synced 2026-02-05 11:31:16 +00:00
Went through #2871, there are several issues, this PR tries to tackle the `HasVoteMessage` with an invalid validator index sent by a bad peer and it prevents the bad vote goes to the peerMsgQueue. Future work, check other bad message cases and plumbing the reactor errors with the peer manager and then can disconnect the peer sending the bad messages.
101 lines
2.5 KiB
Go
101 lines
2.5 KiB
Go
package consensus
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
func peerStateSetup(h, r, v int) *PeerState {
|
|
ps := NewPeerState(log.TestingLogger(), "testPeerState")
|
|
ps.PRS.Height = int64(h)
|
|
ps.PRS.Round = int32(r)
|
|
ps.ensureVoteBitArrays(int64(h), v)
|
|
return ps
|
|
}
|
|
|
|
func TestSetHasVote(t *testing.T) {
|
|
ps := peerStateSetup(1, 1, 1)
|
|
pva := ps.PRS.Prevotes.Copy()
|
|
|
|
// nil vote should return ErrPeerStateNilVote
|
|
err := ps.SetHasVote(nil)
|
|
require.Equal(t, ErrPeerStateSetNilVote, err)
|
|
|
|
// the peer giving an invalid index should returns ErrPeerStateInvalidVoteIndex
|
|
v0 := &types.Vote{
|
|
Height: 1,
|
|
ValidatorIndex: -1,
|
|
Round: 1,
|
|
Type: tmproto.PrevoteType,
|
|
}
|
|
|
|
err = ps.SetHasVote(v0)
|
|
require.Equal(t, ErrPeerStateInvalidVoteIndex, err)
|
|
|
|
// the peer giving an invalid index should returns ErrPeerStateInvalidVoteIndex
|
|
v1 := &types.Vote{
|
|
Height: 1,
|
|
ValidatorIndex: 1,
|
|
Round: 1,
|
|
Type: tmproto.PrevoteType,
|
|
}
|
|
|
|
err = ps.SetHasVote(v1)
|
|
require.Equal(t, ErrPeerStateInvalidVoteIndex, err)
|
|
|
|
// the peer giving a correct index should return nil (vote has been set)
|
|
v2 := &types.Vote{
|
|
Height: 1,
|
|
ValidatorIndex: 0,
|
|
Round: 1,
|
|
Type: tmproto.PrevoteType,
|
|
}
|
|
require.Nil(t, ps.SetHasVote(v2))
|
|
|
|
// verify vote
|
|
pva.SetIndex(0, true)
|
|
require.Equal(t, pva, ps.getVoteBitArray(1, 1, tmproto.PrevoteType))
|
|
|
|
// the vote is not in the correct height/round/voteType should return nil (ignore the vote)
|
|
v3 := &types.Vote{
|
|
Height: 2,
|
|
ValidatorIndex: 0,
|
|
Round: 1,
|
|
Type: tmproto.PrevoteType,
|
|
}
|
|
require.Nil(t, ps.SetHasVote(v3))
|
|
// prevote bitarray has no update
|
|
require.Equal(t, pva, ps.getVoteBitArray(1, 1, tmproto.PrevoteType))
|
|
}
|
|
|
|
func TestApplyHasVoteMessage(t *testing.T) {
|
|
ps := peerStateSetup(1, 1, 1)
|
|
pva := ps.PRS.Prevotes.Copy()
|
|
|
|
// ignore the message with an invalid height
|
|
msg := &HasVoteMessage{
|
|
Height: 2,
|
|
}
|
|
require.Nil(t, ps.ApplyHasVoteMessage(msg))
|
|
|
|
// apply a message like v2 in TestSetHasVote
|
|
msg2 := &HasVoteMessage{
|
|
Height: 1,
|
|
Index: 0,
|
|
Round: 1,
|
|
Type: tmproto.PrevoteType,
|
|
}
|
|
|
|
require.Nil(t, ps.ApplyHasVoteMessage(msg2))
|
|
|
|
// verify vote
|
|
pva.SetIndex(0, true)
|
|
require.Equal(t, pva, ps.getVoteBitArray(1, 1, tmproto.PrevoteType))
|
|
|
|
// skip test cases like v & v3 in TestSetHasVote due to the same path
|
|
}
|