Skip to content

Commit 036a9ef

Browse files
committed
implement key-based pagination for DkimPubKeys query
1 parent 4759f26 commit 036a9ef

1 file changed

Lines changed: 86 additions & 106 deletions

File tree

x/dkim/keeper/query_server.go

Lines changed: 86 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@ package keeper
33
import (
44
"bytes"
55
"context"
6-
"fmt"
7-
stdmath "math"
86
"math/big"
97

108
"github.com/vocdoni/circom2gnark/parser"
119

1210
"cosmossdk.io/collections"
1311
"cosmossdk.io/errors"
14-
"cosmossdk.io/math"
1512

1613
sdk "github.com/cosmos/cosmos-sdk/types"
1714
"github.com/cosmos/cosmos-sdk/types/query"
@@ -48,6 +45,7 @@ func (k Querier) DkimPubKey(ctx context.Context, msg *types.QueryDkimPubKeyReque
4845

4946
// DkimPubKeys implements types.QueryServer
5047
func (k Querier) DkimPubKeys(ctx context.Context, msg *types.QueryDkimPubKeysRequest) (*types.QueryDkimPubKeysResponse, error) {
48+
// Direct lookup when both domain and selector are provided
5149
if msg.Domain != "" && msg.Selector != "" {
5250
key := collections.Join(msg.Domain, msg.Selector)
5351
dkimPubKey, err := k.Keeper.DkimPubKeys.Get(ctx, key)
@@ -67,6 +65,27 @@ func (k Querier) DkimPubKeys(ctx context.Context, msg *types.QueryDkimPubKeysReq
6765
}, nil
6866
}
6967

68+
// Parse pagination parameters
69+
limit := uint64(100)
70+
offset := uint64(0)
71+
useKeyBasedPagination := false
72+
countTotal := false
73+
var paginationKey []byte
74+
75+
if msg.Pagination != nil {
76+
if msg.Pagination.Limit != 0 {
77+
limit = msg.Pagination.Limit
78+
}
79+
if len(msg.Pagination.Key) > 0 {
80+
useKeyBasedPagination = true
81+
paginationKey = msg.Pagination.Key
82+
} else if msg.Pagination.Offset != 0 {
83+
offset = msg.Pagination.Offset
84+
}
85+
countTotal = msg.Pagination.CountTotal
86+
}
87+
88+
// Set up the iterator range
7089
var ranger collections.Ranger[collections.Pair[string, string]]
7190
if msg.Domain != "" {
7291
ranger = collections.NewPrefixedPairRange[string, string](msg.Domain)
@@ -78,17 +97,68 @@ func (k Querier) DkimPubKeys(ctx context.Context, msg *types.QueryDkimPubKeysReq
7897
}
7998
defer iter.Close()
8099

81-
var allPubKeys []*types.DkimPubKey
100+
keyCodec := k.Keeper.DkimPubKeys.KeyCodec()
101+
102+
// For key-based pagination, fast-forward to the starting key
103+
if useKeyBasedPagination && len(paginationKey) > 0 {
104+
for ; iter.Valid(); iter.Next() {
105+
fullKey, err := iter.Key()
106+
if err != nil {
107+
return nil, err
108+
}
109+
buf := make([]byte, 256)
110+
n, err := keyCodec.EncodeNonTerminal(buf, fullKey)
111+
if err != nil {
112+
return nil, err
113+
}
114+
// Start from the first key >= pagination key
115+
if bytes.Compare(buf[:n], paginationKey) >= 0 {
116+
break
117+
}
118+
}
119+
}
120+
121+
// Collect results
122+
var results []*types.DkimPubKey
123+
var lastKey collections.Pair[string, string]
124+
var hasLastKey bool
125+
skipped := uint64(0)
126+
collected := uint64(0)
127+
totalMatching := uint64(0)
128+
82129
for ; iter.Valid(); iter.Next() {
83130
dkimPubKey, err := iter.Value()
84131
if err != nil {
85132
return nil, err
86133
}
87134

135+
// Apply PoseidonHash filter if specified
88136
if len(msg.PoseidonHash) > 0 && !bytes.Equal(dkimPubKey.PoseidonHash, msg.PoseidonHash) {
89137
continue
90138
}
91139

140+
totalMatching++
141+
142+
// For offset-based pagination (without key), skip first 'offset' matching records
143+
if !useKeyBasedPagination && skipped < offset {
144+
skipped++
145+
continue
146+
}
147+
148+
// Check if we've collected enough
149+
if collected >= limit {
150+
// We have one more record, so there's a next page
151+
if !hasLastKey {
152+
lastKey, _ = iter.Key()
153+
hasLastKey = true
154+
}
155+
// Continue iterating to count total if needed (for offset-based pagination or CountTotal)
156+
if !countTotal && useKeyBasedPagination {
157+
break
158+
}
159+
continue
160+
}
161+
92162
pubKey := types.DkimPubKey{
93163
Domain: dkimPubKey.Domain,
94164
PubKey: dkimPubKey.PubKey,
@@ -97,62 +167,28 @@ func (k Querier) DkimPubKeys(ctx context.Context, msg *types.QueryDkimPubKeysReq
97167
Version: types.Version(dkimPubKey.Version),
98168
KeyType: types.KeyType(dkimPubKey.KeyType),
99169
}
100-
allPubKeys = append(allPubKeys, &pubKey)
170+
results = append(results, &pubKey)
171+
collected++
101172
}
102173

103-
// Pagination
104-
offset, limit := uint64(0), uint64(100)
105-
if msg.Pagination != nil {
106-
if msg.Pagination.Offset != 0 {
107-
offset = msg.Pagination.Offset
108-
}
109-
if msg.Pagination.Limit != 0 {
110-
limit = msg.Pagination.Limit
111-
} else {
112-
limit = 100
174+
// Generate NextKey if there are more results
175+
var nextKey []byte
176+
if hasLastKey {
177+
buf := make([]byte, 256)
178+
n, err := keyCodec.EncodeNonTerminal(buf, lastKey)
179+
if err != nil {
180+
return nil, err
113181
}
182+
nextKey = buf[:n]
114183
}
115184

116-
allPubKeysLen := uint64(len(allPubKeys))
117-
118-
// Safe conversion: check if offset is within bounds
119-
if offset >= allPubKeysLen {
120-
return &types.QueryDkimPubKeysResponse{
121-
DkimPubKeys: []*types.DkimPubKey{},
122-
Pagination: &query.PageResponse{
123-
NextKey: nil,
124-
Total: allPubKeysLen,
125-
},
126-
}, nil
127-
}
128-
129-
// Safe addition: check for overflow and bounds
130-
endOffset := math.NewUint(offset).Add(math.NewUint(limit))
131-
var end uint64
132-
if endOffset.GT(math.NewUint(allPubKeysLen)) {
133-
end = allPubKeysLen
134-
} else {
135-
end = endOffset.Uint64()
136-
}
137-
138-
// Safe conversion to int for slicing - validate against math.MaxInt to prevent overflow
139-
if offset > uint64(stdmath.MaxInt) || end > uint64(stdmath.MaxInt) {
140-
return nil, fmt.Errorf("pagination offset or end exceeds maximum int value")
141-
}
142-
offsetInt := int(offset)
143-
endInt := int(end)
144-
paginatedPubKeys := allPubKeys[offsetInt:endInt]
145-
146-
// TODO: Implement key-based pagination for nextKey when needed
147-
nextKey := []byte(nil)
148-
149185
pageRes := &query.PageResponse{
150186
NextKey: nextKey,
151-
Total: allPubKeysLen,
187+
Total: totalMatching,
152188
}
153189

154190
return &types.QueryDkimPubKeysResponse{
155-
DkimPubKeys: paginatedPubKeys,
191+
DkimPubKeys: results,
156192
Pagination: pageRes,
157193
}, nil
158194
}
@@ -281,59 +317,3 @@ func IsSubset[T comparable](a, b []T) bool {
281317
}
282318
return true
283319
}
284-
285-
// func convertPageRequest(request *query.PageRequest) *queryv1beta1.PageRequest {
286-
// if request != nil {
287-
// pageRequest := queryv1beta1.PageRequest{}
288-
// pageRequest.CountTotal = request.CountTotal
289-
// pageRequest.Key = request.Key
290-
// pageRequest.Offset = request.Offset
291-
// pageRequest.Limit = request.Limit
292-
// pageRequest.Reverse = request.Reverse
293-
// return &pageRequest
294-
// }
295-
// return nil
296-
// }
297-
298-
// func convertPageResponse(response *queryv1beta1.PageResponse) *query.PageResponse {
299-
// if response != nil {
300-
// pageResponse := query.PageResponse{}
301-
// pageResponse.NextKey = response.NextKey
302-
// pageResponse.Total = response.Total
303-
// return &pageResponse
304-
// }
305-
// return nil
306-
// }
307-
308-
// func consumeIteratorResults(iterator collections.Iterator[collections.Pair[string, string], apiv1.DkimPubKey], domain string, poseidonHash []byte) ([]*types.DkimPubKey, error) {
309-
// defer iterator.Close()
310-
311-
// var output []*types.DkimPubKey
312-
// for ; iterator.Valid(); iterator.Next() {
313-
// dkimPubKey, err := iterator.Value()
314-
// if err != nil {
315-
// return nil, err
316-
// }
317-
318-
// match := true
319-
// if domain != "" && dkimPubKey.Domain != domain {
320-
// match = false
321-
// }
322-
// if len(poseidonHash) > 0 && !bytes.Equal(dkimPubKey.PoseidonHash, poseidonHash) {
323-
// match = false
324-
// }
325-
326-
// if match {
327-
// output = append(output, &types.DkimPubKey{
328-
// Domain: dkimPubKey.Domain,
329-
// PubKey: dkimPubKey.PubKey,
330-
// Selector: dkimPubKey.Selector,
331-
// PoseidonHash: dkimPubKey.PoseidonHash,
332-
// Version: types.Version(dkimPubKey.Version),
333-
// KeyType: types.KeyType(dkimPubKey.KeyType),
334-
// })
335-
// }
336-
// }
337-
338-
// return output, nil
339-
// }

0 commit comments

Comments
 (0)