tendermint/types/evidence.go

219 lines
6.5 KiB
Go
Raw Normal View History

2017-07-09 11:10:00 -07:00
package types
import (
"bytes"
"fmt"
"github.com/tendermint/go-crypto"
2017-11-19 19:55:59 -08:00
wire "github.com/tendermint/go-wire"
"github.com/tendermint/tmlibs/merkle"
2017-07-09 11:10:00 -07:00
)
// ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid.
2017-07-25 09:29:38 -07:00
type ErrEvidenceInvalid struct {
Evidence Evidence
ErrorValue error
2017-07-25 09:29:38 -07:00
}
func NewEvidenceInvalidErr(ev Evidence, err error) *ErrEvidenceInvalid {
return &ErrEvidenceInvalid{ev, err}
}
// Error returns a string representation of the error.
2017-07-25 09:29:38 -07:00
func (err *ErrEvidenceInvalid) Error() string {
return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.ErrorValue, err.Evidence)
2017-07-25 09:29:38 -07:00
}
//-------------------------------------------
2017-07-09 11:10:00 -07:00
// Evidence represents any provable malicious activity by a validator
type Evidence interface {
2017-12-26 17:34:57 -08:00
Height() int64 // height of the equivocation
Address() []byte // address of the equivocating validator
Index() int // index of the validator in the validator set
Hash() []byte // hash of the evidence
Verify(chainID string) error // verify the evidence
Equal(Evidence) bool // check equality of evidence
String() string
}
//-------------------------------------------
2017-11-19 14:18:43 -08:00
// EvidenceList is a list of Evidence. Evidences is not a word.
type EvidenceList []Evidence
2017-11-02 17:26:07 -07:00
2017-11-19 14:18:43 -08:00
// Hash returns the simple merkle root hash of the EvidenceList.
func (evl EvidenceList) Hash() []byte {
// Recursive impl.
// Copied from tmlibs/merkle to avoid allocations
2017-11-19 14:18:43 -08:00
switch len(evl) {
case 0:
return nil
case 1:
2017-11-19 14:18:43 -08:00
return evl[0].Hash()
default:
2017-11-19 14:18:43 -08:00
left := EvidenceList(evl[:(len(evl)+1)/2]).Hash()
right := EvidenceList(evl[(len(evl)+1)/2:]).Hash()
return merkle.SimpleHashFromTwoHashes(left, right)
}
2017-07-09 11:10:00 -07:00
}
2017-11-19 14:18:43 -08:00
func (evl EvidenceList) String() string {
2017-10-31 23:05:27 -07:00
s := ""
2017-11-19 14:18:43 -08:00
for _, e := range evl {
2017-10-31 23:05:27 -07:00
s += fmt.Sprintf("%s\t\t", e)
}
return s
}
2017-11-19 14:18:43 -08:00
// Has returns true if the evidence is in the EvidenceList.
func (evl EvidenceList) Has(evidence Evidence) bool {
for _, ev := range evl {
2017-11-01 12:57:22 -07:00
if ev.Equal(evidence) {
return true
}
}
return false
}
2017-07-09 11:10:00 -07:00
//-------------------------------------------
2017-11-19 19:55:59 -08:00
const (
evidenceTypeDuplicateVote = byte(0x01)
)
var _ = wire.RegisterInterface(
struct{ Evidence }{},
wire.ConcreteType{&DuplicateVoteEvidence{}, evidenceTypeDuplicateVote},
)
//-------------------------------------------
// DuplicateVoteEvidence contains evidence a validator signed two conflicting votes.
2017-07-09 11:10:00 -07:00
type DuplicateVoteEvidence struct {
PubKey crypto.PubKey
VoteA *Vote
VoteB *Vote
2017-07-09 11:10:00 -07:00
}
// String returns a string representation of the evidence.
func (dve *DuplicateVoteEvidence) String() string {
return fmt.Sprintf("VoteA: %v; VoteB: %v", dve.VoteA, dve.VoteB)
}
2017-11-02 17:26:07 -07:00
// Height returns the height this evidence refers to.
2017-12-26 17:34:57 -08:00
func (dve *DuplicateVoteEvidence) Height() int64 {
2017-11-02 17:26:07 -07:00
return dve.VoteA.Height
}
// Address returns the address of the validator.
2017-07-09 11:10:00 -07:00
func (dve *DuplicateVoteEvidence) Address() []byte {
return dve.PubKey.Address()
2017-07-09 11:10:00 -07:00
}
// Index returns the index of the validator.
func (dve *DuplicateVoteEvidence) Index() int {
return dve.VoteA.ValidatorIndex
}
// Hash returns the hash of the evidence.
func (dve *DuplicateVoteEvidence) Hash() []byte {
2018-02-03 00:23:10 -08:00
return wireHasher(dve).Hash()
}
// Verify returns an error if the two votes aren't conflicting.
// To be conflicting, they must be from the same validator, for the same H/R/S, but for different blocks.
func (dve *DuplicateVoteEvidence) Verify(chainID string) error {
2017-07-09 11:10:00 -07:00
// H/R/S must be the same
if dve.VoteA.Height != dve.VoteB.Height ||
dve.VoteA.Round != dve.VoteB.Round ||
dve.VoteA.Type != dve.VoteB.Type {
return fmt.Errorf("DuplicateVoteEvidence Error: H/R/S does not match. Got %v and %v", dve.VoteA, dve.VoteB)
}
// Address must be the same
2017-07-09 11:10:00 -07:00
if !bytes.Equal(dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress) {
return fmt.Errorf("DuplicateVoteEvidence Error: Validator addresses do not match. Got %X and %X", dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress)
}
// XXX: Should we enforce index is the same ?
2017-07-09 11:10:00 -07:00
if dve.VoteA.ValidatorIndex != dve.VoteB.ValidatorIndex {
return fmt.Errorf("DuplicateVoteEvidence Error: Validator indices do not match. Got %d and %d", dve.VoteA.ValidatorIndex, dve.VoteB.ValidatorIndex)
}
// BlockIDs must be different
if dve.VoteA.BlockID.Equals(dve.VoteB.BlockID) {
return fmt.Errorf("DuplicateVoteEvidence Error: BlockIDs are the same (%v) - not a real duplicate vote!", dve.VoteA.BlockID)
}
// Signatures must be valid
if !dve.PubKey.VerifyBytes(SignBytes(chainID, dve.VoteA), dve.VoteA.Signature) {
2017-12-27 11:46:24 -08:00
return fmt.Errorf("DuplicateVoteEvidence Error verifying VoteA: %v", ErrVoteInvalidSignature)
2017-07-25 09:29:38 -07:00
}
if !dve.PubKey.VerifyBytes(SignBytes(chainID, dve.VoteB), dve.VoteB.Signature) {
2017-12-27 11:46:24 -08:00
return fmt.Errorf("DuplicateVoteEvidence Error verifying VoteB: %v", ErrVoteInvalidSignature)
}
2017-07-09 11:10:00 -07:00
return nil
}
2017-11-01 12:57:22 -07:00
// Equal checks if two pieces of evidence are equal.
func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool {
if _, ok := ev.(*DuplicateVoteEvidence); !ok {
return false
}
// just check their hashes
2018-02-03 00:23:10 -08:00
dveHash := wireHasher(dve).Hash()
evHash := wireHasher(ev).Hash()
return bytes.Equal(dveHash, evHash)
2017-11-01 12:57:22 -07:00
}
//-----------------------------------------------------------------
// UNSTABLE
type MockGoodEvidence struct {
Height_ int64
Address_ []byte
Index_ int
}
// UNSTABLE
func NewMockGoodEvidence(height int64, index int, address []byte) MockGoodEvidence {
return MockGoodEvidence{height, address, index}
}
func (e MockGoodEvidence) Height() int64 { return e.Height_ }
func (e MockGoodEvidence) Address() []byte { return e.Address_ }
func (e MockGoodEvidence) Index() int { return e.Index_ }
func (e MockGoodEvidence) Hash() []byte {
return []byte(fmt.Sprintf("%d-%d", e.Height_, e.Index_))
}
func (e MockGoodEvidence) Verify(chainID string) error { return nil }
func (e MockGoodEvidence) Equal(ev Evidence) bool {
e2 := ev.(MockGoodEvidence)
return e.Height_ == e2.Height_ &&
bytes.Equal(e.Address_, e2.Address_) &&
e.Index_ == e2.Index_
}
func (e MockGoodEvidence) String() string {
return fmt.Sprintf("GoodEvidence: %d/%s/%d", e.Height_, e.Address_, e.Index_)
}
// UNSTABLE
type MockBadEvidence struct {
MockGoodEvidence
}
func (e MockBadEvidence) Verify(chainID string) error { return fmt.Errorf("MockBadEvidence") }
func (e MockBadEvidence) Equal(ev Evidence) bool {
e2 := ev.(MockBadEvidence)
return e.Height_ == e2.Height_ &&
bytes.Equal(e.Address_, e2.Address_) &&
e.Index_ == e2.Index_
}
func (e MockBadEvidence) String() string {
return fmt.Sprintf("BadEvidence: %d/%s/%d", e.Height_, e.Address_, e.Index_)
}