github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/types/evidence.go (about)

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