Skip to content

Commit 8efecba

Browse files
cendhuryjones
authored andcommitted
[FAB-9720] Validate Collection Objects
This CR adds validation logic for the collection configuration. (i) duplicate collections are not allowed (ii) maxPeerCount cannot be lesser than requiredPeerCount (iii) requiredPeerCount cannot be lesser than zero Add unit-test for above validation logic as well as deploy with collection config Change-Id: Id0814b33d00744a7f5b3e24e0fd2553ecd9fa7bd Signed-off-by: senthil <cendhu@gmail.com>
1 parent d45ea1b commit 8efecba

File tree

2 files changed

+410
-67
lines changed

2 files changed

+410
-67
lines changed

core/scc/vscc/validator_onevalidsignature.go

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,50 @@ func (vscc *ValidatorOneValidSignature) checkInstantiationPolicy(chainName strin
241241
return nil
242242
}
243243

244-
// validateDeployRWSetAndCollection performs validation of the rwset
244+
func validateNewCollectionConfigs(newCollectionConfigs []*common.CollectionConfig) error {
245+
newCollectionsMap := make(map[string]bool, len(newCollectionConfigs))
246+
// Process each collection config from a set of collection configs
247+
for _, newCollectionConfig := range newCollectionConfigs {
248+
249+
newCollection := newCollectionConfig.GetStaticCollectionConfig()
250+
if newCollection == nil {
251+
return fmt.Errorf("unknown collection configuration type")
252+
}
253+
254+
// Ensure that there are no duplicate collection names
255+
collectionName := newCollection.GetName()
256+
if _, ok := newCollectionsMap[collectionName]; !ok {
257+
newCollectionsMap[collectionName] = true
258+
} else {
259+
return fmt.Errorf("collection-name: %s -- found duplicate collection configuration", collectionName)
260+
}
261+
262+
// Validate gossip related parameters present in the collection config
263+
maximumPeerCount := newCollection.GetMaximumPeerCount()
264+
requiredPeerCount := newCollection.GetRequiredPeerCount()
265+
if maximumPeerCount < requiredPeerCount {
266+
return fmt.Errorf("collection-name: %s -- maximum peer count (%d) cannot be greater than the required peer count (%d)",
267+
collectionName, maximumPeerCount, requiredPeerCount)
268+
}
269+
if requiredPeerCount < 0 {
270+
return fmt.Errorf("collection-name: %s -- requiredPeerCount (%d) cannot be lesser than zero (%d)",
271+
collectionName, maximumPeerCount, requiredPeerCount)
272+
273+
}
274+
}
275+
return nil
276+
}
277+
278+
// validateRWSetAndCollection performs validation of the rwset
245279
// of an LSCC deploy operation and then it validates any collection
246280
// configuration
247-
func (vscc *ValidatorOneValidSignature) validateDeployRWSetAndCollection(
281+
func (vscc *ValidatorOneValidSignature) validateRWSetAndCollection(
248282
lsccrwset *kvrwset.KVRWSet,
249283
cdRWSet *ccprovider.ChaincodeData,
250284
lsccArgs [][]byte,
251-
chid, ccid string,
285+
lsccFunc string,
286+
ac channelconfig.ApplicationCapabilities,
287+
channelName string,
252288
) error {
253289
/********************************************/
254290
/* security check 0.a - validation of rwset */
@@ -261,9 +297,9 @@ func (vscc *ValidatorOneValidSignature) validateDeployRWSetAndCollection(
261297
/**********************************************************/
262298
/* security check 0.b - validation of the collection data */
263299
/**********************************************************/
264-
var collectionsConfigArgs []byte
300+
var collectionsConfigArg []byte
265301
if len(lsccArgs) > 5 {
266-
collectionsConfigArgs = lsccArgs[5]
302+
collectionsConfigArg = lsccArgs[5]
267303
}
268304

269305
var collectionsConfigLedger []byte
@@ -277,32 +313,48 @@ func (vscc *ValidatorOneValidSignature) validateDeployRWSetAndCollection(
277313
collectionsConfigLedger = lsccrwset.Writes[1].Value
278314
}
279315

280-
if !bytes.Equal(collectionsConfigArgs, collectionsConfigLedger) {
281-
return errors.Errorf("collection configuration mismatch for chaincode %s:%s",
282-
cdRWSet.Name, cdRWSet.Version)
316+
if !bytes.Equal(collectionsConfigArg, collectionsConfigLedger) {
317+
return errors.Errorf("collection configuration mismatch for chaincode %s:%s arg: %s writeset: %s",
318+
cdRWSet.Name, cdRWSet.Version, collectionsConfigArg, collectionsConfigLedger)
283319
}
284320

285-
ccp, err := vscc.collectionStore.RetrieveCollectionConfigPackage(common.CollectionCriteria{Channel: chid, Namespace: ccid})
286-
if err != nil {
287-
// fail if we get any error other than NoSuchCollectionError
288-
// because it means something went wrong while looking up the
289-
// older collection
290-
if _, ok := err.(privdata.NoSuchCollectionError); !ok {
291-
return errors.WithMessage(err, fmt.Sprintf("unable to check whether collection existed earlier for chaincode %s:%s",
292-
cdRWSet.Name, cdRWSet.Version))
321+
// The following condition check addded in v1.1 may not be needed as it is not possible to have the chaincodeName~collection key in
322+
// the lscc namespace before a chaincode deploy. To avoid forks in v1.2, the following condition is retained.
323+
if lsccFunc == lscc.DEPLOY {
324+
ccp, err := vscc.collectionStore.RetrieveCollectionConfigPackage(common.CollectionCriteria{Channel: channelName, Namespace: cdRWSet.Name})
325+
if err != nil {
326+
// fail if we get any error other than NoSuchCollectionError
327+
// because it means something went wrong while looking up the
328+
// older collection
329+
if _, ok := err.(privdata.NoSuchCollectionError); !ok {
330+
return errors.WithMessage(err, fmt.Sprintf("unable to check whether collection existed earlier for chaincode %s:%s",
331+
cdRWSet.Name, cdRWSet.Version))
332+
}
333+
}
334+
if ccp != nil {
335+
return errors.Errorf("collection data should not exist for chaincode %s:%s", cdRWSet.Name, cdRWSet.Version)
293336
}
294337
}
295-
if ccp != nil {
296-
return errors.Errorf("collection data should not exist for chaincode %s:%s", cdRWSet.Name, cdRWSet.Version)
297-
}
298338

299-
if collectionsConfigArgs != nil {
300-
collections := &common.CollectionConfigPackage{}
301-
err := proto.Unmarshal(collectionsConfigArgs, collections)
339+
// TODO: Once the new chaincode lifecycle is available (FAB-8724), the following validation
340+
// and other validation performed in ValidateLSCCInvocation can be moved to LSCC itself.
341+
newCollectionConfigPackage := &common.CollectionConfigPackage{}
342+
343+
if collectionsConfigArg != nil {
344+
err := proto.Unmarshal(collectionsConfigArg, newCollectionConfigPackage)
302345
if err != nil {
303346
return errors.Errorf("invalid collection configuration supplied for chaincode %s:%s",
304347
cdRWSet.Name, cdRWSet.Version)
305348
}
349+
} else {
350+
return nil
351+
}
352+
353+
if ac.V1_2Validation() {
354+
newCollectionConfigs := newCollectionConfigPackage.GetConfig()
355+
if err := validateNewCollectionConfigs(newCollectionConfigs); err != nil {
356+
return err
357+
}
306358
}
307359

308360
// TODO: FAB-6526 - to add validation of the collections object
@@ -410,7 +462,7 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
410462
if len(lsccrwset.Writes) < 1 {
411463
return errors.New("LSCC must issue at least one single putState upon deploy/upgrade")
412464
}
413-
// the first key name must be the chaincode id
465+
// the first key name must be the chaincode id provided in the deployment spec
414466
if lsccrwset.Writes[0].Key != cdsArgs.ChaincodeSpec.ChaincodeId.Name {
415467
return fmt.Errorf("Expected key %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Name, lsccrwset.Writes[0].Key)
416468
}
@@ -420,11 +472,11 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
420472
if err != nil {
421473
return fmt.Errorf("Unmarhsalling of ChaincodeData failed, error %s", err)
422474
}
423-
// the name must match
475+
// the chaincode name in the lsccwriteset must match the chaincode name in the deployment spec
424476
if cdRWSet.Name != cdsArgs.ChaincodeSpec.ChaincodeId.Name {
425477
return fmt.Errorf("Expected cc name %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Name, cdRWSet.Name)
426478
}
427-
// the version must match
479+
// the chaincode version in the lsccwriteset must match the chaincode version in the deployment spec
428480
if cdRWSet.Version != cdsArgs.ChaincodeSpec.ChaincodeId.Version {
429481
return fmt.Errorf("Expected cc version %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Version, cdRWSet.Version)
430482
}
@@ -444,7 +496,7 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
444496
/****************************************************************************/
445497
if ac.PrivateChannelData() {
446498
// do extra validation for collections
447-
err = vscc.validateDeployRWSetAndCollection(lsccrwset, cdRWSet, lsccArgs, chid, cdsArgs.ChaincodeSpec.ChaincodeId.Name)
499+
err = vscc.validateRWSetAndCollection(lsccrwset, cdRWSet, lsccArgs, lsccFunc, ac, chid)
448500
if err != nil {
449501
return err
450502
}

0 commit comments

Comments
 (0)