refactor: switch to filecoin-ffi bls api for bls signatures

This commit is contained in:
dignifiedquire 2021-01-19 17:45:39 +01:00
parent 187a499cca
commit 3d9eb226fa
5 changed files with 57 additions and 36 deletions

View File

@ -13,6 +13,8 @@ import (
"github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/lib/sigs/bls" "github.com/filecoin-project/lotus/lib/sigs/bls"
ffi "github.com/filecoin-project/filecoin-ffi"
) )
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletAPI, bt *api.BlockTemplate) (*types.FullBlock, error) { func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletAPI, bt *api.BlockTemplate) (*types.FullBlock, error) {
@ -140,13 +142,13 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w api.WalletA
} }
func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) { func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) {
sigsS := make([][]byte, len(sigs)) sigsS := make([]ffi.Signature, len(sigs))
for i := 0; i < len(sigs); i++ { for i := 0; i < len(sigs); i++ {
sigsS[i] = sigs[i].Data copy(sigsS[i][:], sigs[i].Data[:ffi.SignatureBytes])
} }
aggregator := new(bls.AggregateSignature).AggregateCompressed(sigsS) aggSig := ffi.Aggregate(sigsS)
if aggregator == nil { if aggSig == nil {
if len(sigs) > 0 { if len(sigs) > 0 {
return nil, xerrors.Errorf("bls.Aggregate returned nil with %d signatures", len(sigs)) return nil, xerrors.Errorf("bls.Aggregate returned nil with %d signatures", len(sigs))
} }
@ -155,20 +157,12 @@ func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) {
// be returned // be returned
return &crypto.Signature{ return &crypto.Signature{
Type: crypto.SigTypeBLS, Type: crypto.SigTypeBLS,
Data: new(bls.Signature).Compress(), Data: ([]byte)(new(bls.Signature)[:]), // TODO: verify this is okay
}, nil }, nil
} }
aggSigAff := aggregator.ToAffine()
if aggSigAff == nil {
return &crypto.Signature{ return &crypto.Signature{
Type: crypto.SigTypeBLS, Type: crypto.SigTypeBLS,
Data: new(bls.Signature).Compress(), Data: ([]byte)(aggSig[:]),
}, nil
}
aggSig := aggSigAff.Compress()
return &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: aggSig,
}, nil }, nil
} }

View File

@ -34,7 +34,8 @@ import (
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
blst "github.com/supranational/blst/bindings/go"
ffi "github.com/filecoin-project/filecoin-ffi"
// named msgarray here to make it clear that these are the types used by // named msgarray here to make it clear that these are the types used by
// messages, regardless of specs-actors version. // messages, regardless of specs-actors version.
@ -55,7 +56,6 @@ import (
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
bstore "github.com/filecoin-project/lotus/lib/blockstore" bstore "github.com/filecoin-project/lotus/lib/blockstore"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/lib/sigs/bls"
"github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/metrics"
) )
@ -1178,17 +1178,21 @@ func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signat
trace.Int64Attribute("msgCount", int64(len(msgs))), trace.Int64Attribute("msgCount", int64(len(msgs))),
) )
msgsS := make([]blst.Message, len(msgs)) msgsS := make([]ffi.Message, len(msgs))
pubksS := make([]ffi.PublicKey, len(msgs))
for i := 0; i < len(msgs); i++ { for i := 0; i < len(msgs); i++ {
msgsS[i] = msgs[i].Bytes() msgsS[i] = msgs[i].Bytes()
copy(pubksS[i][:], pubks[i][:ffi.PublicKeyBytes])
} }
sigS := new(ffi.Signature)
copy(sigS[:], sig.Data[:ffi.SignatureBytes])
if len(msgs) == 0 { if len(msgs) == 0 {
return nil return nil
} }
valid := new(bls.Signature).AggregateVerifyCompressed(sig.Data, pubks, valid := ffi.HashVerify(sigS, msgsS, pubksS)
msgsS, []byte(bls.DST))
if !valid { if !valid {
return xerrors.New("bls aggregate signature failed to verify") return xerrors.New("bls aggregate signature failed to verify")
} }

2
extern/filecoin-ffi vendored

@ -1 +1 @@
Subproject commit 1d9cb3e8ff53f51f9318fc57e5d00bc79bdc0128 Subproject commit 2b1bca4ede20d9f7616aed0481fb2cc5aa8637d4

2
go.mod
View File

@ -126,7 +126,6 @@ require (
github.com/raulk/clock v1.1.0 github.com/raulk/clock v1.1.0
github.com/raulk/go-watchdog v0.0.1 github.com/raulk/go-watchdog v0.0.1
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.6.1
github.com/supranational/blst v0.1.1
github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb v1.0.0
github.com/urfave/cli/v2 v2.2.0 github.com/urfave/cli/v2 v2.2.0
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
@ -158,4 +157,3 @@ replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi
replace github.com/filecoin-project/test-vectors => ./extern/test-vectors replace github.com/filecoin-project/test-vectors => ./extern/test-vectors
replace github.com/supranational/blst => ./extern/blst

View File

@ -7,17 +7,17 @@ import (
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/crypto"
blst "github.com/supranational/blst/bindings/go" ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
) )
const DST = string("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_") const DST = string("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_")
type SecretKey = blst.SecretKey type SecretKey = ffi.PrivateKey
type PublicKey = blst.P1Affine type PublicKey = ffi.PublicKey
type Signature = blst.P2Affine type Signature = ffi.Signature
type AggregateSignature = blst.P2Aggregate type AggregateSignature = ffi.Signature
type blsSigner struct{} type blsSigner struct{}
@ -29,30 +29,55 @@ func (blsSigner) GenPrivate() ([]byte, error) {
return nil, fmt.Errorf("bls signature error generating random data") return nil, fmt.Errorf("bls signature error generating random data")
} }
// Note private keys seem to be serialized little-endian! // Note private keys seem to be serialized little-endian!
pk := blst.KeyGen(ikm[:]).ToLEndian() sk := ffi.PrivateKeyGenerateWithSeed(ikm)
return pk, nil return ([]byte)(sk[:]), nil
} }
func (blsSigner) ToPublic(priv []byte) ([]byte, error) { func (blsSigner) ToPublic(priv []byte) ([]byte, error) {
pk := new(SecretKey).FromLEndian(priv) if priv == nil || len(priv) != ffi.PrivateKeyBytes {
if pk == nil || !pk.Valid() {
return nil, fmt.Errorf("bls signature invalid private key") return nil, fmt.Errorf("bls signature invalid private key")
} }
return new(PublicKey).From(pk).Compress(), nil
sk := new(SecretKey)
copy(sk[:], priv[:ffi.PrivateKeyBytes])
pubkey := ffi.PrivateKeyPublicKey(*sk)
return ([]byte)(pubkey[:]), nil
} }
func (blsSigner) Sign(p []byte, msg []byte) ([]byte, error) { func (blsSigner) Sign(p []byte, msg []byte) ([]byte, error) {
pk := new(SecretKey).FromLEndian(p) if p == nil || len(p) != ffi.PrivateKeyBytes {
if pk == nil || !pk.Valid() {
return nil, fmt.Errorf("bls signature invalid private key") return nil, fmt.Errorf("bls signature invalid private key")
} }
return new(Signature).Sign(pk, msg, []byte(DST)).Compress(), nil
sk := new(SecretKey)
copy(sk[:], p[:ffi.PrivateKeyBytes])
sig := ffi.PrivateKeySign(*sk, msg)
return ([]byte)(sig[:]), nil
} }
func (blsSigner) Verify(sig []byte, a address.Address, msg []byte) error { func (blsSigner) Verify(sig []byte, a address.Address, msg []byte) error {
if !new(Signature).VerifyCompressed(sig, a.Payload()[:], msg, []byte(DST)) { payload := a.Payload()
if sig == nil || len(sig) != ffi.SignatureBytes || len(payload) != ffi.PublicKeyBytes {
return fmt.Errorf("bls signature failed to verify") return fmt.Errorf("bls signature failed to verify")
} }
pk := new(PublicKey)
copy(pk[:], payload[:ffi.PublicKeyBytes])
sigS := new(Signature)
copy(sigS[:], sig[:ffi.SignatureBytes])
msgs := [1]ffi.Message{msg}
pks := [1]PublicKey{*pk}
if !ffi.HashVerify(sigS, msgs[:], pks[:]) {
return fmt.Errorf("bls signature failed to verify")
}
return nil return nil
} }