Add Eth2FastAggregateVerify (#9144)

* Add `Eth2FastAggregateVerify`

* Update propose_test.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
terence tsao 2021-07-02 12:27:08 -07:00 committed by GitHub
parent 00907fd7d1
commit 2ae6452cb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 0 deletions

View File

@ -4,6 +4,7 @@
package blst
import (
"bytes"
"fmt"
"sync"
@ -125,6 +126,33 @@ func (s *Signature) FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte
return s.s.FastAggregateVerify(true, rawKeys, msg[:], dst)
}
// Eth2FastAggregateVerify implements a wrapper on top of bls's FastAggregateVerify. It accepts G2_POINT_AT_INFINITY signature
// when pubkeys empty.
//
// Spec code:
// def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, signature: BLSSignature) -> bool:
// """
// Wrapper to ``bls.FastAggregateVerify`` accepting the ``G2_POINT_AT_INFINITY`` signature when ``pubkeys`` is empty.
// """
// if len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY:
// return True
// return bls.FastAggregateVerify(pubkeys, message, signature)
func (s *Signature) Eth2FastAggregateVerify(pubKeys []common.PublicKey, msg [32]byte) bool {
if featureconfig.Get().SkipBLSVerify {
return true
}
g2PointAtInfinity := append([]byte{0xC0}, make([]byte, 95)...)
if len(pubKeys) == 0 && bytes.Equal(s.Marshal(), g2PointAtInfinity) {
return true
}
rawKeys := make([]*blstPublicKey, len(pubKeys))
for i := 0; i < len(pubKeys); i++ {
rawKeys[i] = pubKeys[i].(*PublicKey).p
}
return s.s.FastAggregateVerify(true, rawKeys, msg[:], dst)
}
// NewAggregateSignature creates a blank aggregate signature.
func NewAggregateSignature() common.Signature {
sig := blst.HashToG2([]byte{'m', 'o', 'c', 'k'}, dst).ToAffine()

View File

@ -94,6 +94,41 @@ func TestFastAggregateVerify_ReturnsFalseOnEmptyPubKeyList(t *testing.T) {
assert.Equal(t, false, aggSig.FastAggregateVerify(pubkeys, msg), "Expected FastAggregateVerify to return false with empty input ")
}
func TestEth2FastAggregateVerify(t *testing.T) {
pubkeys := make([]common.PublicKey, 0, 100)
sigs := make([]common.Signature, 0, 100)
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
for i := 0; i < 100; i++ {
priv, err := RandKey()
require.NoError(t, err)
pub := priv.PublicKey()
sig := priv.Sign(msg[:])
pubkeys = append(pubkeys, pub)
sigs = append(sigs, sig)
}
aggSig := AggregateSignatures(sigs)
assert.Equal(t, true, aggSig.Eth2FastAggregateVerify(pubkeys, msg), "Signature did not verify")
}
func TestEth2FastAggregateVerify_ReturnsFalseOnEmptyPubKeyList(t *testing.T) {
var pubkeys []common.PublicKey
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
aggSig := NewAggregateSignature()
assert.Equal(t, false, aggSig.Eth2FastAggregateVerify(pubkeys, msg), "Expected Eth2FastAggregateVerify to return false with empty input ")
}
func TestEth2FastAggregateVerify_ReturnsTrueOnG2PointAtInfinity(t *testing.T) {
var pubkeys []common.PublicKey
msg := [32]byte{'h', 'e', 'l', 'l', 'o'}
g2PointAtInfinity := append([]byte{0xC0}, make([]byte, 95)...)
aggSig, err := SignatureFromBytes(g2PointAtInfinity)
require.NoError(t, err)
assert.Equal(t, true, aggSig.Eth2FastAggregateVerify(pubkeys, msg))
}
func TestSignatureFromBytes(t *testing.T) {
tests := []struct {
name string

View File

@ -73,6 +73,11 @@ func (s Signature) FastAggregateVerify(_ []common.PublicKey, _ [32]byte) bool {
panic(err)
}
// Eth2FastAggregateVerify -- stub
func (s Signature) Eth2FastAggregateVerify(_ []common.PublicKey, _ [32]byte) bool {
panic(err)
}
// Marshal -- stub
func (s Signature) Marshal() []byte {
panic(err)

View File

@ -26,6 +26,7 @@ type Signature interface {
// Deprecated: Use FastAggregateVerify or use this method in spectests only.
AggregateVerify(pubKeys []PublicKey, msgs [][32]byte) bool
FastAggregateVerify(pubKeys []PublicKey, msg [32]byte) bool
Eth2FastAggregateVerify(pubKeys []PublicKey, msg [32]byte) bool
Marshal() []byte
Copy() Signature
}

View File

@ -44,6 +44,9 @@ func (mockSignature) AggregateVerify([]bls.PublicKey, [][32]byte) bool {
func (mockSignature) FastAggregateVerify([]bls.PublicKey, [32]byte) bool {
return true
}
func (mockSignature) Eth2FastAggregateVerify([]bls.PublicKey, [32]byte) bool {
return true
}
func (mockSignature) Marshal() []byte {
return make([]byte, 32)
}