@@ -12,8 +12,10 @@ import (
12
12
"io/ioutil"
13
13
"os"
14
14
"path/filepath"
15
+ "strconv"
15
16
"syscall"
16
17
"time"
18
+ "unicode/utf8"
17
19
18
20
"github.com/fsouza/go-dockerclient"
19
21
"github.com/golang/protobuf/proto"
@@ -109,7 +111,7 @@ var _ = Describe("Token EndToEnd", func() {
109
111
{
110
112
Quantity : 119 ,
111
113
Type : "ABC123" ,
112
- Id : [] byte ( "ledger-id" ) ,
114
+ Id : & token. InputId { TxId : "ledger-id" , Index : 1 } ,
113
115
},
114
116
},
115
117
}
@@ -225,7 +227,7 @@ var _ = Describe("Token EndToEnd", func() {
225
227
{
226
228
Quantity : 119 - 50 ,
227
229
Type : "ABC123" ,
228
- Id : [] byte ( "ledger-id" ) ,
230
+ Id : & token. InputId { TxId : "ledger-id" , Index : 0 } ,
229
231
},
230
232
},
231
233
}
@@ -354,7 +356,12 @@ func RunListTokens(c *tokenclient.Client, expectedUnspentTokens *token.UnspentTo
354
356
func RunTransferRequest (c * tokenclient.Client , inputTokens []* token.TokenOutput , recipient []byte , expectedTokenTx * token.TokenTransaction ) string {
355
357
inputTokenIDs := make ([][]byte , len (inputTokens ))
356
358
for i , token := range inputTokens {
357
- inputTokenIDs [i ] = token .GetId ()
359
+ index := strconv .Itoa (int (token .GetId ().Index ))
360
+ txID := token .GetId ().TxId
361
+
362
+ id , err := createCompositeKey ("tokenOutput" , []string {txID , index })
363
+ Expect (err ).NotTo (HaveOccurred ())
364
+ inputTokenIDs [i ] = []byte (id )
358
365
}
359
366
shares := []* token.RecipientTransferShare {
360
367
{Recipient : recipient , Quantity : 119 },
@@ -387,7 +394,12 @@ func RunTransferRequest(c *tokenclient.Client, inputTokens []*token.TokenOutput,
387
394
func RunRedeemRequest (c * tokenclient.Client , inputTokens []* token.TokenOutput , quantity uint64 , expectedTokenTx * token.TokenTransaction ) {
388
395
inputTokenIDs := make ([][]byte , len (inputTokens ))
389
396
for i , token := range inputTokens {
390
- inputTokenIDs [i ] = token .GetId ()
397
+ index := strconv .Itoa (int (token .GetId ().Index ))
398
+ txID := token .GetId ().TxId
399
+
400
+ id , err := createCompositeKey ("tokenOutput" , []string {txID , index })
401
+ Expect (err ).NotTo (HaveOccurred ())
402
+ inputTokenIDs [i ] = []byte (id )
391
403
}
392
404
393
405
envelope , txid , ordererStatus , committed , err := c .Redeem (inputTokenIDs , quantity , 30 * time .Second )
@@ -410,9 +422,15 @@ func RunRedeemRequest(c *tokenclient.Client, inputTokens []*token.TokenOutput, q
410
422
func RunTransferRequestWithFailure (c * tokenclient.Client , inputTokens []* token.TokenOutput , recipient []byte ) (string , * common.Status , bool , error ) {
411
423
inputTokenIDs := make ([][]byte , len (inputTokens ))
412
424
var sum uint64 = 0
413
- for i , tk := range inputTokens {
414
- inputTokenIDs [i ] = tk .GetId ()
415
- sum += tk .GetQuantity ()
425
+ for i , token := range inputTokens {
426
+ index := strconv .Itoa (int (token .GetId ().Index ))
427
+ txID := token .GetId ().TxId
428
+
429
+ id , err := createCompositeKey ("tokenOutput" , []string {txID , index })
430
+ Expect (err ).NotTo (HaveOccurred ())
431
+ inputTokenIDs [i ] = []byte (id )
432
+
433
+ sum += token .GetQuantity ()
416
434
}
417
435
shares := []* token.RecipientTransferShare {
418
436
{Recipient : recipient , Quantity : sum },
@@ -529,3 +547,37 @@ func LoadLocalMSPAt(dir, id, mspType string) (msp.MSP, error) {
529
547
}
530
548
return thisMSP , nil
531
549
}
550
+
551
+ // createCompositeKey and its related functions and consts copied from core/chaincode/shim/chaincode.go
552
+ func createCompositeKey (objectType string , attributes []string ) (string , error ) {
553
+ if err := validateCompositeKeyAttribute (objectType ); err != nil {
554
+ return "" , err
555
+ }
556
+ ck := compositeKeyNamespace + objectType + string (minUnicodeRuneValue )
557
+ for _ , att := range attributes {
558
+ if err := validateCompositeKeyAttribute (att ); err != nil {
559
+ return "" , err
560
+ }
561
+ ck += att + string (minUnicodeRuneValue )
562
+ }
563
+ return ck , nil
564
+ }
565
+
566
+ func validateCompositeKeyAttribute (str string ) error {
567
+ if ! utf8 .ValidString (str ) {
568
+ return errors .Errorf ("not a valid utf8 string: [%x]" , str )
569
+ }
570
+ for index , runeValue := range str {
571
+ if runeValue == minUnicodeRuneValue || runeValue == maxUnicodeRuneValue {
572
+ return errors .Errorf (`input contain unicode %#U starting at position [%d]. %#U and %#U are not allowed in the input attribute of a composite key` ,
573
+ runeValue , index , minUnicodeRuneValue , maxUnicodeRuneValue )
574
+ }
575
+ }
576
+ return nil
577
+ }
578
+
579
+ const (
580
+ minUnicodeRuneValue = 0 //U+0000
581
+ maxUnicodeRuneValue = utf8 .MaxRune //U+10FFFF - maximum (and unallocated) code point
582
+ compositeKeyNamespace = "\x00 "
583
+ )
0 commit comments