Skip to content

Commit

Permalink
chore: adds unsafeSignEOTS for testing double signing (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lazar955 authored Dec 5, 2024
1 parent a358d7b commit 9dea909
Show file tree
Hide file tree
Showing 16 changed files with 383 additions and 223 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* [#184](https://github.com/babylonlabs-io/finality-provider/pull/184) eots manager sign record store
* [#189](https://github.com/babylonlabs-io/finality-provider/pull/189) Remove `fpd register-finality-provider` cmd
* [#190](https://github.com/babylonlabs-io/finality-provider/pull/190) Benchmark pub rand
* [#193](https://github.com/babylonlabs-io/finality-provider/pull/193) adds unsafeSignEOTS for e2e tests
* [#195](https://github.com/babylonlabs-io/finality-provider/pull/195) Not block unjailing

### Bug Fixes
Expand Down
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
8 changes: 7 additions & 1 deletion eotsmanager/eotsmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,15 @@ type EOTSManager interface {
// SignEOTS signs an EOTS using the private key of the finality provider and the corresponding
// secret randomness of the given chain at the given height
// It fails if the finality provider does not exist or there's no randomness committed to the given height
// or passPhrase is incorrect
// or passPhrase is incorrect. Has built-in anti-slashing mechanism to ensure signature
// for the same height will not be signed twice.
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.
// Does not offer double sign protection.
// 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
27 changes: 27 additions & 0 deletions eotsmanager/localmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,14 @@ func (lm *LocalEOTSManager) SignEOTS(fpPk []byte, chainID []byte, msg []byte, he
return &s, nil
}

lm.logger.Error(
"double sign error protection",
zap.String("fp", hex.EncodeToString(fpPk)),
zap.String("msg", hex.EncodeToString(msg)),
zap.Uint64("height", height),
zap.String("chainID", string(chainID)),
)

return nil, eotstypes.ErrDoubleSign
}

Expand Down Expand Up @@ -235,6 +243,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
9 changes: 8 additions & 1 deletion finality-provider/cmd/fpd/daemon/daemon_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ func CommandAddFinalitySig() *cobra.Command {
}
cmd.Flags().String(fpdDaemonAddressFlag, defaultFpdDaemonAddress, "The RPC server address of fpd")
cmd.Flags().String(appHashFlag, defaultAppHashStr, "The last commit hash of the chain block")
cmd.Flags().Bool(checkDoubleSignFlag, true, "If 'true', uses anti-slashing protection when doing EOTS sign")

return cmd
}

Expand All @@ -383,6 +385,11 @@ func runCommandAddFinalitySig(cmd *cobra.Command, args []string) error {
return fmt.Errorf("failed to read flag %s: %w", appHashFlag, err)
}

checkDoubleSign, err := flags.GetBool(checkDoubleSignFlag)
if err != nil {
return fmt.Errorf("failed to read flag %s: %w", checkDoubleSignFlag, err)
}

client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress)
if err != nil {
return err
Expand All @@ -398,7 +405,7 @@ func runCommandAddFinalitySig(cmd *cobra.Command, args []string) error {
return err
}

res, err := client.AddFinalitySignature(context.Background(), fpPk.MarshalHex(), blkHeight, appHash)
res, err := client.AddFinalitySignature(context.Background(), fpPk.MarshalHex(), blkHeight, appHash, checkDoubleSign)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions finality-provider/cmd/fpd/daemon/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const (
hdPathFlag = "hd-path"
chainIDFlag = "chain-id"
signedFlag = "signed"
checkDoubleSignFlag = "check-double-sign"

// flags for description
monikerFlag = "moniker"
Expand Down
Loading

0 comments on commit 9dea909

Please sign in to comment.