@@ -275,6 +275,48 @@ func validateNewCollectionConfigs(newCollectionConfigs []*common.CollectionConfi
275
275
return nil
276
276
}
277
277
278
+ func validateNewCollectionConfigsAgainstOld (newCollectionConfigs []* common.CollectionConfig , oldCollectionConfigs []* common.CollectionConfig ,
279
+ ) error {
280
+ // All old collections must exist in the new collection config package
281
+ if len (newCollectionConfigs ) < len (oldCollectionConfigs ) {
282
+ return fmt .Errorf ("Some existing collection configurations are missing in the new collection configuration package" )
283
+ }
284
+ newCollectionsMap := make (map [string ]* common.StaticCollectionConfig , len (newCollectionConfigs ))
285
+
286
+ for _ , newCollectionConfig := range newCollectionConfigs {
287
+ newCollection := newCollectionConfig .GetStaticCollectionConfig ()
288
+ // Collection object itself is stored as value so that we can
289
+ // check whether the block to live is changed -- FAB-7810
290
+ newCollectionsMap [newCollection .GetName ()] = newCollection
291
+ }
292
+
293
+ // In the new collection config package, ensure that there is one entry per old collection. Any
294
+ // number of new collections are allowed.
295
+ for _ , oldCollectionConfig := range oldCollectionConfigs {
296
+
297
+ oldCollection := oldCollectionConfig .GetStaticCollectionConfig ()
298
+ // It cannot be nil
299
+ if oldCollection == nil {
300
+ return fmt .Errorf ("unknown collection configuration type" )
301
+ }
302
+
303
+ // All old collection must exist in the new collection config package
304
+ oldCollectionName := oldCollection .GetName ()
305
+ newCollection , ok := newCollectionsMap [oldCollectionName ]
306
+ if ! ok {
307
+ return fmt .Errorf ("existing collection named %s is missing in the new collection configuration package" ,
308
+ oldCollectionName )
309
+ }
310
+ // BlockToLive cannot be changed
311
+ if newCollection .GetBlockToLive () != oldCollection .GetBlockToLive () {
312
+ return fmt .Errorf ("BlockToLive in the existing collection named %s cannot be changed" ,
313
+ oldCollectionName )
314
+ }
315
+ }
316
+
317
+ return nil
318
+ }
319
+
278
320
// validateRWSetAndCollection performs validation of the rwset
279
321
// of an LSCC deploy operation and then it validates any collection
280
322
// configuration
@@ -355,6 +397,31 @@ func (vscc *ValidatorOneValidSignature) validateRWSetAndCollection(
355
397
if err := validateNewCollectionConfigs (newCollectionConfigs ); err != nil {
356
398
return err
357
399
}
400
+
401
+ if lsccFunc == lscc .UPGRADE {
402
+
403
+ collectionCriteria := common.CollectionCriteria {Channel : channelName , Namespace : cdRWSet .Name }
404
+ // oldCollectionConfigPackage denotes the existing collection config package in the ledger
405
+ oldCollectionConfigPackage , err := vscc .collectionStore .RetrieveCollectionConfigPackage (collectionCriteria )
406
+ if err != nil {
407
+ // fail if we get any error other than NoSuchCollectionError
408
+ // because it means something went wrong while looking up the
409
+ // older collection
410
+ if _ , ok := err .(privdata.NoSuchCollectionError ); ! ok {
411
+ return errors .WithMessage (err , fmt .Sprintf ("unable to check whether collection existed earlier for chaincode %s:%s" ,
412
+ cdRWSet .Name , cdRWSet .Version ))
413
+ }
414
+ }
415
+
416
+ // oldCollectionConfigPackage denotes the existing collection config package in the ledger
417
+ if oldCollectionConfigPackage != nil {
418
+ oldCollectionConfigs := oldCollectionConfigPackage .GetConfig ()
419
+ if err := validateNewCollectionConfigsAgainstOld (newCollectionConfigs , oldCollectionConfigs ); err != nil {
420
+ return err
421
+ }
422
+
423
+ }
424
+ }
358
425
}
359
426
360
427
// TODO: FAB-6526 - to add validation of the collections object
@@ -533,14 +600,6 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
533
600
}
534
601
535
602
case lscc .UPGRADE :
536
- /********************************************/
537
- /* security check 0.a - validation of rwset */
538
- /********************************************/
539
- // there can only be a single ledger write
540
- if len (lsccrwset .Writes ) != 1 {
541
- return errors .New ("LSCC can only issue one putState upon upgrade" )
542
- }
543
-
544
603
/**************************************************************/
545
604
/* security check 1 - cc in the LCCC table of instantiated cc */
546
605
/**************************************************************/
@@ -555,8 +614,25 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
555
614
return fmt .Errorf ("Existing version of the cc on the ledger (%s) should be different from the upgraded one" , cdsArgs .ChaincodeSpec .ChaincodeId .Version )
556
615
}
557
616
617
+ /****************************************************************************/
618
+ /* security check 3 validation of rwset (and of collections if enabled) */
619
+ /****************************************************************************/
620
+ // Only in v1.2, a collection can be updated during a chaincode upgrade
621
+ if ac .V1_2Validation () {
622
+ // do extra validation for collections
623
+ err = vscc .validateRWSetAndCollection (lsccrwset , cdRWSet , lsccArgs , lsccFunc , ac , chid )
624
+ if err != nil {
625
+ return err
626
+ }
627
+ } else {
628
+ // there can only be a single ledger write
629
+ if len (lsccrwset .Writes ) != 1 {
630
+ return errors .New ("LSCC can only issue a single putState upon deploy/upgrade" )
631
+ }
632
+ }
633
+
558
634
/*****************************************************/
559
- /* security check 3 - check the instantiation policy */
635
+ /* security check 4 - check the instantiation policy */
560
636
/*****************************************************/
561
637
pol := cdLedger .InstantiationPolicy
562
638
if pol == nil {
@@ -573,7 +649,7 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
573
649
}
574
650
575
651
/******************************************************************/
576
- /* security check 4 - check the instantiation policy in the rwset */
652
+ /* security check 5 - check the instantiation policy in the rwset */
577
653
/******************************************************************/
578
654
if ac .V1_1Validation () {
579
655
polNew := cdRWSet .InstantiationPolicy
0 commit comments