github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/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/lazyledger/lazyledger-core/abci/types" 13 "github.com/lazyledger/lazyledger-core/crypto/merkle" 14 "github.com/lazyledger/lazyledger-core/crypto/tmhash" 15 tmjson "github.com/lazyledger/lazyledger-core/libs/json" 16 tmrand "github.com/lazyledger/lazyledger-core/libs/rand" 17 tmproto "github.com/lazyledger/lazyledger-core/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 sufficient. 299 func (l *LightClientAttackEvidence) Hash() []byte { 300 buf := make([]byte, binary.MaxVarintLen64) 301 n := binary.PutVarint(buf, l.CommonHeight) 302 bz := make([]byte, tmhash.Size+n) 303 copy(bz[:tmhash.Size-1], l.ConflictingBlock.Hash().Bytes()) 304 copy(bz[tmhash.Size:], buf) 305 return tmhash.Sum(bz) 306 } 307 308 // Height returns the last height at which the primary provider and witness provider had the same header. 309 // We use this as the height of the infraction rather than the actual conflicting header because we know 310 // that the malicious validators were bonded at this height which is important for evidence expiry 311 func (l *LightClientAttackEvidence) Height() int64 { 312 return l.CommonHeight 313 } 314 315 // String returns a string representation of LightClientAttackEvidence 316 func (l *LightClientAttackEvidence) String() string { 317 return fmt.Sprintf("LightClientAttackEvidence{ConflictingBlock: %v, CommonHeight: %d}", 318 l.ConflictingBlock.String(), l.CommonHeight) 319 } 320 321 // Time returns the time of the common block where the infraction leveraged off. 322 func (l *LightClientAttackEvidence) Time() time.Time { 323 return l.Timestamp 324 } 325 326 // ValidateBasic performs basic validation such that the evidence is consistent and can now be used for verification. 327 func (l *LightClientAttackEvidence) ValidateBasic() error { 328 if l.ConflictingBlock == nil { 329 return errors.New("conflicting block is nil") 330 } 331 332 // this check needs to be done before we can run validate basic 333 if l.ConflictingBlock.Header == nil { 334 return errors.New("conflicting block missing header") 335 } 336 337 if err := l.ConflictingBlock.ValidateBasic(l.ConflictingBlock.ChainID); err != nil { 338 return fmt.Errorf("invalid conflicting light block: %w", err) 339 } 340 341 if l.CommonHeight <= 0 { 342 return errors.New("negative or zero common height") 343 } 344 345 // check that common height isn't ahead of the height of the conflicting block. It 346 // is possible that they are the same height if the light node witnesses either an 347 // amnesia or a equivocation attack. 348 if l.CommonHeight > l.ConflictingBlock.Height { 349 return fmt.Errorf("common height is ahead of the conflicting block height (%d > %d)", 350 l.CommonHeight, l.ConflictingBlock.Height) 351 } 352 353 return nil 354 } 355 356 // ToProto encodes LightClientAttackEvidence to protobuf 357 func (l *LightClientAttackEvidence) ToProto() (*tmproto.LightClientAttackEvidence, error) { 358 conflictingBlock, err := l.ConflictingBlock.ToProto() 359 if err != nil { 360 return nil, err 361 } 362 363 byzVals := make([]*tmproto.Validator, len(l.ByzantineValidators)) 364 for idx, val := range l.ByzantineValidators { 365 valpb, err := val.ToProto() 366 if err != nil { 367 return nil, err 368 } 369 byzVals[idx] = valpb 370 } 371 372 return &tmproto.LightClientAttackEvidence{ 373 ConflictingBlock: conflictingBlock, 374 CommonHeight: l.CommonHeight, 375 ByzantineValidators: byzVals, 376 TotalVotingPower: l.TotalVotingPower, 377 Timestamp: l.Timestamp, 378 }, nil 379 } 380 381 // LightClientAttackEvidenceFromProto decodes protobuf 382 func LightClientAttackEvidenceFromProto(lpb *tmproto.LightClientAttackEvidence) (*LightClientAttackEvidence, error) { 383 if lpb == nil { 384 return nil, errors.New("empty light client attack evidence") 385 } 386 387 conflictingBlock, err := LightBlockFromProto(lpb.ConflictingBlock) 388 if err != nil { 389 return nil, err 390 } 391 392 byzVals := make([]*Validator, len(lpb.ByzantineValidators)) 393 for idx, valpb := range lpb.ByzantineValidators { 394 val, err := ValidatorFromProto(valpb) 395 if err != nil { 396 return nil, err 397 } 398 byzVals[idx] = val 399 } 400 401 l := &LightClientAttackEvidence{ 402 ConflictingBlock: conflictingBlock, 403 CommonHeight: lpb.CommonHeight, 404 ByzantineValidators: byzVals, 405 TotalVotingPower: lpb.TotalVotingPower, 406 Timestamp: lpb.Timestamp, 407 } 408 409 return l, l.ValidateBasic() 410 } 411 412 //------------------------------------------------------------------------------------------ 413 414 // EvidenceList is a list of Evidence. Evidences is not a word. 415 type EvidenceList []Evidence 416 417 // Hash returns the simple merkle root hash of the EvidenceList. 418 func (evl EvidenceList) Hash() []byte { 419 // These allocations are required because Evidence is not of type Bytes, and 420 // golang slices can't be typed cast. This shouldn't be a performance problem since 421 // the Evidence size is capped. 422 evidenceBzs := make([][]byte, len(evl)) 423 for i := 0; i < len(evl); i++ { 424 evidenceBzs[i] = evl[i].Bytes() 425 } 426 return merkle.HashFromByteSlices(evidenceBzs) 427 } 428 429 func (evl EvidenceList) String() string { 430 s := "" 431 for _, e := range evl { 432 s += fmt.Sprintf("%s\t\t", e) 433 } 434 return s 435 } 436 437 // Has returns true if the evidence is in the EvidenceList. 438 func (evl EvidenceList) Has(evidence Evidence) bool { 439 for _, ev := range evl { 440 if bytes.Equal(evidence.Hash(), ev.Hash()) { 441 return true 442 } 443 } 444 return false 445 } 446 447 //------------------------------------------ PROTO -------------------------------------- 448 449 // EvidenceToProto is a generalized function for encoding evidence that conforms to the 450 // evidence interface to protobuf 451 func EvidenceToProto(evidence Evidence) (*tmproto.Evidence, error) { 452 if evidence == nil { 453 return nil, errors.New("nil evidence") 454 } 455 456 switch evi := evidence.(type) { 457 case *DuplicateVoteEvidence: 458 pbev := evi.ToProto() 459 return &tmproto.Evidence{ 460 Sum: &tmproto.Evidence_DuplicateVoteEvidence{ 461 DuplicateVoteEvidence: pbev, 462 }, 463 }, nil 464 465 case *LightClientAttackEvidence: 466 pbev, err := evi.ToProto() 467 if err != nil { 468 return nil, err 469 } 470 return &tmproto.Evidence{ 471 Sum: &tmproto.Evidence_LightClientAttackEvidence{ 472 LightClientAttackEvidence: pbev, 473 }, 474 }, nil 475 476 default: 477 return nil, fmt.Errorf("toproto: evidence is not recognized: %T", evi) 478 } 479 } 480 481 // EvidenceFromProto is a generalized function for decoding protobuf into the 482 // evidence interface 483 func EvidenceFromProto(evidence *tmproto.Evidence) (Evidence, error) { 484 if evidence == nil { 485 return nil, errors.New("nil evidence") 486 } 487 488 switch evi := evidence.Sum.(type) { 489 case *tmproto.Evidence_DuplicateVoteEvidence: 490 return DuplicateVoteEvidenceFromProto(evi.DuplicateVoteEvidence) 491 case *tmproto.Evidence_LightClientAttackEvidence: 492 return LightClientAttackEvidenceFromProto(evi.LightClientAttackEvidence) 493 default: 494 return nil, errors.New("evidence is not recognized") 495 } 496 } 497 498 func init() { 499 tmjson.RegisterType(&DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence") 500 tmjson.RegisterType(&LightClientAttackEvidence{}, "tendermint/LightClientAttackEvidence") 501 } 502 503 //-------------------------------------------- ERRORS -------------------------------------- 504 505 // ErrInvalidEvidence wraps a piece of evidence and the error denoting how or why it is invalid. 506 type ErrInvalidEvidence struct { 507 Evidence Evidence 508 Reason error 509 } 510 511 // NewErrInvalidEvidence returns a new EvidenceInvalid with the given err. 512 func NewErrInvalidEvidence(ev Evidence, err error) *ErrInvalidEvidence { 513 return &ErrInvalidEvidence{ev, err} 514 } 515 516 // Error returns a string representation of the error. 517 func (err *ErrInvalidEvidence) Error() string { 518 return fmt.Sprintf("Invalid evidence: %v. Evidence: %v", err.Reason, err.Evidence) 519 } 520 521 // ErrEvidenceOverflow is for when there the amount of evidence exceeds the max bytes. 522 type ErrEvidenceOverflow struct { 523 Max int64 524 Got int64 525 } 526 527 // NewErrEvidenceOverflow returns a new ErrEvidenceOverflow where got > max. 528 func NewErrEvidenceOverflow(max, got int64) *ErrEvidenceOverflow { 529 return &ErrEvidenceOverflow{max, got} 530 } 531 532 // Error returns a string representation of the error. 533 func (err *ErrEvidenceOverflow) Error() string { 534 return fmt.Sprintf("Too much evidence: Max %d, got %d", err.Max, err.Got) 535 } 536 537 //-------------------------------------------- MOCKING -------------------------------------- 538 539 // unstable - use only for testing 540 541 // assumes the round to be 0 and the validator index to be 0 542 func NewMockDuplicateVoteEvidence(height int64, time time.Time, chainID string) *DuplicateVoteEvidence { 543 val := NewMockPV() 544 return NewMockDuplicateVoteEvidenceWithValidator(height, time, val, chainID) 545 } 546 547 // assumes voting power to be 10 and validator to be the only one in the set 548 func NewMockDuplicateVoteEvidenceWithValidator(height int64, time time.Time, 549 pv PrivValidator, chainID string) *DuplicateVoteEvidence { 550 pubKey, _ := pv.GetPubKey() 551 val := NewValidator(pubKey, 10) 552 voteA := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) 553 vA := voteA.ToProto() 554 _ = pv.SignVote(chainID, vA) 555 voteA.Signature = vA.Signature 556 voteB := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) 557 vB := voteB.ToProto() 558 _ = pv.SignVote(chainID, vB) 559 voteB.Signature = vB.Signature 560 return NewDuplicateVoteEvidence(voteA, voteB, time, NewValidatorSet([]*Validator{val})) 561 } 562 563 func makeMockVote(height int64, round, index int32, addr Address, 564 blockID BlockID, time time.Time) *Vote { 565 return &Vote{ 566 Type: tmproto.SignedMsgType(2), 567 Height: height, 568 Round: round, 569 BlockID: blockID, 570 Timestamp: time, 571 ValidatorAddress: addr, 572 ValidatorIndex: index, 573 } 574 } 575 576 func randBlockID() BlockID { 577 return BlockID{ 578 Hash: tmrand.Bytes(tmhash.Size), 579 PartSetHeader: PartSetHeader{ 580 Total: 1, 581 Hash: tmrand.Bytes(tmhash.Size), 582 }, 583 } 584 }