tendermint/types/vote_test.go

152 lines
3.9 KiB
Go

package types
import (
"math"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/tmhash"
tmtime "github.com/tendermint/tendermint/types/time"
)
func examplePrevote() *Vote {
return exampleVote(VoteTypePrevote)
}
func examplePrecommit() *Vote {
return exampleVote(VoteTypePrecommit)
}
func exampleVote(t byte) *Vote {
var stamp, err = time.Parse(TimeFormat, "2017-12-25T03:00:01.234Z")
if err != nil {
panic(err)
}
return &Vote{
ValidatorAddress: tmhash.Sum([]byte("validator_address")),
ValidatorIndex: 56789,
Height: 12345,
Round: 2,
Timestamp: stamp,
Type: t,
BlockID: BlockID{
Hash: tmhash.Sum([]byte("blockID_hash")),
PartsHeader: PartSetHeader{
Total: 1000000,
Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
},
},
}
}
func TestVoteSignable(t *testing.T) {
vote := examplePrecommit()
signBytes := vote.SignBytes("test_chain_id")
signStr := string(signBytes)
expected := `{"@chain_id":"test_chain_id","@type":"vote","block_id":{"hash":"8B01023386C371778ECB6368573E539AFC3CC860","parts":{"hash":"72DB3D959635DFF1BB567BEDAA70573392C51596","total":"1000000"}},"height":"12345","round":"2","timestamp":"2017-12-25T03:00:01.234Z","type":2}`
if signStr != expected {
// NOTE: when this fails, you probably want to fix up consensus/replay_test too
t.Errorf("Got unexpected sign string for Vote. Expected:\n%v\nGot:\n%v", expected, signStr)
}
}
func TestVoteVerifySignature(t *testing.T) {
privVal := NewMockPV()
pubkey := privVal.GetPubKey()
vote := examplePrecommit()
signBytes := vote.SignBytes("test_chain_id")
// sign it
err := privVal.SignVote("test_chain_id", vote)
require.NoError(t, err)
// verify the same vote
valid := pubkey.VerifyBytes(vote.SignBytes("test_chain_id"), vote.Signature)
require.True(t, valid)
// serialize, deserialize and verify again....
precommit := new(Vote)
bs, err := cdc.MarshalBinary(vote)
require.NoError(t, err)
err = cdc.UnmarshalBinary(bs, &precommit)
require.NoError(t, err)
// verify the transmitted vote
newSignBytes := precommit.SignBytes("test_chain_id")
require.Equal(t, string(signBytes), string(newSignBytes))
valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature)
require.True(t, valid)
}
func TestIsVoteTypeValid(t *testing.T) {
tc := []struct {
name string
in byte
out bool
}{
{"Prevote", VoteTypePrevote, true},
{"Precommit", VoteTypePrecommit, true},
{"InvalidType", byte(3), false},
}
for _, tt := range tc {
tt := tt
t.Run(tt.name, func(st *testing.T) {
if rs := IsVoteTypeValid(tt.in); rs != tt.out {
t.Errorf("Got unexpected Vote type. Expected:\n%v\nGot:\n%v", rs, tt.out)
}
})
}
}
func TestVoteVerify(t *testing.T) {
privVal := NewMockPV()
pubkey := privVal.GetPubKey()
vote := examplePrevote()
vote.ValidatorAddress = pubkey.Address()
err := vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey())
if assert.Error(t, err) {
assert.Equal(t, ErrVoteInvalidValidatorAddress, err)
}
err = vote.Verify("test_chain_id", pubkey)
if assert.Error(t, err) {
assert.Equal(t, ErrVoteInvalidSignature, err)
}
}
func TestMaxVoteBytes(t *testing.T) {
vote := &Vote{
ValidatorAddress: tmhash.Sum([]byte("validator_address")),
ValidatorIndex: math.MaxInt64,
Height: math.MaxInt64,
Round: math.MaxInt64,
Timestamp: tmtime.Now(),
Type: VoteTypePrevote,
BlockID: BlockID{
Hash: tmhash.Sum([]byte("blockID_hash")),
PartsHeader: PartSetHeader{
Total: math.MaxInt64,
Hash: tmhash.Sum([]byte("blockID_part_set_header_hash")),
},
},
}
privVal := NewMockPV()
err := privVal.SignVote("test_chain_id", vote)
require.NoError(t, err)
bz, err := cdc.MarshalBinary(vote)
require.NoError(t, err)
assert.EqualValues(t, MaxVoteBytes, len(bz))
}