github.com/Team-Kujira/tendermint@v0.34.24-indexer/spec/light-client/verification/verification_003_draft.md (about) 1 # Light Client Verificaiton 2 3 #### **[LCV-FUNC-VERIFYCOMMITLIGHT.1]** 4 5 VerifyCommitLight verifies that 2/3+ of the signatures for a validator set were for 6 a given blockID. The function will finish early and thus may not check all signatures. 7 8 ```go 9 func VerifyCommitLight(chainID string, vals *ValidatorSet, blockID BlockID, 10 height int64, commit *Commit) error { 11 // run a basic validation of the arguments 12 if err := verifyBasicValsAndCommit(vals, commit, height, blockID); err != nil { 13 return err 14 } 15 16 // calculate voting power needed 17 votingPowerNeeded := vals.TotalVotingPower() * 2 / 3 18 19 var ( 20 val *Validator 21 valIdx int32 22 seenVals = make(map[int32]int, len(commit.Signatures)) 23 talliedVotingPower int64 = 0 24 voteSignBytes []byte 25 ) 26 for idx, commitSig := range commit.Signatures { 27 // ignore all commit signatures that are not for the block 28 if !commitSig.ForBlock() { 29 continue 30 } 31 32 // If the vals and commit have a 1-to-1 correspondance we can retrieve 33 // them by index else we need to retrieve them by address 34 if lookUpByIndex { 35 val = vals.Validators[idx] 36 } else { 37 valIdx, val = vals.GetByAddress(commitSig.ValidatorAddress) 38 39 // if the signature doesn't belong to anyone in the validator set 40 // then we just skip over it 41 if val == nil { 42 continue 43 } 44 45 // because we are getting validators by address we need to make sure 46 // that the same validator doesn't commit twice 47 if firstIndex, ok := seenVals[valIdx]; ok { 48 secondIndex := idx 49 return fmt.Errorf("double vote from %v (%d and %d)", val, firstIndex, secondIndex) 50 } 51 seenVals[valIdx] = idx 52 } 53 54 voteSignBytes = commit.VoteSignBytes(chainID, int32(idx)) 55 56 if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { 57 return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) 58 } 59 60 // Add the voting power of the validator 61 // to the tally 62 talliedVotingPower += val.VotingPower 63 64 // check if we have enough signatures and can thus exit early 65 if talliedVotingPower > votingPowerNeeded { 66 return nil 67 } 68 } 69 70 if got, needed := talliedVotingPower, votingPowerNeeded; got <= needed { 71 return ErrNotEnoughVotingPowerSigned{Got: got, Needed: needed} 72 } 73 74 return nil 75 } 76 ```