package herumi import ( "fmt" "github.com/dgraph-io/ristretto" bls12 "github.com/herumi/bls-eth-go-binary/bls" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/shared/bls/iface" "github.com/prysmaticlabs/prysm/shared/featureconfig" "github.com/prysmaticlabs/prysm/shared/params" ) var maxKeys = int64(100000) var pubkeyCache, _ = ristretto.NewCache(&ristretto.Config{ NumCounters: maxKeys, MaxCost: 1 << 22, // ~4mb is cache max size BufferItems: 64, }) // PublicKey used in the BLS signature scheme. type PublicKey struct { p *bls12.PublicKey } // PublicKeyFromBytes creates a BLS public key from a BigEndian byte slice. func PublicKeyFromBytes(pubKey []byte) (iface.PublicKey, error) { if featureconfig.Get().SkipBLSVerify { return &PublicKey{}, nil } if len(pubKey) != params.BeaconConfig().BLSPubkeyLength { return nil, fmt.Errorf("public key must be %d bytes", params.BeaconConfig().BLSPubkeyLength) } if cv, ok := pubkeyCache.Get(string(pubKey)); ok { return cv.(*PublicKey).Copy(), nil } p := &bls12.PublicKey{} err := p.Deserialize(pubKey) if err != nil { return nil, errors.Wrap(err, "could not unmarshal bytes into public key") } pubKeyObj := &PublicKey{p: p} pubkeyCache.Set(string(pubKey), pubKeyObj.Copy(), 48) return pubKeyObj, nil } // AggregatePublicKeys aggregates the provided raw public keys into a single key. func AggregatePublicKeys(pubs [][]byte) (iface.PublicKey, error) { if len(pubs) == 0 { return &PublicKey{}, nil } p, err := PublicKeyFromBytes(pubs[0]) if err != nil { return nil, err } for _, k := range pubs[1:] { pubkey, err := PublicKeyFromBytes(k) if err != nil { return nil, err } p.Aggregate(pubkey) } return p, nil } // Marshal a public key into a LittleEndian byte slice. func (p *PublicKey) Marshal() []byte { return p.p.Serialize() } // Copy the public key to a new pointer reference. func (p *PublicKey) Copy() iface.PublicKey { np := *p.p return &PublicKey{p: &np} } // Aggregate two public keys. func (p *PublicKey) Aggregate(p2 iface.PublicKey) iface.PublicKey { if featureconfig.Get().SkipBLSVerify { return p } p.p.Add(p2.(*PublicKey).p) return p }