Пример #1
0
// Returns whether +2/3 have prevoted/committed for BlockHash.
func (pol *POL) Verify(valSet *sm.ValidatorSet) error {

	if uint(len(pol.Votes)) != valSet.Size() {
		return fmt.Errorf("Invalid POL votes count: Expected %v, got %v",
			valSet.Size(), len(pol.Votes))
	}

	talliedVotingPower := uint64(0)
	prevoteDoc := account.SignBytes(&types.Vote{
		Height: pol.Height, Round: pol.Round, Type: types.VoteTypePrevote,
		BlockHash:  pol.BlockHash,
		BlockParts: pol.BlockParts,
	})
	seenValidators := map[string]struct{}{}

	for idx, vote := range pol.Votes {
		// vote may be zero, in which case skip.
		if vote.Signature.IsZero() {
			continue
		}
		voteDoc := prevoteDoc
		_, val := valSet.GetByIndex(uint(idx))

		// Commit vote?
		if vote.Round < pol.Round {
			voteDoc = account.SignBytes(&types.Vote{
				Height: pol.Height, Round: vote.Round, Type: types.VoteTypeCommit,
				BlockHash:  pol.BlockHash,
				BlockParts: pol.BlockParts,
			})
		} else if vote.Round > pol.Round {
			return fmt.Errorf("Invalid commit round %v for POL %v", vote.Round, pol)
		}

		// Validate
		if _, seen := seenValidators[string(val.Address)]; seen {
			return fmt.Errorf("Duplicate validator for vote %v for POL %v", vote, pol)
		}

		if !val.PubKey.VerifyBytes(voteDoc, vote.Signature) {
			return fmt.Errorf("Invalid signature for vote %v for POL %v", vote, pol)
		}

		// Tally
		seenValidators[string(val.Address)] = struct{}{}
		talliedVotingPower += val.VotingPower
	}

	if talliedVotingPower > valSet.TotalVotingPower()*2/3 {
		return nil
	} else {
		return fmt.Errorf("Invalid POL, insufficient voting power %v, needed %v",
			talliedVotingPower, (valSet.TotalVotingPower()*2/3 + 1))
	}

}
Пример #2
0
// Convenience method.
// Signs the vote and sets the POL's vote at the desired index
// Returns the POLVoteSignature pointer, so you can modify it afterwards.
func signAddPOLVoteSignature(val *sm.PrivValidator, valSet *sm.ValidatorSet, vote *types.Vote, pol *POL) *POLVoteSignature {
	vote = vote.Copy()
	err := val.SignVote(vote)
	if err != nil {
		panic(err)
	}
	idx, _ := valSet.GetByAddress(val.Address) // now we have the index
	pol.Votes[idx] = POLVoteSignature{vote.Round, vote.Signature}
	return &pol.Votes[idx]
}
Пример #3
0
// Constructs a new VoteSet struct used to accumulate votes for given height/round.
func NewVoteSet(height uint, round uint, type_ byte, valSet *sm.ValidatorSet) *VoteSet {
	if height == 0 {
		panic("Cannot make VoteSet for height == 0, doesn't make sense.")
	}
	if type_ == types.VoteTypeCommit && round != 0 {
		panic("Expected round 0 for commit vote set")
	}
	return &VoteSet{
		height:        height,
		round:         round,
		type_:         type_,
		valSet:        valSet,
		votes:         make([]*types.Vote, valSet.Size()),
		votesBitArray: NewBitArray(valSet.Size()),
		votesByBlock:  make(map[string]uint64),
		totalVotes:    0,
	}
}