From e8b99de608f8dcc1c6cda25016ca93b4892c1348 Mon Sep 17 00:00:00 2001 From: zblocker64 Date: Thu, 11 Sep 2025 14:39:55 +0200 Subject: [PATCH 1/6] fix: fix pagination key handling and Base64 decoding --- x/market/keeper/grpc_query.go | 46 ++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/x/market/keeper/grpc_query.go b/x/market/keeper/grpc_query.go index ad80fbe49d..25528ccafd 100644 --- a/x/market/keeper/grpc_query.go +++ b/x/market/keeper/grpc_query.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "encoding/base64" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -49,10 +50,21 @@ func (k Querier) Orders(c context.Context, req *types.QueryOrdersRequest) (*type // setup for case 3 - cross-index search // nolint: gocritic - if len(req.Pagination.Key) > 0 { + hasPaginationKey := len(req.Pagination.Key) > 0 + if hasPaginationKey { var key []byte var err error - states, searchPrefix, key, _, err = query.DecodePaginationKey(req.Pagination.Key) + + // Handle Base64 encoded pagination keys + paginationKeyBytes := req.Pagination.Key + if isBase64String(req.Pagination.Key) { + paginationKeyBytes, err = base64.StdEncoding.DecodeString(string(req.Pagination.Key)) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "invalid base64 pagination key") + } + } + + states, searchPrefix, key, _, err = query.DecodePaginationKey(paginationKeyBytes) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -84,7 +96,7 @@ func (k Querier) Orders(c context.Context, req *types.QueryOrdersRequest) (*type state := types.Order_State(states[idx]) var err error - if idx > 0 { + if idx > 0 && !hasPaginationKey { req.Pagination.Key = nil } @@ -125,13 +137,7 @@ func (k Querier) Orders(c context.Context, req *types.QueryOrdersRequest) (*type return nil, status.Error(codes.Internal, err.Error()) } - if len(pageRes.NextKey) > 0 { - nextKey := make([]byte, len(searchPrefix)+len(pageRes.NextKey)) - copy(nextKey, searchPrefix) - copy(nextKey[len(searchPrefix):], pageRes.NextKey) - - pageRes.NextKey = nextKey - } + // Keep raw Cosmos SDK nextKey; do not prepend searchPrefix req.Pagination.Limit -= count total += count @@ -278,13 +284,7 @@ func (k Querier) Bids(c context.Context, req *types.QueryBidsRequest) (*types.Qu return nil, status.Error(codes.Internal, err.Error()) } - if len(pageRes.NextKey) > 0 { - nextKey := make([]byte, len(searchPrefix)+len(pageRes.NextKey)) - copy(nextKey, searchPrefix) - copy(nextKey[len(searchPrefix):], pageRes.NextKey) - - pageRes.NextKey = nextKey - } + // Keep raw Cosmos SDK nextKey; do not prepend searchPrefix req.Pagination.Limit -= count total += count @@ -559,3 +559,15 @@ func (k Querier) Lease(c context.Context, req *types.QueryLeaseRequest) (*types. EscrowPayment: payment, }, nil } + +// Helper function to check if bytes represent a Base64 string +func isBase64String(data []byte) bool { + // Check if all bytes are valid Base64 characters + for _, b := range data { + if !((b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') || (b >= '0' && b <= '9') || b == '+' || b == '/' || b == '=') { + return false + } + } + // Additional check: Base64 strings should have length divisible by 4 (with padding) + return len(data) > 0 && len(data)%4 == 0 +} From 426eb823d1ce9c28caac699d446c8693caaff0f6 Mon Sep 17 00:00:00 2001 From: zblocker64 Date: Thu, 11 Sep 2025 14:48:40 +0200 Subject: [PATCH 2/6] chore: fix linter error --- x/market/keeper/grpc_query.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x/market/keeper/grpc_query.go b/x/market/keeper/grpc_query.go index 25528ccafd..02ef0ed99f 100644 --- a/x/market/keeper/grpc_query.go +++ b/x/market/keeper/grpc_query.go @@ -49,9 +49,8 @@ func (k Querier) Orders(c context.Context, req *types.QueryOrdersRequest) (*type var searchPrefix []byte // setup for case 3 - cross-index search - // nolint: gocritic hasPaginationKey := len(req.Pagination.Key) > 0 - if hasPaginationKey { + if hasPaginationKey { // nolint: gocritic var key []byte var err error From ff9500e9660be86a6d9326c5baec31d20442d3c2 Mon Sep 17 00:00:00 2001 From: zblocker64 Date: Thu, 11 Sep 2025 15:01:22 +0200 Subject: [PATCH 3/6] fix(x/market): improve pagination key handling per CodeRabbit review --- x/market/keeper/grpc_query.go | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/x/market/keeper/grpc_query.go b/x/market/keeper/grpc_query.go index 02ef0ed99f..ca7ac6e59e 100644 --- a/x/market/keeper/grpc_query.go +++ b/x/market/keeper/grpc_query.go @@ -3,6 +3,7 @@ package keeper import ( "context" "encoding/base64" + "errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -50,26 +51,28 @@ func (k Querier) Orders(c context.Context, req *types.QueryOrdersRequest) (*type // setup for case 3 - cross-index search hasPaginationKey := len(req.Pagination.Key) > 0 - if hasPaginationKey { // nolint: gocritic + switch { + case hasPaginationKey: var key []byte var err error - // Handle Base64 encoded pagination keys + // Accept both raw and base64-encoded keys: try raw first, then base64. paginationKeyBytes := req.Pagination.Key - if isBase64String(req.Pagination.Key) { - paginationKeyBytes, err = base64.StdEncoding.DecodeString(string(req.Pagination.Key)) - if err != nil { - return nil, status.Error(codes.InvalidArgument, "invalid base64 pagination key") + states, searchPrefix, key, _, err = query.DecodePaginationKey(paginationKeyBytes) + if err != nil { + if decoded, decErr := base64.StdEncoding.DecodeString(string(req.Pagination.Key)); decErr == nil { + states, searchPrefix, key, _, err = query.DecodePaginationKey(decoded) } } - - states, searchPrefix, key, _, err = query.DecodePaginationKey(paginationKeyBytes) if err != nil { + if errors.Is(err, query.ErrInvalidPaginationKey) { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } return nil, status.Error(codes.Internal, err.Error()) } req.Pagination.Key = key - } else if req.Filters.State != "" { + case req.Filters.State != "": stateVal := types.Order_State(types.Order_State_value[req.Filters.State]) if req.Filters.State != "" && stateVal == types.OrderStateInvalid { @@ -77,7 +80,7 @@ func (k Querier) Orders(c context.Context, req *types.QueryOrdersRequest) (*type } states = append(states, byte(stateVal)) - } else { + default: // request does not have pagination set. Start from open store states = append(states, byte(types.OrderOpen)) states = append(states, byte(types.OrderActive)) @@ -558,15 +561,3 @@ func (k Querier) Lease(c context.Context, req *types.QueryLeaseRequest) (*types. EscrowPayment: payment, }, nil } - -// Helper function to check if bytes represent a Base64 string -func isBase64String(data []byte) bool { - // Check if all bytes are valid Base64 characters - for _, b := range data { - if !((b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') || (b >= '0' && b <= '9') || b == '+' || b == '/' || b == '=') { - return false - } - } - // Additional check: Base64 strings should have length divisible by 4 (with padding) - return len(data) > 0 && len(data)%4 == 0 -} From efd7c85ad5be2289e9e2b66936c65b15e145f79e Mon Sep 17 00:00:00 2001 From: zblocker64 Date: Thu, 11 Sep 2025 15:06:33 +0200 Subject: [PATCH 4/6] chore: fix linter error --- x/market/keeper/grpc_query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/market/keeper/grpc_query.go b/x/market/keeper/grpc_query.go index ca7ac6e59e..e91c425acd 100644 --- a/x/market/keeper/grpc_query.go +++ b/x/market/keeper/grpc_query.go @@ -55,7 +55,7 @@ func (k Querier) Orders(c context.Context, req *types.QueryOrdersRequest) (*type case hasPaginationKey: var key []byte var err error - + // Accept both raw and base64-encoded keys: try raw first, then base64. paginationKeyBytes := req.Pagination.Key states, searchPrefix, key, _, err = query.DecodePaginationKey(paginationKeyBytes) From fa46bbef75afb9710e502f7f21c12e3fa98dbc21 Mon Sep 17 00:00:00 2001 From: zblocker64 Date: Thu, 11 Sep 2025 15:21:39 +0200 Subject: [PATCH 5/6] fix(x/market): apply pagination fixes to all query handlers --- x/market/keeper/grpc_query.go | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/x/market/keeper/grpc_query.go b/x/market/keeper/grpc_query.go index e91c425acd..86f8143496 100644 --- a/x/market/keeper/grpc_query.go +++ b/x/market/keeper/grpc_query.go @@ -194,8 +194,19 @@ func (k Querier) Bids(c context.Context, req *types.QueryBidsRequest) (*types.Qu var key []byte var unsolicited []byte var err error - states, searchPrefix, key, unsolicited, err = query.DecodePaginationKey(req.Pagination.Key) + + // Accept both raw and base64-encoded keys: try raw first, then base64. + paginationKeyBytes := req.Pagination.Key + states, searchPrefix, key, unsolicited, err = query.DecodePaginationKey(paginationKeyBytes) + if err != nil { + if decoded, decErr := base64.StdEncoding.DecodeString(string(req.Pagination.Key)); decErr == nil { + states, searchPrefix, key, unsolicited, err = query.DecodePaginationKey(decoded) + } + } if err != nil { + if errors.Is(err, query.ErrInvalidPaginationKey) { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } return nil, status.Error(codes.Internal, err.Error()) } @@ -204,7 +215,7 @@ func (k Querier) Bids(c context.Context, req *types.QueryBidsRequest) (*types.Qu } req.Pagination.Key = key - if unsolicited[1] == 1 { + if unsolicited[0] == 1 { reverseSearch = true } } else if req.Filters.State != "" { @@ -348,8 +359,19 @@ func (k Querier) Leases(c context.Context, req *types.QueryLeasesRequest) (*type var key []byte var unsolicited []byte var err error - states, searchPrefix, key, unsolicited, err = query.DecodePaginationKey(req.Pagination.Key) + + // Accept both raw and base64-encoded keys: try raw first, then base64. + paginationKeyBytes := req.Pagination.Key + states, searchPrefix, key, unsolicited, err = query.DecodePaginationKey(paginationKeyBytes) if err != nil { + if decoded, decErr := base64.StdEncoding.DecodeString(string(req.Pagination.Key)); decErr == nil { + states, searchPrefix, key, unsolicited, err = query.DecodePaginationKey(decoded) + } + } + if err != nil { + if errors.Is(err, query.ErrInvalidPaginationKey) { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } return nil, status.Error(codes.Internal, err.Error()) } From 595cf81d20bd6a932a0d476ab18755959668ab80 Mon Sep 17 00:00:00 2001 From: zblocker64 Date: Thu, 11 Sep 2025 15:26:24 +0200 Subject: [PATCH 6/6] chore: fix lint --- x/market/keeper/grpc_query.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/market/keeper/grpc_query.go b/x/market/keeper/grpc_query.go index 86f8143496..19c39bcd87 100644 --- a/x/market/keeper/grpc_query.go +++ b/x/market/keeper/grpc_query.go @@ -194,7 +194,7 @@ func (k Querier) Bids(c context.Context, req *types.QueryBidsRequest) (*types.Qu var key []byte var unsolicited []byte var err error - + // Accept both raw and base64-encoded keys: try raw first, then base64. paginationKeyBytes := req.Pagination.Key states, searchPrefix, key, unsolicited, err = query.DecodePaginationKey(paginationKeyBytes) @@ -359,7 +359,7 @@ func (k Querier) Leases(c context.Context, req *types.QueryLeasesRequest) (*type var key []byte var unsolicited []byte var err error - + // Accept both raw and base64-encoded keys: try raw first, then base64. paginationKeyBytes := req.Pagination.Key states, searchPrefix, key, unsolicited, err = query.DecodePaginationKey(paginationKeyBytes)