Skip to content

Commit

Permalink
fix updateOperators and add update-operators command
Browse files Browse the repository at this point in the history
Signed-off-by: Jun Kimura <[email protected]>
  • Loading branch information
bluele committed Jun 14, 2024
1 parent 571bc3e commit 29f98d9
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 8 deletions.
1 change: 1 addition & 0 deletions light-clients/lcp/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
(*exported.ClientMessage)(nil),
&UpdateClientMessage{},
&RegisterEnclaveKeyMessage{},
&UpdateOperatorsMessage{},
)
}
28 changes: 24 additions & 4 deletions light-clients/lcp/types/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,13 @@ func (cs ClientState) verifyUpdateOperators(ctx sdk.Context, store storetypes.KV
if err != nil {
return err
}
nextNonce := cs.OperatorsNonce + 1
if message.Nonce != nextNonce {
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "invalid nonce: expected=%v actual=%v clientID=%v", nextNonce, message.Nonce, clientID)
}
newOperators, err := message.GetNewOperators()
if err != nil {
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "failed to get new operators: %v", err)
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "failed to get new operators: %v clientID=%v", err, clientID)
}
signBytes, err := ComputeEIP712UpdateOperators(
ctx.ChainID(),
Expand All @@ -170,10 +174,25 @@ func (cs ClientState) verifyUpdateOperators(ctx sdk.Context, store storetypes.KV
message.NewOperatorsThresholdDenominator,
)
if err != nil {
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "failed to compute sign bytes: %v", err)
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "failed to compute sign bytes: err=%v clientID=%v", err, clientID)
}
commitment := crypto.Keccak256Hash(signBytes)
var success uint64 = 0
for i, op := range cs.GetOperators() {
if len(message.Signatures[i]) == 0 {
continue
}
addr, err := RecoverAddress(commitment, message.Signatures[i])
if err != nil {
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "failed to recover operator address: err=%v clientID=%v", err, clientID)
}
if addr != op {
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "invalid operator: expected=%v actual=%v clientID=%v", op, addr, clientID)
}
success++
}
if err := cs.VerifySignatures(ctx, store, crypto.Keccak256Hash(signBytes), message.Signatures); err != nil {
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "failed to verify signatures: %v", err)
if success*cs.OperatorsThresholdDenominator < cs.OperatorsThresholdDenominator*uint64(len(cs.Operators)) {
return errorsmod.Wrapf(clienttypes.ErrInvalidHeader, "insufficient signatures: expected=%v actual=%v clientID=%v", cs.OperatorsThresholdDenominator, success, clientID)
}
return nil
}
Expand Down Expand Up @@ -259,6 +278,7 @@ func (cs ClientState) updateOperators(cdc codec.BinaryCodec, clientStore storety
cs.Operators = message.NewOperators
cs.OperatorsThresholdNumerator = message.NewOperatorsThresholdNumerator
cs.OperatorsThresholdDenominator = message.NewOperatorsThresholdDenominator
cs.OperatorsNonce = message.Nonce
setClientState(clientStore, cdc, &cs)
return nil
}
Expand Down
89 changes: 85 additions & 4 deletions relay/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ import (
"fmt"

"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/ethereum/go-ethereum/common"
"github.com/hyperledger-labs/yui-relayer/config"
"github.com/hyperledger-labs/yui-relayer/core"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

const (
flagSrc = "src"
flagHeight = "height"
flagELCClientID = "elc_client_id"
flagSrc = "src"
flagHeight = "height"
flagELCClientID = "elc_client_id"
flagOperators = "operators"
flagNonce = "nonce"
flagThresholdNumerator = "threshold_numerator"
flagThresholdDenominator = "threshold_denominator"
)

func LCPCmd(ctx *config.Context) *cobra.Command {
Expand All @@ -33,6 +38,7 @@ func LCPCmd(ctx *config.Context) *cobra.Command {
updateEnclaveKeyCmd(ctx),
activateClientCmd(ctx),
removeEnclaveKeyInfoCmd(ctx),
updateOperatorsCmd(ctx),
)

return cmd
Expand Down Expand Up @@ -276,6 +282,53 @@ func removeEnclaveKeyInfoCmd(ctx *config.Context) *cobra.Command {
return srcFlag(cmd)
}

func updateOperatorsCmd(ctx *config.Context) *cobra.Command {
cmd := &cobra.Command{
Use: "update-operators [path]",
Short: "Update operators",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
c, src, dst, err := ctx.Config.ChainsFromPath(args[0])
if err != nil {
return err
}
var (
target *core.ProvableChain
counterparty *core.ProvableChain
)
if viper.GetBool(flagSrc) {
target = c[src]
counterparty = c[dst]
} else {
target = c[dst]
counterparty = c[src]
}
prover := target.Prover.(*Prover)
operators := viper.GetStringSlice(flagOperators)
threshold := Fraction{
Numerator: viper.GetUint64(flagThresholdNumerator),
Denominator: viper.GetUint64(flagThresholdDenominator),
}
nonce := viper.GetUint64(flagNonce)

var newOperators []common.Address
for _, op := range operators {
if !common.IsHexAddress(op) {
return fmt.Errorf("invalid operator address: %s", op)
}
newOperators = append(newOperators, common.HexToAddress(op))
}
return prover.updateOperators(counterparty, nonce, newOperators, threshold)
},
}
cmd = thresholdFlag(nonceFlag(operatorsFlag(srcFlag(cmd))))
cmd.MarkFlagRequired(flagOperators)
cmd.MarkFlagRequired(flagThresholdNumerator)
cmd.MarkFlagRequired(flagThresholdDenominator)
cmd.MarkFlagRequired(flagNonce)
return cmd
}

func srcFlag(cmd *cobra.Command) *cobra.Command {
cmd.Flags().BoolP(flagSrc, "", true, "a boolean value whether src is the target chain")
if err := viper.BindPFlag(flagSrc, cmd.Flags().Lookup(flagSrc)); err != nil {
Expand All @@ -293,9 +346,37 @@ func heightFlag(cmd *cobra.Command) *cobra.Command {
}

func elcClientIDFlag(cmd *cobra.Command) *cobra.Command {
cmd.Flags().StringP("elc_client_id", "", "", "a client ID of the ELC client")
cmd.Flags().StringP(flagELCClientID, "", "", "a client ID of the ELC client")
if err := viper.BindPFlag(flagELCClientID, cmd.Flags().Lookup(flagELCClientID)); err != nil {
panic(err)
}
return cmd
}

func operatorsFlag(cmd *cobra.Command) *cobra.Command {
cmd.Flags().StringSliceP(flagOperators, "", nil, "new operator addresses")
if err := viper.BindPFlag(flagOperators, cmd.Flags().Lookup(flagOperators)); err != nil {
panic(err)
}
return cmd
}

func nonceFlag(cmd *cobra.Command) *cobra.Command {
cmd.Flags().Uint64P(flagNonce, "", 0, "a nonce")
if err := viper.BindPFlag(flagNonce, cmd.Flags().Lookup(flagNonce)); err != nil {
panic(err)
}
return cmd
}

func thresholdFlag(cmd *cobra.Command) *cobra.Command {
cmd.Flags().Uint64P(flagThresholdNumerator, "", 0, "a numerator of new threshold")
cmd.Flags().Uint64P(flagThresholdDenominator, "", 0, "a denominator of new threshold")
if err := viper.BindPFlag(flagThresholdNumerator, cmd.Flags().Lookup(flagThresholdNumerator)); err != nil {
panic(err)
}
if err := viper.BindPFlag(flagThresholdDenominator, cmd.Flags().Lookup(flagThresholdDenominator)); err != nil {
panic(err)
}
return cmd
}
8 changes: 8 additions & 0 deletions relay/lcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,14 @@ func (pr *Prover) ComputeEIP712RegisterEnclaveKeyHash(report string) (common.Has
return crypto.Keccak256Hash(bz), nil
}

func (pr *Prover) ComputeEIP712UpdateOperatorsHash(nonce uint64, newOperators []common.Address, thresholdNumerator, thresholdDenominator uint64) (common.Hash, error) {
bz, err := lcptypes.ComputeEIP712UpdateOperatorsWithSalt(pr.computeEIP712ChainSalt(), pr.path.ClientID, nonce, newOperators, thresholdNumerator, thresholdDenominator)
if err != nil {
return common.Hash{}, err
}
return crypto.Keccak256Hash(bz), nil
}

func (pr *Prover) computeEIP712ChainSalt() common.Hash {
switch pr.config.ChainType() {
case ChainTypeEVM:
Expand Down
49 changes: 49 additions & 0 deletions relay/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import (
"fmt"
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
lcptypes "github.com/datachainlab/lcp-go/light-clients/lcp/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/hyperledger-labs/yui-relayer/core"
)

func (pr *Prover) OperatorSign(commitment [32]byte) ([]byte, error) {
Expand Down Expand Up @@ -44,3 +48,48 @@ func (pr *Prover) GetOperatorsThreshold() Fraction {
}
return pr.config.OperatorsThreshold
}

func (pr *Prover) updateOperators(verifier core.Chain, nonce uint64, newOperators []common.Address, threshold Fraction) error {
if nonce == 0 {
return fmt.Errorf("invalid nonce: %v", nonce)
}
if threshold.Numerator == 0 || threshold.Denominator == 0 {
return fmt.Errorf("invalid threshold: %v", threshold)
}
commitment, err := pr.ComputeEIP712UpdateOperatorsHash(
nonce,
newOperators,
threshold.Numerator,
threshold.Denominator,
)
if err != nil {
return err
}
sig, err := pr.OperatorSign(commitment)
if err != nil {
return err
}
var ops [][]byte
for _, operator := range newOperators {
ops = append(ops, operator.Bytes())
}
message := &lcptypes.UpdateOperatorsMessage{
Nonce: nonce,
NewOperators: ops,
NewOperatorsThresholdNumerator: threshold.Numerator,
NewOperatorsThresholdDenominator: threshold.Denominator,
Signatures: [][]byte{sig},
}
signer, err := verifier.GetAddress()
if err != nil {
return err
}
msg, err := clienttypes.NewMsgUpdateClient(verifier.Path().ClientID, message, signer.String())
if err != nil {
return err
}
if _, err := verifier.SendMsgs([]sdk.Msg{msg}); err != nil {
return err
}
return nil
}

0 comments on commit 29f98d9

Please sign in to comment.