Files
tendermint/internal/consensus/peer_state_test.go
JayT106 ce898a738c consensus: HasVoteMessage index boundary check (#7720)
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.
2022-02-21 13:21:24 +00:00

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
}