Compare commits

...

2 Commits

Author SHA1 Message Date
nisdas
a8572352e1 fix build 2023-05-17 13:34:20 +08:00
nisdas
1848d76796 fix 2023-05-17 13:03:08 +08:00
3 changed files with 64 additions and 31 deletions

View File

@@ -4,16 +4,16 @@ package blst
import ( import (
"fmt" "fmt"
"sync"
"github.com/pkg/errors" "github.com/pkg/errors"
lruwrpr "github.com/prysmaticlabs/prysm/v4/cache/lru"
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
"github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/crypto/bls/common" "github.com/prysmaticlabs/prysm/v4/crypto/bls/common"
) )
var maxKeys = 1_000_000 var pubkeyLock sync.RWMutex
var pubkeyCache = lruwrpr.New(maxKeys) var pubkeyMap = make(map[[48]byte]*PublicKey)
// PublicKey used in the BLS signature scheme. // PublicKey used in the BLS signature scheme.
type PublicKey struct { type PublicKey struct {
@@ -26,9 +26,13 @@ func PublicKeyFromBytes(pubKey []byte) (common.PublicKey, error) {
return nil, fmt.Errorf("public key must be %d bytes", params.BeaconConfig().BLSPubkeyLength) return nil, fmt.Errorf("public key must be %d bytes", params.BeaconConfig().BLSPubkeyLength)
} }
newKey := (*[fieldparams.BLSPubkeyLength]byte)(pubKey) newKey := (*[fieldparams.BLSPubkeyLength]byte)(pubKey)
if cv, ok := pubkeyCache.Get(*newKey); ok { pubkeyLock.RLock()
return cv.(*PublicKey).Copy(), nil if cv, ok := pubkeyMap[*newKey]; ok {
pubkeyLock.RUnlock()
return cv.Copy(), nil
} }
pubkeyLock.RUnlock()
// Subgroup check NOT done when decompressing pubkey. // Subgroup check NOT done when decompressing pubkey.
p := new(blstPublicKey).Uncompress(pubKey) p := new(blstPublicKey).Uncompress(pubKey)
if p == nil { if p == nil {
@@ -41,8 +45,16 @@ func PublicKeyFromBytes(pubKey []byte) (common.PublicKey, error) {
} }
pubKeyObj := &PublicKey{p: p} pubKeyObj := &PublicKey{p: p}
copiedKey := pubKeyObj.Copy() copiedKey := pubKeyObj.Copy()
assertedKey, ok := (copiedKey).(*PublicKey)
// Should be impossible to happen, this is checked
// to satisfy lint tools.
if !ok {
return pubKeyObj, nil
}
cacheKey := *newKey cacheKey := *newKey
pubkeyCache.Add(cacheKey, copiedKey) pubkeyLock.Lock()
pubkeyMap[cacheKey] = assertedKey
pubkeyLock.Unlock()
return pubKeyObj, nil return pubKeyObj, nil
} }

View File

@@ -5,6 +5,7 @@ package blst_test
import ( import (
"bytes" "bytes"
"errors" "errors"
"sync"
"testing" "testing"
"github.com/prysmaticlabs/prysm/v4/crypto/bls/blst" "github.com/prysmaticlabs/prysm/v4/crypto/bls/blst"
@@ -98,26 +99,51 @@ func TestPublicKeysEmpty(t *testing.T) {
require.ErrorContains(t, "nil or empty public keys", err) require.ErrorContains(t, "nil or empty public keys", err)
} }
func TestPublicKeyMap(t *testing.T) {
priv, err := blst.RandKey()
require.NoError(t, err)
pubkeyA := priv.PublicKey().Marshal()
priv2, err := blst.RandKey()
require.NoError(t, err)
pubkeyB := priv2.PublicKey().Marshal()
km := blst.KeyMap()
_, ok := km[[48]byte(pubkeyA)]
require.Equal(t, false, ok, "pubkey a exists")
_, ok = km[[48]byte(pubkeyB)]
require.Equal(t, false, ok, "pubkey b exists")
wg := new(sync.WaitGroup)
wg.Add(1)
go func() {
_, err := blst.PublicKeyFromBytes(pubkeyA)
require.NoError(t, err)
wg.Done()
}()
wg.Add(1)
go func() {
_, err := blst.PublicKeyFromBytes(pubkeyB)
require.NoError(t, err)
wg.Done()
}()
wg.Wait()
km = blst.KeyMap()
_, ok = km[[48]byte(pubkeyA)]
require.Equal(t, true, ok, "pubkey a does not exist")
_, ok = km[[48]byte(pubkeyB)]
require.Equal(t, true, ok, "pubkey b does not exist")
}
func BenchmarkPublicKeyFromBytes(b *testing.B) { func BenchmarkPublicKeyFromBytes(b *testing.B) {
priv, err := blst.RandKey() priv, err := blst.RandKey()
require.NoError(b, err) require.NoError(b, err)
pubkey := priv.PublicKey() pubkey := priv.PublicKey()
pubkeyBytes := pubkey.Marshal() pubkeyBytes := pubkey.Marshal()
b.Run("cache on", func(b *testing.B) { for i := 0; i < b.N; i++ {
blst.EnableCaches() _, err := blst.PublicKeyFromBytes(pubkeyBytes)
for i := 0; i < b.N; i++ { require.NoError(b, err)
_, err := blst.PublicKeyFromBytes(pubkeyBytes) }
require.NoError(b, err)
}
})
b.Run("cache off", func(b *testing.B) {
blst.DisableCaches()
for i := 0; i < b.N; i++ {
_, err := blst.PublicKeyFromBytes(pubkeyBytes)
require.NoError(b, err)
}
})
} }

View File

@@ -1,13 +1,8 @@
package blst package blst
// Note: These functions are for tests to access private globals, such as pubkeyCache. // Note: These functions are for tests to access private globals, such as pubkeyMap.
// DisableCaches sets the cache sizes to 0. // KeyMap returns the pubkey cache.
func DisableCaches() { func KeyMap() map[[48]byte]*PublicKey {
pubkeyCache.Resize(0) return pubkeyMap
}
// EnableCaches sets the cache sizes to the default values.
func EnableCaches() {
pubkeyCache.Resize(maxKeys)
} }