|
|
@ -2,6 +2,7 @@ package consensus |
|
|
|
|
|
|
|
import ( |
|
|
|
. "github.com/tendermint/tendermint/blocks" |
|
|
|
. "github.com/tendermint/tendermint/common" |
|
|
|
. "github.com/tendermint/tendermint/state" |
|
|
|
|
|
|
|
"testing" |
|
|
@ -16,7 +17,7 @@ func makeValidator(id uint64, votingPower uint64) (*Validator, *PrivAccount) { |
|
|
|
}, privAccount |
|
|
|
} |
|
|
|
|
|
|
|
func makeVoteSet(numValidators int, votingPower uint64) (*VoteSet, *ValidatorSet, []*PrivAccount) { |
|
|
|
func makeVoteSet(height uint32, round uint16, numValidators int, votingPower uint64) (*VoteSet, *ValidatorSet, []*PrivAccount) { |
|
|
|
vals := make([]*Validator, numValidators) |
|
|
|
privAccounts := make([]*PrivAccount, numValidators) |
|
|
|
for i := 0; i < numValidators; i++ { |
|
|
@ -25,26 +26,177 @@ func makeVoteSet(numValidators int, votingPower uint64) (*VoteSet, *ValidatorSet |
|
|
|
privAccounts[i] = privAccount |
|
|
|
} |
|
|
|
valSet := NewValidatorSet(vals) |
|
|
|
return NewVoteSet(0, 0, VoteTypeBare, valSet), valSet, privAccounts |
|
|
|
return NewVoteSet(height, round, VoteTypeBare, valSet), valSet, privAccounts |
|
|
|
} |
|
|
|
|
|
|
|
func TestAddVote(t *testing.T) { |
|
|
|
voteSet, valSet, privAccounts := makeVoteSet(10, 1) |
|
|
|
vote := &Vote{Height: 0, Round: 0, Type: VoteTypeBare, BlockHash: nil} |
|
|
|
voteSet, _, privAccounts := makeVoteSet(0, 0, 10, 1) |
|
|
|
|
|
|
|
t.Logf(">> %v", voteSet) |
|
|
|
t.Logf(">> %v", valSet) |
|
|
|
t.Logf(">> %v", privAccounts) |
|
|
|
// t.Logf(">> %v", voteSet)
|
|
|
|
|
|
|
|
if voteSet.GetVote(0) != nil { |
|
|
|
t.Errorf("Expected GetVote(0) to be nil") |
|
|
|
} |
|
|
|
if voteSet.BitArray().GetIndex(0) { |
|
|
|
t.Errorf("Expected BitArray.GetIndex(0) to be false") |
|
|
|
} |
|
|
|
hash, commitTime, ok := voteSet.TwoThirdsMajority() |
|
|
|
if hash != nil || !commitTime.IsZero() || ok { |
|
|
|
t.Errorf("There should be no 2/3 majority") |
|
|
|
} |
|
|
|
|
|
|
|
vote := &Vote{Height: 0, Round: 0, Type: VoteTypeBare, BlockHash: nil} |
|
|
|
privAccounts[0].Sign(vote) |
|
|
|
voteSet.Add(vote) |
|
|
|
|
|
|
|
t.Logf(">> %v", voteSet) |
|
|
|
t.Logf(">> %v", valSet) |
|
|
|
t.Logf(">> %v", privAccounts) |
|
|
|
|
|
|
|
if voteSet.GetVote(0) == nil { |
|
|
|
t.Errorf("Expected GetVote(0) to be present") |
|
|
|
} |
|
|
|
if !voteSet.BitArray().GetIndex(0) { |
|
|
|
t.Errorf("Expected BitArray.GetIndex(0) to be true") |
|
|
|
} |
|
|
|
hash, commitTime, ok = voteSet.TwoThirdsMajority() |
|
|
|
if hash != nil || !commitTime.IsZero() || ok { |
|
|
|
t.Errorf("There should be no 2/3 majority") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func Test2_3Majority(t *testing.T) { |
|
|
|
// XXX
|
|
|
|
voteSet, _, privAccounts := makeVoteSet(0, 0, 10, 1) |
|
|
|
|
|
|
|
// 6 out of 10 voted for nil.
|
|
|
|
vote := &Vote{Height: 0, Round: 0, Type: VoteTypeBare, BlockHash: nil} |
|
|
|
for i := 0; i < 6; i++ { |
|
|
|
privAccounts[i].Sign(vote) |
|
|
|
voteSet.Add(vote) |
|
|
|
} |
|
|
|
hash, commitTime, ok := voteSet.TwoThirdsMajority() |
|
|
|
if hash != nil || !commitTime.IsZero() || ok { |
|
|
|
t.Errorf("There should be no 2/3 majority") |
|
|
|
} |
|
|
|
|
|
|
|
// 7th validator voted for some blockhash
|
|
|
|
vote.BlockHash = CRandBytes(32) |
|
|
|
privAccounts[6].Sign(vote) |
|
|
|
voteSet.Add(vote) |
|
|
|
hash, commitTime, ok = voteSet.TwoThirdsMajority() |
|
|
|
if hash != nil || !commitTime.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, commitTime, ok = voteSet.TwoThirdsMajority() |
|
|
|
if hash != nil || commitTime.IsZero() || !ok { |
|
|
|
t.Errorf("There should be 2/3 majority for nil") |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
func TestBadVotes(t *testing.T) { |
|
|
|
voteSet, _, privAccounts := makeVoteSet(1, 0, 10, 1) |
|
|
|
|
|
|
|
// val0 votes for nil.
|
|
|
|
vote := &Vote{Height: 1, Round: 0, Type: VoteTypeBare, BlockHash: nil} |
|
|
|
privAccounts[0].Sign(vote) |
|
|
|
added, err := voteSet.Add(vote) |
|
|
|
if !added || err != nil { |
|
|
|
t.Errorf("Expected Add(vote) to succeed") |
|
|
|
} |
|
|
|
|
|
|
|
// val0 votes again for some block.
|
|
|
|
vote = &Vote{Height: 1, Round: 0, Type: VoteTypeBare, BlockHash: CRandBytes(32)} |
|
|
|
privAccounts[0].Sign(vote) |
|
|
|
added, err = voteSet.Add(vote) |
|
|
|
if added || err == nil { |
|
|
|
t.Errorf("Expected Add(vote) to fail, dupeout.") |
|
|
|
} |
|
|
|
|
|
|
|
// val1 votes on another height
|
|
|
|
vote = &Vote{Height: 0, Round: 0, Type: VoteTypeBare, BlockHash: nil} |
|
|
|
privAccounts[1].Sign(vote) |
|
|
|
added, err = voteSet.Add(vote) |
|
|
|
if added { |
|
|
|
t.Errorf("Expected Add(vote) to fail, wrong height") |
|
|
|
} |
|
|
|
|
|
|
|
// val2 votes on another round
|
|
|
|
vote = &Vote{Height: 1, Round: 1, Type: VoteTypeBare, BlockHash: nil} |
|
|
|
privAccounts[2].Sign(vote) |
|
|
|
added, err = voteSet.Add(vote) |
|
|
|
if added { |
|
|
|
t.Errorf("Expected Add(vote) to fail, wrong round") |
|
|
|
} |
|
|
|
|
|
|
|
// val3 votes of another type.
|
|
|
|
vote = &Vote{Height: 1, Round: 0, Type: VoteTypePrecommit, BlockHash: nil} |
|
|
|
privAccounts[3].Sign(vote) |
|
|
|
added, err = voteSet.Add(vote) |
|
|
|
if added { |
|
|
|
t.Errorf("Expected Add(vote) to fail, wrong type") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func TestAddCommitsToBareVotes(t *testing.T) { |
|
|
|
voteSet, _, privAccounts := makeVoteSet(1, 5, 10, 1) |
|
|
|
|
|
|
|
// val0, val1, val2, val3, val4, val5 vote for nil.
|
|
|
|
vote := &Vote{Height: 1, Round: 5, Type: VoteTypeBare, BlockHash: nil} |
|
|
|
for i := 0; i < 6; i++ { |
|
|
|
privAccounts[i].Sign(vote) |
|
|
|
voteSet.Add(vote) |
|
|
|
} |
|
|
|
hash, commitTime, ok := voteSet.TwoThirdsMajority() |
|
|
|
if hash != nil || !commitTime.IsZero() || ok { |
|
|
|
t.Errorf("There should be no 2/3 majority") |
|
|
|
} |
|
|
|
|
|
|
|
// Attempt to add a commit from val6 at a previous height
|
|
|
|
vote = &Vote{Height: 0, Round: 5, Type: VoteTypeCommit, BlockHash: nil} |
|
|
|
privAccounts[6].Sign(vote) |
|
|
|
added, _ := voteSet.Add(vote) |
|
|
|
if added { |
|
|
|
t.Errorf("Expected Add(vote) to fail, wrong height.") |
|
|
|
} |
|
|
|
|
|
|
|
// Attempt to add a commit from val6 at a later round
|
|
|
|
vote = &Vote{Height: 1, Round: 6, Type: VoteTypeCommit, BlockHash: nil} |
|
|
|
privAccounts[6].Sign(vote) |
|
|
|
added, _ = voteSet.Add(vote) |
|
|
|
if added { |
|
|
|
t.Errorf("Expected Add(vote) to fail, cannot add future round vote.") |
|
|
|
} |
|
|
|
|
|
|
|
// Attempt to add a commit from val6 for currrent height/round.
|
|
|
|
vote = &Vote{Height: 1, Round: 5, Type: VoteTypeCommit, BlockHash: nil} |
|
|
|
privAccounts[6].Sign(vote) |
|
|
|
added, err := voteSet.Add(vote) |
|
|
|
if added || err == nil { |
|
|
|
t.Errorf("Expected Add(vote) to fail, only prior round commits can be added.") |
|
|
|
} |
|
|
|
|
|
|
|
// Add commit from val6 at a previous round
|
|
|
|
vote = &Vote{Height: 1, Round: 4, Type: VoteTypeCommit, BlockHash: nil} |
|
|
|
privAccounts[6].Sign(vote) |
|
|
|
added, err = voteSet.Add(vote) |
|
|
|
if !added || err != nil { |
|
|
|
t.Errorf("Expected Add(vote) to succeed, commit for prior rounds are relevant.") |
|
|
|
} |
|
|
|
|
|
|
|
// Also add commit from val7 for previous round.
|
|
|
|
vote = &Vote{Height: 1, Round: 3, Type: VoteTypeCommit, BlockHash: nil} |
|
|
|
privAccounts[7].Sign(vote) |
|
|
|
added, err = voteSet.Add(vote) |
|
|
|
if !added || err != nil { |
|
|
|
t.Errorf("Expected Add(vote) to succeed. err: %v", err) |
|
|
|
} |
|
|
|
|
|
|
|
// We should have 2/3 majority
|
|
|
|
hash, commitTime, ok = voteSet.TwoThirdsMajority() |
|
|
|
if hash != nil || commitTime.IsZero() || !ok { |
|
|
|
t.Errorf("There should be 2/3 majority for nil") |
|
|
|
} |
|
|
|
|
|
|
|
} |