Skip to content

Commit

Permalink
feat: use operator encryption key to validate dkg signed msg
Browse files Browse the repository at this point in the history
  • Loading branch information
aayush-rockx committed Jul 2, 2023
1 parent 2424b91 commit 3b501a3
Show file tree
Hide file tree
Showing 29 changed files with 484 additions and 479 deletions.
10 changes: 1 addition & 9 deletions dkg/frost/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"github.com/coinbase/kryptology/pkg/core/curves"
"github.com/coinbase/kryptology/pkg/dkg/frost"
ecies "github.com/ecies/go/v2"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -211,13 +209,7 @@ func (fr *Instance) validateSignedMessage(msg *dkg.SignedMessage) error {
return errors.Wrap(err, "failed to get root")
}

pk, err := crypto.Ecrecover(root, msg.Signature)
if err != nil {
return errors.Wrap(err, "unable to recover public key")
}

addr := ethcommon.BytesToAddress(crypto.Keccak256(pk[1:])[12:])
if addr != operator.ETHAddress {
if !types.Verify(operator.EncryptionPubKey, root, msg.Signature) {
return errors.New("invalid signature")
}
return nil
Expand Down
6 changes: 5 additions & 1 deletion dkg/frost/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package frost

import (
"encoding/json"
"fmt"

"github.com/bloxapp/ssv-spec/dkg"
"github.com/bloxapp/ssv-spec/dkg/common"
Expand Down Expand Up @@ -91,8 +92,11 @@ func (msg *ProtocolMsg) ToSignedMessage(id dkg.RequestID, operatorID types.Opera
if !exist {
return nil, errors.Errorf("operator with id %d not found", operatorID)
}
if operator.EncryptionPrivateKey == nil {
return nil, fmt.Errorf("failed to retrieve operator's private key for signature: %w", err)
}

sig, err := signer.SignDKGOutput(bcastMessage, operator.ETHAddress)
sig, err := signer.SignDKGOutput(bcastMessage, operator.EncryptionPrivateKey)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion dkg/frost/testing_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

func testSignedMessage(round common.ProtocolRound, operatorID types.OperatorID) *dkg.SignedMessage {
sk := testingutils.TestingKeygenKeySet().DKGOperators[operatorID].SK
sk := testingutils.TestingKeygenKeySet().DKGOperators[operatorID].EncryptionKey
msg := &dkg.Message{
MsgType: dkg.ProtocolMsgType,
Identifier: dkg.NewRequestID(testingutils.TestingKeygenKeySet().DKGOperators[operatorID].ETHAddress, uint32(operatorID)),
Expand Down
14 changes: 3 additions & 11 deletions dkg/keysign/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"github.com/bloxapp/ssv-spec/dkg"
"github.com/bloxapp/ssv-spec/dkg/common"
"github.com/bloxapp/ssv-spec/types"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/herumi/bls-eth-go-binary/bls"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -107,7 +105,7 @@ func (instance *Instance) ProcessMsg(msg *dkg.SignedMessage) (finished bool, pro

_, err = instance.state.msgContainer.SaveMsg(protocolMessage.Round, msg)
if err != nil {
return true, nil, err // message already exists or err with saving msg
return false, nil, err // message already exists or err with saving msg
}

switch protocolMessage.Round {
Expand All @@ -116,7 +114,7 @@ func (instance *Instance) ProcessMsg(msg *dkg.SignedMessage) (finished bool, pro
case common.Round1:
return instance.processKeysignOutput()
default:
return true, nil, dkg.ErrInvalidRound{}
return false, nil, dkg.ErrInvalidRound{}
}
}

Expand Down Expand Up @@ -148,13 +146,7 @@ func (instance *Instance) validateSignedMessage(msg *dkg.SignedMessage) error {
return errors.Wrap(err, "failed to get root")
}

pk, err := crypto.Ecrecover(root, msg.Signature)
if err != nil {
return errors.Wrap(err, "unable to recover public key")
}

addr := ethcommon.BytesToAddress(crypto.Keccak256(pk[1:])[12:])
if addr != operator.ETHAddress {
if !types.Verify(operator.EncryptionPubKey, root, msg.Signature) {
return errors.New("invalid signature")
}
return nil
Expand Down
8 changes: 6 additions & 2 deletions dkg/keysign/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keysign

import (
"encoding/json"
"fmt"

"github.com/bloxapp/ssv-spec/dkg"
"github.com/bloxapp/ssv-spec/dkg/common"
Expand Down Expand Up @@ -74,10 +75,13 @@ func (msg *ProtocolMsg) ToSignedMessage(id dkg.RequestID, operatorID types.Opera
return nil, err
}
if !exist {
return nil, errors.Errorf("operator with id %d not found", operatorID)
return nil, fmt.Errorf("operator with id %d not found", operatorID)
}
if operator.EncryptionPrivateKey == nil {
return nil, fmt.Errorf("failed to retrieve operator's private key for signature: %w", err)
}

sig, err := signer.SignDKGOutput(bcastMessage, operator.ETHAddress)
sig, err := signer.SignDKGOutput(bcastMessage, operator.EncryptionPrivateKey)
if err != nil {
return nil, err
}
Expand Down
56 changes: 16 additions & 40 deletions dkg/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,6 @@ func (n *Node) ProcessMessage(msg *types.SSVMessage) error {
}
}

func (n *Node) validateSignedMessage(message *SignedMessage) error {
if err := message.Validate(); err != nil {
return errors.Wrap(err, "message invalid")
}

return nil
}

func (n *Node) startNewDKGMsg(message *SignedMessage) error {
initMsg, err := n.validateInitMsg(message)
if err != nil {
Expand Down Expand Up @@ -218,11 +210,6 @@ func (n *Node) startKeySign(message *SignedMessage) error {
}

func (n *Node) validateInitMsg(message *SignedMessage) (*Init, error) {
// validate identifier.GetEthAddress is the signer for message
if err := message.Signature.ECRecover(message, n.config.SignatureDomainType, types.DKGSignatureType, message.Message.Identifier.GetETHAddress()); err != nil {
return nil, errors.Wrap(err, "signed message invalid")
}

initMsg := &Init{}
if err := initMsg.Decode(message.Message.Data); err != nil {
return nil, errors.Wrap(err, "could not get dkg init Message from signed Messages")
Expand All @@ -236,16 +223,10 @@ func (n *Node) validateInitMsg(message *SignedMessage) (*Init, error) {
if n.runners.RunnerForID(message.Message.Identifier) != nil {
return nil, errors.New("dkg started already")
}

return initMsg, nil
}

func (n *Node) validateReshareMsg(message *SignedMessage) (*Reshare, error) {
// validate identifier.GetEthAddress is the signer for message
if err := message.Signature.ECRecover(message, n.config.SignatureDomainType, types.DKGSignatureType, message.Message.Identifier.GetETHAddress()); err != nil {
return nil, errors.Wrap(err, "signed message invalid")
}

reshareMsg := &Reshare{}
if err := reshareMsg.Decode(message.Message.Data); err != nil {
return nil, errors.Wrap(err, "could not get reshare Message from signed Messages")
Expand All @@ -259,16 +240,10 @@ func (n *Node) validateReshareMsg(message *SignedMessage) (*Reshare, error) {
if n.runners.RunnerForID(message.Message.Identifier) != nil {
return nil, errors.New("dkg started already")
}

return reshareMsg, nil
}

func (n *Node) validateKeySignMsg(message *SignedMessage) (*KeySign, error) {
// validate identifier.GetEthAddress is the signer for message
if err := message.Signature.ECRecover(message, n.config.SignatureDomainType, types.DKGSignatureType, message.Message.Identifier.GetETHAddress()); err != nil {
return nil, errors.Wrap(err, "signed message invalid")
}

keySign := &KeySign{}
if err := keySign.Decode(message.Message.Data); err != nil {
return nil, errors.Wrap(err, "could not get validator exit msg params from signed message")
Expand All @@ -282,46 +257,47 @@ func (n *Node) validateKeySignMsg(message *SignedMessage) (*KeySign, error) {
if n.runners.RunnerForID(message.Message.Identifier) != nil {
return nil, errors.New("signature protocol started already")
}

return keySign, nil
}

func (n *Node) processDKGMsg(message *SignedMessage) error {

if !n.runners.Exists(message.Message.Identifier) {
return errors.New("could not find dkg runner")
}

if err := n.validateDKGMsg(message); err != nil {
return errors.Wrap(err, "dkg msg not valid")
}

r := n.runners.RunnerForID(message.Message.Identifier)

finished, err := r.ProcessMsg(message)
if err != nil {
return errors.Wrap(err, "could not process dkg message")
}

if finished {
n.runners.DeleteRunner(message.Message.Identifier)
}

return nil
}

func (n *Node) validateDKGMsg(message *SignedMessage) error {

// find signing operator and verify sig
found, signingOperator, err := n.config.Storage.GetDKGOperator(message.Signer)
func (n *Node) validateSignedMessage(message *SignedMessage) error {
found, operator, err := n.config.Storage.GetDKGOperator(message.Signer)
if err != nil {
return errors.Wrap(err, "can't fetch operator")
return fmt.Errorf("failed to retrieve operator info for signer %d: %w", message.Signer, err)
}
if !found {
return errors.New("can't find operator")
return fmt.Errorf("operator %d not found", message.Signer)
}
if err := message.Signature.ECRecover(message, n.config.SignatureDomainType, types.DKGSignatureType, signingOperator.ETHAddress); err != nil {

root, _ := types.ComputeSigningRoot(&SignedMessage{
Message: message.Message,
Signer: message.Signer,
}, types.ComputeSignatureDomain(n.config.SignatureDomainType, types.DKGSignatureType))

isValid := types.Verify(operator.EncryptionPubKey, root, message.Signature)
if !isValid {
return errors.Wrap(err, "signed message invalid")
}

return nil
return message.Message.Validate()
}

func (n *Node) GetConfig() *Config {
Expand Down
29 changes: 20 additions & 9 deletions dkg/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/crypto"
"github.com/herumi/bls-eth-go-binary/bls"
"github.com/pkg/errors"
)

type ProtocolOutcome struct {
Expand All @@ -14,14 +13,26 @@ type ProtocolOutcome struct {
BlameOutput *BlameOutput
}

func (o *ProtocolOutcome) IsFailedWithBlame() (bool, error) {
if o.ProtocolOutput == nil && o.BlameOutput == nil {
return false, errors.New("invalid outcome - missing KeyGenOutput and BlameOutput")
}
if o.ProtocolOutput != nil && o.BlameOutput != nil {
return false, errors.New("invalid outcome - has both KeyGenOutput and BlameOutput")
}
return o.BlameOutput != nil, nil
func (o *ProtocolOutcome) IsFinishedWithKeygen() bool {
return o.ProtocolOutput != nil
}

func (o *ProtocolOutcome) IsFinishedWithKeySign() bool {
return o.KeySignOutput != nil
}

func (o *ProtocolOutcome) IsFailedWithBlame() bool {
return o.BlameOutput != nil
}

func (o *ProtocolOutcome) isValid() bool {
a := o.ProtocolOutput
b := o.KeySignOutput
c := o.BlameOutput
hasA := a != nil && b == nil && c == nil
hasB := a == nil && b != nil && c == nil
hasC := a == nil && b == nil && c != nil
return hasA || hasB || hasC
}

// KeyGenOutput is the bare minimum output from the protocol
Expand Down
Loading

0 comments on commit 3b501a3

Please sign in to comment.