Skip to content

Commit

Permalink
Set default query limit and ensure constraints (#1632)
Browse files Browse the repository at this point in the history
* Set default query limit and ensure constraints

* Update x/wasm/client/cli/query.go

Co-authored-by: pinosu <95283998+pinosu@users.noreply.github.com>

---------

Co-authored-by: pinosu <95283998+pinosu@users.noreply.github.com>
  • Loading branch information
alpe and pinosu authored Sep 18, 2023
1 parent c12e85e commit afa85da
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 51 deletions.
22 changes: 13 additions & 9 deletions x/wasm/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func GetCmdListCode() *cobra.Command {
SilenceUsage: true,
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "list codes")
addPaginationFlags(cmd, "list codes")
return cmd
}

Expand Down Expand Up @@ -190,7 +190,7 @@ func GetCmdListContractByCode() *cobra.Command {
SilenceUsage: true,
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "list contracts by code")
addPaginationFlags(cmd, "list contracts by code")
return cmd
}

Expand Down Expand Up @@ -368,10 +368,7 @@ func GetCmdGetContractStateAll() *cobra.Command {
SilenceUsage: true,
}
flags.AddQueryFlagsToCmd(cmd)
cmd.Flags().String(flags.FlagPageKey, "", "pagination page-key of contract state to query for")
cmd.Flags().Uint64(flags.FlagLimit, 100, "pagination limit of contract state to query for")
cmd.Flags().Bool(flags.FlagReverse, false, "results are sorted in descending order")

addPaginationFlags(cmd, "contract state")
return cmd
}

Expand Down Expand Up @@ -507,7 +504,7 @@ func GetCmdGetContractHistory() *cobra.Command {
}

flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "contract history")
addPaginationFlags(cmd, "contract history")
return cmd
}

Expand Down Expand Up @@ -543,7 +540,7 @@ func GetCmdListPinnedCode() *cobra.Command {
SilenceUsage: true,
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "list codes")
addPaginationFlags(cmd, "list codes")
return cmd
}

Expand Down Expand Up @@ -584,7 +581,7 @@ func GetCmdListContractsByCreator() *cobra.Command {
SilenceUsage: true,
}
flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, "list contracts by creator")
addPaginationFlags(cmd, "list contracts by creator")
return cmd
}

Expand Down Expand Up @@ -677,3 +674,10 @@ func GetCmdQueryParams() *cobra.Command {

return cmd
}

// supports a subset of the SDK pagination params for better resource utilization
func addPaginationFlags(cmd *cobra.Command, query string) {
cmd.Flags().String(flags.FlagPageKey, "", fmt.Sprintf("pagination page-key of %s to query for", query))
cmd.Flags().Uint64(flags.FlagLimit, 100, fmt.Sprintf("pagination limit of %s to query for", query))
cmd.Flags().Bool(flags.FlagReverse, false, "results are sorted in descending order")
}
71 changes: 58 additions & 13 deletions x/wasm/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,15 @@ func (q GrpcQuerier) ContractHistory(c context.Context, req *types.QueryContract
if err != nil {
return nil, err
}
paginationParams, err := ensurePaginationParams(req.Pagination)
if err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(c)
r := make([]types.ContractCodeHistoryEntry, 0)

prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.GetContractCodeHistoryElementPrefix(contractAddr))
pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key, value []byte, accumulate bool) (bool, error) {
pageRes, err := query.FilteredPaginate(prefixStore, paginationParams, func(key, value []byte, accumulate bool) (bool, error) {
if accumulate {
var e types.ContractCodeHistoryEntry
if err := q.cdc.Unmarshal(value, &e); err != nil {
Expand All @@ -93,11 +96,15 @@ func (q GrpcQuerier) ContractsByCode(c context.Context, req *types.QueryContract
if req.CodeId == 0 {
return nil, errorsmod.Wrap(types.ErrInvalid, "code id")
}
paginationParams, err := ensurePaginationParams(req.Pagination)
if err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(c)
r := make([]string, 0)

prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.GetContractByCodeIDSecondaryIndexPrefix(req.CodeId))
pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key, value []byte, accumulate bool) (bool, error) {
pageRes, err := query.FilteredPaginate(prefixStore, paginationParams, func(key, value []byte, accumulate bool) (bool, error) {
if accumulate {
var contractAddr sdk.AccAddress = key[types.AbsoluteTxPositionLen:]
r = append(r, contractAddr.String())
Expand All @@ -117,14 +124,16 @@ func (q GrpcQuerier) AllContractState(c context.Context, req *types.QueryAllCont
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if req.Pagination != nil &&
(req.Pagination.Offset != 0 || req.Pagination.CountTotal) {
return nil, status.Error(codes.InvalidArgument, "offset and count queries not supported anymore")
}

contractAddr, err := sdk.AccAddressFromBech32(req.Address)
if err != nil {
return nil, err
}
paginationParams, err := ensurePaginationParams(req.Pagination)
if err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(c)
if !q.keeper.HasContractInfo(ctx, contractAddr) {
return nil, types.ErrNoSuchContractFn(contractAddr.String()).
Expand All @@ -133,7 +142,7 @@ func (q GrpcQuerier) AllContractState(c context.Context, req *types.QueryAllCont

r := make([]types.Model, 0)
prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.GetContractStorePrefix(contractAddr))
pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key, value []byte, accumulate bool) (bool, error) {
pageRes, err := query.FilteredPaginate(prefixStore, paginationParams, func(key, value []byte, accumulate bool) (bool, error) {
if accumulate {
r = append(r, types.Model{
Key: key,
Expand Down Expand Up @@ -238,10 +247,15 @@ func (q GrpcQuerier) Codes(c context.Context, req *types.QueryCodesRequest) (*ty
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
paginationParams, err := ensurePaginationParams(req.Pagination)
if err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(c)
r := make([]types.CodeInfoResponse, 0)
prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.CodeKeyPrefix)
pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key, value []byte, accumulate bool) (bool, error) {
pageRes, err := query.FilteredPaginate(prefixStore, paginationParams, func(key, value []byte, accumulate bool) (bool, error) {
if accumulate {
var c types.CodeInfo
if err := q.cdc.Unmarshal(value, &c); err != nil {
Expand Down Expand Up @@ -302,11 +316,15 @@ func (q GrpcQuerier) PinnedCodes(c context.Context, req *types.QueryPinnedCodesR
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
paginationParams, err := ensurePaginationParams(req.Pagination)
if err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(c)
r := make([]uint64, 0)

prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.PinnedCodeIndexPrefix)
pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key, _ []byte, accumulate bool) (bool, error) {
pageRes, err := query.FilteredPaginate(prefixStore, paginationParams, func(key, _ []byte, accumulate bool) (bool, error) {
if accumulate {
r = append(r, sdk.BigEndianToUint64(key))
}
Expand All @@ -332,6 +350,11 @@ func (q GrpcQuerier) ContractsByCreator(c context.Context, req *types.QueryContr
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
paginationParams, err := ensurePaginationParams(req.Pagination)
if err != nil {
return nil, err
}

ctx := sdk.UnwrapSDKContext(c)
contracts := make([]string, 0)

Expand All @@ -340,7 +363,7 @@ func (q GrpcQuerier) ContractsByCreator(c context.Context, req *types.QueryContr
return nil, err
}
prefixStore := prefix.NewStore(ctx.KVStore(q.storeKey), types.GetContractsByCreatorPrefix(creatorAddress))
pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key, _ []byte, accumulate bool) (bool, error) {
pageRes, err := query.FilteredPaginate(prefixStore, paginationParams, func(key, _ []byte, accumulate bool) (bool, error) {
if accumulate {
accAddres := sdk.AccAddress(key[types.AbsoluteTxPositionLen:])
contracts = append(contracts, accAddres.String())
Expand All @@ -356,3 +379,25 @@ func (q GrpcQuerier) ContractsByCreator(c context.Context, req *types.QueryContr
Pagination: pageRes,
}, nil
}

// max limit to pagination queries
const maxResultEntries = 100

var errLegacyPaginationUnsupported = status.Error(codes.InvalidArgument, "offset and count queries not supported")

// ensure that pagination is done via key iterator with reasonable limit
func ensurePaginationParams(req *query.PageRequest) (*query.PageRequest, error) {
if req == nil {
return &query.PageRequest{
Key: nil,
Limit: query.DefaultLimit,
}, nil
}
if req.Offset != 0 || req.CountTotal {
return nil, errLegacyPaginationUnsupported
}
if req.Limit > maxResultEntries || req.Limit <= 0 {
req.Limit = maxResultEntries
}
return req, nil
}
Loading

0 comments on commit afa85da

Please # to comment.