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 }