@@ -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