Skip to content

Commit

Permalink
feat: implement g1 sign api (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
shrimalmadhur authored Jan 14, 2025
1 parent bd104ca commit 6d0c13b
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 17 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ toolchain go1.22.3
require (
cloud.google.com/go/secretmanager v1.14.2
github.com/Layr-Labs/bn254-keystore-go v0.0.0-20250107020618-26bd412fae87
github.com/Layr-Labs/cerberus-api v0.0.2-0.20250107174124-05df6050f723
github.com/Layr-Labs/cerberus-api v0.0.2-0.20250108174619-d5e1eb03fbd5
github.com/aws/aws-sdk-go-v2 v1.32.5
github.com/aws/aws-sdk-go-v2/config v1.28.5
github.com/aws/aws-sdk-go-v2/credentials v1.17.46
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Layr-Labs/bn254-keystore-go v0.0.0-20250107020618-26bd412fae87 h1:EkaBNT0o8RTgtFeYSKaoNHNbnCVxrcsAyRpUeN29hiQ=
github.com/Layr-Labs/bn254-keystore-go v0.0.0-20250107020618-26bd412fae87/go.mod h1:7J8hptSX8cFq7KmVb+rEO5aEifj7E44c3i0afIyr4WA=
github.com/Layr-Labs/cerberus-api v0.0.2-0.20250107174124-05df6050f723 h1:f6gJS/egys133nGcOGKduiPHq9hyK9KRiEB9fARB5t0=
github.com/Layr-Labs/cerberus-api v0.0.2-0.20250107174124-05df6050f723/go.mod h1:Lm4fhzy0S3P7GjerzuseGaBFVczsIKmEhIjcT52Hluo=
github.com/Layr-Labs/cerberus-api v0.0.2-0.20250108174619-d5e1eb03fbd5 h1:s24M6HYObEuV9OSY36jUM09kp5fOhuz/g1ev2qWDPzU=
github.com/Layr-Labs/cerberus-api v0.0.2-0.20250108174619-d5e1eb03fbd5/go.mod h1:Lm4fhzy0S3P7GjerzuseGaBFVczsIKmEhIjcT52Hluo=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo=
Expand Down
23 changes: 23 additions & 0 deletions internal/services/signing/keystore_map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package signing

import (
"sync"

"github.com/Layr-Labs/cerberus/internal/crypto"
)

type KeyStoreMap struct {
sync.Map
}

func (k *KeyStoreMap) Load(key string) (*crypto.KeyPair, bool) {
value, ok := k.Map.Load(key)
if !ok {
return nil, false
}
return value.(*crypto.KeyPair), true
}

func (k *KeyStoreMap) Store(key string, value *crypto.KeyPair) {
k.Map.Store(key, value)
}
66 changes: 52 additions & 14 deletions internal/services/signing/signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import (
)

type Service struct {
config *configuration.Configuration
logger *slog.Logger
store store.Store
metrics metrics.Recorder
keyCache map[string]*crypto.KeyPair
config *configuration.Configuration
logger *slog.Logger
store store.Store
metrics metrics.Recorder
keyMap KeyStoreMap
v1.UnimplementedSignerServer
}

Expand All @@ -33,11 +33,11 @@ func NewService(
metrics metrics.Recorder,
) *Service {
return &Service{
config: config,
store: store,
metrics: metrics,
logger: logger.With("component", "signing"),
keyCache: make(map[string]*crypto.KeyPair),
config: config,
store: store,
metrics: metrics,
logger: logger.With("component", "signing"),
keyMap: KeyStoreMap{},
}
}

Expand All @@ -49,16 +49,16 @@ func (s *Service) SignGeneric(
pubKeyHex := common.Trim0x(req.GetPublicKeyG1())
password := req.GetPassword()

if _, ok := s.keyCache[pubKeyHex]; !ok {
if _, ok := s.keyMap.Load(pubKeyHex); !ok {
s.logger.Info(fmt.Sprintf("In memory cache miss. Retrieving key for %s", pubKeyHex))
blsKey, err := s.store.RetrieveKey(ctx, pubKeyHex, password)
if err != nil {
s.logger.Error(fmt.Sprintf("Failed to retrieve key: %v", err))
return nil, status.Error(codes.Internal, err.Error())
}
s.keyCache[pubKeyHex] = blsKey
s.keyMap.Store(pubKeyHex, blsKey)
}
blsKey := s.keyCache[pubKeyHex]
blsKey, _ := s.keyMap.Load(pubKeyHex)

data := req.GetData()
if len(data) > 32 {
Expand All @@ -71,5 +71,43 @@ func (s *Service) SignGeneric(
// Sign the data with the private key
sig := blsKey.SignMessage(byteArray)
s.logger.Info(fmt.Sprintf("Signed a message successfully using %s", pubKeyHex))
return &v1.SignGenericResponse{Signature: sig.Serialize()}, nil
signatureBytes := sig.RawBytes()
return &v1.SignGenericResponse{Signature: signatureBytes[:]}, nil
}

func (s *Service) SignG1(
ctx context.Context,
req *v1.SignG1Request,
) (*v1.SignG1Response, error) {
// Take the public key and data from the request
pubKeyHex := common.Trim0x(req.GetPublicKeyG1())
password := req.GetPassword()

if pubKeyHex == "" {
return nil, status.Error(codes.InvalidArgument, "public key is required")
}

g1Bytes := req.GetData()
if len(g1Bytes) == 0 {
return nil, status.Error(codes.InvalidArgument, "data must be > 0 bytes")
}

if _, ok := s.keyMap.Load(pubKeyHex); !ok {
s.logger.Info(fmt.Sprintf("In memory cache miss. Retrieving key for %s", pubKeyHex))
blsKey, err := s.store.RetrieveKey(ctx, pubKeyHex, password)
if err != nil {
s.logger.Error(fmt.Sprintf("Failed to retrieve key: %v", err))
return nil, status.Error(codes.Internal, err.Error())
}
s.keyMap.Store(pubKeyHex, blsKey)
}
blsKey, _ := s.keyMap.Load(pubKeyHex)

g1Point := new(crypto.G1Point)
g1Point = g1Point.Deserialize(g1Bytes)

sig := blsKey.SignHashedToCurveMessage(g1Point.G1Affine)
s.logger.Info(fmt.Sprintf("Signed a G1 message successfully using %s", pubKeyHex))
signatureBytes := sig.RawBytes()
return &v1.SignG1Response{Signature: signatureBytes[:]}, nil
}
26 changes: 26 additions & 0 deletions internal/services/signing/signing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,29 @@ func TestSigning(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, expectedSig, hex.EncodeToString(resp.Signature))
}

func TestSigningG1(t *testing.T) {
// private key: 0x040ad69253b921aca71dd714cccc3095576fbe1a21f86c9b10cb5b119b1c6899
pubKeyHex := "a3111a2232584734d526d62cbb7c9a0d4ce1984a92b7ecb85bde8878fea5d1b0"
password := "p@$$w0rd"
expectedSig := "24a87f9eab63a40c62831d2e9598e698f8819b15093c268b89c1a521f7d986650000000000000000000000000000000000000000000000000000000000000000"
data := []byte("somedata")
var bytes [64]byte
copy(bytes[:], data)

config := &configuration.Configuration{
KeystoreDir: "testdata/keystore",
}
logger := testutils.GetTestLogger()
store := filesystem.NewStore(config.KeystoreDir, logger)
m := metrics.NewNoopRPCMetrics()
signingService := NewService(config, store, logger, m)

resp, err := signingService.SignG1(context.Background(), &v1.SignG1Request{
PublicKeyG1: pubKeyHex,
Data: bytes[:],
Password: password,
})
assert.NoError(t, err)
assert.Equal(t, expectedSig, hex.EncodeToString(resp.Signature))
}

0 comments on commit 6d0c13b

Please sign in to comment.