github.com/evdatsion/aphelion-dpos-bft@v0.32.1/types/evidence.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/pkg/errors"
     8  	"github.com/evdatsion/aphelion-dpos-bft/crypto/tmhash"
     9  
    10  	amino "github.com/evdatsion/go-amino"
    11  
    12  	"github.com/evdatsion/aphelion-dpos-bft/crypto"
    13  	"github.com/evdatsion/aphelion-dpos-bft/crypto/merkle"
    14  )
    15  
    16  const (
    17  	// MaxEvidenceBytes is a maximum size of any evidence (including amino overhead).
    18  	MaxEvidenceBytes int64 = 484
    19  )
    20  
    21  // ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid.
    22  type ErrEvidenceInvalid struct {
    23  	Evidence   Evidence
    24  	ErrorValue error
    25  }
    26  
    27  // NewErrEvidenceInvalid returns a new EvidenceInvalid with the given err.
    28  func NewErrEvidenceInvalid(ev Evidence, err error) *ErrEvidenceInvalid {
    29  	return &ErrEvidenceInvalid{ev, err}
    30  }
    31  
    32  // Error returns a string representation of the error.
    33  func (err *ErrEvidenceInvalid) Error() string {
    34  	return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.ErrorValue, err.Evidence)
    35  }
    36  
    37  // ErrEvidenceOverflow is for when there is too much evidence in a block.
    38  type ErrEvidenceOverflow struct {
    39  	MaxNum int64
    40  	GotNum int64
    41  }
    42  
    43  // NewErrEvidenceOverflow returns a new ErrEvidenceOverflow where got > max.
    44  func NewErrEvidenceOverflow(max, got int64) *ErrEvidenceOverflow {
    45  	return &ErrEvidenceOverflow{max, got}
    46  }
    47  
    48  // Error returns a string representation of the error.
    49  func (err *ErrEvidenceOverflow) Error() string {
    50  	return fmt.Sprintf("Too much evidence: Max %d, got %d", err.MaxNum, err.GotNum)
    51  }
    52  
    53  //-------------------------------------------
    54  
    55  // Evidence represents any provable malicious activity by a validator
    56  type Evidence interface {
    57  	Height() int64                                     // height of the equivocation
    58  	Address() []byte                                   // address of the equivocating validator
    59  	Bytes() []byte                                     // bytes which compromise the evidence
    60  	Hash() []byte                                      // hash of the evidence
    61  	Verify(chainID string, pubKey crypto.PubKey) error // verify the evidence
    62  	Equal(Evidence) bool                               // check equality of evidence
    63  
    64  	ValidateBasic() error
    65  	String() string
    66  }
    67  
    68  func RegisterEvidences(cdc *amino.Codec) {
    69  	cdc.RegisterInterface((*Evidence)(nil), nil)
    70  	cdc.RegisterConcrete(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence", nil)
    71  }
    72  
    73  func RegisterMockEvidences(cdc *amino.Codec) {
    74  	cdc.RegisterConcrete(MockGoodEvidence{}, "tendermint/MockGoodEvidence", nil)
    75  	cdc.RegisterConcrete(MockRandomGoodEvidence{}, "tendermint/MockRandomGoodEvidence", nil)
    76  	cdc.RegisterConcrete(MockBadEvidence{}, "tendermint/MockBadEvidence", nil)
    77  }
    78  
    79  const (
    80  	MaxEvidenceBytesDenominator = 10
    81  )
    82  
    83  // MaxEvidencePerBlock returns the maximum number of evidences
    84  // allowed in the block and their maximum total size (limitted to 1/10th
    85  // of the maximum block size).
    86  // TODO: change to a constant, or to a fraction of the validator set size.
    87  // See https://github.com/evdatsion/aphelion-dpos-bft/issues/2590
    88  func MaxEvidencePerBlock(blockMaxBytes int64) (int64, int64) {
    89  	maxBytes := blockMaxBytes / MaxEvidenceBytesDenominator
    90  	maxNum := maxBytes / MaxEvidenceBytes
    91  	return maxNum, maxBytes
    92  }
    93  
    94  //-------------------------------------------
    95  
    96  // DuplicateVoteEvidence contains evidence a validator signed two conflicting
    97  // votes.
    98  type DuplicateVoteEvidence struct {
    99  	PubKey crypto.PubKey
   100  	VoteA  *Vote
   101  	VoteB  *Vote
   102  }
   103  
   104  var _ Evidence = &DuplicateVoteEvidence{}
   105  
   106  // String returns a string representation of the evidence.
   107  func (dve *DuplicateVoteEvidence) String() string {
   108  	return fmt.Sprintf("VoteA: %v; VoteB: %v", dve.VoteA, dve.VoteB)
   109  
   110  }
   111  
   112  // Height returns the height this evidence refers to.
   113  func (dve *DuplicateVoteEvidence) Height() int64 {
   114  	return dve.VoteA.Height
   115  }
   116  
   117  // Address returns the address of the validator.
   118  func (dve *DuplicateVoteEvidence) Address() []byte {
   119  	return dve.PubKey.Address()
   120  }
   121  
   122  // Hash returns the hash of the evidence.
   123  func (dve *DuplicateVoteEvidence) Bytes() []byte {
   124  	return cdcEncode(dve)
   125  }
   126  
   127  // Hash returns the hash of the evidence.
   128  func (dve *DuplicateVoteEvidence) Hash() []byte {
   129  	return tmhash.Sum(cdcEncode(dve))
   130  }
   131  
   132  // Verify returns an error if the two votes aren't conflicting.
   133  // To be conflicting, they must be from the same validator, for the same H/R/S, but for different blocks.
   134  func (dve *DuplicateVoteEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
   135  	// H/R/S must be the same
   136  	if dve.VoteA.Height != dve.VoteB.Height ||
   137  		dve.VoteA.Round != dve.VoteB.Round ||
   138  		dve.VoteA.Type != dve.VoteB.Type {
   139  		return fmt.Errorf("DuplicateVoteEvidence Error: H/R/S does not match. Got %v and %v", dve.VoteA, dve.VoteB)
   140  	}
   141  
   142  	// Address must be the same
   143  	if !bytes.Equal(dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress) {
   144  		return fmt.Errorf("DuplicateVoteEvidence Error: Validator addresses do not match. Got %X and %X", dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress)
   145  	}
   146  
   147  	// Index must be the same
   148  	if dve.VoteA.ValidatorIndex != dve.VoteB.ValidatorIndex {
   149  		return fmt.Errorf("DuplicateVoteEvidence Error: Validator indices do not match. Got %d and %d", dve.VoteA.ValidatorIndex, dve.VoteB.ValidatorIndex)
   150  	}
   151  
   152  	// BlockIDs must be different
   153  	if dve.VoteA.BlockID.Equals(dve.VoteB.BlockID) {
   154  		return fmt.Errorf("DuplicateVoteEvidence Error: BlockIDs are the same (%v) - not a real duplicate vote", dve.VoteA.BlockID)
   155  	}
   156  
   157  	// pubkey must match address (this should already be true, sanity check)
   158  	addr := dve.VoteA.ValidatorAddress
   159  	if !bytes.Equal(pubKey.Address(), addr) {
   160  		return fmt.Errorf("DuplicateVoteEvidence FAILED SANITY CHECK - address (%X) doesn't match pubkey (%v - %X)",
   161  			addr, pubKey, pubKey.Address())
   162  	}
   163  
   164  	// Signatures must be valid
   165  	if !pubKey.VerifyBytes(dve.VoteA.SignBytes(chainID), dve.VoteA.Signature) {
   166  		return fmt.Errorf("DuplicateVoteEvidence Error verifying VoteA: %v", ErrVoteInvalidSignature)
   167  	}
   168  	if !pubKey.VerifyBytes(dve.VoteB.SignBytes(chainID), dve.VoteB.Signature) {
   169  		return fmt.Errorf("DuplicateVoteEvidence Error verifying VoteB: %v", ErrVoteInvalidSignature)
   170  	}
   171  
   172  	return nil
   173  }
   174  
   175  // Equal checks if two pieces of evidence are equal.
   176  func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool {
   177  	if _, ok := ev.(*DuplicateVoteEvidence); !ok {
   178  		return false
   179  	}
   180  
   181  	// just check their hashes
   182  	dveHash := tmhash.Sum(cdcEncode(dve))
   183  	evHash := tmhash.Sum(cdcEncode(ev))
   184  	return bytes.Equal(dveHash, evHash)
   185  }
   186  
   187  // ValidateBasic performs basic validation.
   188  func (dve *DuplicateVoteEvidence) ValidateBasic() error {
   189  	if len(dve.PubKey.Bytes()) == 0 {
   190  		return errors.New("Empty PubKey")
   191  	}
   192  	if dve.VoteA == nil || dve.VoteB == nil {
   193  		return fmt.Errorf("One or both of the votes are empty %v, %v", dve.VoteA, dve.VoteB)
   194  	}
   195  	if err := dve.VoteA.ValidateBasic(); err != nil {
   196  		return fmt.Errorf("Invalid VoteA: %v", err)
   197  	}
   198  	if err := dve.VoteB.ValidateBasic(); err != nil {
   199  		return fmt.Errorf("Invalid VoteB: %v", err)
   200  	}
   201  	return nil
   202  }
   203  
   204  //-----------------------------------------------------------------
   205  
   206  // UNSTABLE
   207  type MockRandomGoodEvidence struct {
   208  	MockGoodEvidence
   209  	randBytes []byte
   210  }
   211  
   212  var _ Evidence = &MockRandomGoodEvidence{}
   213  
   214  // UNSTABLE
   215  func NewMockRandomGoodEvidence(height int64, address []byte, randBytes []byte) MockRandomGoodEvidence {
   216  	return MockRandomGoodEvidence{
   217  		MockGoodEvidence{height, address}, randBytes,
   218  	}
   219  }
   220  
   221  func (e MockRandomGoodEvidence) Hash() []byte {
   222  	return []byte(fmt.Sprintf("%d-%x", e.Height_, e.randBytes))
   223  }
   224  
   225  // UNSTABLE
   226  type MockGoodEvidence struct {
   227  	Height_  int64
   228  	Address_ []byte
   229  }
   230  
   231  var _ Evidence = &MockGoodEvidence{}
   232  
   233  // UNSTABLE
   234  func NewMockGoodEvidence(height int64, idx int, address []byte) MockGoodEvidence {
   235  	return MockGoodEvidence{height, address}
   236  }
   237  
   238  func (e MockGoodEvidence) Height() int64   { return e.Height_ }
   239  func (e MockGoodEvidence) Address() []byte { return e.Address_ }
   240  func (e MockGoodEvidence) Hash() []byte {
   241  	return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_))
   242  }
   243  func (e MockGoodEvidence) Bytes() []byte {
   244  	return []byte(fmt.Sprintf("%d-%x", e.Height_, e.Address_))
   245  }
   246  func (e MockGoodEvidence) Verify(chainID string, pubKey crypto.PubKey) error { return nil }
   247  func (e MockGoodEvidence) Equal(ev Evidence) bool {
   248  	e2 := ev.(MockGoodEvidence)
   249  	return e.Height_ == e2.Height_ &&
   250  		bytes.Equal(e.Address_, e2.Address_)
   251  }
   252  func (e MockGoodEvidence) ValidateBasic() error { return nil }
   253  func (e MockGoodEvidence) String() string {
   254  	return fmt.Sprintf("GoodEvidence: %d/%s", e.Height_, e.Address_)
   255  }
   256  
   257  // UNSTABLE
   258  type MockBadEvidence struct {
   259  	MockGoodEvidence
   260  }
   261  
   262  func (e MockBadEvidence) Verify(chainID string, pubKey crypto.PubKey) error {
   263  	return fmt.Errorf("MockBadEvidence")
   264  }
   265  func (e MockBadEvidence) Equal(ev Evidence) bool {
   266  	e2 := ev.(MockBadEvidence)
   267  	return e.Height_ == e2.Height_ &&
   268  		bytes.Equal(e.Address_, e2.Address_)
   269  }
   270  func (e MockBadEvidence) ValidateBasic() error { return nil }
   271  func (e MockBadEvidence) String() string {
   272  	return fmt.Sprintf("BadEvidence: %d/%s", e.Height_, e.Address_)
   273  }
   274  
   275  //-------------------------------------------
   276  
   277  // EvidenceList is a list of Evidence. Evidences is not a word.
   278  type EvidenceList []Evidence
   279  
   280  // Hash returns the simple merkle root hash of the EvidenceList.
   281  func (evl EvidenceList) Hash() []byte {
   282  	// These allocations are required because Evidence is not of type Bytes, and
   283  	// golang slices can't be typed cast. This shouldn't be a performance problem since
   284  	// the Evidence size is capped.
   285  	evidenceBzs := make([][]byte, len(evl))
   286  	for i := 0; i < len(evl); i++ {
   287  		evidenceBzs[i] = evl[i].Bytes()
   288  	}
   289  	return merkle.SimpleHashFromByteSlices(evidenceBzs)
   290  }
   291  
   292  func (evl EvidenceList) String() string {
   293  	s := ""
   294  	for _, e := range evl {
   295  		s += fmt.Sprintf("%s\t\t", e)
   296  	}
   297  	return s
   298  }
   299  
   300  // Has returns true if the evidence is in the EvidenceList.
   301  func (evl EvidenceList) Has(evidence Evidence) bool {
   302  	for _, ev := range evl {
   303  		if ev.Equal(evidence) {
   304  			return true
   305  		}
   306  	}
   307  	return false
   308  }