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

feat: kv query keys validation #78

Merged
44 changes: 43 additions & 1 deletion x/interchainqueries/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper_test

import (
"fmt"
"strconv"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -67,6 +68,21 @@ func (suite *KeeperTestSuite) TestRegisterInterchainQuery() {
},
sdkerrors.ErrInsufficientFunds,
},
{
"too many keys",
false,
func(sender string) {
msg = iqtypes.MsgRegisterInterchainQuery{
ConnectionId: suite.Path.EndpointA.ConnectionID,
TransactionsFilter: "",
Keys: craftKVKeys(200),
QueryType: string(iqtypes.InterchainQueryTypeKV),
UpdatePeriod: 1,
Sender: sender,
}
},
iqtypes.ErrTooManyKVQueryKeys,
},
{
"valid",
true,
Expand Down Expand Up @@ -214,7 +230,21 @@ func (suite *KeeperTestSuite) TestUpdateInterchainQuery() {
},
},
{
"invavid query id",
"too many query keys",
func(sender string) {
msg = iqtypes.MsgUpdateInterchainQueryRequest{
QueryId: 1,
NewKeys: craftKVKeys(200),
NewUpdatePeriod: 2,
Sender: sender,
}
},
iqtypes.ErrTooManyKVQueryKeys,
2,
nil,
},
{
"invalid query id",
func(sender string) {
msg = iqtypes.MsgUpdateInterchainQueryRequest{
QueryId: 2,
Expand Down Expand Up @@ -909,6 +939,18 @@ func (suite *KeeperTestSuite) TopUpWallet(ctx sdktypes.Context, sender sdktypes.
bankKeeper.SendCoins(ctx, sender, contractAddress, coinsAmnt)
}

func craftKVKeys(n uint64) []*iqtypes.KVKey {
keys := make([]*iqtypes.KVKey, n)
for i := uint64(0); i < n; i++ {
keys[i] = &iqtypes.KVKey{
Path: "path-" + strconv.FormatUint(i, 10),
Key: []byte(fmt.Sprintf("key-%d", i)),
}
}

return keys
}

func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
}
14 changes: 14 additions & 0 deletions x/interchainqueries/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import (
"github.com/neutron-org/neutron/x/interchainqueries/types"
)

const (
MaxKVQueryKeysCount = 32
)

type msgServer struct {
Keeper
}
Expand Down Expand Up @@ -49,6 +53,11 @@ func (k msgServer) RegisterInterchainQuery(goCtx context.Context, msg *types.Msg
return nil, sdkerrors.Wrapf(types.ErrInvalidConnectionID, "failed to get connection with ID '%s': %v", msg.ConnectionId, err)
}

if types.InterchainQueryType(msg.QueryType).IsKV() && uint64(len(msg.Keys)) > MaxKVQueryKeysCount {
pr0n00gler marked this conversation as resolved.
Show resolved Hide resolved
ctx.Logger().Debug("RegisterInterchainQuery: too many keys in KV query", "message", msg)
return nil, sdkerrors.Wrapf(types.ErrTooManyKVQueryKeys, "too many keys in KV query: %d", len(msg.Keys))
}

lastID := k.GetLastRegisteredQueryKey(ctx)
lastID += 1

Expand Down Expand Up @@ -132,6 +141,11 @@ func (k msgServer) UpdateInterchainQuery(goCtx context.Context, msg *types.MsgUp
return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "authorization failed")
}

if types.InterchainQueryType(query.QueryType).IsKV() && uint64(len(msg.NewKeys)) > MaxKVQueryKeysCount {
pr0n00gler marked this conversation as resolved.
Show resolved Hide resolved
ctx.Logger().Debug("RegisterInterchainQuery: too many keys in KV query", "message", msg)
return nil, sdkerrors.Wrapf(types.ErrTooManyKVQueryKeys, "too many keys in KV query: %d", len(msg.NewKeys))
}

if msg.GetNewUpdatePeriod() > 0 {
query.UpdatePeriod = msg.GetNewUpdatePeriod()
}
Expand Down
4 changes: 4 additions & 0 deletions x/interchainqueries/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ var (
ErrInvalidHeight = sdkerrors.Register(ModuleName, 1114, "height is invalid")
ErrNoQueryResult = sdkerrors.Register(ModuleName, 1115, "no query result")
ErrNotContract = sdkerrors.Register(ModuleName, 1116, "not a contract")
ErrEmptyKeys = sdkerrors.Register(ModuleName, 1117, "keys are empty")
ErrEmptyKeyPath = sdkerrors.Register(ModuleName, 1118, "key path is empty")
ErrEmptyKeyId = sdkerrors.Register(ModuleName, 1119, "key id is empty")
ErrTooManyKVQueryKeys = sdkerrors.Register(ModuleName, 1120, "too many keys")
)
16 changes: 16 additions & 0 deletions x/interchainqueries/types/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ func (msg MsgRegisterInterchainQuery) ValidateBasic() error {
return sdkerrors.Wrap(ErrInvalidQueryType, "invalid query type")
}

if InterchainQueryType(msg.QueryType).IsKV() {
if len(msg.Keys) == 0 {
return sdkerrors.Wrap(ErrEmptyKeys, "keys cannot be empty")
}

// check msg.Keys has path
for _, key := range msg.Keys {
pr0n00gler marked this conversation as resolved.
Show resolved Hide resolved
if len(key.Path) == 0 {
return sdkerrors.Wrap(ErrEmptyKeyPath, "keys path cannot be empty")
}
if len(key.Key) == 0 {
return sdkerrors.Wrap(ErrEmptyKeyId, "keys id cannot be empty")
}
}
}

if InterchainQueryType(msg.QueryType).IsTX() {
if err := ValidateTransactionsFilter(msg.TransactionsFilter); err != nil {
return sdkerrors.Wrap(ErrInvalidTransactionsFilter, err.Error())
Expand Down
44 changes: 43 additions & 1 deletion x/interchainqueries/types/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func TestMsgRegisterInterchainQueryValidate(t *testing.T) {
iqtypes.ErrInvalidConnectionID,
},
{
"valid",
"empty keys",
func() sdktypes.Msg {
return &iqtypes.MsgRegisterInterchainQuery{
ConnectionId: "connection-0",
Expand All @@ -116,6 +116,48 @@ func TestMsgRegisterInterchainQueryValidate(t *testing.T) {
Sender: TestAddress,
}
},
iqtypes.ErrEmptyKeys,
},
{
"empty key path",
func() sdktypes.Msg {
return &iqtypes.MsgRegisterInterchainQuery{
ConnectionId: "connection-0",
TransactionsFilter: "{}",
Keys: []*iqtypes.KVKey{{Key: []byte("key1"), Path: ""}},
QueryType: string(iqtypes.InterchainQueryTypeKV),
UpdatePeriod: 1,
Sender: TestAddress,
}
},
iqtypes.ErrEmptyKeyPath,
},
{
"empty key id",
func() sdktypes.Msg {
return &iqtypes.MsgRegisterInterchainQuery{
ConnectionId: "connection-0",
TransactionsFilter: "{}",
Keys: []*iqtypes.KVKey{{Key: []byte(""), Path: "path"}},
QueryType: string(iqtypes.InterchainQueryTypeKV),
UpdatePeriod: 1,
Sender: TestAddress,
}
},
iqtypes.ErrEmptyKeyId,
},
{
"valid",
func() sdktypes.Msg {
return &iqtypes.MsgRegisterInterchainQuery{
ConnectionId: "connection-0",
TransactionsFilter: "{}",
Keys: []*iqtypes.KVKey{{Key: []byte("key1"), Path: "path1"}},
QueryType: string(iqtypes.InterchainQueryTypeKV),
UpdatePeriod: 1,
Sender: TestAddress,
}
},
nil,
},
}
Expand Down