diff --git a/state/execution.go b/state/execution.go index 31f2662bf..d838531f8 100644 --- a/state/execution.go +++ b/state/execution.go @@ -309,7 +309,14 @@ func (s *State) validateBlock(b *types.Block) error { } } - // TODO: Validate evidence + for _, ev := range block.Evidence.Evidence { + if err := ev.VoteA.Verify(s.ChainID, ev.PubKey); err != nil { + return types.ErrEvidenceInvalid(ev, err) + } + if err := ev.VoteB.Verify(s.ChainID, ev.PubKey); err != nil { + return types.ErrEvidenceInvalid(ev, err) + } + } return nil } diff --git a/types/evidence.go b/types/evidence.go index 6eb744277..5e2be9b50 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -7,6 +7,15 @@ import ( "github.com/tendermint/go-crypto" ) +type ErrEvidenceInvalid struct { + Evidence Evidence + Error error +} + +func (err *ErrEvidenceInvalid) Error() string { + return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.Error, err.Evidence) +} + // Evidence represents any provable malicious activity by a validator type Evidence interface { Verify() error @@ -49,7 +58,9 @@ func (dve *DuplicateVoteEvidence) Verify() error { } // Signatures must be valid - // TODO + if !dve.PubKey.Verify(SignBytes(chainID, dve.VoteA), dve.VoteA.Signature) { + return ErrVoteInvalidSignature + } return nil } diff --git a/types/vote.go b/types/vote.go index a34bf9d45..82adf0d11 100644 --- a/types/vote.go +++ b/types/vote.go @@ -101,3 +101,14 @@ func (vote *Vote) String() string { cmn.Fingerprint(vote.BlockID.Hash), vote.Signature, CanonicalTime(vote.Timestamp)) } + +func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error { + if !bytes.Equal(pubKey.Address(), v.ValidatorAddress) { + return ErrVoteInvalidValidatorAddress + } + + if !pubKey.VerifyBytes(SignBytes(chainID, vote), vote.Signature) { + return ErrVoteInvalidSignature + } + return nil +} diff --git a/types/vote_set.go b/types/vote_set.go index 5b802ceb8..3f8a96e3a 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -178,9 +178,8 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) { } // Check signature. - if !val.PubKey.VerifyBytes(SignBytes(voteSet.chainID, vote), vote.Signature) { - // Bad signature. - return false, ErrVoteInvalidSignature + if err := vote.Verify(voteSet.chainID, val.PubKey); err != nil { + return false, err } // Add vote and get conflicting vote if any