Change Commit to hold signatures+timestamps instead of votes
This commit is contained in:
parent
debe56326f
commit
e47a8939f9
|
@ -69,8 +69,11 @@ var (
|
||||||
partSet = block.MakePartSet(2)
|
partSet = block.MakePartSet(2)
|
||||||
part1 = partSet.GetPart(0)
|
part1 = partSet.GetPart(0)
|
||||||
part2 = partSet.GetPart(1)
|
part2 = partSet.GetPart(1)
|
||||||
seenCommit1 = &types.Commit{Precommits: []*types.Vote{{Height: 10,
|
seenCommit1 = &types.Commit{
|
||||||
Timestamp: time.Now().UTC()}}}
|
Precommits: []*types.CommitSig{{
|
||||||
|
Timestamp: time.Now().UTC()}},
|
||||||
|
HeightNum: 10,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: This test should be simplified ...
|
// TODO: This test should be simplified ...
|
||||||
|
@ -90,8 +93,11 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
|
||||||
// save a block
|
// save a block
|
||||||
block := makeBlock(bs.Height()+1, state)
|
block := makeBlock(bs.Height()+1, state)
|
||||||
validPartSet := block.MakePartSet(2)
|
validPartSet := block.MakePartSet(2)
|
||||||
seenCommit := &types.Commit{Precommits: []*types.Vote{{Height: 10,
|
seenCommit := &types.Commit{
|
||||||
Timestamp: time.Now().UTC()}}}
|
Precommits: []*types.CommitSig{{
|
||||||
|
Timestamp: time.Now().UTC()}},
|
||||||
|
HeightNum: 10,
|
||||||
|
}
|
||||||
bs.SaveBlock(block, partSet, seenCommit)
|
bs.SaveBlock(block, partSet, seenCommit)
|
||||||
require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed")
|
require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed")
|
||||||
|
|
||||||
|
@ -110,8 +116,11 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
|
||||||
|
|
||||||
// End of setup, test data
|
// End of setup, test data
|
||||||
|
|
||||||
commitAtH10 := &types.Commit{Precommits: []*types.Vote{{Height: 10,
|
commitAtH10 := &types.Commit{
|
||||||
Timestamp: time.Now().UTC()}}}
|
Precommits: []*types.CommitSig{{
|
||||||
|
Timestamp: time.Now().UTC()}},
|
||||||
|
HeightNum: 10,
|
||||||
|
}
|
||||||
tuples := []struct {
|
tuples := []struct {
|
||||||
block *types.Block
|
block *types.Block
|
||||||
parts *types.PartSet
|
parts *types.PartSet
|
||||||
|
@ -334,8 +343,11 @@ func TestBlockFetchAtHeight(t *testing.T) {
|
||||||
block := makeBlock(bs.Height()+1, state)
|
block := makeBlock(bs.Height()+1, state)
|
||||||
|
|
||||||
partSet := block.MakePartSet(2)
|
partSet := block.MakePartSet(2)
|
||||||
seenCommit := &types.Commit{Precommits: []*types.Vote{{Height: 10,
|
seenCommit := &types.Commit{
|
||||||
Timestamp: time.Now().UTC()}}}
|
Precommits: []*types.CommitSig{{
|
||||||
|
Timestamp: time.Now().UTC()}},
|
||||||
|
HeightNum: 10,
|
||||||
|
}
|
||||||
|
|
||||||
bs.SaveBlock(block, partSet, seenCommit)
|
bs.SaveBlock(block, partSet, seenCommit)
|
||||||
require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed")
|
require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed")
|
||||||
|
|
|
@ -607,12 +607,6 @@ func validateBlock(block *types.Block, activeVals map[string]struct{}) error {
|
||||||
if block.LastCommit.Size() != len(activeVals) {
|
if block.LastCommit.Size() != len(activeVals) {
|
||||||
return fmt.Errorf("Commit size doesn't match number of active validators. Got %d, expected %d", block.LastCommit.Size(), len(activeVals))
|
return fmt.Errorf("Commit size doesn't match number of active validators. Got %d, expected %d", block.LastCommit.Size(), len(activeVals))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, vote := range block.LastCommit.Precommits {
|
|
||||||
if _, ok := activeVals[string(vote.ValidatorAddress)]; !ok {
|
|
||||||
return fmt.Errorf("Found vote for unactive validator %X", vote.ValidatorAddress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -531,7 +531,7 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.Commit, error) {
|
||||||
if block.Height != height+1 {
|
if block.Height != height+1 {
|
||||||
panic(fmt.Sprintf("read bad block from wal. got height %d, expected %d", block.Height, height+1))
|
panic(fmt.Sprintf("read bad block from wal. got height %d, expected %d", block.Height, height+1))
|
||||||
}
|
}
|
||||||
commitHeight := thisBlockCommit.Precommits[0].Height
|
commitHeight := thisBlockCommit.Height()
|
||||||
if commitHeight != height+1 {
|
if commitHeight != height+1 {
|
||||||
panic(fmt.Sprintf("commit doesnt match. got height %d, expected %d", commitHeight, height+1))
|
panic(fmt.Sprintf("commit doesnt match. got height %d, expected %d", commitHeight, height+1))
|
||||||
}
|
}
|
||||||
|
@ -549,8 +549,15 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.Commit, error) {
|
||||||
case *types.Vote:
|
case *types.Vote:
|
||||||
if p.Type == types.VoteTypePrecommit {
|
if p.Type == types.VoteTypePrecommit {
|
||||||
thisBlockCommit = &types.Commit{
|
thisBlockCommit = &types.Commit{
|
||||||
BlockID: p.BlockID,
|
BlockID: p.BlockID,
|
||||||
Precommits: []*types.Vote{p},
|
Precommits: []*types.CommitSig{
|
||||||
|
&types.CommitSig{
|
||||||
|
Signature: p.Signature,
|
||||||
|
Timestamp: p.Timestamp,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HeightNum: p.Height,
|
||||||
|
RoundNum: p.Round,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -564,7 +571,7 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.Commit, error) {
|
||||||
if block.Height != height+1 {
|
if block.Height != height+1 {
|
||||||
panic(fmt.Sprintf("read bad block from wal. got height %d, expected %d", block.Height, height+1))
|
panic(fmt.Sprintf("read bad block from wal. got height %d, expected %d", block.Height, height+1))
|
||||||
}
|
}
|
||||||
commitHeight := thisBlockCommit.Precommits[0].Height
|
commitHeight := thisBlockCommit.Height()
|
||||||
if commitHeight != height+1 {
|
if commitHeight != height+1 {
|
||||||
panic(fmt.Sprintf("commit doesnt match. got height %d, expected %d", commitHeight, height+1))
|
panic(fmt.Sprintf("commit doesnt match. got height %d, expected %d", commitHeight, height+1))
|
||||||
}
|
}
|
||||||
|
|
|
@ -453,11 +453,14 @@ func (cs *ConsensusState) reconstructLastCommit(state sm.State) {
|
||||||
}
|
}
|
||||||
seenCommit := cs.blockStore.LoadSeenCommit(state.LastBlockHeight)
|
seenCommit := cs.blockStore.LoadSeenCommit(state.LastBlockHeight)
|
||||||
lastPrecommits := types.NewVoteSet(state.ChainID, state.LastBlockHeight, seenCommit.Round(), types.VoteTypePrecommit, state.LastValidators)
|
lastPrecommits := types.NewVoteSet(state.ChainID, state.LastBlockHeight, seenCommit.Round(), types.VoteTypePrecommit, state.LastValidators)
|
||||||
for _, precommit := range seenCommit.Precommits {
|
for idx := 0; idx < len(seenCommit.Precommits); idx++ {
|
||||||
if precommit == nil {
|
if seenCommit.Precommits[idx] == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
added, err := lastPrecommits.AddVote(precommit)
|
addr, _ := state.LastValidators.GetByIndex(idx)
|
||||||
|
vote := seenCommit.GetByIndex(idx)
|
||||||
|
vote.ValidatorAddress = addr
|
||||||
|
added, err := lastPrecommits.AddVote(vote)
|
||||||
if !added || err != nil {
|
if !added || err != nil {
|
||||||
cmn.PanicCrisis(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))
|
cmn.PanicCrisis(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1347,7 @@ func (cs *ConsensusState) recordMetrics(height int64, block *types.Block) {
|
||||||
missingValidators := 0
|
missingValidators := 0
|
||||||
missingValidatorsPower := int64(0)
|
missingValidatorsPower := int64(0)
|
||||||
for i, val := range cs.Validators.Validators {
|
for i, val := range cs.Validators.Validators {
|
||||||
var vote *types.Vote
|
var vote *types.CommitSig
|
||||||
if i < len(block.LastCommit.Precommits) {
|
if i < len(block.LastCommit.Precommits) {
|
||||||
vote = block.LastCommit.Precommits[i]
|
vote = block.LastCommit.Precommits[i]
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) {
|
||||||
// Random validators
|
// Random validators
|
||||||
nval, ntxs := 100, 100
|
nval, ntxs := 100, 100
|
||||||
vset, _ := types.RandValidatorSet(nval, 1)
|
vset, _ := types.RandValidatorSet(nval, 1)
|
||||||
precommits := make([]*types.Vote, nval)
|
precommits := make([]*types.CommitSig, nval)
|
||||||
blockID := types.BlockID{
|
blockID := types.BlockID{
|
||||||
Hash: cmn.RandBytes(20),
|
Hash: cmn.RandBytes(20),
|
||||||
PartsHeader: types.PartSetHeader{
|
PartsHeader: types.PartSetHeader{
|
||||||
|
@ -25,11 +25,9 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) {
|
||||||
}
|
}
|
||||||
sig := make([]byte, ed25519.SignatureSize)
|
sig := make([]byte, ed25519.SignatureSize)
|
||||||
for i := 0; i < nval; i++ {
|
for i := 0; i < nval; i++ {
|
||||||
precommits[i] = &types.Vote{
|
precommits[i] = &types.CommitSig{
|
||||||
ValidatorAddress: types.Address(cmn.RandBytes(20)),
|
Timestamp: time.Now(),
|
||||||
Timestamp: time.Now(),
|
Signature: sig,
|
||||||
BlockID: blockID,
|
|
||||||
Signature: sig,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
txs := make([]types.Tx, ntxs)
|
txs := make([]types.Tx, ntxs)
|
||||||
|
|
|
@ -71,7 +71,7 @@ func (pkz privKeys) ToValidators(init, inc int64) *types.ValidatorSet {
|
||||||
|
|
||||||
// signHeader properly signs the header with all keys from first to last exclusive.
|
// signHeader properly signs the header with all keys from first to last exclusive.
|
||||||
func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Commit {
|
func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Commit {
|
||||||
votes := make([]*types.Vote, len(pkz))
|
cs := make([]*types.CommitSig, len(pkz))
|
||||||
|
|
||||||
// We need this list to keep the ordering.
|
// We need this list to keep the ordering.
|
||||||
vset := pkz.ToValidators(1, 0)
|
vset := pkz.ToValidators(1, 0)
|
||||||
|
@ -79,12 +79,17 @@ func (pkz privKeys) signHeader(header *types.Header, first, last int) *types.Com
|
||||||
// Fill in the votes we want.
|
// Fill in the votes we want.
|
||||||
for i := first; i < last && i < len(pkz); i++ {
|
for i := first; i < last && i < len(pkz); i++ {
|
||||||
vote := makeVote(header, vset, pkz[i])
|
vote := makeVote(header, vset, pkz[i])
|
||||||
votes[vote.ValidatorIndex] = vote
|
cs[vote.ValidatorIndex] = &types.CommitSig{
|
||||||
|
Signature: vote.Signature,
|
||||||
|
Timestamp: vote.Timestamp,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res := &types.Commit{
|
res := &types.Commit{
|
||||||
BlockID: types.BlockID{Hash: header.Hash()},
|
BlockID: types.BlockID{Hash: header.Hash()},
|
||||||
Precommits: votes,
|
Precommits: cs,
|
||||||
|
RoundNum: 1,
|
||||||
|
HeightNum: header.Height,
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,7 +241,7 @@ func getBeginBlockValidatorInfo(block *types.Block, lastValSet *types.ValidatorS
|
||||||
// Collect the vote info (list of validators and whether or not they signed).
|
// Collect the vote info (list of validators and whether or not they signed).
|
||||||
voteInfos := make([]abci.VoteInfo, len(lastValSet.Validators))
|
voteInfos := make([]abci.VoteInfo, len(lastValSet.Validators))
|
||||||
for i, val := range lastValSet.Validators {
|
for i, val := range lastValSet.Validators {
|
||||||
var vote *types.Vote
|
var vote *types.CommitSig
|
||||||
if i < len(block.LastCommit.Precommits) {
|
if i < len(block.LastCommit.Precommits) {
|
||||||
vote = block.LastCommit.Precommits[i]
|
vote = block.LastCommit.Precommits[i]
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,17 +63,17 @@ func TestBeginBlockValidators(t *testing.T) {
|
||||||
prevBlockID := types.BlockID{prevHash, prevParts}
|
prevBlockID := types.BlockID{prevHash, prevParts}
|
||||||
|
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}
|
vote0 := &types.CommitSig{Timestamp: now}
|
||||||
vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now}
|
vote1 := &types.CommitSig{Timestamp: now}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
lastCommitPrecommits []*types.Vote
|
lastCommitPrecommits []*types.CommitSig
|
||||||
expectedAbsentValidators []int
|
expectedAbsentValidators []int
|
||||||
}{
|
}{
|
||||||
{"none absent", []*types.Vote{vote0, vote1}, []int{}},
|
{"none absent", []*types.CommitSig{vote0, vote1}, []int{}},
|
||||||
{"one absent", []*types.Vote{vote0, nil}, []int{1}},
|
{"one absent", []*types.CommitSig{vote0, nil}, []int{1}},
|
||||||
{"multiple absent", []*types.Vote{nil, nil}, []int{0, 1}},
|
{"multiple absent", []*types.CommitSig{nil, nil}, []int{0, 1}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
@ -133,9 +133,9 @@ func TestBeginBlockByzantineValidators(t *testing.T) {
|
||||||
types.TM2PB.Evidence(ev2, valSet, now)}},
|
types.TM2PB.Evidence(ev2, valSet, now)}},
|
||||||
}
|
}
|
||||||
|
|
||||||
vote0 := &types.Vote{ValidatorIndex: 0, Timestamp: now, Type: types.VoteTypePrecommit}
|
vote0 := &types.CommitSig{Timestamp: now}
|
||||||
vote1 := &types.Vote{ValidatorIndex: 1, Timestamp: now}
|
vote1 := &types.CommitSig{Timestamp: now}
|
||||||
votes := []*types.Vote{vote0, vote1}
|
votes := []*types.CommitSig{vote0, vote1}
|
||||||
lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: votes}
|
lastCommit := &types.Commit{BlockID: prevBlockID, Precommits: votes}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
|
||||||
|
|
|
@ -296,49 +296,38 @@ type Commit struct {
|
||||||
// NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
|
// NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
|
||||||
// Any peer with a block can gossip precommits by index with a peer without recalculating the
|
// Any peer with a block can gossip precommits by index with a peer without recalculating the
|
||||||
// active ValidatorSet.
|
// active ValidatorSet.
|
||||||
BlockID BlockID `json:"block_id"`
|
BlockID BlockID `json:"block_id"`
|
||||||
Precommits []*Vote `json:"precommits"`
|
Precommits []*CommitSig `json:"precommits"`
|
||||||
|
RoundNum int
|
||||||
|
HeightNum int64
|
||||||
|
|
||||||
// Volatile
|
// Volatile
|
||||||
firstPrecommit *Vote
|
hash cmn.HexBytes
|
||||||
hash cmn.HexBytes
|
bitArray *cmn.BitArray
|
||||||
bitArray *cmn.BitArray
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirstPrecommit returns the first non-nil precommit in the commit.
|
type CommitSig struct {
|
||||||
// If all precommits are nil, it returns an empty precommit with height 0.
|
Signature []byte
|
||||||
func (commit *Commit) FirstPrecommit() *Vote {
|
Timestamp time.Time
|
||||||
if len(commit.Precommits) == 0 {
|
}
|
||||||
return nil
|
|
||||||
}
|
func (cs *CommitSig) String(index int, address Address, height int64, round int, blockID BlockID) string {
|
||||||
if commit.firstPrecommit != nil {
|
return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %X @ %s}",
|
||||||
return commit.firstPrecommit
|
index, cmn.Fingerprint(address),
|
||||||
}
|
height, round, VoteTypePrecommit, "Precommit",
|
||||||
for _, precommit := range commit.Precommits {
|
cmn.Fingerprint(blockID.Hash),
|
||||||
if precommit != nil {
|
cmn.Fingerprint(cs.Signature),
|
||||||
commit.firstPrecommit = precommit
|
CanonicalTime(cs.Timestamp))
|
||||||
return precommit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &Vote{
|
|
||||||
Type: VoteTypePrecommit,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Height returns the height of the commit
|
// Height returns the height of the commit
|
||||||
func (commit *Commit) Height() int64 {
|
func (commit *Commit) Height() int64 {
|
||||||
if len(commit.Precommits) == 0 {
|
return commit.HeightNum
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return commit.FirstPrecommit().Height
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round returns the round of the commit
|
// Round returns the round of the commit
|
||||||
func (commit *Commit) Round() int {
|
func (commit *Commit) Round() int {
|
||||||
if len(commit.Precommits) == 0 {
|
return commit.RoundNum
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return commit.FirstPrecommit().Round
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns the vote type of the commit, which is always VoteTypePrecommit
|
// Type returns the vote type of the commit, which is always VoteTypePrecommit
|
||||||
|
@ -368,8 +357,16 @@ func (commit *Commit) BitArray() *cmn.BitArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByIndex returns the vote corresponding to a given validator index
|
// GetByIndex returns the vote corresponding to a given validator index
|
||||||
func (commit *Commit) GetByIndex(index int) *Vote {
|
func (com *Commit) GetByIndex(index int) *Vote {
|
||||||
return commit.Precommits[index]
|
return &Vote{
|
||||||
|
ValidatorIndex: index,
|
||||||
|
Height: com.HeightNum,
|
||||||
|
Round: com.RoundNum,
|
||||||
|
Timestamp: com.Precommits[index].Timestamp,
|
||||||
|
Type: VoteTypePrecommit,
|
||||||
|
BlockID: com.BlockID,
|
||||||
|
Signature: com.Precommits[index].Signature,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsCommit returns true if there is at least one vote
|
// IsCommit returns true if there is at least one vote
|
||||||
|
@ -386,30 +383,6 @@ func (commit *Commit) ValidateBasic() error {
|
||||||
if len(commit.Precommits) == 0 {
|
if len(commit.Precommits) == 0 {
|
||||||
return errors.New("No precommits in commit")
|
return errors.New("No precommits in commit")
|
||||||
}
|
}
|
||||||
height, round := commit.Height(), commit.Round()
|
|
||||||
|
|
||||||
// Validate the precommits.
|
|
||||||
for _, precommit := range commit.Precommits {
|
|
||||||
// It's OK for precommits to be missing.
|
|
||||||
if precommit == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Ensure that all votes are precommits.
|
|
||||||
if precommit.Type != VoteTypePrecommit {
|
|
||||||
return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
|
|
||||||
precommit.Type)
|
|
||||||
}
|
|
||||||
// Ensure that all heights are the same.
|
|
||||||
if precommit.Height != height {
|
|
||||||
return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
|
|
||||||
height, precommit.Height)
|
|
||||||
}
|
|
||||||
// Ensure that all rounds are the same.
|
|
||||||
if precommit.Round != round {
|
|
||||||
return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
|
|
||||||
round, precommit.Round)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +408,8 @@ func (commit *Commit) StringIndented(indent string) string {
|
||||||
}
|
}
|
||||||
precommitStrings := make([]string, len(commit.Precommits))
|
precommitStrings := make([]string, len(commit.Precommits))
|
||||||
for i, precommit := range commit.Precommits {
|
for i, precommit := range commit.Precommits {
|
||||||
precommitStrings[i] = precommit.String()
|
precommitStrings[i] = precommit.String(i, []byte("---"),
|
||||||
|
commit.HeightNum, commit.RoundNum, commit.BlockID)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`Commit{
|
return fmt.Sprintf(`Commit{
|
||||||
%s BlockID: %v
|
%s BlockID: %v
|
||||||
|
|
|
@ -118,7 +118,7 @@ func TestBlockMakePartSetWithEvidence(t *testing.T) {
|
||||||
|
|
||||||
partSet := MakeBlock(h, txs, commit, evList).MakePartSet(1024)
|
partSet := MakeBlock(h, txs, commit, evList).MakePartSet(1024)
|
||||||
assert.NotNil(t, partSet)
|
assert.NotNil(t, partSet)
|
||||||
assert.Equal(t, 3, partSet.Total())
|
assert.Equal(t, 2, partSet.Total())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockHashesTo(t *testing.T) {
|
func TestBlockHashesTo(t *testing.T) {
|
||||||
|
@ -193,7 +193,6 @@ func TestCommit(t *testing.T) {
|
||||||
commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals)
|
commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.NotNil(t, commit.FirstPrecommit())
|
|
||||||
assert.Equal(t, h-1, commit.Height())
|
assert.Equal(t, h-1, commit.Height())
|
||||||
assert.Equal(t, 1, commit.Round())
|
assert.Equal(t, 1, commit.Round())
|
||||||
assert.Equal(t, VoteTypePrecommit, commit.Type())
|
assert.Equal(t, VoteTypePrecommit, commit.Type())
|
||||||
|
@ -204,7 +203,9 @@ func TestCommit(t *testing.T) {
|
||||||
require.NotNil(t, commit.BitArray())
|
require.NotNil(t, commit.BitArray())
|
||||||
assert.Equal(t, cmn.NewBitArray(10).Size(), commit.BitArray().Size())
|
assert.Equal(t, cmn.NewBitArray(10).Size(), commit.BitArray().Size())
|
||||||
|
|
||||||
assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0))
|
cv := commit.GetByIndex(0)
|
||||||
|
cv.ValidatorAddress = voteSet.GetByIndex(0).ValidatorAddress
|
||||||
|
assert.Equal(t, voteSet.GetByIndex(0), cv)
|
||||||
assert.True(t, commit.IsCommit())
|
assert.True(t, commit.IsCommit())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,21 +217,6 @@ func TestCommitValidateBasic(t *testing.T) {
|
||||||
commit = randCommit()
|
commit = randCommit()
|
||||||
commit.Precommits[0] = nil
|
commit.Precommits[0] = nil
|
||||||
assert.NoError(t, commit.ValidateBasic())
|
assert.NoError(t, commit.ValidateBasic())
|
||||||
|
|
||||||
// tamper with types
|
|
||||||
commit = randCommit()
|
|
||||||
commit.Precommits[0].Type = VoteTypePrevote
|
|
||||||
assert.Error(t, commit.ValidateBasic())
|
|
||||||
|
|
||||||
// tamper with height
|
|
||||||
commit = randCommit()
|
|
||||||
commit.Precommits[0].Height = int64(100)
|
|
||||||
assert.Error(t, commit.ValidateBasic())
|
|
||||||
|
|
||||||
// tamper with round
|
|
||||||
commit = randCommit()
|
|
||||||
commit.Precommits[0].Round = 100
|
|
||||||
assert.Error(t, commit.ValidateBasic())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func randCommit() *Commit {
|
func randCommit() *Commit {
|
||||||
|
|
|
@ -270,34 +270,27 @@ func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height i
|
||||||
}
|
}
|
||||||
|
|
||||||
talliedVotingPower := int64(0)
|
talliedVotingPower := int64(0)
|
||||||
round := commit.Round()
|
|
||||||
|
baseVote := Vote{
|
||||||
|
Height: height,
|
||||||
|
Round: commit.Round(),
|
||||||
|
Type: VoteTypePrecommit,
|
||||||
|
BlockID: blockID,
|
||||||
|
}
|
||||||
|
|
||||||
for idx, precommit := range commit.Precommits {
|
for idx, precommit := range commit.Precommits {
|
||||||
if precommit == nil {
|
if precommit == nil {
|
||||||
continue // OK, some precommits can be missing.
|
continue // OK, some precommits can be missing.
|
||||||
}
|
}
|
||||||
if precommit.Height != height {
|
|
||||||
return fmt.Errorf("Invalid commit -- wrong height: want %v got %v", height, precommit.Height)
|
|
||||||
}
|
|
||||||
if precommit.Round != round {
|
|
||||||
return fmt.Errorf("Invalid commit -- wrong round: want %v got %v", round, precommit.Round)
|
|
||||||
}
|
|
||||||
if precommit.Type != VoteTypePrecommit {
|
|
||||||
return fmt.Errorf("Invalid commit -- not precommit @ index %v", idx)
|
|
||||||
}
|
|
||||||
_, val := vals.GetByIndex(idx)
|
_, val := vals.GetByIndex(idx)
|
||||||
|
baseVote.Timestamp = precommit.Timestamp
|
||||||
// Validate signature.
|
// Validate signature.
|
||||||
precommitSignBytes := precommit.SignBytes(chainID)
|
precommitSignBytes := baseVote.SignBytes(chainID)
|
||||||
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
||||||
return fmt.Errorf("Invalid commit -- invalid signature: %v", precommit)
|
return fmt.Errorf("Invalid commit -- invalid signature: %v", precommit)
|
||||||
}
|
}
|
||||||
// Good precommit!
|
// Good precommit!
|
||||||
if blockID.Equals(precommit.BlockID) {
|
talliedVotingPower += val.VotingPower
|
||||||
talliedVotingPower += val.VotingPower
|
|
||||||
} else {
|
|
||||||
// It's OK that the BlockID doesn't match. We include stray
|
|
||||||
// precommits to measure validator availability.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if talliedVotingPower > vals.TotalVotingPower()*2/3 {
|
if talliedVotingPower > vals.TotalVotingPower()*2/3 {
|
||||||
|
@ -349,40 +342,33 @@ func (vals *ValidatorSet) VerifyFutureCommit(newSet *ValidatorSet, chainID strin
|
||||||
// Check old voting power.
|
// Check old voting power.
|
||||||
oldVotingPower := int64(0)
|
oldVotingPower := int64(0)
|
||||||
seen := map[int]bool{}
|
seen := map[int]bool{}
|
||||||
round := commit.Round()
|
baseVote := Vote{
|
||||||
|
Height: height,
|
||||||
|
Round: commit.Round(),
|
||||||
|
Type: VoteTypePrecommit,
|
||||||
|
BlockID: blockID,
|
||||||
|
}
|
||||||
|
|
||||||
for idx, precommit := range commit.Precommits {
|
for idx, precommit := range commit.Precommits {
|
||||||
if precommit == nil {
|
if precommit == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if precommit.Height != height {
|
|
||||||
return cmn.NewError("Blocks don't match - %d vs %d", round, precommit.Round)
|
|
||||||
}
|
|
||||||
if precommit.Round != round {
|
|
||||||
return cmn.NewError("Invalid commit -- wrong round: %v vs %v", round, precommit.Round)
|
|
||||||
}
|
|
||||||
if precommit.Type != VoteTypePrecommit {
|
|
||||||
return cmn.NewError("Invalid commit -- not precommit @ index %v", idx)
|
|
||||||
}
|
|
||||||
// See if this validator is in oldVals.
|
// See if this validator is in oldVals.
|
||||||
idx, val := oldVals.GetByAddress(precommit.ValidatorAddress)
|
adr, _ := newSet.GetByIndex(idx)
|
||||||
|
idx, val := oldVals.GetByAddress(adr)
|
||||||
if val == nil || seen[idx] {
|
if val == nil || seen[idx] {
|
||||||
continue // missing or double vote...
|
continue // missing or double vote...
|
||||||
}
|
}
|
||||||
seen[idx] = true
|
seen[idx] = true
|
||||||
|
|
||||||
// Validate signature.
|
// Validate signature.
|
||||||
precommitSignBytes := precommit.SignBytes(chainID)
|
baseVote.Timestamp = precommit.Timestamp
|
||||||
|
precommitSignBytes := baseVote.SignBytes(chainID)
|
||||||
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
||||||
return cmn.NewError("Invalid commit -- invalid signature: %v", precommit)
|
return cmn.NewError("Invalid commit -- invalid signature: %v", precommit)
|
||||||
}
|
}
|
||||||
// Good precommit!
|
// Good precommit!
|
||||||
if blockID.Equals(precommit.BlockID) {
|
oldVotingPower += val.VotingPower
|
||||||
oldVotingPower += val.VotingPower
|
|
||||||
} else {
|
|
||||||
// It's OK that the BlockID doesn't match. We include stray
|
|
||||||
// precommits to measure validator availability.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldVotingPower <= oldVals.TotalVotingPower()*2/3 {
|
if oldVotingPower <= oldVals.TotalVotingPower()*2/3 {
|
||||||
|
|
|
@ -392,8 +392,15 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
vote.Signature = sig
|
vote.Signature = sig
|
||||||
commit := &Commit{
|
commit := &Commit{
|
||||||
BlockID: blockID,
|
BlockID: blockID,
|
||||||
Precommits: []*Vote{vote},
|
Precommits: []*CommitSig{
|
||||||
|
&CommitSig{
|
||||||
|
Signature: sig,
|
||||||
|
Timestamp: vote.Timestamp,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HeightNum: height,
|
||||||
|
RoundNum: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
badChainID := "notmychainID"
|
badChainID := "notmychainID"
|
||||||
|
@ -401,7 +408,9 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
|
||||||
badHeight := height + 1
|
badHeight := height + 1
|
||||||
badCommit := &Commit{
|
badCommit := &Commit{
|
||||||
BlockID: blockID,
|
BlockID: blockID,
|
||||||
Precommits: []*Vote{nil},
|
Precommits: []*CommitSig{nil},
|
||||||
|
HeightNum: height,
|
||||||
|
RoundNum: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
// test some error cases
|
// test some error cases
|
||||||
|
|
|
@ -543,9 +543,20 @@ func (voteSet *VoteSet) MakeCommit() *Commit {
|
||||||
// For every validator, get the precommit
|
// For every validator, get the precommit
|
||||||
votesCopy := make([]*Vote, len(voteSet.votes))
|
votesCopy := make([]*Vote, len(voteSet.votes))
|
||||||
copy(votesCopy, voteSet.votes)
|
copy(votesCopy, voteSet.votes)
|
||||||
|
precommits := make([]*CommitSig, len(voteSet.votes))
|
||||||
|
for i, v := range votesCopy {
|
||||||
|
if v != nil {
|
||||||
|
precommits[i] = &CommitSig{
|
||||||
|
Signature: v.Signature,
|
||||||
|
Timestamp: v.Timestamp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return &Commit{
|
return &Commit{
|
||||||
BlockID: *voteSet.maj23,
|
BlockID: *voteSet.maj23,
|
||||||
Precommits: votesCopy,
|
Precommits: precommits,
|
||||||
|
RoundNum: voteSet.round,
|
||||||
|
HeightNum: voteSet.height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue