Skip to content

Commit

Permalink
chore: refine oracle module (#145)
Browse files Browse the repository at this point in the history
  • Loading branch information
owen-reorg authored Mar 22, 2023
1 parent 298e28e commit a6cfc5d
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 91 deletions.
8 changes: 4 additions & 4 deletions proto/cosmos/oracle/v1/oracle.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/oracle/types";

// Params holds parameters for the oracle module.
message Params {
// Timeout for the in turn relayer
uint64 relayer_timeout = 1; // in s
// RelayInterval is for in-turn relayer
uint64 relayer_interval = 2; // in s
// Timeout for the in turn relayer in seconds
uint64 relayer_timeout = 1;
// RelayInterval is for in-turn relayer in seconds
uint64 relayer_interval = 2;
// Reward share for the relayer sends the claim message,
// the other relayers signed the bls message will share the reward evenly.
uint32 relayer_reward_share = 3; // in percentage
Expand Down
32 changes: 32 additions & 0 deletions x/oracle/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func GetQueryCmd() *cobra.Command {

cmd.AddCommand(
QueryParamsCmd(),
QueryInturnRelayerCmd(),
)

return cmd
Expand Down Expand Up @@ -57,3 +58,34 @@ $ <appd> query oracle params

return cmd
}

// QueryParamsCmd returns the command handler for evidence parameter querying.
func QueryInturnRelayerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "inturn-relayer",
Short: "Query the inturn relayer",
Args: cobra.NoArgs,
Long: strings.TrimSpace(`Query the inturn relayer:
$ <appd> query oracle inturn-relayer
`),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.InturnRelayer(cmd.Context(), &types.QueryInturnRelayerRequest{})
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}
50 changes: 31 additions & 19 deletions x/oracle/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package keeper

import (
"bytes"
"encoding/hex"
"fmt"

sdkerrors "cosmossdk.io/errors"

Expand Down Expand Up @@ -96,32 +96,36 @@ func (k Keeper) IsRelayerValid(ctx sdk.Context, relayer sdk.AccAddress, validato
}

if validatorIndex < 0 {
return false, sdkerrors.Wrapf(types.ErrNotRelayer, fmt.Sprintf("sender(%s) is not a relayer", relayer.String()))
return false, sdkerrors.Wrapf(types.ErrNotRelayer, "sender(%s) is not a relayer", relayer.String())
}

inturnRelayerTimeout, relayerInterval := k.GetRelayerParams(ctx)

// check whether submitter of msgClaim is an in-turn relayer
inturnRelayer, err := k.GetInturnRelayer(ctx, relayerInterval)
inturnRelayerBlsKey, _, err := k.getInturnRelayer(ctx, relayerInterval)
if err != nil {
return false, err
}

if inturnRelayer.BlsPubKey == hex.EncodeToString(vldr.BlsKey) {
if bytes.Equal(inturnRelayerBlsKey, vldr.BlsKey) {
return true, nil
}

// It is possible that claim comes from out-turn relayers when exceeding the inturnRelayerTimeout, all other
// relayers can relay within the in-turn relayer's current interval
curTime := ctx.BlockTime().Unix()
if uint64(curTime) < claimTimestamp {
return false, nil
}

return uint64(curTime)-claimTimestamp >= inturnRelayerTimeout, nil
}

// CheckClaim checks the bls signature
func (k Keeper) CheckClaim(ctx sdk.Context, claim *types.MsgClaim) (sdk.AccAddress, []string, error) {
func (k Keeper) CheckClaim(ctx sdk.Context, claim *types.MsgClaim) (sdk.AccAddress, []sdk.AccAddress, error) {
relayer, err := sdk.AccAddressFromHexUnsafe(claim.FromAddress)
if err != nil {
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrInvalidAddress, fmt.Sprintf("from address (%s) is invalid", claim.FromAddress))
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrInvalidAddress, "from address (%s) is invalid", claim.FromAddress)
}

historicalInfo, ok := k.StakingKeeper.GetHistoricalInfo(ctx, ctx.BlockHeight())
Expand All @@ -136,39 +140,39 @@ func (k Keeper) CheckClaim(ctx sdk.Context, claim *types.MsgClaim) (sdk.AccAddre
}

if !isValid {
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrRelayerNotInTurn, fmt.Sprintf("relayer(%s) is not in turn", claim.FromAddress))
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrRelayerNotInTurn, "relayer(%s) is not in turn", claim.FromAddress)
}

validatorsBitSet := bitset.From(claim.VoteAddressSet)
if validatorsBitSet.Count() > uint(len(validators)) {
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrValidatorSet, "number of validator set is larger than validators")
}

signedRelayers := make([]string, 0, validatorsBitSet.Count())
signedRelayers := make([]sdk.AccAddress, 0, validatorsBitSet.Count())
votedPubKeys := make([]bls.PublicKey, 0, validatorsBitSet.Count())
for index, val := range validators {
if !validatorsBitSet.Test(uint(index)) {
continue
}

signedRelayers = append(signedRelayers, val.RelayerAddress)
signedRelayers = append(signedRelayers, sdk.MustAccAddressFromHex(val.RelayerAddress))

votePubKey, err := bls.PublicKeyFromBytes(val.BlsKey)
if err != nil {
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrBlsPubKey, fmt.Sprintf("BLS public key converts failed: %v", err))
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrBlsPubKey, "BLS public key converts failed: %v", err)
}
votedPubKeys = append(votedPubKeys, votePubKey)
}

// The valid voted validators should be no less than 2/3 validators.
if len(votedPubKeys) <= len(validators)*2/3 {
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrBlsVotesNotEnough, fmt.Sprintf("not enough validators voted, need: %d, voted: %d", len(validators)*2/3, len(votedPubKeys)))
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrBlsVotesNotEnough, "not enough validators voted, need: %d, voted: %d", len(validators)*2/3, len(votedPubKeys))
}

// Verify the aggregated signature.
aggSig, err := bls.SignatureFromBytes(claim.AggSignature)
if err != nil {
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrInvalidBlsSignature, fmt.Sprintf("BLS signature converts failed: %v", err))
return sdk.AccAddress{}, nil, sdkerrors.Wrapf(types.ErrInvalidBlsSignature, "BLS signature converts failed: %v", err)
}

if !aggSig.FastAggregateVerify(votedPubKeys, claim.GetBlsSignBytes()) {
Expand All @@ -184,10 +188,10 @@ func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
return params
}

func (k Keeper) GetInturnRelayer(ctx sdk.Context, relayerInterval uint64) (*types.QueryInturnRelayerResponse, error) {
func (k Keeper) getInturnRelayer(ctx sdk.Context, relayerInterval uint64) ([]byte, *types.RelayInterval, error) {
historicalInfo, ok := k.StakingKeeper.GetHistoricalInfo(ctx, ctx.BlockHeight())
if !ok {
return nil, sdkerrors.Wrapf(types.ErrValidatorSet, "get historical validators failed")
return nil, nil, sdkerrors.Wrapf(types.ErrValidatorSet, "get historical validators failed")
}
validators := historicalInfo.Valset

Expand All @@ -207,12 +211,20 @@ func (k Keeper) GetInturnRelayer(ctx sdk.Context, relayerInterval uint64) (*type

inturnRelayer := validators[inTurnRelayerIndex]

return inturnRelayer.BlsKey, &types.RelayInterval{
Start: start,
End: end,
}, nil
}

func (k Keeper) GetInturnRelayer(ctx sdk.Context, relayerInterval uint64) (*types.QueryInturnRelayerResponse, error) {
blsKey, interval, err := k.getInturnRelayer(ctx, relayerInterval)
if err != nil {
return nil, err
}
res := &types.QueryInturnRelayerResponse{
BlsPubKey: hex.EncodeToString(inturnRelayer.BlsKey),
RelayInterval: &types.RelayInterval{
Start: start,
End: end,
},
BlsPubKey: hex.EncodeToString(blsKey),
RelayInterval: interval,
}
return res, nil
}
Loading

0 comments on commit a6cfc5d

Please sign in to comment.