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