Skip to content

Commit 3069d99

Browse files
committed
refactor(x/oracle): grpc queries
Signed-off-by: Artur Troian <troian@users.noreply.github.com>
1 parent 5b4119b commit 3069d99

1 file changed

Lines changed: 99 additions & 90 deletions

File tree

x/escrow/keeper/grpc_query.go

Lines changed: 99 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import (
44
"bytes"
55
"context"
66

7+
"google.golang.org/grpc/codes"
8+
"google.golang.org/grpc/status"
9+
710
"cosmossdk.io/store/prefix"
11+
storetypes "cosmossdk.io/store/types"
812
sdk "github.com/cosmos/cosmos-sdk/types"
913
sdkquery "github.com/cosmos/cosmos-sdk/types/query"
10-
"google.golang.org/grpc/codes"
11-
"google.golang.org/grpc/status"
14+
1215
types "pkg.akt.dev/go/node/escrow/types/v1"
1316
etypes "pkg.akt.dev/go/node/escrow/v1"
1417

@@ -37,20 +40,26 @@ func (k Querier) Accounts(c context.Context, req *etypes.QueryAccountsRequest) (
3740
}
3841

3942
states := make([]byte, 0, 3)
40-
4143
var searchPrefix []byte
44+
var startKey []byte
4245

43-
// setup for case 3 - cross-index search
4446
// nolint: gocritic
4547
if len(req.Pagination.Key) > 0 {
46-
var key []byte
48+
var innerKey []byte
4749
var err error
48-
states, searchPrefix, key, _, err = query.DecodePaginationKey(req.Pagination.Key)
50+
states, searchPrefix, innerKey, _, err = query.DecodePaginationKey(req.Pagination.Key)
4951
if err != nil {
50-
return nil, status.Error(codes.Internal, err.Error())
52+
return nil, status.Error(codes.InvalidArgument, err.Error())
53+
}
54+
55+
// Validate the inner key by parsing the reconstructed full store key
56+
if _, _, err = ParseAccountKey(append(bytes.Clone(searchPrefix), innerKey...)); err != nil {
57+
return nil, status.Error(codes.InvalidArgument, err.Error())
5158
}
5259

53-
req.Pagination.Key = key
60+
// Safe copy -- iterator may hold a reference to the start key
61+
startKey = make([]byte, len(innerKey))
62+
copy(startKey, innerKey)
5463
} else if req.State != "" {
5564
stateVal := types.State(types.State_value[req.State])
5665

@@ -60,80 +69,77 @@ func (k Querier) Accounts(c context.Context, req *etypes.QueryAccountsRequest) (
6069

6170
states = append(states, byte(stateVal))
6271
} else {
63-
// request does not have a pagination set. Start from active store
64-
states = append(states, []byte{byte(types.StateOpen), byte(types.StateClosed), byte(types.StateOverdrawn)}...)
72+
states = append(states, byte(types.StateOpen), byte(types.StateClosed), byte(types.StateOverdrawn))
6573
}
6674

6775
var accounts types.Accounts
68-
var pageRes *sdkquery.PageResponse
69-
76+
var nextKey []byte
7077
total := uint64(0)
7178

72-
for idx := range states {
79+
iters := make([]storetypes.Iterator, 0, len(states))
80+
defer func() {
81+
for _, it := range iters {
82+
_ = it.Close()
83+
}
84+
}()
85+
86+
var idx int
87+
88+
for idx = range states {
7389
state := types.State(states[idx])
7490

75-
var err error
7691
if idx > 0 {
77-
req.Pagination.Key = nil
92+
startKey = nil
7893
}
7994

80-
if len(req.Pagination.Key) == 0 {
95+
if startKey == nil {
8196
req.State = state.String()
82-
8397
searchPrefix = BuildSearchPrefix(AccountPrefix, req.State, req.XID)
8498
}
8599

86100
searchStore := prefix.NewStore(ctx.KVStore(k.skey), searchPrefix)
101+
iter := searchStore.Iterator(startKey, nil)
102+
iters = append(iters, iter)
87103

88104
count := uint64(0)
89105

90-
pageRes, err = sdkquery.FilteredPaginate(searchStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) {
91-
id, _, err := ParseAccountKey(append(searchPrefix, key...))
106+
for ; iter.Valid() && req.Pagination.Limit > 0; iter.Next() {
107+
id, _, err := ParseAccountKey(append(searchPrefix, iter.Key()...))
92108
if err != nil {
93-
return true, err
94-
}
95-
acc := types.Account{
96-
ID: id,
109+
return nil, status.Error(codes.Internal, err.Error())
97110
}
98111

99-
er := k.cdc.Unmarshal(value, &acc.State)
100-
if er != nil {
101-
return false, er
112+
acc := types.Account{ID: id}
113+
114+
if err := k.cdc.Unmarshal(iter.Value(), &acc.State); err != nil {
115+
return nil, status.Error(codes.Internal, err.Error())
102116
}
103117

104118
accounts = append(accounts, acc)
119+
req.Pagination.Limit--
105120
count++
106-
107-
return false, nil
108-
})
109-
if err != nil {
110-
return nil, status.Error(codes.Internal, err.Error())
111121
}
112122

113-
req.Pagination.Limit -= count
114123
total += count
115124

116-
if req.Pagination.Limit == 0 {
117-
if len(pageRes.NextKey) > 0 {
118-
pageRes.NextKey, err = query.EncodePaginationKey(states[idx:], searchPrefix, pageRes.NextKey, nil)
119-
if err != nil {
120-
pageRes.Total = total
121-
return &etypes.QueryAccountsResponse{
122-
Accounts: accounts,
123-
Pagination: pageRes,
124-
}, status.Error(codes.Internal, err.Error())
125-
}
125+
// Page full and more items exist -- encode NextKey for continuation
126+
if iter.Valid() && req.Pagination.Limit == 0 {
127+
var err error
128+
nextKey, err = query.EncodePaginationKey(states[idx:], searchPrefix, iter.Key(), nil)
129+
if err != nil {
130+
return nil, status.Error(codes.Internal, err.Error())
126131
}
127132

128133
break
129134
}
130135
}
131136

132-
pageRes.Total = total
133-
134137
return &etypes.QueryAccountsResponse{
135-
Accounts: accounts,
136-
Pagination: pageRes,
138+
Accounts: accounts,
139+
Pagination: &sdkquery.PageResponse{
140+
Total: total,
141+
NextKey: nextKey,
142+
},
137143
}, nil
138144
}
139145

@@ -152,20 +158,26 @@ func (k Querier) Payments(c context.Context, req *etypes.QueryPaymentsRequest) (
152158
}
153159

154160
states := make([]byte, 0, 3)
155-
156161
var searchPrefix []byte
162+
var startKey []byte
157163

158-
// setup for case 3 - cross-index search
159164
// nolint: gocritic
160165
if len(req.Pagination.Key) > 0 {
161-
var key []byte
166+
var innerKey []byte
162167
var err error
163-
states, searchPrefix, key, _, err = query.DecodePaginationKey(req.Pagination.Key)
168+
states, searchPrefix, innerKey, _, err = query.DecodePaginationKey(req.Pagination.Key)
164169
if err != nil {
165-
return nil, status.Error(codes.Internal, err.Error())
170+
return nil, status.Error(codes.InvalidArgument, err.Error())
166171
}
167172

168-
req.Pagination.Key = key
173+
// Validate the inner key by parsing the reconstructed full store key
174+
if _, _, err = ParsePaymentKey(append(bytes.Clone(searchPrefix), innerKey...)); err != nil {
175+
return nil, status.Error(codes.InvalidArgument, err.Error())
176+
}
177+
178+
// Safe copy -- iterator may hold a reference to the start key
179+
startKey = make([]byte, len(innerKey))
180+
copy(startKey, innerKey)
169181
} else if req.State != "" {
170182
stateVal := types.State(types.State_value[req.State])
171183

@@ -175,80 +187,77 @@ func (k Querier) Payments(c context.Context, req *etypes.QueryPaymentsRequest) (
175187

176188
states = append(states, byte(stateVal))
177189
} else {
178-
// request does not have a pagination set. Start from active store
179-
states = append(states, []byte{byte(types.StateOpen), byte(types.StateClosed), byte(types.StateOverdrawn)}...)
190+
states = append(states, byte(types.StateOpen), byte(types.StateClosed), byte(types.StateOverdrawn))
180191
}
181192

182193
var payments types.Payments
183-
var pageRes *sdkquery.PageResponse
184-
194+
var nextKey []byte
185195
total := uint64(0)
186196

187-
for idx := range states {
197+
iters := make([]storetypes.Iterator, 0, len(states))
198+
defer func() {
199+
for _, it := range iters {
200+
_ = it.Close()
201+
}
202+
}()
203+
204+
var idx int
205+
206+
for idx = range states {
188207
state := types.State(states[idx])
189208

190-
var err error
191209
if idx > 0 {
192-
req.Pagination.Key = nil
210+
startKey = nil
193211
}
194212

195-
if len(req.Pagination.Key) == 0 {
213+
if startKey == nil {
196214
req.State = state.String()
197-
198215
searchPrefix = BuildSearchPrefix(PaymentPrefix, req.State, req.XID)
199216
}
200217

201218
searchStore := prefix.NewStore(ctx.KVStore(k.skey), searchPrefix)
219+
iter := searchStore.Iterator(startKey, nil)
220+
iters = append(iters, iter)
202221

203222
count := uint64(0)
204223

205-
pageRes, err = sdkquery.FilteredPaginate(searchStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) {
206-
id, _, err := ParsePaymentKey(append(searchPrefix, key...))
224+
for ; iter.Valid() && req.Pagination.Limit > 0; iter.Next() {
225+
id, _, err := ParsePaymentKey(append(searchPrefix, iter.Key()...))
207226
if err != nil {
208-
return true, err
209-
}
210-
pmnt := types.Payment{
211-
ID: id,
227+
return nil, status.Error(codes.Internal, err.Error())
212228
}
213229

214-
er := k.cdc.Unmarshal(value, &pmnt.State)
215-
if er != nil {
216-
return false, er
230+
pmnt := types.Payment{ID: id}
231+
232+
if err := k.cdc.Unmarshal(iter.Value(), &pmnt.State); err != nil {
233+
return nil, status.Error(codes.Internal, err.Error())
217234
}
218235

219236
payments = append(payments, pmnt)
237+
req.Pagination.Limit--
220238
count++
221-
222-
return false, nil
223-
})
224-
if err != nil {
225-
return nil, status.Error(codes.Internal, err.Error())
226239
}
227240

228-
req.Pagination.Limit -= count
229241
total += count
230242

231-
if req.Pagination.Limit == 0 {
232-
if len(pageRes.NextKey) > 0 {
233-
pageRes.NextKey, err = query.EncodePaginationKey(states[idx:], searchPrefix, pageRes.NextKey, nil)
234-
if err != nil {
235-
pageRes.Total = total
236-
return &etypes.QueryPaymentsResponse{
237-
Payments: payments,
238-
Pagination: pageRes,
239-
}, status.Error(codes.Internal, err.Error())
240-
}
243+
// Page full and more items exist -- encode NextKey for continuation
244+
if iter.Valid() && req.Pagination.Limit == 0 {
245+
var err error
246+
nextKey, err = query.EncodePaginationKey(states[idx:], searchPrefix, iter.Key(), nil)
247+
if err != nil {
248+
return nil, status.Error(codes.Internal, err.Error())
241249
}
242250

243251
break
244252
}
245253
}
246254

247-
pageRes.Total = total
248-
249255
return &etypes.QueryPaymentsResponse{
250-
Payments: payments,
251-
Pagination: pageRes,
256+
Payments: payments,
257+
Pagination: &sdkquery.PageResponse{
258+
Total: total,
259+
NextKey: nextKey,
260+
},
252261
}, nil
253262
}
254263

0 commit comments

Comments
 (0)