mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
Re-use ValidatorSet.VerifyValidation()
This commit is contained in:
parent
7752405945
commit
829df93577
@ -232,7 +232,7 @@ FOR_LOOP:
|
||||
firstPartsHeader := firstParts.Header()
|
||||
// Finally, verify the first block using the second's validation.
|
||||
err := bcR.state.BondedValidators.VerifyValidation(
|
||||
bcR.state.ChainID, first.Hash(), firstPartsHeader, first.Height, second.Validation)
|
||||
bcR.state.ChainID, first.Hash(), firstPartsHeader, first.Height, second.LastValidation)
|
||||
if err != nil {
|
||||
log.Debug("error in validation", "error", err)
|
||||
bcR.pool.RedoRequest(first.Height)
|
||||
@ -244,7 +244,7 @@ FOR_LOOP:
|
||||
// TODO This is bad, are we zombie?
|
||||
panic(Fmt("Failed to process committed block: %v", err))
|
||||
}
|
||||
bcR.store.SaveBlock(first, firstParts, second.Validation)
|
||||
bcR.store.SaveBlock(first, firstParts, second.LastValidation)
|
||||
bcR.state.Save()
|
||||
}
|
||||
}
|
||||
|
@ -38,50 +38,26 @@ func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate block Validation.
|
||||
// Validate block LastValidation.
|
||||
if block.Height == 1 {
|
||||
if len(block.Validation.Precommits) != 0 {
|
||||
return errors.New("Block at height 1 (first block) should have no Validation precommits")
|
||||
if len(block.LastValidation.Precommits) != 0 {
|
||||
return errors.New("Block at height 1 (first block) should have no LastValidation precommits")
|
||||
}
|
||||
} else {
|
||||
if uint(len(block.Validation.Precommits)) != s.LastBondedValidators.Size() {
|
||||
if uint(len(block.LastValidation.Precommits)) != s.LastBondedValidators.Size() {
|
||||
return errors.New(Fmt("Invalid block validation size. Expected %v, got %v",
|
||||
s.LastBondedValidators.Size(), len(block.Validation.Precommits)))
|
||||
s.LastBondedValidators.Size(), len(block.LastValidation.Precommits)))
|
||||
}
|
||||
var sumVotingPower uint64
|
||||
s.LastBondedValidators.Iterate(func(index uint, val *Validator) bool {
|
||||
precommit := block.Validation.Precommits[index]
|
||||
if precommit.IsZero() {
|
||||
return false
|
||||
} else {
|
||||
vote := &types.Vote{
|
||||
Height: block.Height - 1,
|
||||
Round: block.Validation.Round,
|
||||
Type: types.VoteTypePrecommit,
|
||||
BlockHash: block.LastBlockHash,
|
||||
BlockParts: block.LastBlockParts,
|
||||
}
|
||||
if val.PubKey.VerifyBytes(account.SignBytes(s.ChainID, vote), precommit.Signature) {
|
||||
sumVotingPower += val.VotingPower
|
||||
return false
|
||||
} else {
|
||||
log.Warn(Fmt("Invalid validation signature.\nval: %v\nvote: %v", val, vote))
|
||||
err = errors.New("Invalid validation signature")
|
||||
return true
|
||||
}
|
||||
}
|
||||
})
|
||||
err := s.LastBondedValidators.VerifyValidation(
|
||||
s.ChainID, s.LastBlockHash, s.LastBlockParts, block.Height-1, block.LastValidation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sumVotingPower <= s.LastBondedValidators.TotalVotingPower()*2/3 {
|
||||
return errors.New("Insufficient validation voting power")
|
||||
}
|
||||
}
|
||||
|
||||
// Update Validator.LastCommitHeight as necessary.
|
||||
for i, precommit := range block.Validation.Precommits {
|
||||
if precommit.IsZero() {
|
||||
for i, precommit := range block.LastValidation.Precommits {
|
||||
if precommit == nil {
|
||||
continue
|
||||
}
|
||||
_, val := s.LastBondedValidators.GetByIndex(uint(i))
|
||||
|
@ -2,7 +2,6 @@ package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -201,45 +200,52 @@ func (valSet *ValidatorSet) Iterate(fn func(index uint, val *Validator) bool) {
|
||||
}
|
||||
|
||||
// Verify that +2/3 of the set had signed the given signBytes
|
||||
func (valSet *ValidatorSet) VerifyValidation(chainID string, hash []byte, parts types.PartSetHeader, height uint, v *types.Validation) error {
|
||||
func (valSet *ValidatorSet) VerifyValidation(chainID string,
|
||||
hash []byte, parts types.PartSetHeader, height uint, v *types.Validation) error {
|
||||
if valSet.Size() != uint(len(v.Precommits)) {
|
||||
return errors.New(Fmt("Invalid validation -- wrong set size: %v vs %v",
|
||||
valSet.Size(), len(v.Precommits)))
|
||||
return fmt.Errorf("Invalid validation -- wrong set size: %v vs %v", valSet.Size(), len(v.Precommits))
|
||||
}
|
||||
if height != v.Height() {
|
||||
return fmt.Errorf("Invalid validation -- wrong height: %v vs %v", height, v.Height())
|
||||
}
|
||||
|
||||
talliedVotingPower := uint64(0)
|
||||
seenValidators := map[string]struct{}{}
|
||||
round := v.Round()
|
||||
|
||||
for idx, precommit := range v.Precommits {
|
||||
// may be zero, in which case skip.
|
||||
if precommit.Signature.IsZero() {
|
||||
// may be nil if validator skipped.
|
||||
if precommit == nil {
|
||||
continue
|
||||
}
|
||||
if precommit.Height != height {
|
||||
return fmt.Errorf("Invalid validation -- wrong height: %v vs %v", height, precommit.Height)
|
||||
}
|
||||
if precommit.Round != round {
|
||||
return fmt.Errorf("Invalid validation -- wrong round: %v vs %v", round, precommit.Round)
|
||||
}
|
||||
if precommit.Type != types.VoteTypePrecommit {
|
||||
return fmt.Errorf("Invalid validation -- not precommit @ index %v", idx)
|
||||
}
|
||||
_, val := valSet.GetByIndex(uint(idx))
|
||||
precommitSignBytes := account.SignBytes(chainID, &types.Vote{
|
||||
Height: height, Round: v.Round, Type: types.VoteTypePrecommit,
|
||||
BlockHash: hash,
|
||||
BlockParts: parts,
|
||||
})
|
||||
|
||||
// Validate
|
||||
if _, seen := seenValidators[string(val.Address)]; seen {
|
||||
return fmt.Errorf("Duplicate validator for precommit %v for Validation %v", precommit, v)
|
||||
}
|
||||
|
||||
// Validate signature
|
||||
precommitSignBytes := account.SignBytes(chainID, precommit)
|
||||
if !val.PubKey.VerifyBytes(precommitSignBytes, precommit.Signature) {
|
||||
return fmt.Errorf("Invalid signature for precommit %v for Validation %v", precommit, v)
|
||||
return fmt.Errorf("Invalid validation -- invalid signature: %v", precommit)
|
||||
}
|
||||
|
||||
// Tally
|
||||
seenValidators[string(val.Address)] = struct{}{}
|
||||
if !bytes.Equal(precommit.BlockHash, hash) {
|
||||
continue // Not an error, but doesn't count
|
||||
}
|
||||
if !parts.Equals(precommit.BlockParts) {
|
||||
continue // Not an error, but doesn't count
|
||||
}
|
||||
// Good precommit!
|
||||
talliedVotingPower += val.VotingPower
|
||||
}
|
||||
|
||||
if talliedVotingPower > valSet.TotalVotingPower()*2/3 {
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("insufficient voting power %v, needed %v",
|
||||
return fmt.Errorf("Invalid validation -- insufficient voting power: got %v, needed %v",
|
||||
talliedVotingPower, (valSet.TotalVotingPower()*2/3 + 1))
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +206,24 @@ func (v *Validation) ValidateBasic() error {
|
||||
if len(v.Precommits) == 0 {
|
||||
return errors.New("No precommits in validation")
|
||||
}
|
||||
// TODO Additional validation?
|
||||
height, round := v.Height(), v.Round()
|
||||
for _, precommit := range v.Precommits {
|
||||
// Ensure that all votes are precommits
|
||||
if precommit.Type != VoteTypePrecommit {
|
||||
return fmt.Errorf("Invalid validation vote. Expected precommit, got %v",
|
||||
precommit.Type)
|
||||
}
|
||||
// Ensure that all heights are the same
|
||||
if precommit.Height != height {
|
||||
return fmt.Errorf("Invalid validation precommit height. Expected %v, got %v",
|
||||
height, precommit.Height)
|
||||
}
|
||||
// Ensure that all rounds are the same
|
||||
if precommit.Round != round {
|
||||
return fmt.Errorf("Invalid validation precommit round. Expected %v, got %v",
|
||||
round, precommit.Round)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -241,7 +258,7 @@ func (v *Validation) BitArray() *BitArray {
|
||||
if v.bitArray == nil {
|
||||
v.bitArray = NewBitArray(uint(len(v.Precommits)))
|
||||
for i, precommit := range v.Precommits {
|
||||
v.bitArray.SetIndex(uint(i), !precommit.IsZero())
|
||||
v.bitArray.SetIndex(uint(i), precommit != nil)
|
||||
}
|
||||
}
|
||||
return v.bitArray
|
||||
|
Loading…
x
Reference in New Issue
Block a user