Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refine oracle module #145

Merged
merged 4 commits into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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