Skip to content

Commit

Permalink
adds unsafeSignEOTS
Browse files Browse the repository at this point in the history
  • Loading branch information
Lazar955 committed Dec 4, 2024
1 parent 7d7f4f8 commit f47f1c8
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 29 deletions.
19 changes: 19 additions & 0 deletions eotsmanager/client/rpcclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,25 @@ func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64,
return &s, nil
}

func (c *EOTSManagerGRpcClient) UnsafeSignEOTS(uid, chaiID, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) {
req := &proto.SignEOTSRequest{
Uid: uid,
ChainId: chaiID,
Msg: msg,
Height: height,
Passphrase: passphrase,
}
res, err := c.client.UnsafeSignEOTS(context.Background(), req)
if err != nil {
return nil, err
}

var s btcec.ModNScalar
s.SetByteSlice(res.Sig)

return &s, nil
}

func (c *EOTSManagerGRpcClient) SignSchnorrSig(uid, msg []byte, passphrase string) (*schnorr.Signature, error) {
req := &proto.SignSchnorrSigRequest{Uid: uid, Msg: msg, Passphrase: passphrase}
res, err := c.client.SignSchnorrSig(context.Background(), req)
Expand Down
3 changes: 3 additions & 0 deletions eotsmanager/eotsmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ type EOTSManager interface {
// or passPhrase is incorrect
SignEOTS(uid []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error)

// UnsafeSignEOTS should only be used in e2e tests for demonstration purposes. Use SignEOTS for real operations
UnsafeSignEOTS(uid []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error)

// SignSchnorrSig signs a Schnorr signature using the private key of the finality provider
// It fails if the finality provider does not exist or the message size is not 32 bytes
// or passPhrase is incorrect
Expand Down
19 changes: 19 additions & 0 deletions eotsmanager/localmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,25 @@ func (lm *LocalEOTSManager) SignEOTS(fpPk []byte, chainID []byte, msg []byte, he
return signedBytes, nil
}

// UnsafeSignEOTS should only be used in e2e test to demonstrate double sign
func (lm *LocalEOTSManager) UnsafeSignEOTS(fpPk []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) {
privRand, _, err := lm.getRandomnessPair(fpPk, chainID, height, passphrase)
if err != nil {
return nil, fmt.Errorf("failed to get private randomness: %w", err)
}

privKey, err := lm.getEOTSPrivKey(fpPk, passphrase)
if err != nil {
return nil, fmt.Errorf("failed to get EOTS private key: %w", err)
}

// Update metrics
lm.metrics.IncrementEotsFpTotalEotsSignCounter(hex.EncodeToString(fpPk))
lm.metrics.SetEotsFpLastEotsSignHeight(hex.EncodeToString(fpPk), float64(height))

return eots.Sign(privKey, privRand, msg)
}

func (lm *LocalEOTSManager) SignSchnorrSig(fpPk []byte, msg []byte, passphrase string) (*schnorr.Signature, error) {
privKey, err := lm.getEOTSPrivKey(fpPk, passphrase)
if err != nil {
Expand Down
46 changes: 26 additions & 20 deletions eotsmanager/proto/eotsmanager.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions eotsmanager/proto/eotsmanager.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ service EOTSManager {
rpc SignEOTS (SignEOTSRequest)
returns (SignEOTSResponse);

// UnsafeSignEOTS used only for testing purpose. Use SignEOTS for real operations
rpc UnsafeSignEOTS (SignEOTSRequest)
returns (SignEOTSResponse);

// SignSchnorrSig signs a Schnorr sig with the EOTS private key
rpc SignSchnorrSig (SignSchnorrSigRequest)
returns (SignSchnorrSigResponse);
Expand Down
39 changes: 39 additions & 0 deletions eotsmanager/proto/eotsmanager_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions eotsmanager/service/rpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,19 @@ func (r *rpcServer) SignEOTS(_ context.Context, req *proto.SignEOTSRequest) (
return &proto.SignEOTSResponse{Sig: sigBytes[:]}, nil
}

// UnsafeSignEOTS only used for testing purposes. Doesn't offer slashing protection!
func (r *rpcServer) UnsafeSignEOTS(_ context.Context, req *proto.SignEOTSRequest) (
*proto.SignEOTSResponse, error) {
sig, err := r.em.UnsafeSignEOTS(req.Uid, req.ChainId, req.Msg, req.Height, req.Passphrase)
if err != nil {
return nil, err
}

sigBytes := sig.Bytes()

return &proto.SignEOTSResponse{Sig: sigBytes[:]}, nil
}

// SignSchnorrSig signs a Schnorr sig with the EOTS private key
func (r *rpcServer) SignSchnorrSig(_ context.Context, req *proto.SignSchnorrSigRequest) (
*proto.SignSchnorrSigResponse, error) {
Expand Down
12 changes: 11 additions & 1 deletion finality-provider/service/fp_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,8 +695,18 @@ func (fp *FinalityProviderInstance) TestSubmitFinalitySignatureAndExtractPrivKey
return nil, nil, fmt.Errorf("failed to get public randomness inclusion proof: %w", err)
}

unsafeSign := func(b *types.BlockInfo) (*bbntypes.SchnorrEOTSSig, error) {
msgToSign := getMsgToSignForVote(b.Height, b.Hash)
sig, err := fp.em.UnsafeSignEOTS(fp.btcPk.MustMarshal(), fp.GetChainID(), msgToSign, b.Height, fp.passphrase)
if err != nil {
return nil, fmt.Errorf("failed to sign EOTS: %w", err)
}

return bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), nil
}

// sign block
eotsSig, err := fp.signFinalitySig(b)
eotsSig, err := unsafeSign(b)
if err != nil {
return nil, nil, err
}
Expand Down
13 changes: 5 additions & 8 deletions itest/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,11 @@ func TestDoubleSigning(t *testing.T) {
Height: finalizedBlocks[0].Height,
Hash: datagen.GenRandomByteArray(r, 32),
}
_, _, err = fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(b)
require.Error(t, err)

// todo(lazar): implement UnsafeSignEOTS, containing logic without double sign protection
//require.NoError(t, err)
//require.NotNil(t, extractedKey)
//localKey := tm.GetFpPrivKey(t, fpIns.GetBtcPkBIP340().MustMarshal())
//require.True(t, localKey.Key.Equals(&extractedKey.Key) || localKey.Key.Negate().Equals(&extractedKey.Key))
_, extractedKey, err = fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(b)
require.NoError(t, err)
require.NotNil(t, extractedKey)
localKey := tm.GetFpPrivKey(t, fpIns.GetBtcPkBIP340().MustMarshal())
require.True(t, localKey.Key.Equals(&extractedKey.Key) || localKey.Key.Negate().Equals(&extractedKey.Key))

t.Logf("the equivocation attack is successful")
}
Expand Down

0 comments on commit f47f1c8

Please sign in to comment.