@@ -11,7 +11,6 @@ import (
11
11
12
12
"github.com/hashicorp/go-uuid"
13
13
"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/tracing"
14
- "github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
15
14
"github.com/hyperledger-labs/fabric-token-sdk/token"
16
15
"github.com/hyperledger-labs/fabric-token-sdk/token/driver"
17
16
token2 "github.com/hyperledger-labs/fabric-token-sdk/token/token"
@@ -51,15 +50,10 @@ type selector struct {
51
50
52
51
// Select selects tokens to be spent based on ownership, quantity, and type
53
52
func (s * selector ) Select (ownerFilter token.OwnerFilter , q , tokenType string ) ([]* token2.ID , token2.Quantity , error ) {
54
- if ownerFilter == nil {
55
- ownerFilter = & allOwners {}
53
+ if ownerFilter == nil || len ( ownerFilter . ID ()) == 0 {
54
+ return nil , nil , errors . Errorf ( "no owner filter specified" )
56
55
}
57
-
58
- if len (ownerFilter .ID ()) != 0 {
59
- return s .selectByID (ownerFilter , q , tokenType )
60
- }
61
-
62
- return s .selectByOwner (ownerFilter , q , tokenType )
56
+ return s .selectByID (ownerFilter , q , tokenType )
63
57
}
64
58
65
59
func (s * selector ) concurrencyCheck (ids []* token2.ID ) error {
@@ -78,7 +72,6 @@ func (s *selector) selectByID(ownerFilter token.OwnerFilter, q string, tokenType
78
72
var toBeSpent []* token2.ID
79
73
var sum token2.Quantity
80
74
var potentialSumWithLocked token2.Quantity
81
- var potentialSumWithNonCertified token2.Quantity
82
75
target , err := token2 .ToQuantity (q , s .precision )
83
76
if err != nil {
84
77
return nil , nil , errors .Wrap (err , "failed to convert quantity" )
@@ -106,7 +99,6 @@ func (s *selector) selectByID(ownerFilter token.OwnerFilter, q string, tokenType
106
99
// First select only certified
107
100
sum = token2 .NewZeroQuantity (s .precision )
108
101
potentialSumWithLocked = token2 .NewZeroQuantity (s .precision )
109
- potentialSumWithNonCertified = token2 .NewZeroQuantity (s .precision )
110
102
toBeSpent = nil
111
103
var toBeCertified []* token2.ID
112
104
@@ -144,155 +136,6 @@ func (s *selector) selectByID(ownerFilter token.OwnerFilter, q string, tokenType
144
136
toBeSpent = append (toBeSpent , t .Id )
145
137
sum = sum .Add (q )
146
138
potentialSumWithLocked = potentialSumWithLocked .Add (q )
147
- potentialSumWithNonCertified = potentialSumWithNonCertified .Add (q )
148
-
149
- if target .Cmp (sum ) <= 0 {
150
- break
151
- }
152
- }
153
-
154
- concurrencyIssue := false
155
- if target .Cmp (sum ) <= 0 {
156
- err := s .concurrencyCheck (toBeSpent )
157
- if err == nil {
158
- return toBeSpent , sum , nil
159
- }
160
- concurrencyIssue = true
161
- logger .Errorf ("concurrency issue, some of the tokens might not exist anymore [%s]" , err )
162
- }
163
-
164
- // Unlock and check the conditions for a retry
165
- s .locker .UnlockIDs (toBeSpent ... )
166
- s .locker .UnlockIDs (toBeCertified ... )
167
-
168
- if target .Cmp (potentialSumWithLocked ) <= 0 && potentialSumWithLocked .Cmp (sum ) != 0 {
169
- // funds are potentially enough but they are locked
170
- logger .Debugf ("token selection: sufficient funds but partially locked" )
171
- }
172
- if target .Cmp (potentialSumWithNonCertified ) <= 0 && potentialSumWithNonCertified .Cmp (sum ) != 0 {
173
- // funds are potentially enough but they are locked
174
- logger .Debugf ("token selection: sufficient funds but partially not certified" )
175
- }
176
-
177
- i ++
178
- if i >= s .numRetry {
179
- // it is time to fail but how?
180
- if concurrencyIssue {
181
- logger .Debugf ("concurrency issue, some of the tokens might not exist anymore" )
182
- return nil , nil , errors .WithMessagef (
183
- token .SelectorSufficientFundsButConcurrencyIssue ,
184
- "token selection failed: sufficient funs but concurrency issue, potential [%s] tokens of type [%s] were available" , potentialSumWithLocked , tokenType ,
185
- )
186
- }
187
-
188
- if target .Cmp (potentialSumWithLocked ) <= 0 && potentialSumWithLocked .Cmp (sum ) != 0 {
189
- // funds are potentially enough but they are locked
190
- logger .Debugf ("token selection: it is time to fail but how, sufficient funds but locked" )
191
- return nil , nil , errors .WithMessagef (
192
- token .SelectorSufficientButLockedFunds ,
193
- "token selection failed: sufficient but partially locked funds, potential [%s] tokens of type [%s] are available" , potentialSumWithLocked .Decimal (), tokenType ,
194
- )
195
- }
196
-
197
- if target .Cmp (potentialSumWithNonCertified ) <= 0 && potentialSumWithNonCertified .Cmp (sum ) != 0 {
198
- // funds are potentially enough but they are locked
199
- logger .Debugf ("token selection: it is time to fail but how, sufficient funds but locked" )
200
- return nil , nil , errors .WithMessagef (
201
- token .SelectorSufficientButNotCertifiedFunds ,
202
- "token selection failed: sufficient but partially not certified, potential [%s] tokens of type [%s] are available" , potentialSumWithNonCertified , tokenType ,
203
- )
204
- }
205
-
206
- // funds are insufficient
207
- logger .Debugf ("token selection: it is time to fail but how, insufficient funds" )
208
- return nil , nil , errors .WithMessagef (
209
- token .SelectorInsufficientFunds ,
210
- "token selection failed: insufficient funds, only [%s] tokens of type [%s] are available" , sum .Decimal (), tokenType ,
211
- )
212
- }
213
-
214
- logger .Debugf ("token selection: let's wait [%v] before retry..." , s .timeout )
215
- time .Sleep (s .timeout )
216
- }
217
- }
218
-
219
- func (s * selector ) selectByOwner (ownerFilter token.OwnerFilter , q string , tokenType string ) ([]* token2.ID , token2.Quantity , error ) {
220
- var toBeSpent []* token2.ID
221
- var sum token2.Quantity
222
- var potentialSumWithLocked token2.Quantity
223
- var potentialSumWithNonCertified token2.Quantity
224
- target , err := token2 .ToQuantity (q , s .precision )
225
- if err != nil {
226
- return nil , nil , errors .Wrap (err , "failed to convert quantity" )
227
- }
228
-
229
- i := 0
230
- for {
231
- logger .Debugf ("start token selection, iteration [%d/%d]" , i , s .numRetry )
232
- unspentTokens , err := s .queryService .UnspentTokensIterator ()
233
- if err != nil {
234
- return nil , nil , errors .Wrap (err , "token selection failed" )
235
- }
236
- defer unspentTokens .Close ()
237
- logger .Debugf ("select token for a quantity of [%s] of type [%s]" , q , tokenType )
238
-
239
- // First select only certified
240
- sum = token2 .NewZeroQuantity (s .precision )
241
- potentialSumWithLocked = token2 .NewZeroQuantity (s .precision )
242
- potentialSumWithNonCertified = token2 .NewZeroQuantity (s .precision )
243
- toBeSpent = nil
244
- var toBeCertified []* token2.ID
245
-
246
- reclaim := s .numRetry == 1 || i > 0
247
- for {
248
- t , err := unspentTokens .Next ()
249
- if err != nil {
250
- return nil , nil , errors .Wrap (err , "token selection failed" )
251
- }
252
- if t == nil {
253
- break
254
- }
255
-
256
- q , err := token2 .ToQuantity (t .Quantity , s .precision )
257
- if err != nil {
258
- s .locker .UnlockIDs (toBeSpent ... )
259
- s .locker .UnlockIDs (toBeCertified ... )
260
- return nil , nil , errors .Wrap (err , "failed to convert quantity" )
261
- }
262
-
263
- // check type and ownership
264
- if t .Type != tokenType {
265
- if logger .IsEnabledFor (zapcore .DebugLevel ) {
266
- logger .Debugf ("token [%s,%s] type does not match" , q , tokenType )
267
- }
268
- continue
269
- }
270
-
271
- rightOwner := ownerFilter .ContainsToken (t )
272
-
273
- if ! rightOwner {
274
- if logger .IsEnabledFor (zapcore .DebugLevel ) {
275
- logger .Debugf ("token [%s,%s,%s,%v] owner does not belong to the passed wallet" , view .Identity (t .Owner .Raw ), q , tokenType , rightOwner )
276
- }
277
- continue
278
- }
279
-
280
- // lock the token
281
- if _ , err := s .locker .Lock (t .Id , s .txID , reclaim ); err != nil {
282
- potentialSumWithLocked = potentialSumWithLocked .Add (q )
283
-
284
- if logger .IsEnabledFor (zapcore .DebugLevel ) {
285
- logger .Debugf ("token [%s,%s,%v] cannot be locked [%s]" , q , tokenType , rightOwner , err )
286
- }
287
- continue
288
- }
289
-
290
- // Append token
291
- logger .Debugf ("adding quantity [%s]" , q .Decimal ())
292
- toBeSpent = append (toBeSpent , t .Id )
293
- sum = sum .Add (q )
294
- potentialSumWithLocked = potentialSumWithLocked .Add (q )
295
- potentialSumWithNonCertified = potentialSumWithNonCertified .Add (q )
296
139
297
140
if target .Cmp (sum ) <= 0 {
298
141
break
@@ -317,10 +160,6 @@ func (s *selector) selectByOwner(ownerFilter token.OwnerFilter, q string, tokenT
317
160
// funds are potentially enough but they are locked
318
161
logger .Debugf ("token selection: sufficient funds but partially locked" )
319
162
}
320
- if target .Cmp (potentialSumWithNonCertified ) <= 0 && potentialSumWithNonCertified .Cmp (sum ) != 0 {
321
- // funds are potentially enough but they are locked
322
- logger .Debugf ("token selection: sufficient funds but partially not certified" )
323
- }
324
163
325
164
i ++
326
165
if i >= s .numRetry {
@@ -342,15 +181,6 @@ func (s *selector) selectByOwner(ownerFilter token.OwnerFilter, q string, tokenT
342
181
)
343
182
}
344
183
345
- if target .Cmp (potentialSumWithNonCertified ) <= 0 && potentialSumWithNonCertified .Cmp (sum ) != 0 {
346
- // funds are potentially enough but they are locked
347
- logger .Debugf ("token selection: it is time to fail but how, sufficient funds but locked" )
348
- return nil , nil , errors .WithMessagef (
349
- token .SelectorSufficientButNotCertifiedFunds ,
350
- "token selection failed: sufficient but partially not certified, potential [%s] tokens of type [%s] are available" , potentialSumWithNonCertified , tokenType ,
351
- )
352
- }
353
-
354
184
// funds are insufficient
355
185
logger .Debugf ("token selection: it is time to fail but how, insufficient funds" )
356
186
return nil , nil , errors .WithMessagef (
@@ -363,13 +193,3 @@ func (s *selector) selectByOwner(ownerFilter token.OwnerFilter, q string, tokenT
363
193
time .Sleep (s .timeout )
364
194
}
365
195
}
366
-
367
- type allOwners struct {}
368
-
369
- func (a * allOwners ) ID () string {
370
- return ""
371
- }
372
-
373
- func (a * allOwners ) ContainsToken (token * token2.UnspentToken ) bool {
374
- return true
375
- }
0 commit comments