consensus: broadcast evidence tx on ErrVoteConflictingSignature

This commit is contained in:
Ethan Buchman
2015-03-16 17:28:53 -07:00
committed by Jae Kwon
parent 77a16f100c
commit 33f8943543
4 changed files with 33 additions and 9 deletions

View File

@@ -11,13 +11,21 @@ import (
)
var (
ErrVoteUnexpectedStep = errors.New("Unexpected step")
ErrVoteInvalidAccount = errors.New("Invalid round vote account")
ErrVoteInvalidSignature = errors.New("Invalid round vote signature")
ErrVoteInvalidBlockHash = errors.New("Invalid block hash")
ErrVoteConflictingSignature = errors.New("Conflicting round vote signature")
ErrVoteUnexpectedStep = errors.New("Unexpected step")
ErrVoteInvalidAccount = errors.New("Invalid round vote account")
ErrVoteInvalidSignature = errors.New("Invalid round vote signature")
ErrVoteInvalidBlockHash = errors.New("Invalid block hash")
)
type ErrVoteConflictingSignature struct {
VoteA *Vote
VoteB *Vote
}
func (err *ErrVoteConflictingSignature) Error() string {
return "Conflicting round vote signature"
}
// Represents a prevote, precommit, or commit vote from validators for consensus.
// Commit votes get aggregated into the next block's Validaiton.
// See the whitepaper for details.

View File

@@ -175,8 +175,21 @@ func (conR *ConsensusReactor) Receive(chId byte, peer *p2p.Peer, msgBytes []byte
address, _ := rs.Validators.GetByIndex(validatorIndex)
added, index, err := conR.conS.AddVote(address, vote)
if err != nil {
// Probably an invalid signature. Bad peer.
log.Warn("Error attempting to add vote", "error", err)
// If conflicting sig, broadcast evidence tx for slashing. Else punish peer.
if errDupe, ok := err.(*blk.ErrVoteConflictingSignature); ok {
log.Warn("Found conflicting vote. Publish evidence")
evidenceTx := &blk.DupeoutTx{
Address: address,
VoteA: *errDupe.VoteA,
VoteB: *errDupe.VoteB,
}
conR.conS.mempoolReactor.BroadcastTx(evidenceTx) // shouldn't need to check returned err
} else {
// Probably an invalid signature. Bad peer.
log.Warn("Error attempting to add vote", "error", err)
// TODO: punish peer
}
}
// Initialize Prevotes/Precommits/Commits if needed
ps.EnsureVoteBitArrays(rs.Height, rs.Validators.Size())

View File

@@ -106,7 +106,10 @@ func (voteSet *VoteSet) addVote(valIndex uint, vote *blk.Vote) (bool, uint, erro
if bytes.Equal(existingVote.BlockHash, vote.BlockHash) {
return false, 0, nil
} else {
return false, 0, blk.ErrVoteConflictingSignature
return false, 0, &blk.ErrVoteConflictingSignature{
VoteA: existingVote,
VoteB: vote,
}
}
}

View File

@@ -388,7 +388,7 @@ func (s *State) ExecTx(tx_ blk.Tx) error {
return errors.New("DupeoutTx heights don't match")
}
if tx.VoteA.Type == blk.VoteTypeCommit && tx.VoteA.Round < tx.VoteB.Round {
// Check special case.
// Check special case (not an error, validator must be slashed!)
// Validators should not sign another vote after committing.
} else {
if tx.VoteA.Round != tx.VoteB.Round {