mirror of
https://github.com/tendermint/tendermint.git
synced 2026-08-20 22:26:15 +00:00
Validation tests
This commit is contained in:
+8
-9
@@ -84,20 +84,20 @@ func (part *Part) StringWithIndent(indent string) string {
|
||||
//-------------------------------------
|
||||
|
||||
type PartSetHeader struct {
|
||||
Hash []byte
|
||||
Total uint16
|
||||
Hash []byte
|
||||
}
|
||||
|
||||
func ReadPartSetHeader(r io.Reader, n *int64, err *error) PartSetHeader {
|
||||
return PartSetHeader{
|
||||
Hash: ReadByteSlice(r, n, err),
|
||||
Total: ReadUInt16(r, n, err),
|
||||
Hash: ReadByteSlice(r, n, err),
|
||||
}
|
||||
}
|
||||
|
||||
func (psh PartSetHeader) WriteTo(w io.Writer) (n int64, err error) {
|
||||
WriteByteSlice(w, psh.Hash, &n, &err)
|
||||
WriteUInt16(w, psh.Total, &n, &err)
|
||||
WriteByteSlice(w, psh.Hash, &n, &err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -110,15 +110,14 @@ func (psh PartSetHeader) String() string {
|
||||
}
|
||||
|
||||
func (psh PartSetHeader) Equals(other PartSetHeader) bool {
|
||||
return bytes.Equal(psh.Hash, other.Hash) &&
|
||||
psh.Total == other.Total
|
||||
return psh.Total == other.Total && bytes.Equal(psh.Hash, other.Hash)
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
type PartSet struct {
|
||||
hash []byte
|
||||
total uint16
|
||||
hash []byte
|
||||
|
||||
mtx sync.Mutex
|
||||
parts []*Part
|
||||
@@ -148,8 +147,8 @@ func NewPartSetFromData(data []byte) *PartSet {
|
||||
parts[i].Trail = merkle.HashTrailForIndex(hashTree, i)
|
||||
}
|
||||
return &PartSet{
|
||||
hash: hashTree[len(hashTree)/2],
|
||||
total: uint16(total),
|
||||
hash: hashTree[len(hashTree)/2],
|
||||
parts: parts,
|
||||
partsBitArray: partsBitArray,
|
||||
count: uint16(total),
|
||||
@@ -159,8 +158,8 @@ func NewPartSetFromData(data []byte) *PartSet {
|
||||
// Returns an empty PartSet ready to be populated.
|
||||
func NewPartSetFromHeader(header PartSetHeader) *PartSet {
|
||||
return &PartSet{
|
||||
hash: header.Hash,
|
||||
total: header.Total,
|
||||
hash: header.Hash,
|
||||
parts: make([]*Part, header.Total),
|
||||
partsBitArray: NewBitArray(uint(header.Total)),
|
||||
count: 0,
|
||||
@@ -172,8 +171,8 @@ func (ps *PartSet) Header() PartSetHeader {
|
||||
return PartSetHeader{}
|
||||
} else {
|
||||
return PartSetHeader{
|
||||
Hash: ps.hash,
|
||||
Total: ps.total,
|
||||
Hash: ps.hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestBasicPartSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test adding parts to a new partSet.
|
||||
partSet2 := NewPartSetFromHeader(PartSetHeader{partSet.Hash(), partSet.Total()})
|
||||
partSet2 := NewPartSetFromHeader(partSet.Header())
|
||||
|
||||
for i := uint16(0); i < partSet.Total(); i++ {
|
||||
part := partSet.GetPart(i)
|
||||
@@ -65,7 +65,7 @@ func TestWrongTrail(t *testing.T) {
|
||||
partSet := NewPartSetFromData(data)
|
||||
|
||||
// Test adding a part with wrong data.
|
||||
partSet2 := NewPartSetFromHeader(PartSetHeader{partSet.Hash(), partSet.Total()})
|
||||
partSet2 := NewPartSetFromHeader(partSet.Header())
|
||||
|
||||
// Test adding a part with wrong trail.
|
||||
part := partSet.GetPart(0)
|
||||
|
||||
@@ -62,6 +62,11 @@ func (v *Vote) SetSignature(sig Signature) {
|
||||
v.Signature = sig
|
||||
}
|
||||
|
||||
func (v *Vote) Copy() *Vote {
|
||||
vCopy := *v
|
||||
return &vCopy
|
||||
}
|
||||
|
||||
func (v *Vote) String() string {
|
||||
var typeString string
|
||||
switch v.Type {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func AssertPanics(t *testing.T, msg string, f func()) {
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Errorf("Should have panic'd, but didn't: %v", msg)
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
||||
+47
-32
@@ -11,17 +11,19 @@ import (
|
||||
// NOTE: see consensus/test.go for common test methods.
|
||||
|
||||
func TestVerifyVotes(t *testing.T) {
|
||||
_, valSet, privAccounts := makeVoteSet(0, 0, 10, 1)
|
||||
height, round := uint32(1), uint16(0)
|
||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// Make a POL with -2/3 votes.
|
||||
blockHash := RandBytes(32)
|
||||
pol := &POL{
|
||||
Height: 0, Round: 0, BlockHash: blockHash,
|
||||
Height: height, Round: round, BlockHash: blockHash,
|
||||
}
|
||||
vote := &Vote{
|
||||
Height: 0, Round: 0, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||
voteProto := &Vote{
|
||||
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||
}
|
||||
for i := 0; i < 6; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
pol.Votes = append(pol.Votes, vote.Signature)
|
||||
}
|
||||
@@ -32,6 +34,7 @@ func TestVerifyVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// Make a POL with +2/3 votes.
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[7].Sign(vote)
|
||||
pol.Votes = append(pol.Votes, vote.Signature)
|
||||
|
||||
@@ -42,17 +45,19 @@ func TestVerifyVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVerifyInvalidVote(t *testing.T) {
|
||||
_, valSet, privAccounts := makeVoteSet(0, 0, 10, 1)
|
||||
height, round := uint32(1), uint16(0)
|
||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// Make a POL with +2/3 votes with the wrong signature.
|
||||
blockHash := RandBytes(32)
|
||||
pol := &POL{
|
||||
Height: 0, Round: 0, BlockHash: blockHash,
|
||||
Height: height, Round: round, BlockHash: blockHash,
|
||||
}
|
||||
vote := &Vote{
|
||||
Height: 0, Round: 0, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||
voteProto := &Vote{
|
||||
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||
}
|
||||
for i := 0; i < 7; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
// Mutate the signature.
|
||||
vote.Signature.Bytes[0] += byte(0x01)
|
||||
@@ -66,19 +71,21 @@ func TestVerifyInvalidVote(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVerifyCommits(t *testing.T) {
|
||||
_, valSet, privAccounts := makeVoteSet(0, 2, 10, 1)
|
||||
height, round := uint32(1), uint16(2)
|
||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// Make a POL with +2/3 votes.
|
||||
blockHash := RandBytes(32)
|
||||
pol := &POL{
|
||||
Height: 0, Round: 2, BlockHash: blockHash,
|
||||
Height: height, Round: round, BlockHash: blockHash,
|
||||
}
|
||||
vote := &Vote{
|
||||
Height: 0, Round: 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||
voteProto := &Vote{
|
||||
Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||
}
|
||||
for i := 0; i < 7; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
pol.Commits = append(pol.Commits, RoundSignature{1, vote.Signature})
|
||||
pol.Commits = append(pol.Commits, RoundSignature{round - 1, vote.Signature})
|
||||
}
|
||||
|
||||
// Check that validation succeeds.
|
||||
@@ -88,21 +95,23 @@ func TestVerifyCommits(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVerifyInvalidCommits(t *testing.T) {
|
||||
_, valSet, privAccounts := makeVoteSet(0, 2, 10, 1)
|
||||
height, round := uint32(1), uint16(2)
|
||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// Make a POL with +2/3 votes with the wrong signature.
|
||||
blockHash := RandBytes(32)
|
||||
pol := &POL{
|
||||
Height: 0, Round: 2, BlockHash: blockHash,
|
||||
Height: height, Round: round, BlockHash: blockHash,
|
||||
}
|
||||
vote := &Vote{
|
||||
Height: 0, Round: 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||
voteProto := &Vote{
|
||||
Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||
}
|
||||
for i := 0; i < 7; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
// Mutate the signature.
|
||||
vote.Signature.Bytes[0] += byte(0x01)
|
||||
pol.Commits = append(pol.Commits, RoundSignature{1, vote.Signature})
|
||||
pol.Commits = append(pol.Commits, RoundSignature{round - 1, vote.Signature})
|
||||
}
|
||||
|
||||
// Check that validation fails.
|
||||
@@ -112,19 +121,21 @@ func TestVerifyInvalidCommits(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVerifyInvalidCommitRounds(t *testing.T) {
|
||||
_, valSet, privAccounts := makeVoteSet(0, 2, 10, 1)
|
||||
height, round := uint32(1), uint16(2)
|
||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// Make a POL with +2/3 commits for the current round.
|
||||
blockHash := RandBytes(32)
|
||||
pol := &POL{
|
||||
Height: 0, Round: 2, BlockHash: blockHash,
|
||||
Height: height, Round: round, BlockHash: blockHash,
|
||||
}
|
||||
vote := &Vote{
|
||||
Height: 0, Round: 2, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||
voteProto := &Vote{
|
||||
Height: height, Round: round, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||
}
|
||||
for i := 0; i < 7; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
pol.Commits = append(pol.Commits, RoundSignature{2, vote.Signature})
|
||||
pol.Commits = append(pol.Commits, RoundSignature{round, vote.Signature})
|
||||
}
|
||||
|
||||
// Check that validation fails.
|
||||
@@ -134,19 +145,21 @@ func TestVerifyInvalidCommitRounds(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVerifyInvalidCommitRounds2(t *testing.T) {
|
||||
_, valSet, privAccounts := makeVoteSet(0, 2, 10, 1)
|
||||
height, round := uint32(1), uint16(2)
|
||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// Make a POL with +2/3 commits for future round.
|
||||
blockHash := RandBytes(32)
|
||||
pol := &POL{
|
||||
Height: 0, Round: 2, BlockHash: blockHash,
|
||||
Height: height, Round: round, BlockHash: blockHash,
|
||||
}
|
||||
vote := &Vote{
|
||||
Height: 0, Round: 3, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||
voteProto := &Vote{
|
||||
Height: height, Round: round + 1, Type: VoteTypeCommit, BlockHash: blockHash,
|
||||
}
|
||||
for i := 0; i < 7; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
pol.Commits = append(pol.Commits, RoundSignature{3, vote.Signature})
|
||||
pol.Commits = append(pol.Commits, RoundSignature{round + 1, vote.Signature})
|
||||
}
|
||||
|
||||
// Check that validation fails.
|
||||
@@ -156,17 +169,19 @@ func TestVerifyInvalidCommitRounds2(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReadWrite(t *testing.T) {
|
||||
_, valSet, privAccounts := makeVoteSet(0, 0, 10, 1)
|
||||
height, round := uint32(1), uint16(2)
|
||||
_, valSet, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// Make a POL with +2/3 votes.
|
||||
blockHash := RandBytes(32)
|
||||
pol := &POL{
|
||||
Height: 0, Round: 0, BlockHash: blockHash,
|
||||
Height: height, Round: round, BlockHash: blockHash,
|
||||
}
|
||||
vote := &Vote{
|
||||
Height: 0, Round: 0, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||
voteProto := &Vote{
|
||||
Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash,
|
||||
}
|
||||
for i := 0; i < 7; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
pol.Votes = append(pol.Votes, vote.Signature)
|
||||
}
|
||||
|
||||
+12
-21
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
. "github.com/tendermint/tendermint/blocks"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
. "github.com/tendermint/tendermint/common/test"
|
||||
db_ "github.com/tendermint/tendermint/db"
|
||||
"github.com/tendermint/tendermint/mempool"
|
||||
"github.com/tendermint/tendermint/state"
|
||||
@@ -50,15 +51,6 @@ func makeConsensusState() (*ConsensusState, []*state.PrivAccount) {
|
||||
return cs, privAccounts
|
||||
}
|
||||
|
||||
func assertPanics(t *testing.T, msg string, f func()) {
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Errorf("Should have panic'd, but didn't: %v", msg)
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
func TestSetupRound(t *testing.T) {
|
||||
@@ -131,17 +123,16 @@ func TestRunActionPropose(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkRoundState(t *testing.T, cs *ConsensusState,
|
||||
func checkRoundState(t *testing.T, rs *RoundState,
|
||||
height uint32, round uint16, step RoundStep) {
|
||||
rs := cs.GetRoundState()
|
||||
if rs.Height != height {
|
||||
t.Errorf("cs.RoundState.Height should be %v, got %v", height, rs.Height)
|
||||
t.Errorf("rs.Height should be %v, got %v", height, rs.Height)
|
||||
}
|
||||
if rs.Round != round {
|
||||
t.Errorf("cs.RoundState.Round should be %v, got %v", round, rs.Round)
|
||||
t.Errorf("rs.Round should be %v, got %v", round, rs.Round)
|
||||
}
|
||||
if rs.Step != step {
|
||||
t.Errorf("cs.RoundState.Step should be %v, got %v", step, rs.Step)
|
||||
t.Errorf("rs.Step should be %v, got %v", step, rs.Step)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,8 +151,8 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||
<-cs.NewStepCh() // TODO: test this value too.
|
||||
|
||||
// Test RunActionPrecommit failures:
|
||||
assertPanics(t, "Wrong height ", func() { cs.RunActionPrecommit(2, 0) })
|
||||
assertPanics(t, "Wrong round", func() { cs.RunActionPrecommit(1, 1) })
|
||||
AssertPanics(t, "Wrong height ", func() { cs.RunActionPrecommit(2, 0) })
|
||||
AssertPanics(t, "Wrong round", func() { cs.RunActionPrecommit(1, 1) })
|
||||
cs.RunActionPrecommit(1, 0)
|
||||
<-cs.NewStepCh() // TODO: test this value too.
|
||||
if cs.Precommits.GetById(0) != nil {
|
||||
@@ -187,11 +178,11 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||
if cs.Precommits.GetById(0) == nil {
|
||||
t.Errorf("RunActionPrecommit should have succeeded")
|
||||
}
|
||||
checkRoundState(t, cs, 1, 0, RoundStepPrecommit)
|
||||
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepPrecommit)
|
||||
|
||||
// Test RunActionCommit failures:
|
||||
assertPanics(t, "Wrong height ", func() { cs.RunActionCommit(2) })
|
||||
assertPanics(t, "Wrong round", func() { cs.RunActionCommit(1) })
|
||||
AssertPanics(t, "Wrong height ", func() { cs.RunActionCommit(2) })
|
||||
AssertPanics(t, "Wrong round", func() { cs.RunActionCommit(1) })
|
||||
|
||||
// Add at least +2/3 precommits.
|
||||
for i := 0; i < 7; i++ {
|
||||
@@ -212,7 +203,7 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||
if cs.Commits.GetById(0) == nil {
|
||||
t.Errorf("RunActionCommit should have succeeded")
|
||||
}
|
||||
checkRoundState(t, cs, 1, 0, RoundStepCommit)
|
||||
checkRoundState(t, cs.GetRoundState(), 1, 0, RoundStepCommit)
|
||||
|
||||
// cs.CommitTime should still be zero
|
||||
if !cs.CommitTime.IsZero() {
|
||||
@@ -235,5 +226,5 @@ func TestRunActionPrecommitCommitFinalize(t *testing.T) {
|
||||
// Test TryFinalizeCommit:
|
||||
cs.TryFinalizeCommit(1)
|
||||
<-cs.NewStepCh() // TODO: test this value too.
|
||||
checkRoundState(t, cs, 2, 0, RoundStepNewHeight)
|
||||
checkRoundState(t, cs.GetRoundState(), 2, 0, RoundStepNewHeight)
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,7 +1,6 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
. "github.com/tendermint/tendermint/blocks"
|
||||
"github.com/tendermint/tendermint/state"
|
||||
)
|
||||
|
||||
@@ -16,7 +15,7 @@ func makeValidator(id uint64, votingPower uint64) (*state.Validator, *state.Priv
|
||||
}, privAccount
|
||||
}
|
||||
|
||||
func makeVoteSet(height uint32, round uint16, numValidators int, votingPower uint64) (*VoteSet, *state.ValidatorSet, []*state.PrivAccount) {
|
||||
func makeVoteSet(height uint32, round uint16, type_ byte, numValidators int, votingPower uint64) (*VoteSet, *state.ValidatorSet, []*state.PrivAccount) {
|
||||
vals := make([]*state.Validator, numValidators)
|
||||
privAccounts := make([]*state.PrivAccount, numValidators)
|
||||
for i := 0; i < numValidators; i++ {
|
||||
@@ -25,5 +24,5 @@ func makeVoteSet(height uint32, round uint16, numValidators int, votingPower uin
|
||||
privAccounts[i] = privAccount
|
||||
}
|
||||
valSet := state.NewValidatorSet(vals)
|
||||
return NewVoteSet(height, round, VoteTypePrevote, valSet), valSet, privAccounts
|
||||
return NewVoteSet(height, round, type_, valSet), valSet, privAccounts
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ type VoteSet struct {
|
||||
|
||||
// Constructs a new VoteSet struct used to accumulate votes for each round.
|
||||
func NewVoteSet(height uint32, round uint16, type_ byte, vset *state.ValidatorSet) *VoteSet {
|
||||
if height == 0 {
|
||||
panic("Cannot make VoteSet for height == 0, doesn't make sense.")
|
||||
}
|
||||
if type_ == VoteTypeCommit && round != 0 {
|
||||
panic("Expected round 0 for commit vote set")
|
||||
}
|
||||
@@ -214,7 +217,7 @@ func (vs *VoteSet) MakePOL() *POL {
|
||||
|
||||
func (vs *VoteSet) MakeValidation() Validation {
|
||||
if vs.type_ != VoteTypeCommit {
|
||||
panic("Cannot MakeValidation() unless VoteSet.Type is VoteTypePrevote")
|
||||
panic("Cannot MakeValidation() unless VoteSet.Type is VoteTypeCommit")
|
||||
}
|
||||
vs.mtx.Lock()
|
||||
defer vs.mtx.Unlock()
|
||||
@@ -224,6 +227,7 @@ func (vs *VoteSet) MakeValidation() Validation {
|
||||
rsigs := make([]RoundSignature, vs.vset.Size())
|
||||
vs.vset.Iterate(func(index uint, val *state.Validator) bool {
|
||||
vote := vs.votes[val.Id]
|
||||
|
||||
if vote == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
+181
-28
@@ -1,8 +1,11 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
. "github.com/tendermint/tendermint/blocks"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
. "github.com/tendermint/tendermint/common/test"
|
||||
|
||||
"testing"
|
||||
)
|
||||
@@ -10,7 +13,8 @@ import (
|
||||
// NOTE: see consensus/test.go for common test methods.
|
||||
|
||||
func TestAddVote(t *testing.T) {
|
||||
voteSet, _, privAccounts := makeVoteSet(0, 0, 10, 1)
|
||||
height, round := uint32(1), uint16(0)
|
||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// t.Logf(">> %v", voteSet)
|
||||
|
||||
@@ -25,7 +29,7 @@ func TestAddVote(t *testing.T) {
|
||||
t.Errorf("There should be no 2/3 majority")
|
||||
}
|
||||
|
||||
vote := &Vote{Height: 0, Round: 0, Type: VoteTypePrevote, BlockHash: nil}
|
||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||
privAccounts[0].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
|
||||
@@ -42,11 +46,13 @@ func TestAddVote(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test2_3Majority(t *testing.T) {
|
||||
voteSet, _, privAccounts := makeVoteSet(0, 0, 10, 1)
|
||||
height, round := uint32(1), uint16(0)
|
||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// 6 out of 10 voted for nil.
|
||||
vote := &Vote{Height: 0, Round: 0, Type: VoteTypePrevote, BlockHash: nil}
|
||||
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||
for i := 0; i < 6; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
}
|
||||
@@ -56,30 +62,112 @@ func Test2_3Majority(t *testing.T) {
|
||||
}
|
||||
|
||||
// 7th validator voted for some blockhash
|
||||
vote.BlockHash = CRandBytes(32)
|
||||
privAccounts[6].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
{
|
||||
vote := voteProto.Copy()
|
||||
vote.BlockHash = CRandBytes(32)
|
||||
privAccounts[6].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
if hash != nil || !header.IsZero() || ok {
|
||||
t.Errorf("There should be no 2/3 majority")
|
||||
}
|
||||
}
|
||||
|
||||
// 8th validator voted for nil.
|
||||
{
|
||||
vote := voteProto.Copy()
|
||||
vote.BlockHash = nil
|
||||
privAccounts[7].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
if hash != nil || !header.IsZero() || !ok {
|
||||
t.Errorf("There should be 2/3 majority for nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test2_3MajorityRedux(t *testing.T) {
|
||||
height, round := uint32(1), uint16(0)
|
||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 100, 1)
|
||||
|
||||
blockHash := CRandBytes(32)
|
||||
blockPartsTotal := uint16(123)
|
||||
blockParts := PartSetHeader{blockPartsTotal, CRandBytes(32)}
|
||||
|
||||
// 66 out of 100 voted for nil.
|
||||
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: blockParts}
|
||||
for i := 0; i < 66; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
}
|
||||
hash, header, ok := voteSet.TwoThirdsMajority()
|
||||
if hash != nil || !header.IsZero() || ok {
|
||||
t.Errorf("There should be no 2/3 majority")
|
||||
}
|
||||
|
||||
// 8th validator voted for nil.
|
||||
vote.BlockHash = nil
|
||||
privAccounts[7].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
if hash != nil || !header.IsZero() || !ok {
|
||||
t.Errorf("There should be 2/3 majority for nil")
|
||||
// 67th validator voted for nil
|
||||
{
|
||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil, BlockParts: PartSetHeader{}}
|
||||
privAccounts[66].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
if hash != nil || !header.IsZero() || ok {
|
||||
t.Errorf("There should be no 2/3 majority: last vote added was nil")
|
||||
}
|
||||
}
|
||||
|
||||
// 68th validator voted for a different BlockParts PartSetHeader
|
||||
{
|
||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: PartSetHeader{blockPartsTotal, CRandBytes(32)}}
|
||||
privAccounts[67].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
if hash != nil || !header.IsZero() || ok {
|
||||
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Hash")
|
||||
}
|
||||
}
|
||||
|
||||
// 69th validator voted for different BlockParts Total
|
||||
{
|
||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: PartSetHeader{blockPartsTotal + 1, blockParts.Hash}}
|
||||
privAccounts[68].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
if hash != nil || !header.IsZero() || ok {
|
||||
t.Errorf("There should be no 2/3 majority: last vote added had different PartSetHeader Total")
|
||||
}
|
||||
}
|
||||
|
||||
// 70th validator voted for different BlockHash
|
||||
{
|
||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: CRandBytes(32), BlockParts: blockParts}
|
||||
privAccounts[69].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
if hash != nil || !header.IsZero() || ok {
|
||||
t.Errorf("There should be no 2/3 majority: last vote added had different BlockHash")
|
||||
}
|
||||
}
|
||||
|
||||
// 71st validator voted for the right BlockHash & BlockParts
|
||||
{
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[70].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||
if !bytes.Equal(hash, blockHash) || !header.Equals(blockParts) || !ok {
|
||||
t.Errorf("There should be 2/3 majority")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadVotes(t *testing.T) {
|
||||
voteSet, _, privAccounts := makeVoteSet(1, 0, 10, 1)
|
||||
height, round := uint32(1), uint16(0)
|
||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// val0 votes for nil.
|
||||
vote := &Vote{Height: 1, Round: 0, Type: VoteTypePrevote, BlockHash: nil}
|
||||
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||
privAccounts[0].Sign(vote)
|
||||
added, err := voteSet.Add(vote)
|
||||
if !added || err != nil {
|
||||
@@ -87,7 +175,7 @@ func TestBadVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// val0 votes again for some block.
|
||||
vote = &Vote{Height: 1, Round: 0, Type: VoteTypePrevote, BlockHash: CRandBytes(32)}
|
||||
vote = &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: CRandBytes(32)}
|
||||
privAccounts[0].Sign(vote)
|
||||
added, err = voteSet.Add(vote)
|
||||
if added || err == nil {
|
||||
@@ -95,7 +183,7 @@ func TestBadVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// val1 votes on another height
|
||||
vote = &Vote{Height: 0, Round: 0, Type: VoteTypePrevote, BlockHash: nil}
|
||||
vote = &Vote{Height: height + 1, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||
privAccounts[1].Sign(vote)
|
||||
added, err = voteSet.Add(vote)
|
||||
if added {
|
||||
@@ -103,7 +191,7 @@ func TestBadVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// val2 votes on another round
|
||||
vote = &Vote{Height: 1, Round: 1, Type: VoteTypePrevote, BlockHash: nil}
|
||||
vote = &Vote{Height: height, Round: round + 1, Type: VoteTypePrevote, BlockHash: nil}
|
||||
privAccounts[2].Sign(vote)
|
||||
added, err = voteSet.Add(vote)
|
||||
if added {
|
||||
@@ -111,7 +199,7 @@ func TestBadVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// val3 votes of another type.
|
||||
vote = &Vote{Height: 1, Round: 0, Type: VoteTypePrecommit, BlockHash: nil}
|
||||
vote = &Vote{Height: height, Round: round, Type: VoteTypePrecommit, BlockHash: nil}
|
||||
privAccounts[3].Sign(vote)
|
||||
added, err = voteSet.Add(vote)
|
||||
if added {
|
||||
@@ -120,11 +208,13 @@ func TestBadVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
||||
voteSet, _, privAccounts := makeVoteSet(1, 5, 10, 1)
|
||||
height, round := uint32(2), uint16(5)
|
||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||
|
||||
// val0, val1, val2, val3, val4, val5 vote for nil.
|
||||
vote := &Vote{Height: 1, Round: 5, Type: VoteTypePrevote, BlockHash: nil}
|
||||
voteProto := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||
for i := 0; i < 6; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
}
|
||||
@@ -134,7 +224,7 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// Attempt to add a commit from val6 at a previous height
|
||||
vote = &Vote{Height: 0, Round: 5, Type: VoteTypeCommit, BlockHash: nil}
|
||||
vote := &Vote{Height: height - 1, Round: round, Type: VoteTypeCommit, BlockHash: nil}
|
||||
privAccounts[6].Sign(vote)
|
||||
added, _ := voteSet.Add(vote)
|
||||
if added {
|
||||
@@ -142,7 +232,7 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// Attempt to add a commit from val6 at a later round
|
||||
vote = &Vote{Height: 1, Round: 6, Type: VoteTypeCommit, BlockHash: nil}
|
||||
vote = &Vote{Height: height, Round: round + 1, Type: VoteTypeCommit, BlockHash: nil}
|
||||
privAccounts[6].Sign(vote)
|
||||
added, _ = voteSet.Add(vote)
|
||||
if added {
|
||||
@@ -150,7 +240,7 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// Attempt to add a commit from val6 for currrent height/round.
|
||||
vote = &Vote{Height: 1, Round: 5, Type: VoteTypeCommit, BlockHash: nil}
|
||||
vote = &Vote{Height: height, Round: round, Type: VoteTypeCommit, BlockHash: nil}
|
||||
privAccounts[6].Sign(vote)
|
||||
added, err := voteSet.Add(vote)
|
||||
if added || err == nil {
|
||||
@@ -158,7 +248,7 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// Add commit from val6 at a previous round
|
||||
vote = &Vote{Height: 1, Round: 4, Type: VoteTypeCommit, BlockHash: nil}
|
||||
vote = &Vote{Height: height, Round: round - 1, Type: VoteTypeCommit, BlockHash: nil}
|
||||
privAccounts[6].Sign(vote)
|
||||
added, err = voteSet.Add(vote)
|
||||
if !added || err != nil {
|
||||
@@ -166,7 +256,7 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
// Also add commit from val7 for previous round.
|
||||
vote = &Vote{Height: 1, Round: 3, Type: VoteTypeCommit, BlockHash: nil}
|
||||
vote = &Vote{Height: height, Round: round - 2, Type: VoteTypeCommit, BlockHash: nil}
|
||||
privAccounts[7].Sign(vote)
|
||||
added, err = voteSet.Add(vote)
|
||||
if !added || err != nil {
|
||||
@@ -180,3 +270,66 @@ func TestAddCommitsToPrevoteVotes(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMakeValidation(t *testing.T) {
|
||||
height, round := uint32(1), uint16(0)
|
||||
voteSet, _, privAccounts := makeVoteSet(height, round, VoteTypeCommit, 10, 1)
|
||||
blockHash, blockParts := CRandBytes(32), PartSetHeader{123, CRandBytes(32)}
|
||||
|
||||
// 6 out of 10 voted for some block.
|
||||
voteProto := &Vote{Height: height, Round: round, Type: VoteTypeCommit,
|
||||
BlockHash: blockHash, BlockParts: blockParts}
|
||||
for i := 0; i < 6; i++ {
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[i].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
}
|
||||
|
||||
// MakeValidation should fail.
|
||||
AssertPanics(t, "Doesn't have +2/3 majority", func() { voteSet.MakeValidation() })
|
||||
|
||||
// 7th voted for some other block.
|
||||
{
|
||||
vote := &Vote{Height: height, Round: round, Type: VoteTypeCommit,
|
||||
BlockHash: CRandBytes(32),
|
||||
BlockParts: PartSetHeader{123, CRandBytes(32)}}
|
||||
privAccounts[6].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
}
|
||||
|
||||
// The 8th voted like everyone else.
|
||||
{
|
||||
vote := voteProto.Copy()
|
||||
privAccounts[7].Sign(vote)
|
||||
voteSet.Add(vote)
|
||||
}
|
||||
|
||||
validation := voteSet.MakeValidation()
|
||||
|
||||
// Validation should have 10 elements
|
||||
if len(validation.Commits) != 10 {
|
||||
t.Errorf("Validation Commits should have the same number of commits as validators")
|
||||
}
|
||||
|
||||
// Ensure that Validation commits are ordered.
|
||||
for i, rsig := range validation.Commits {
|
||||
if i < 6 || i == 7 {
|
||||
if rsig.Round != round {
|
||||
t.Errorf("Expected round %v but got %v", round, rsig.Round)
|
||||
}
|
||||
if rsig.SignerId != uint64(i) {
|
||||
t.Errorf("Validation commit signer out of order. Expected %v, got %v", i, rsig.Signature)
|
||||
}
|
||||
vote := &Vote{Height: height, Round: rsig.Round, Type: VoteTypeCommit,
|
||||
BlockHash: blockHash, BlockParts: blockParts,
|
||||
Signature: rsig.Signature}
|
||||
if !privAccounts[i].Verify(vote) {
|
||||
t.Errorf("Validation commit did not verify")
|
||||
}
|
||||
} else {
|
||||
if !rsig.IsZero() {
|
||||
t.Errorf("Expected zero RoundSignature for the rest")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -168,7 +168,9 @@ func (pa *PrivAccount) SignBytes(msg []byte) Signature {
|
||||
}
|
||||
|
||||
func (pa *PrivAccount) Sign(o Signable) {
|
||||
o.SetSignature(Signature{}) // clear
|
||||
if !o.GetSignature().IsZero() {
|
||||
panic("Cannot sign: already signed")
|
||||
}
|
||||
msg := BinaryBytes(o)
|
||||
sig := pa.SignBytes(msg)
|
||||
o.SetSignature(sig)
|
||||
|
||||
Reference in New Issue
Block a user