github.com/devwanda/aphelion-staking@v0.33.9/types/evidence.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "fmt" 6 "strings" 7 "time" 8 9 amino "github.com/evdatsion/go-amino" 10 "github.com/pkg/errors" 11 12 "github.com/devwanda/aphelion-staking/crypto" 13 cryptoenc "github.com/devwanda/aphelion-staking/crypto/encoding" 14 "github.com/devwanda/aphelion-staking/crypto/merkle" 15 "github.com/devwanda/aphelion-staking/crypto/tmhash" 16 tmproto "github.com/devwanda/aphelion-staking/proto/types" 17 ) 18 19 const ( 20 // MaxEvidenceBytes is a maximum size of any evidence (including amino overhead). 21 MaxEvidenceBytes int64 = 484 22 ) 23 24 // ErrEvidenceInvalid wraps a piece of evidence and the error denoting how or why it is invalid. 25 type ErrEvidenceInvalid struct { 26 Evidence Evidence 27 ErrorValue error 28 } 29 30 // NewErrEvidenceInvalid returns a new EvidenceInvalid with the given err. 31 func NewErrEvidenceInvalid(ev Evidence, err error) *ErrEvidenceInvalid { 32 return &ErrEvidenceInvalid{ev, err} 33 } 34 35 // Error returns a string representation of the error. 36 func (err *ErrEvidenceInvalid) Error() string { 37 return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.ErrorValue, err.Evidence) 38 } 39 40 // ErrEvidenceOverflow is for when there is too much evidence in a block. 41 type ErrEvidenceOverflow struct { 42 MaxNum int64 43 GotNum int64 44 } 45 46 // NewErrEvidenceOverflow returns a new ErrEvidenceOverflow where got > max. 47 func NewErrEvidenceOverflow(max, got int64) *ErrEvidenceOverflow { 48 return &ErrEvidenceOverflow{max, got} 49 } 50 51 // Error returns a string representation of the error. 52 func (err *ErrEvidenceOverflow) Error() string { 53 return fmt.Sprintf("Too much evidence: Max %d, got %d", err.MaxNum, err.GotNum) 54 } 55 56 //------------------------------------------- 57 58 // Evidence represents any provable malicious activity by a validator 59 type Evidence interface { 60 Height() int64 // height of the equivocation 61 Time() time.Time // time of the equivocation 62 Address() []byte // address of the equivocating validator 63 Bytes() []byte // bytes which comprise the evidence 64 Hash() []byte // hash of the evidence 65 Verify(chainID string, pubKey crypto.PubKey) error // verify the evidence 66 Equal(Evidence) bool // check equality of evidence 67 68 ValidateBasic() error 69 String() string 70 } 71 72 func EvidenceToProto(evidence Evidence) (*tmproto.Evidence, error) { 73 if evidence == nil { 74 return nil, errors.New("nil evidence") 75 } 76 77 switch evi := evidence.(type) { 78 case *DuplicateVoteEvidence: 79 voteB := evi.VoteB.ToProto() 80 voteA := evi.VoteA.ToProto() 81 pk, err := cryptoenc.PubKeyToProto(evi.PubKey) 82 if err != nil { 83 return nil, err 84 } 85 tp := &tmproto.Evidence{ 86 Sum: &tmproto.Evidence_DuplicateVoteEvidence{ 87 DuplicateVoteEvidence: &tmproto.DuplicateVoteEvidence{ 88 PubKey: &pk, 89 VoteA: voteA, 90 VoteB: voteB, 91 }, 92 }, 93 } 94 return tp, nil 95 case MockEvidence: 96 if err := evi.ValidateBasic(); err != nil { 97 return nil, err 98 } 99 100 tp := &tmproto.Evidence{ 101 Sum: &tmproto.Evidence_MockEvidence{ 102 MockEvidence: &tmproto.MockEvidence{ 103 EvidenceHeight: evi.Height(), 104 EvidenceTime: evi.Time(), 105 EvidenceAddress: evi.Address(), 106 }, 107 }, 108 } 109 110 return tp, nil 111 case MockRandomEvidence: 112 if err := evi.ValidateBasic(); err != nil { 113 return nil, err 114 } 115 116 tp := &tmproto.Evidence{ 117 Sum: &tmproto.Evidence_MockRandomEvidence{ 118 MockRandomEvidence: &tmproto.MockRandomEvidence{ 119 EvidenceHeight: evi.Height(), 120 EvidenceTime: evi.Time(), 121 EvidenceAddress: evi.Address(), 122 RandBytes: evi.randBytes, 123 }, 124 }, 125 } 126 return tp, nil 127 default: 128 return nil, fmt.Errorf("toproto: evidence is not recognized: %T", evi) 129 } 130 } 131 132 func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) { 133 if evidence == nil { 134 return nil, errors.New("nil evidence") 135 } 136 137 switch evi := evidence.Sum.(type) { 138 case *tmproto.Evidence_DuplicateVoteEvidence: 139 140 vA, err := VoteFromProto(evi.DuplicateVoteEvidence.VoteA) 141 if err != nil { 142 return nil, err 143 } 144 145 vB, err := VoteFromProto(evi.DuplicateVoteEvidence.VoteB) 146 if err != nil { 147 return nil, err 148 } 149 150 pk, err := cryptoenc.PubKeyFromProto(evi.DuplicateVoteEvidence.GetPubKey()) 151 if err != nil { 152 return nil, err 153 } 154 155 dve := DuplicateVoteEvidence{ 156 PubKey: pk, 157 VoteA: vA, 158 VoteB: vB, 159 } 160 161 return &dve, dve.ValidateBasic() 162 case *tmproto.Evidence_MockEvidence: 163 me := MockEvidence{ 164 EvidenceHeight: evi.MockEvidence.GetEvidenceHeight(), 165 EvidenceAddress: evi.MockEvidence.GetEvidenceAddress(), 166 EvidenceTime: evi.MockEvidence.GetEvidenceTime(), 167 } 168 return me, me.ValidateBasic() 169 case *tmproto.Evidence_MockRandomEvidence: 170 mre := MockRandomEvidence{ 171 MockEvidence: MockEvidence{ 172 EvidenceHeight: evi.MockRandomEvidence.GetEvidenceHeight(), 173 EvidenceAddress: evi.MockRandomEvidence.GetEvidenceAddress(), 174 EvidenceTime: evi.MockRandomEvidence.GetEvidenceTime(), 175 }, 176 randBytes: evi.MockRandomEvidence.RandBytes, 177 } 178 return mre, mre.ValidateBasic() 179 default: 180 return nil, errors.New("evidence is not recognized") 181 } 182 } 183 184 func RegisterEvidences(cdc *amino.Codec) { 185 cdc.RegisterInterface((*Evidence)(nil), nil) 186 cdc.RegisterConcrete(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence", nil) 187 } 188 189 func RegisterMockEvidences(cdc *amino.Codec) { 190 cdc.RegisterConcrete(MockEvidence{}, "tendermint/MockEvidence", nil) 191 cdc.RegisterConcrete(MockRandomEvidence{}, "tendermint/MockRandomEvidence", nil) 192 } 193 194 const ( 195 MaxEvidenceBytesDenominator = 10 196 ) 197 198 // MaxEvidencePerBlock returns the maximum number of evidences 199 // allowed in the block and their maximum total size (limitted to 1/10th 200 // of the maximum block size). 201 // TODO: change to a constant, or to a fraction of the validator set size. 202 // See https://github.com/devwanda/aphelion-staking/issues/2590 203 func MaxEvidencePerBlock(blockMaxBytes int64) (int64, int64) { 204 maxBytes := blockMaxBytes / MaxEvidenceBytesDenominator 205 maxNum := maxBytes / MaxEvidenceBytes 206 return maxNum, maxBytes 207 } 208 209 //------------------------------------------- 210 211 // DuplicateVoteEvidence contains evidence a validator signed two conflicting 212 // votes. 213 type DuplicateVoteEvidence struct { 214 PubKey crypto.PubKey 215 VoteA *Vote 216 VoteB *Vote 217 } 218 219 var _ Evidence = &DuplicateVoteEvidence{} 220 221 // NewDuplicateVoteEvidence creates DuplicateVoteEvidence with right ordering given 222 // two conflicting votes. If one of the votes is nil, evidence returned is nil as well 223 func NewDuplicateVoteEvidence(pubkey crypto.PubKey, vote1 *Vote, vote2 *Vote) *DuplicateVoteEvidence { 224 var voteA, voteB *Vote 225 if vote1 == nil || vote2 == nil { 226 return nil 227 } 228 if strings.Compare(vote1.BlockID.Key(), vote2.BlockID.Key()) == -1 { 229 voteA = vote1 230 voteB = vote2 231 } else { 232 voteA = vote2 233 voteB = vote1 234 } 235 return &DuplicateVoteEvidence{ 236 PubKey: pubkey, 237 VoteA: voteA, 238 VoteB: voteB, 239 } 240 } 241 242 // String returns a string representation of the evidence. 243 func (dve *DuplicateVoteEvidence) String() string { 244 return fmt.Sprintf("VoteA: %v; VoteB: %v", dve.VoteA, dve.VoteB) 245 246 } 247 248 // Height returns the height this evidence refers to. 249 func (dve *DuplicateVoteEvidence) Height() int64 { 250 return dve.VoteA.Height 251 } 252 253 // Time return the time the evidence was created 254 func (dve *DuplicateVoteEvidence) Time() time.Time { 255 return dve.VoteA.Timestamp 256 } 257 258 // Address returns the address of the validator. 259 func (dve *DuplicateVoteEvidence) Address() []byte { 260 return dve.PubKey.Address() 261 } 262 263 // Hash returns the hash of the evidence. 264 func (dve *DuplicateVoteEvidence) Bytes() []byte { 265 return cdcEncode(dve) 266 } 267 268 // Hash returns the hash of the evidence. 269 func (dve *DuplicateVoteEvidence) Hash() []byte { 270 return tmhash.Sum(cdcEncode(dve)) 271 } 272 273 // Verify returns an error if the two votes aren't conflicting. 274 // To be conflicting, they must be from the same validator, for the same H/R/S, but for different blocks. 275 func (dve *DuplicateVoteEvidence) Verify(chainID string, pubKey crypto.PubKey) error { 276 // H/R/S must be the same 277 if dve.VoteA.Height != dve.VoteB.Height || 278 dve.VoteA.Round != dve.VoteB.Round || 279 dve.VoteA.Type != dve.VoteB.Type { 280 return fmt.Errorf("duplicateVoteEvidence Error: H/R/S does not match. Got %v and %v", dve.VoteA, dve.VoteB) 281 } 282 283 // Address must be the same 284 if !bytes.Equal(dve.VoteA.ValidatorAddress, dve.VoteB.ValidatorAddress) { 285 return fmt.Errorf( 286 "duplicateVoteEvidence Error: Validator addresses do not match. Got %X and %X", 287 dve.VoteA.ValidatorAddress, 288 dve.VoteB.ValidatorAddress, 289 ) 290 } 291 292 // Index must be the same 293 if dve.VoteA.ValidatorIndex != dve.VoteB.ValidatorIndex { 294 return fmt.Errorf( 295 "duplicateVoteEvidence Error: Validator indices do not match. Got %d and %d", 296 dve.VoteA.ValidatorIndex, 297 dve.VoteB.ValidatorIndex, 298 ) 299 } 300 301 // BlockIDs must be different 302 if dve.VoteA.BlockID.Equals(dve.VoteB.BlockID) { 303 return fmt.Errorf( 304 "duplicateVoteEvidence Error: BlockIDs are the same (%v) - not a real duplicate vote", 305 dve.VoteA.BlockID, 306 ) 307 } 308 309 // pubkey must match address (this should already be true, sanity check) 310 addr := dve.VoteA.ValidatorAddress 311 if !bytes.Equal(pubKey.Address(), addr) { 312 return fmt.Errorf("duplicateVoteEvidence FAILED SANITY CHECK - address (%X) doesn't match pubkey (%v - %X)", 313 addr, pubKey, pubKey.Address()) 314 } 315 316 // Signatures must be valid 317 if !pubKey.VerifyBytes(dve.VoteA.SignBytes(chainID), dve.VoteA.Signature) { 318 return fmt.Errorf("duplicateVoteEvidence Error verifying VoteA: %v", ErrVoteInvalidSignature) 319 } 320 if !pubKey.VerifyBytes(dve.VoteB.SignBytes(chainID), dve.VoteB.Signature) { 321 return fmt.Errorf("duplicateVoteEvidence Error verifying VoteB: %v", ErrVoteInvalidSignature) 322 } 323 324 return nil 325 } 326 327 // Equal checks if two pieces of evidence are equal. 328 func (dve *DuplicateVoteEvidence) Equal(ev Evidence) bool { 329 if _, ok := ev.(*DuplicateVoteEvidence); !ok { 330 return false 331 } 332 333 // just check their hashes 334 dveHash := tmhash.Sum(cdcEncode(dve)) 335 evHash := tmhash.Sum(cdcEncode(ev)) 336 fmt.Println(dveHash, evHash) 337 return bytes.Equal(dveHash, evHash) 338 } 339 340 // ValidateBasic performs basic validation. 341 func (dve *DuplicateVoteEvidence) ValidateBasic() error { 342 if len(dve.PubKey.Bytes()) == 0 { 343 return errors.New("empty PubKey") 344 } 345 if dve.VoteA == nil || dve.VoteB == nil { 346 return fmt.Errorf("one or both of the votes are empty %v, %v", dve.VoteA, dve.VoteB) 347 } 348 if err := dve.VoteA.ValidateBasic(); err != nil { 349 return fmt.Errorf("invalid VoteA: %v", err) 350 } 351 if err := dve.VoteB.ValidateBasic(); err != nil { 352 return fmt.Errorf("invalid VoteB: %v", err) 353 } 354 // Enforce Votes are lexicographically sorted on blockID 355 if strings.Compare(dve.VoteA.BlockID.Key(), dve.VoteB.BlockID.Key()) >= 0 { 356 return errors.New("duplicate votes in invalid order") 357 } 358 return nil 359 } 360 361 //----------------------------------------------------------------- 362 363 // UNSTABLE 364 type MockRandomEvidence struct { 365 MockEvidence 366 randBytes []byte 367 } 368 369 var _ Evidence = &MockRandomEvidence{} 370 371 // UNSTABLE 372 func NewMockRandomEvidence(height int64, eTime time.Time, address []byte, randBytes []byte) MockRandomEvidence { 373 return MockRandomEvidence{ 374 MockEvidence{ 375 EvidenceHeight: height, 376 EvidenceTime: eTime, 377 EvidenceAddress: address}, randBytes, 378 } 379 } 380 381 func (e MockRandomEvidence) Hash() []byte { 382 return []byte(fmt.Sprintf("%d-%x", e.EvidenceHeight, e.randBytes)) 383 } 384 385 // UNSTABLE 386 type MockEvidence struct { 387 EvidenceHeight int64 388 EvidenceTime time.Time 389 EvidenceAddress []byte 390 } 391 392 var _ Evidence = &MockEvidence{} 393 394 // UNSTABLE 395 func NewMockEvidence(height int64, eTime time.Time, idx int, address []byte) MockEvidence { 396 return MockEvidence{ 397 EvidenceHeight: height, 398 EvidenceTime: eTime, 399 EvidenceAddress: address} 400 } 401 402 func (e MockEvidence) Height() int64 { return e.EvidenceHeight } 403 func (e MockEvidence) Time() time.Time { return e.EvidenceTime } 404 func (e MockEvidence) Address() []byte { return e.EvidenceAddress } 405 func (e MockEvidence) Hash() []byte { 406 return []byte(fmt.Sprintf("%d-%x-%s", 407 e.EvidenceHeight, e.EvidenceAddress, e.EvidenceTime)) 408 } 409 func (e MockEvidence) Bytes() []byte { 410 return []byte(fmt.Sprintf("%d-%x-%s", 411 e.EvidenceHeight, e.EvidenceAddress, e.EvidenceTime)) 412 } 413 func (e MockEvidence) Verify(chainID string, pubKey crypto.PubKey) error { return nil } 414 func (e MockEvidence) Equal(ev Evidence) bool { 415 e2 := ev.(MockEvidence) 416 return e.EvidenceHeight == e2.EvidenceHeight && 417 bytes.Equal(e.EvidenceAddress, e2.EvidenceAddress) 418 } 419 func (e MockEvidence) ValidateBasic() error { return nil } 420 func (e MockEvidence) String() string { 421 return fmt.Sprintf("Evidence: %d/%s/%s", e.EvidenceHeight, e.Time(), e.EvidenceAddress) 422 } 423 424 //------------------------------------------- 425 426 // EvidenceList is a list of Evidence. Evidences is not a word. 427 type EvidenceList []Evidence 428 429 // Hash returns the simple merkle root hash of the EvidenceList. 430 func (evl EvidenceList) Hash() []byte { 431 // These allocations are required because Evidence is not of type Bytes, and 432 // golang slices can't be typed cast. This shouldn't be a performance problem since 433 // the Evidence size is capped. 434 evidenceBzs := make([][]byte, len(evl)) 435 for i := 0; i < len(evl); i++ { 436 evidenceBzs[i] = evl[i].Bytes() 437 } 438 return merkle.SimpleHashFromByteSlices(evidenceBzs) 439 } 440 441 func (evl EvidenceList) String() string { 442 s := "" 443 for _, e := range evl { 444 s += fmt.Sprintf("%s\t\t", e) 445 } 446 return s 447 } 448 449 // Has returns true if the evidence is in the EvidenceList. 450 func (evl EvidenceList) Has(evidence Evidence) bool { 451 for _, ev := range evl { 452 if ev.Equal(evidence) { 453 return true 454 } 455 } 456 return false 457 }