Skip to content

Commit

Permalink
fix: Address to the problem that the signature of bls voter cannot be…
Browse files Browse the repository at this point in the history
… verified (#202)

* fix: Address to the problem that the signature of bls voter cannot be verified

* fix: fix error handling

* fix: fix error handling omission

* fix: Specify the capacity of the slice `blsPubKeys` and `msgs` in advance
  • Loading branch information
Kynea0b authored Mar 31, 2021
1 parent 23a9391 commit b77afff
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 10 deletions.
36 changes: 30 additions & 6 deletions types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -761,17 +761,41 @@ func (commit *Commit) MaxCommitBytes() int64 {
// Panics if signatures from the commit can't be added to the voteset.
// Inverse of VoteSet.MakeCommit().
func CommitToVoteSet(chainID string, commit *Commit, voters *VoterSet) *VoteSet {
if commit.AggregatedSignature != nil {
panic("Aggregated commit cannot make a VoteSet")
}
voteSet := NewVoteSet(chainID, commit.Height, commit.Round, PrecommitType, voters)
blsPubKeys := make([]bls.PubKeyBLS12, 0, len(commit.Signatures))
msgs := make([][]byte, 0, len(commit.Signatures))
for idx, commitSig := range commit.Signatures {
if commitSig.Absent() {
continue // OK, some precommits can be missing.
}
added, err := voteSet.AddVote(commit.GetVote(idx))
if !added || err != nil {
panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))
vote := commit.GetVote(idx)
if vote.Signature != nil {
added, err := voteSet.AddVote(vote)
if !added || err != nil {
panic(fmt.Sprintf("Failed to reconstruct LastCommit from Votes: %v", err))
}
} else {
added, err := voteSet.AddAggregatedVote(vote)
if !added || err != nil {
panic(fmt.Sprintf("Failed to reconstruct LastCommit from AggregatedVotes : %v", err))
}
// Ensure that signer is a validator.
addr, voter := voters.GetByIndex(vote.ValidatorIndex)
if voter == nil || addr == nil {
panic(fmt.Sprintf("Cannot find voter %d in voterSet of size %d", vote.ValidatorIndex, voters.Size()))
}
msg, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeVote(chainID, vote))
if err != nil {
panic(fmt.Sprintf("Failed to MarshalBinaryLengthPrefixed : %v", err))
}
blsPubKeys = append(blsPubKeys, voter.PubKey.(composite.PubKeyComposite).SignKey.(bls.PubKeyBLS12))
msgs = append(msgs, msg)
}
}
if commit.AggregatedSignature != nil {
err := bls.VerifyAggregatedSignature(commit.AggregatedSignature, blsPubKeys, msgs)
if err != nil {
panic(fmt.Sprintf("Failed to VerifyAggregatedSignature : %v", err))
}
}
return voteSet
Expand Down
24 changes: 20 additions & 4 deletions types/vote_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"sync"

"github.com/pkg/errors"

"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/libs/bits"
)

Expand Down Expand Up @@ -148,11 +148,27 @@ func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) {
voteSet.mtx.Lock()
defer voteSet.mtx.Unlock()

return voteSet.addVote(vote)
return voteSet.addVote(vote, vote.Verify)
}

func (voteSet *VoteSet) AddAggregatedVote(vote *Vote) (added bool, err error) {
if voteSet == nil {
panic("AddAggregatedVote() on nil VoteSet")
}
voteSet.mtx.Lock()
defer voteSet.mtx.Unlock()

return voteSet.addVote(vote, func(chainID string, pubKey crypto.PubKey) (err error) {
if !bytes.Equal(pubKey.Address(), vote.ValidatorAddress) {
return ErrVoteInvalidValidatorAddress
}
return nil
})
}

// NOTE: Validates as much as possible before attempting to verify the signature.
func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
func (voteSet *VoteSet) addVote(vote *Vote, execVoteVerify func(chainID string,
pub crypto.PubKey) (err error)) (added bool, err error) {
if vote == nil {
return false, ErrVoteNil
}
Expand Down Expand Up @@ -200,7 +216,7 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) {
}

// Check signature.
if err := vote.Verify(voteSet.chainID, voter.PubKey); err != nil {
if err := execVoteVerify(voteSet.chainID, voter.PubKey); err != nil {
return false, errors.Wrapf(err, "Failed to verify vote with ChainID %s and PubKey %s", voteSet.chainID, voter.PubKey)
}

Expand Down

0 comments on commit b77afff

Please sign in to comment.