From 0f3105a01fda2dc5870434885300f6ab5b8222f6 Mon Sep 17 00:00:00 2001 From: Simon Peffers Date: Sat, 25 Jul 2020 21:38:18 -0400 Subject: [PATCH] Integrate blst signature library: https://github.com/supranational/blst --- chain/gen/mining.go | 21 +++++++++---------- chain/stmgr/stmgr.go | 6 ++---- chain/sync.go | 25 +++++++++++++--------- go.mod | 1 + go.sum | 4 ++++ lib/sigs/bls/init.go | 50 +++++++++++++++++++++++++------------------- 6 files changed, 60 insertions(+), 47 deletions(-) diff --git a/chain/gen/mining.go b/chain/gen/mining.go index bc809a888..1fc27ec5c 100644 --- a/chain/gen/mining.go +++ b/chain/gen/mining.go @@ -3,7 +3,6 @@ package gen import ( "context" - bls "github.com/filecoin-project/filecoin-ffi" amt "github.com/filecoin-project/go-amt-ipld/v2" "github.com/filecoin-project/specs-actors/actors/crypto" cid "github.com/ipfs/go-cid" @@ -17,6 +16,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/wallet" + "github.com/filecoin-project/lotus/lib/sigs/bls" ) func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) { @@ -142,28 +142,27 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal } func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) { - var blsSigs []bls.Signature - for _, s := range sigs { - var bsig bls.Signature - copy(bsig[:], s.Data) - blsSigs = append(blsSigs, bsig) + sigsS := make([][]byte, len(sigs)) + for i := 0; i < len(sigs); i++ { + sigsS[i] = sigs[i].Data } - aggSig := bls.Aggregate(blsSigs) - if aggSig == nil { + aggregator := new(bls.AggregateSignature).AggregateCompressed(sigsS) + if aggregator == nil { if len(sigs) > 0 { return nil, xerrors.Errorf("bls.Aggregate returned nil with %d signatures", len(sigs)) } + // Note: for blst this condition should not happen - nil should not be returned return &crypto.Signature{ Type: crypto.SigTypeBLS, - Data: new(bls.Signature)[:], + Data: new(bls.Signature).Compress(), }, nil } - + aggSig := aggregator.ToAffine().Compress() return &crypto.Signature{ Type: crypto.SigTypeBLS, - Data: aggSig[:], + Data: aggSig, }, nil } diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 917b5ca26..6ee6a6051 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -23,7 +23,6 @@ import ( cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - bls "github.com/filecoin-project/filecoin-ffi" "github.com/ipfs/go-cid" hamt "github.com/ipfs/go-hamt-ipld" blockstore "github.com/ipfs/go-ipfs-blockstore" @@ -433,7 +432,7 @@ func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Ad return vm.ResolveToKeyAddr(tree, cst, addr) } -func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Address, ts *types.TipSet) (pubk bls.PublicKey, err error) { +func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Address, ts *types.TipSet) (pubk []byte, err error) { kaddr, err := sm.ResolveToKeyAddress(ctx, addr, ts) if err != nil { return pubk, xerrors.Errorf("failed to resolve address to key address: %w", err) @@ -443,8 +442,7 @@ func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Addres return pubk, xerrors.Errorf("address must be BLS address to load bls public key") } - copy(pubk[:], kaddr.Payload()) - return pubk, nil + return kaddr.Payload(), nil } func (sm *StateManager) LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { diff --git a/chain/sync.go b/chain/sync.go index 66bb8318c..8459d4b94 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -25,7 +25,7 @@ import ( "go.opencensus.io/trace" "golang.org/x/xerrors" - bls "github.com/filecoin-project/filecoin-ffi" + blst "github.com/supranational/blst/bindings/go" "github.com/filecoin-project/go-address" amt "github.com/filecoin-project/go-amt-ipld/v2" "github.com/filecoin-project/sector-storage/ffiwrapper" @@ -46,6 +46,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/lib/sigs" + "github.com/filecoin-project/lotus/lib/sigs/bls" "github.com/filecoin-project/lotus/metrics" ) @@ -915,7 +916,7 @@ func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.Block func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error { { var sigCids []cid.Cid // this is what we get for people not wanting the marshalcbor method on the cid type - var pubks []bls.PublicKey + var pubks [][]byte for _, m := range b.BlsMessages { sigCids = append(sigCids, m.Cid()) @@ -1036,24 +1037,28 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock return nil } -func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error { +func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signature, msgs []cid.Cid, pubks [][]byte) error { _, span := trace.StartSpan(ctx, "syncer.verifyBlsAggregate") defer span.End() span.AddAttributes( trace.Int64Attribute("msgCount", int64(len(msgs))), ) - bmsgs := make([]bls.Message, len(msgs)) - for i, m := range msgs { - bmsgs[i] = m.Bytes() + msgsS := make([]blst.Message, len(msgs)) + for i := 0; i < len(msgs); i++ { + msgsS[i] = msgs[i].Bytes() } - var bsig bls.Signature - copy(bsig[:], sig.Data) - if !bls.HashVerify(&bsig, bmsgs, pubks) { + // TODO: empty aggregates are considered valid? + if len(msgs) == 0 { + return nil + } + + valid := new(bls.Signature).AggregateVerifyCompressed(sig.Data, pubks, + msgsS, []byte(bls.DST)) + if !valid { return xerrors.New("bls aggregate signature failed to verify") } - return nil } diff --git a/go.mod b/go.mod index 11987ba16..87901d1a2 100644 --- a/go.mod +++ b/go.mod @@ -106,6 +106,7 @@ require ( github.com/opentracing/opentracing-go v1.1.0 github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.6.1 + github.com/supranational/blst v0.1.1 github.com/syndtr/goleveldb v1.0.0 github.com/urfave/cli/v2 v2.2.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba diff --git a/go.sum b/go.sum index cfde3752f..f7b825211 100644 --- a/go.sum +++ b/go.sum @@ -1316,6 +1316,10 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/supranational/blst v0.1.0 h1:2LzeBbOidhTD87UezqGvIffWZAd3FOCfhi2b7IbJCMc= +github.com/supranational/blst v0.1.0/go.mod h1:Z70pOaiBHpXP+JFNOwIyCHKjec/He56CC5UdLaYpuzY= +github.com/supranational/blst v0.1.1 h1:GsK4oq7QZ7yfHI6dCh2NQsUe4imjlFwm5NXF5PWAWoo= +github.com/supranational/blst v0.1.1/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= diff --git a/lib/sigs/bls/init.go b/lib/sigs/bls/init.go index 66a5ade81..9876827a4 100644 --- a/lib/sigs/bls/init.go +++ b/lib/sigs/bls/init.go @@ -1,51 +1,57 @@ package bls import ( + "crypto/rand" "fmt" "github.com/filecoin-project/go-address" "github.com/filecoin-project/specs-actors/actors/crypto" - ffi "github.com/filecoin-project/filecoin-ffi" + blst "github.com/supranational/blst/bindings/go" "github.com/filecoin-project/lotus/lib/sigs" ) +const DST = string("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_") + +type SecretKey = blst.SecretKey +type PublicKey = blst.P1Affine +type Signature = blst.P2Affine +type AggregateSignature = blst.P2Aggregate + type blsSigner struct{} func (blsSigner) GenPrivate() ([]byte, error) { - pk := ffi.PrivateKeyGenerate() - return pk[:], nil + // Generate 32 bytes of randomness + var ikm [32]byte + _, err := rand.Read(ikm[:]) + if err != nil { + return nil, fmt.Errorf("bls signature error generating random data") + } + pk := blst.KeyGen(ikm[:]).Serialize() + return pk, nil } func (blsSigner) ToPublic(priv []byte) ([]byte, error) { - var pk ffi.PrivateKey - copy(pk[:], priv) - pub := ffi.PrivateKeyPublicKey(pk) - return pub[:], nil + pk := new(SecretKey).Deserialize(priv) + if pk == nil { + return nil, fmt.Errorf("bls signature invalid private key") + } + return new(PublicKey).From(pk).Compress(), nil } func (blsSigner) Sign(p []byte, msg []byte) ([]byte, error) { - var pk ffi.PrivateKey - copy(pk[:], p) - sig := ffi.PrivateKeySign(pk, msg) - return sig[:], nil + pk := new(SecretKey).Deserialize(p) + if pk == nil { + return nil, fmt.Errorf("bls signature invalid private key") + } + return new(Signature).Sign(pk, msg, []byte(DST)).Compress(), nil } func (blsSigner) Verify(sig []byte, a address.Address, msg []byte) error { - - var pubk ffi.PublicKey - copy(pubk[:], a.Payload()) - pubkeys := []ffi.PublicKey{pubk} - digests := []ffi.Message{msg} - - var s ffi.Signature - copy(s[:], sig) - - if !ffi.HashVerify(&s, digests, pubkeys) { + if !new(Signature).VerifyCompressed(sig, a.Payload()[:], msg, []byte(DST)) { return fmt.Errorf("bls signature failed to verify") } - return nil }