Skip to content

Commit

Permalink
Merge pull request #117 from line/feature/bls_aggregation_and_verific…
Browse files Browse the repository at this point in the history
…ation

BLS Signature Aggregation and Verification
  • Loading branch information
torao authored Dec 3, 2020
2 parents 0e64010 + f902ba5 commit 112f943
Show file tree
Hide file tree
Showing 21 changed files with 889 additions and 149 deletions.
1 change: 1 addition & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

- Blockchain Protocol
- [consensus] [\#101](https:/line/tendermint/pull/101) Introduce composite key to delegate features to each function key
- [consensus] [\#117](https:/line/tendermint/pull/117) BLS Signature Aggregation and Verification

### FEATURES:
- [init command] [\#125](https:/line/tendermint/pull/125) Add an option selecting private key type to init, testnet commands
Expand Down
4 changes: 2 additions & 2 deletions blockchain/v1/reactor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@ func TestFastSyncNoBlockResponse(t *testing.T) {
for _, tt := range tests {
block := reactorPairs[1].bcR.store.LoadBlock(tt.height)
if tt.existent {
assert.True(t, block != nil)
assert.True(t, block != nil, "height=%d, existent=%t", tt.height, tt.existent)
} else {
assert.True(t, block == nil)
assert.True(t, block == nil, "height=%d, existent=%t", tt.height, tt.existent)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/pkg/errors"

"github.com/tendermint/tendermint/privval"
)

Expand Down
1 change: 1 addition & 0 deletions consensus/byzantine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/stretchr/testify/require"

config2 "github.com/tendermint/tendermint/config"

"github.com/tendermint/tendermint/libs/service"
Expand Down
4 changes: 3 additions & 1 deletion consensus/invalid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ func invalidDoPrevoteFunc(t *testing.T, height int64, round int, cs *State, sw *
Hash: blockHash,
PartsHeader: types.PartSetHeader{Total: 1, Hash: tmrand.Bytes(32)}},
}
cs.privValidator.SignVote(cs.state.ChainID, precommit)
if err = cs.privValidator.SignVote(cs.state.ChainID, precommit); err != nil {
panic(err)
}
cs.privValidator = nil // disable priv val so we don't do normal votes
cs.mtx.Unlock()

Expand Down
6 changes: 4 additions & 2 deletions consensus/reactor.go
Original file line number Diff line number Diff line change
Expand Up @@ -652,9 +652,11 @@ OUTER_LOOP:
// Catchup logic
// If peer is lagging by more than 1, send Commit.
if prs.Height != 0 && rs.Height >= prs.Height+2 {
// Load the block commit for prs.Height,
// Load the seen commit for prs.Height,
// which contains precommit signatures for prs.Height.
commit := conR.conS.blockStore.LoadBlockCommit(prs.Height)
// Originally the block commit was used, but with the addition of the BLS signature-aggregation,
// we use seen commit instead of the block commit because block commit has no individual signature.
commit := conR.conS.blockStore.LoadSeenCommit(prs.Height)
if ps.PickSendVote(commit) {
logger.Debug("Picked Catchup commit to send", "height", prs.Height)
continue OUTER_LOOP
Expand Down
2 changes: 2 additions & 0 deletions consensus/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/pkg/errors"

"github.com/tendermint/tendermint/libs/fail"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
Expand Down Expand Up @@ -1086,6 +1087,7 @@ func (cs *State) createProposalBlock(round int) (block *types.Block, blockParts
case cs.LastCommit.HasTwoThirdsMajority():
// Make the commit from LastCommit
commit = cs.LastCommit.MakeCommit()
commit.AggregateSignatures()
default: // This shouldn't happen.
cs.Logger.Error("enterPropose: Cannot propose anything: No commit for the previous block")
return
Expand Down
72 changes: 70 additions & 2 deletions crypto/bls/bls.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bls

import (
"bytes"
"crypto/sha512"
"crypto/subtle"
"fmt"

Expand Down Expand Up @@ -46,6 +47,71 @@ func init() {
// PrivKeyBLS12 implements crypto.PrivKey.
type PrivKeyBLS12 [PrivKeyBLS12Size]byte

// AddSignature adds a BLS signature to the init. When the init is nil, then a new aggregate signature is built
// from specified signature.
func AddSignature(init []byte, signature []byte) (aggrSign []byte, err error) {
if init == nil {
blsSign := bls.Sign{}
init = blsSign.Serialize()
} else if len(init) != SignatureSize {
err = fmt.Errorf("invalid BLS signature: aggregated signature size %d is not valid size %d",
len(init), SignatureSize)
return
}
if len(signature) != SignatureSize {
err = fmt.Errorf("invalid BLS signature: signature size %d is not valid size %d",
len(signature), SignatureSize)
return
}
blsSign := bls.Sign{}
err = blsSign.Deserialize(signature)
if err != nil {
return
}
aggrBLSSign := bls.Sign{}
err = aggrBLSSign.Deserialize(init)
if err != nil {
return
}
aggrBLSSign.Add(&blsSign)
aggrSign = aggrBLSSign.Serialize()
return
}

func VerifyAggregatedSignature(aggregatedSignature []byte, pubKeys []PubKeyBLS12, msgs [][]byte) error {
if len(pubKeys) != len(msgs) {
return fmt.Errorf("the number of public keys %d doesn't match the one of messages %d",
len(pubKeys), len(msgs))
}
if aggregatedSignature == nil {
if len(pubKeys) == 0 {
return nil
}
return fmt.Errorf(
"the aggregate signature was omitted, even though %d public keys were specified", len(pubKeys))
}
aggrSign := bls.Sign{}
err := aggrSign.Deserialize(aggregatedSignature)
if err != nil {
return err
}
blsPubKeys := make([]bls.PublicKey, len(pubKeys))
hashes := make([][]byte, len(msgs))
for i := 0; i < len(pubKeys); i++ {
blsPubKeys[i] = bls.PublicKey{}
err = blsPubKeys[i].Deserialize(pubKeys[i][:])
if err != nil {
return err
}
hash := sha512.Sum512_256(msgs[i])
hashes[i] = hash[:]
}
if !aggrSign.VerifyAggregateHashes(blsPubKeys, hashes) {
return fmt.Errorf("failed to verify the aggregated hashes by %d public keys", len(blsPubKeys))
}
return nil
}

// GenPrivKey generates a new BLS12-381 private key.
func GenPrivKey() PrivKeyBLS12 {
sigKey := bls.SecretKey{}
Expand Down Expand Up @@ -74,7 +140,8 @@ func (privKey PrivKeyBLS12) Sign(msg []byte) ([]byte, error) {
if err != nil {
panic(fmt.Sprintf("Failed to copy the private key: %s", err))
}
sign := blsKey.SignByte(msg)
hash := sha512.Sum512_256(msg)
sign := blsKey.SignHash(hash[:])
return sign.Serialize(), nil
}

Expand Down Expand Up @@ -143,7 +210,8 @@ func (pubKey PubKeyBLS12) VerifyBytes(msg []byte, sig []byte) bool {
if err != nil {
return false
}
return blsSign.VerifyByte(&blsPubKey, msg)
hash := sha512.Sum512_256(msg)
return blsSign.VerifyHash(&blsPubKey, hash[:])
}

// VRFVerify is not supported in BLS12.
Expand Down
Loading

0 comments on commit 112f943

Please sign in to comment.