Browse Source

consensus: broadcast evidence tx on ErrVoteConflictingSignature

pull/32/head
Ethan Buchman 9 years ago
committed by Jae Kwon
parent
commit
33f8943543
4 changed files with 33 additions and 9 deletions
  1. +13
    -5
      block/vote.go
  2. +15
    -2
      consensus/reactor.go
  3. +4
    -1
      consensus/vote_set.go
  4. +1
    -1
      state/state.go

+ 13
- 5
block/vote.go 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.


+ 15
- 2
consensus/reactor.go 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())


+ 4
- 1
consensus/vote_set.go 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,
}
}
}


+ 1
- 1
state/state.go 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 {


Loading…
Cancel
Save