github.com/Oyster-zx/tendermint@v0.34.24-fork/types/evidence.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "sort" 9 "strings" 10 "time" 11 12 abci "github.com/tendermint/tendermint/abci/types" 13 "github.com/tendermint/tendermint/crypto/merkle" 14 "github.com/tendermint/tendermint/crypto/tmhash" 15 tmjson "github.com/tendermint/tendermint/libs/json" 16 tmrand "github.com/tendermint/tendermint/libs/rand" 17 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 18 ) 19 20 // Evidence represents any provable malicious activity by a validator. 21 // Verification logic for each evidence is part of the evidence module. 22 type Evidence interface { 23 ABCI() []abci.Evidence // forms individual evidence to be sent to the application 24 Bytes() []byte // bytes which comprise the evidence 25 Hash() []byte // hash of the evidence 26 Height() int64 // height of the infraction 27 String() string // string format of the evidence 28 Time() time.Time // time of the infraction 29 ValidateBasic() error // basic consistency check 30 } 31 32 //-------------------------------------------------------------------------------------- 33 34 // DuplicateVoteEvidence contains evidence of a single validator signing two conflicting votes. 35 type DuplicateVoteEvidence struct { 36 VoteA *Vote `json:"vote_a"` 37 VoteB *Vote `json:"vote_b"` 38 39 // abci specific information 40 TotalVotingPower int64 41 ValidatorPower int64 42 Timestamp time.Time 43 } 44 45 var _ Evidence = &DuplicateVoteEvidence{} 46 47 // NewDuplicateVoteEvidence creates DuplicateVoteEvidence with right ordering given 48 // two conflicting votes. If one of the votes is nil, evidence returned is nil as well 49 func NewDuplicateVoteEvidence(vote1, vote2 *Vote, blockTime time.Time, valSet *ValidatorSet) *DuplicateVoteEvidence { 50 var voteA, voteB *Vote 51 if vote1 == nil || vote2 == nil || valSet == nil { 52 return nil 53 } 54 idx, val := valSet.GetByAddress(vote1.ValidatorAddress) 55 if idx == -1 { 56 return nil 57 } 58 59 if strings.Compare(vote1.BlockID.Key(), vote2.BlockID.Key()) == -1 { 60 voteA = vote1 61 voteB = vote2 62 } else { 63 voteA = vote2 64 voteB = vote1 65 } 66 return &DuplicateVoteEvidence{ 67 VoteA: voteA, 68 VoteB: voteB, 69 TotalVotingPower: valSet.TotalVotingPower(), 70 ValidatorPower: val.VotingPower, 71 Timestamp: blockTime, 72 } 73 } 74 75 // ABCI returns the application relevant representation of the evidence 76 func (dve *DuplicateVoteEvidence) ABCI() []abci.Evidence { 77 return []abci.Evidence{{ 78 Type: abci.EvidenceType_DUPLICATE_VOTE, 79 Validator: abci.Validator{ 80 Address: dve.VoteA.ValidatorAddress, 81 Power: dve.ValidatorPower, 82 }, 83 Height: dve.VoteA.Height, 84 Time: dve.Timestamp, 85 TotalVotingPower: dve.TotalVotingPower, 86 }} 87 } 88 89 // Bytes returns the proto-encoded evidence as a byte array. 90 func (dve *DuplicateVoteEvidence) Bytes() []byte { 91 pbe := dve.ToProto() 92 bz, err := pbe.Marshal() 93 if err != nil { 94 panic(err) 95 } 96 97 return bz 98 } 99 100 // Hash returns the hash of the evidence. 101 func (dve *DuplicateVoteEvidence) Hash() []byte { 102 return tmhash.Sum(dve.Bytes()) 103 } 104 105 // Height returns the height of the infraction 106 func (dve *DuplicateVoteEvidence) Height() int64 { 107 return dve.VoteA.Height 108 } 109 110 // String returns a string representation of the evidence. 111 func (dve *DuplicateVoteEvidence) String() string { 112 return fmt.Sprintf("DuplicateVoteEvidence{VoteA: %v, VoteB: %v}", dve.VoteA, dve.VoteB) 113 } 114 115 // Time returns the time of the infraction 116 func (dve *DuplicateVoteEvidence) Time() time.Time { 117 return dve.Timestamp 118 } 119 120 // ValidateBasic performs basic validation. 121 func (dve *DuplicateVoteEvidence) ValidateBasic() error { 122 if dve == nil { 123 return errors.New("empty duplicate vote evidence") 124 } 125 126 if dve.VoteA == nil || dve.VoteB == nil { 127 return fmt.Errorf("one or both of the votes are empty %v, %v", dve.VoteA, dve.VoteB) 128 } 129 if err := dve.VoteA.ValidateBasic(); err != nil { 130 return fmt.Errorf("invalid VoteA: %w", err) 131 } 132 if err := dve.VoteB.ValidateBasic(); err != nil { 133 return fmt.Errorf("invalid VoteB: %w", err) 134 } 135 // Enforce Votes are lexicographically sorted on blockID 136 if strings.Compare(dve.VoteA.BlockID.Key(), dve.VoteB.BlockID.Key()) >= 0 { 137 return errors.New("duplicate votes in invalid order") 138 } 139 return nil 140 } 141 142 // ToProto encodes DuplicateVoteEvidence to protobuf 143 func (dve *DuplicateVoteEvidence) ToProto() *tmproto.DuplicateVoteEvidence { 144 voteB := dve.VoteB.ToProto() 145 voteA := dve.VoteA.ToProto() 146 tp := tmproto.DuplicateVoteEvidence{ 147 VoteA: voteA, 148 VoteB: voteB, 149 TotalVotingPower: dve.TotalVotingPower, 150 ValidatorPower: dve.ValidatorPower, 151 Timestamp: dve.Timestamp, 152 } 153 return &tp 154 } 155 156 // DuplicateVoteEvidenceFromProto decodes protobuf into DuplicateVoteEvidence 157 func DuplicateVoteEvidenceFromProto(pb *tmproto.DuplicateVoteEvidence) (*DuplicateVoteEvidence, error) { 158 if pb == nil { 159 return nil, errors.New("nil duplicate vote evidence") 160 } 161 162 vA, err := VoteFromProto(pb.VoteA) 163 if err != nil { 164 return nil, err 165 } 166 167 vB, err := VoteFromProto(pb.VoteB) 168 if err != nil { 169 return nil, err 170 } 171 172 dve := &DuplicateVoteEvidence{ 173 VoteA: vA, 174 VoteB: vB, 175 TotalVotingPower: pb.TotalVotingPower, 176 ValidatorPower: pb.ValidatorPower, 177 Timestamp: pb.Timestamp, 178 } 179 180 return dve, dve.ValidateBasic() 181 } 182 183 //------------------------------------ LIGHT EVIDENCE -------------------------------------- 184 185 // LightClientAttackEvidence is a generalized evidence that captures all forms of known attacks on 186 // a light client such that a full node can verify, propose and commit the evidence on-chain for 187 // punishment of the malicious validators. There are three forms of attacks: Lunatic, Equivocation 188 // and Amnesia. These attacks are exhaustive. You can find a more detailed overview of this at 189 // tendermint/docs/architecture/adr-047-handling-evidence-from-light-client.md 190 type LightClientAttackEvidence struct { 191 ConflictingBlock *LightBlock 192 CommonHeight int64 193 194 // abci specific information 195 ByzantineValidators []*Validator // validators in the validator set that misbehaved in creating the conflicting block 196 TotalVotingPower int64 // total voting power of the validator set at the common height 197 Timestamp time.Time // timestamp of the block at the common height 198 } 199 200 var _ Evidence = &LightClientAttackEvidence{} 201 202 // ABCI forms an array of abci evidence for each byzantine validator 203 func (l *LightClientAttackEvidence) ABCI() []abci.Evidence { 204 abciEv := make([]abci.Evidence, len(l.ByzantineValidators)) 205 for idx, val := range l.ByzantineValidators { 206 abciEv[idx] = abci.Evidence{ 207 Type: abci.EvidenceType_LIGHT_CLIENT_ATTACK, 208 Validator: TM2PB.Validator(val), 209 Height: l.Height(), 210 Time: l.Timestamp, 211 TotalVotingPower: l.TotalVotingPower, 212 } 213 } 214 return abciEv 215 } 216 217 // Bytes returns the proto-encoded evidence as a byte array 218 func (l *LightClientAttackEvidence) Bytes() []byte { 219 pbe, err := l.ToProto() 220 if err != nil { 221 panic(err) 222 } 223 bz, err := pbe.Marshal() 224 if err != nil { 225 panic(err) 226 } 227 return bz 228 } 229 230 // GetByzantineValidators finds out what style of attack LightClientAttackEvidence was and then works out who 231 // the malicious validators were and returns them. This is used both for forming the ByzantineValidators 232 // field and for validating that it is correct. Validators are ordered based on validator power 233 func (l *LightClientAttackEvidence) GetByzantineValidators(commonVals *ValidatorSet, 234 trusted *SignedHeader) []*Validator { 235 var validators []*Validator 236 // First check if the header is invalid. This means that it is a lunatic attack and therefore we take the 237 // validators who are in the commonVals and voted for the lunatic header 238 if l.ConflictingHeaderIsInvalid(trusted.Header) { 239 for _, commitSig := range l.ConflictingBlock.Commit.Signatures { 240 if !commitSig.ForBlock() { 241 continue 242 } 243 244 _, val := commonVals.GetByAddress(commitSig.ValidatorAddress) 245 if val == nil { 246 // validator wasn't in the common validator set 247 continue 248 } 249 validators = append(validators, val) 250 } 251 sort.Sort(ValidatorsByVotingPower(validators)) 252 return validators 253 } else if trusted.Commit.Round == l.ConflictingBlock.Commit.Round { 254 // This is an equivocation attack as both commits are in the same round. We then find the validators 255 // from the conflicting light block validator set that voted in both headers. 256 // Validator hashes are the same therefore the indexing order of validators are the same and thus we 257 // only need a single loop to find the validators that voted twice. 258 for i := 0; i < len(l.ConflictingBlock.Commit.Signatures); i++ { 259 sigA := l.ConflictingBlock.Commit.Signatures[i] 260 if sigA.Absent() { 261 continue 262 } 263 264 sigB := trusted.Commit.Signatures[i] 265 if sigB.Absent() { 266 continue 267 } 268 269 _, val := l.ConflictingBlock.ValidatorSet.GetByAddress(sigA.ValidatorAddress) 270 validators = append(validators, val) 271 } 272 sort.Sort(ValidatorsByVotingPower(validators)) 273 return validators 274 } 275 // if the rounds are different then this is an amnesia attack. Unfortunately, given the nature of the attack, 276 // we aren't able yet to deduce which are malicious validators and which are not hence we return an 277 // empty validator set. 278 return validators 279 } 280 281 // ConflictingHeaderIsInvalid takes a trusted header and matches it againt a conflicting header 282 // to determine whether the conflicting header was the product of a valid state transition 283 // or not. If it is then all the deterministic fields of the header should be the same. 284 // If not, it is an invalid header and constitutes a lunatic attack. 285 func (l *LightClientAttackEvidence) ConflictingHeaderIsInvalid(trustedHeader *Header) bool { 286 return !bytes.Equal(trustedHeader.ValidatorsHash, l.ConflictingBlock.ValidatorsHash) || 287 !bytes.Equal(trustedHeader.NextValidatorsHash, l.ConflictingBlock.NextValidatorsHash) || 288 !bytes.Equal(trustedHeader.ConsensusHash, l.ConflictingBlock.ConsensusHash) || 289 !bytes.Equal(trustedHeader.AppHash, l.ConflictingBlock.AppHash) || 290 !bytes.Equal(trustedHeader.LastResultsHash, l.ConflictingBlock.LastResultsHash) 291 292 } 293 294 // Hash returns the hash of the header and the commonHeight. This is designed to cause hash collisions 295 // with evidence that have the same conflicting header and common height but different permutations 296 // of validator commit signatures. The reason for this is that we don't want to allow several 297 // permutations of the same evidence to be committed on chain. Ideally we commit the header with the 298 // most commit signatures (captures the most byzantine validators) but anything greater than 1/3 is 299 // sufficient. 300 // TODO: We should change the hash to include the commit, header, total voting power, byzantine 301 // validators and timestamp 302 func (l *LightClientAttackEvidence) Hash() []byte { 303 buf := make([]byte, binary.MaxVarintLen64) 304 n := binary.PutVarint(buf, l.CommonHeight) 305 bz := make([]byte, tmhash.Size+n) 306 copy(bz[:tmhash.Size-1], l.ConflictingBlock.Hash().Bytes()) 307 copy(bz[tmhash.Size:], buf) 308 return tmhash.Sum(bz) 309 } 310 311 // Height returns the last height at which the primary provider and witness provider had the same header. 312 // We use this as the height of the infraction rather than the actual conflicting header because we know 313 // that the malicious validators were bonded at this height which is important for evidence expiry 314 func (l *LightClientAttackEvidence) Height() int64 { 315 return l.CommonHeight 316 } 317 318 // String returns a string representation of LightClientAttackEvidence 319 func (l *LightClientAttackEvidence) String() string { 320 return fmt.Sprintf(`LightClientAttackEvidence{ 321 ConflictingBlock: %v, 322 CommonHeight: %d, 323 ByzatineValidators: %v, 324 TotalVotingPower: %d, 325 Timestamp: %v}#%X`, 326 l.ConflictingBlock.String(), l.CommonHeight, l.ByzantineValidators, 327 l.TotalVotingPower, l.Timestamp, l.Hash()) 328 } 329 330 // Time returns the time of the common block where the infraction leveraged off. 331 func (l *LightClientAttackEvidence) Time() time.Time { 332 return l.Timestamp 333 } 334 335 // ValidateBasic performs basic validation such that the evidence is consistent and can now be used for verification. 336 func (l *LightClientAttackEvidence) ValidateBasic() error { 337 if l.ConflictingBlock == nil { 338 return errors.New("conflicting block is nil") 339 } 340 341 // this check needs to be done before we can run validate basic 342 if l.ConflictingBlock.Header == nil { 343 return errors.New("conflicting block missing header") 344 } 345 346 if l.TotalVotingPower <= 0 { 347 return errors.New("negative or zero total voting power") 348 } 349 350 if l.CommonHeight <= 0 { 351 return errors.New("negative or zero common height") 352 } 353 354 // check that common height isn't ahead of the height of the conflicting block. It 355 // is possible that they are the same height if the light node witnesses either an 356 // amnesia or a equivocation attack. 357 if l.CommonHeight > l.ConflictingBlock.Height { 358 return fmt.Errorf("common height is ahead of the conflicting block height (%d > %d)", 359 l.CommonHeight, l.ConflictingBlock.Height) 360 } 361 362 if err := l.ConflictingBlock.ValidateBasic(l.ConflictingBlock.ChainID); err != nil { 363 return fmt.Errorf("invalid conflicting light block: %w", err) 364 } 365 366 return nil 367 } 368 369 // ToProto encodes LightClientAttackEvidence to protobuf 370 func (l *LightClientAttackEvidence) ToProto() (*tmproto.LightClientAttackEvidence, error) { 371 conflictingBlock, err := l.ConflictingBlock.ToProto() 372 if err != nil { 373 return nil, err 374 } 375 376 byzVals := make([]*tmproto.Validator, len(l.ByzantineValidators)) 377 for idx, val := range l.ByzantineValidators { 378 valpb, err := val.ToProto() 379 if err != nil { 380 return nil, err 381 } 382 byzVals[idx] = valpb 383 } 384 385 return &tmproto.LightClientAttackEvidence{ 386 ConflictingBlock: conflictingBlock, 387 CommonHeight: l.CommonHeight, 388 ByzantineValidators: byzVals, 389 TotalVotingPower: l.TotalVotingPower, 390 Timestamp: l.Timestamp, 391 }, nil 392 } 393 394 // LightClientAttackEvidenceFromProto decodes protobuf 395 func LightClientAttackEvidenceFromProto(lpb *tmproto.LightClientAttackEvidence) (*LightClientAttackEvidence, error) { 396 if lpb == nil { 397 return nil, errors.New("empty light client attack evidence") 398 } 399 400 conflictingBlock, err := LightBlockFromProto(lpb.ConflictingBlock) 401 if err != nil { 402 return nil, err 403 } 404 405 byzVals := make([]*Validator, len(lpb.ByzantineValidators)) 406 for idx, valpb := range lpb.ByzantineValidators { 407 val, err := ValidatorFromProto(valpb) 408 if err != nil { 409 return nil, err 410 } 411 byzVals[idx] = val 412 } 413 414 l := &LightClientAttackEvidence{ 415 ConflictingBlock: conflictingBlock, 416 CommonHeight: lpb.CommonHeight, 417 ByzantineValidators: byzVals, 418 TotalVotingPower: lpb.TotalVotingPower, 419 Timestamp: lpb.Timestamp, 420 } 421 422 return l, l.ValidateBasic() 423 } 424 425 //------------------------------------------------------------------------------------------ 426 427 // EvidenceList is a list of Evidence. Evidences is not a word. 428 type EvidenceList []Evidence 429 430 // Hash returns the simple merkle root hash of the EvidenceList. 431 func (evl EvidenceList) Hash() []byte { 432 // These allocations are required because Evidence is not of type Bytes, and 433 // golang slices can't be typed cast. This shouldn't be a performance problem since 434 // the Evidence size is capped. 435 evidenceBzs := make([][]byte, len(evl)) 436 for i := 0; i < len(evl); i++ { 437 // TODO: We should change this to the hash. Using bytes contains some unexported data that 438 // may cause different hashes 439 evidenceBzs[i] = evl[i].Bytes() 440 } 441 return merkle.HashFromByteSlices(evidenceBzs) 442 } 443 444 func (evl EvidenceList) String() string { 445 s := "" 446 for _, e := range evl { 447 s += fmt.Sprintf("%s\t\t", e) 448 } 449 return s 450 } 451 452 // Has returns true if the evidence is in the EvidenceList. 453 func (evl EvidenceList) Has(evidence Evidence) bool { 454 for _, ev := range evl { 455 if bytes.Equal(evidence.Hash(), ev.Hash()) { 456 return true 457 } 458 } 459 return false 460 } 461 462 //------------------------------------------ PROTO -------------------------------------- 463 464 // EvidenceToProto is a generalized function for encoding evidence that conforms to the 465 // evidence interface to protobuf 466 func EvidenceToProto(evidence Evidence) (*tmproto.Evidence, error) { 467 if evidence == nil { 468 return nil, errors.New("nil evidence") 469 } 470 471 switch evi := evidence.(type) { 472 case *DuplicateVoteEvidence: 473 pbev := evi.ToProto() 474 return &tmproto.Evidence{ 475 Sum: &tmproto.Evidence_DuplicateVoteEvidence{ 476 DuplicateVoteEvidence: pbev, 477 }, 478 }, nil 479 480 case *LightClientAttackEvidence: 481 pbev, err := evi.ToProto() 482 if err != nil { 483 return nil, err 484 } 485 return &tmproto.Evidence{ 486 Sum: &tmproto.Evidence_LightClientAttackEvidence{ 487 LightClientAttackEvidence: pbev, 488 }, 489 }, nil 490 491 default: 492 return nil, fmt.Errorf("toproto: evidence is not recognized: %T", evi) 493 } 494 } 495 496 // EvidenceFromProto is a generalized function for decoding protobuf into the 497 // evidence interface 498 func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) { 499 if evidence == nil { 500 return nil, errors.New("nil evidence") 501 } 502 503 switch evi := evidence.Sum.(type) { 504 case *tmproto.Evidence_DuplicateVoteEvidence: 505 return DuplicateVoteEvidenceFromProto(evi.DuplicateVoteEvidence) 506 case *tmproto.Evidence_LightClientAttackEvidence: 507 return LightClientAttackEvidenceFromProto(evi.LightClientAttackEvidence) 508 default: 509 return nil, errors.New("evidence is not recognized") 510 } 511 } 512 513 func init() { 514 tmjson.RegisterType(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence") 515 tmjson.RegisterType(&LightClientAttackEvidence{}, "tendermint/LightClientAttackEvidence") 516 } 517 518 //-------------------------------------------- ERRORS -------------------------------------- 519 520 // ErrInvalidEvidence wraps a piece of evidence and the error denoting how or why it is invalid. 521 type ErrInvalidEvidence struct { 522 Evidence Evidence 523 Reason error 524 } 525 526 // NewErrInvalidEvidence returns a new EvidenceInvalid with the given err. 527 func NewErrInvalidEvidence(ev Evidence, err error) *ErrInvalidEvidence { 528 return &ErrInvalidEvidence{ev, err} 529 } 530 531 // Error returns a string representation of the error. 532 func (err *ErrInvalidEvidence) Error() string { 533 return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.Reason, err.Evidence) 534 } 535 536 // ErrEvidenceOverflow is for when there the amount of evidence exceeds the max bytes. 537 type ErrEvidenceOverflow struct { 538 Max int64 539 Got int64 540 } 541 542 // NewErrEvidenceOverflow returns a new ErrEvidenceOverflow where got > max. 543 func NewErrEvidenceOverflow(max, got int64) *ErrEvidenceOverflow { 544 return &ErrEvidenceOverflow{max, got} 545 } 546 547 // Error returns a string representation of the error. 548 func (err *ErrEvidenceOverflow) Error() string { 549 return fmt.Sprintf("Too much evidence: Max %d, got %d", err.Max, err.Got) 550 } 551 552 //-------------------------------------------- MOCKING -------------------------------------- 553 554 // unstable - use only for testing 555 556 // assumes the round to be 0 and the validator index to be 0 557 func NewMockDuplicateVoteEvidence(height int64, time time.Time, chainID string) *DuplicateVoteEvidence { 558 val := NewMockPV() 559 return NewMockDuplicateVoteEvidenceWithValidator(height, time, val, chainID) 560 } 561 562 // assumes voting power to be 10 and validator to be the only one in the set 563 func NewMockDuplicateVoteEvidenceWithValidator(height int64, time time.Time, 564 pv PrivValidator, chainID string) *DuplicateVoteEvidence { 565 pubKey, _ := pv.GetPubKey() 566 val := NewValidator(pubKey, 10) 567 voteA := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) 568 vA := voteA.ToProto() 569 _ = pv.SignVote(chainID, vA) 570 voteA.Signature = vA.Signature 571 voteB := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) 572 vB := voteB.ToProto() 573 _ = pv.SignVote(chainID, vB) 574 voteB.Signature = vB.Signature 575 return NewDuplicateVoteEvidence(voteA, voteB, time, NewValidatorSet([]*Validator{val})) 576 } 577 578 func makeMockVote(height int64, round, index int32, addr Address, 579 blockID BlockID, time time.Time) *Vote { 580 return &Vote{ 581 Type: tmproto.SignedMsgType(2), 582 Height: height, 583 Round: round, 584 BlockID: blockID, 585 Timestamp: time, 586 ValidatorAddress: addr, 587 ValidatorIndex: index, 588 } 589 } 590 591 func randBlockID() BlockID { 592 return BlockID{ 593 Hash: tmrand.Bytes(tmhash.Size), 594 PartSetHeader: PartSetHeader{ 595 Total: 1, 596 Hash: tmrand.Bytes(tmhash.Size), 597 }, 598 } 599 }