You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2.3 KiB

Light Client Verificaiton

[LCV-FUNC-VERIFYCOMMITLIGHT.1]

VerifyCommitLight verifies that 2/3+ of the signatures for a validator set were for a given blockID. The function will finish early and thus may not check all signatures.

func VerifyCommitLight(chainID string, vals *ValidatorSet, blockID BlockID,
height int64, commit *Commit) error {
  // run a basic validation of the arguments
  if err := verifyBasicValsAndCommit(vals, commit, height, blockID); err != nil {
    return err
  }

  // calculate voting power needed
  votingPowerNeeded := vals.TotalVotingPower() * 2 / 3

  var (
    val                *Validator
    valIdx             int32
    seenVals                 = make(map[int32]int, len(commit.Signatures))
    talliedVotingPower int64 = 0
    voteSignBytes      []byte
  )
  for idx, commitSig := range commit.Signatures {
    // ignore all commit signatures that are not for the block
    if !commitSig.ForBlock() {
      continue
    }

    // If the vals and commit have a 1-to-1 correspondance we can retrieve
    // them by index else we need to retrieve them by address
    if lookUpByIndex {
      val = vals.Validators[idx]
    } else {
      valIdx, val = vals.GetByAddress(commitSig.ValidatorAddress)  

      // if the signature doesn't belong to anyone in the validator set
      // then we just skip over it
      if val == nil {
        continue
      }

      // because we are getting validators by address we need to make sure
      // that the same validator doesn't commit twice
      if firstIndex, ok := seenVals[valIdx]; ok {
        secondIndex := idx
        return fmt.Errorf("double vote from %v (%d and %d)", val, firstIndex, secondIndex)
      }
      seenVals[valIdx] = idx
    }

    voteSignBytes = commit.VoteSignBytes(chainID, int32(idx))

    if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) {
      return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature)
    }

    // Add the voting power of the validator
    // to the tally
    talliedVotingPower += val.VotingPower

    // check if we have enough signatures and can thus exit early
    if talliedVotingPower > votingPowerNeeded {
      return nil
    }
  }

  if got, needed := talliedVotingPower, votingPowerNeeded; got <= needed {
    return ErrNotEnoughVotingPowerSigned{Got: got, Needed: needed}
  }

  return nil
}