github.com/anjalikarhana/fabric@v2.1.1+incompatible/core/handlers/validation/builtin/v12/validation_logic.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package v12
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"regexp"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	"github.com/hyperledger/fabric-protos-go/common"
    16  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    17  	"github.com/hyperledger/fabric-protos-go/msp"
    18  	pb "github.com/hyperledger/fabric-protos-go/peer"
    19  	commonerrors "github.com/hyperledger/fabric/common/errors"
    20  	"github.com/hyperledger/fabric/common/flogging"
    21  	"github.com/hyperledger/fabric/core/common/ccprovider"
    22  	"github.com/hyperledger/fabric/core/common/privdata"
    23  	vc "github.com/hyperledger/fabric/core/handlers/validation/api/capabilities"
    24  	vi "github.com/hyperledger/fabric/core/handlers/validation/api/identities"
    25  	vp "github.com/hyperledger/fabric/core/handlers/validation/api/policies"
    26  	vs "github.com/hyperledger/fabric/core/handlers/validation/api/state"
    27  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
    28  	"github.com/hyperledger/fabric/core/scc/lscc"
    29  	"github.com/hyperledger/fabric/protoutil"
    30  	"github.com/pkg/errors"
    31  )
    32  
    33  var (
    34  	logger = flogging.MustGetLogger("vscc")
    35  
    36  	// currently defined system chaincode names that shouldn't
    37  	// be allowed as user-defined chaincode names
    38  	systemChaincodeNames = map[string]struct{}{
    39  		"cscc": {},
    40  		"escc": {},
    41  		"lscc": {},
    42  		"qscc": {},
    43  		"vscc": {},
    44  	}
    45  )
    46  
    47  const (
    48  	DUPLICATED_IDENTITY_ERROR = "Endorsement policy evaluation failure might be caused by duplicated identities"
    49  )
    50  
    51  const AllowedCharsCollectionName = "[A-Za-z0-9_-]+"
    52  
    53  var validCollectionNameRegex = regexp.MustCompile(AllowedCharsCollectionName)
    54  
    55  //go:generate mockery -dir . -name Capabilities -case underscore -output mocks/
    56  
    57  // Capabilities is the local interface that used to generate mocks for foreign interface.
    58  type Capabilities interface {
    59  	vc.Capabilities
    60  }
    61  
    62  //go:generate mockery -dir . -name StateFetcher -case underscore -output mocks/
    63  
    64  // StateFetcher is the local interface that used to generate mocks for foreign interface.
    65  type StateFetcher interface {
    66  	vs.StateFetcher
    67  }
    68  
    69  //go:generate mockery -dir . -name IdentityDeserializer -case underscore -output mocks/
    70  
    71  // IdentityDeserializer is the local interface that used to generate mocks for foreign interface.
    72  type IdentityDeserializer interface {
    73  	vi.IdentityDeserializer
    74  }
    75  
    76  //go:generate mockery -dir . -name PolicyEvaluator -case underscore -output mocks/
    77  
    78  // PolicyEvaluator is the local interface that used to generate mocks for foreign interface.
    79  type PolicyEvaluator interface {
    80  	vp.PolicyEvaluator
    81  }
    82  
    83  // New creates a new instance of the default VSCC
    84  // Typically this will only be invoked once per peer.
    85  func New(c vc.Capabilities, s vs.StateFetcher, d vi.IdentityDeserializer, pe vp.PolicyEvaluator) *Validator {
    86  	return &Validator{
    87  		capabilities:    c,
    88  		stateFetcher:    s,
    89  		deserializer:    d,
    90  		policyEvaluator: pe,
    91  	}
    92  }
    93  
    94  // Validator implements the default transaction validation policy,
    95  // which is to check the correctness of the read-write set and the endorsement
    96  // signatures against an endorsement policy that is supplied as argument to
    97  // every invoke.
    98  type Validator struct {
    99  	deserializer    vi.IdentityDeserializer
   100  	capabilities    vc.Capabilities
   101  	stateFetcher    vs.StateFetcher
   102  	policyEvaluator vp.PolicyEvaluator
   103  }
   104  
   105  // Validate validates the given envelope corresponding to a transaction with an endorsement
   106  // policy as given in its serialized form.
   107  func (vscc *Validator) Validate(
   108  	block *common.Block,
   109  	namespace string,
   110  	txPosition int,
   111  	actionPosition int,
   112  	policyBytes []byte,
   113  ) commonerrors.TxValidationError {
   114  	// get the envelope...
   115  	env, err := protoutil.GetEnvelopeFromBlock(block.Data.Data[txPosition])
   116  	if err != nil {
   117  		logger.Errorf("VSCC error: GetEnvelope failed, err %s", err)
   118  		return policyErr(err)
   119  	}
   120  
   121  	// ...and the payload...
   122  	payl, err := protoutil.UnmarshalPayload(env.Payload)
   123  	if err != nil {
   124  		logger.Errorf("VSCC error: GetPayload failed, err %s", err)
   125  		return policyErr(err)
   126  	}
   127  
   128  	chdr, err := protoutil.UnmarshalChannelHeader(payl.Header.ChannelHeader)
   129  	if err != nil {
   130  		return policyErr(err)
   131  	}
   132  
   133  	// validate the payload type
   134  	if common.HeaderType(chdr.Type) != common.HeaderType_ENDORSER_TRANSACTION {
   135  		logger.Errorf("Only Endorser Transactions are supported, provided type %d", chdr.Type)
   136  		return policyErr(fmt.Errorf("Only Endorser Transactions are supported, provided type %d", chdr.Type))
   137  	}
   138  
   139  	// ...and the transaction...
   140  	tx, err := protoutil.UnmarshalTransaction(payl.Data)
   141  	if err != nil {
   142  		logger.Errorf("VSCC error: GetTransaction failed, err %s", err)
   143  		return policyErr(err)
   144  	}
   145  
   146  	cap, err := protoutil.UnmarshalChaincodeActionPayload(tx.Actions[actionPosition].Payload)
   147  	if err != nil {
   148  		logger.Errorf("VSCC error: GetChaincodeActionPayload failed, err %s", err)
   149  		return policyErr(err)
   150  	}
   151  
   152  	signatureSet, err := vscc.deduplicateIdentity(cap)
   153  	if err != nil {
   154  		return policyErr(err)
   155  	}
   156  
   157  	// evaluate the signature set against the policy
   158  	err = vscc.policyEvaluator.Evaluate(policyBytes, signatureSet)
   159  	if err != nil {
   160  		logger.Warningf("Endorsement policy failure for transaction txid=%s, err: %s", chdr.GetTxId(), err.Error())
   161  		if len(signatureSet) < len(cap.Action.Endorsements) {
   162  			// Warning: duplicated identities exist, endorsement failure might be cause by this reason
   163  			return policyErr(errors.New(DUPLICATED_IDENTITY_ERROR))
   164  		}
   165  		return policyErr(fmt.Errorf("VSCC error: endorsement policy failure, err: %s", err))
   166  	}
   167  
   168  	// do some extra validation that is specific to lscc
   169  	if namespace == "lscc" {
   170  		logger.Debugf("VSCC info: doing special validation for LSCC")
   171  		err := vscc.ValidateLSCCInvocation(chdr.ChannelId, env, cap, payl, vscc.capabilities)
   172  		if err != nil {
   173  			logger.Errorf("VSCC error: ValidateLSCCInvocation failed, err %s", err)
   174  			return err
   175  		}
   176  	}
   177  
   178  	return nil
   179  }
   180  
   181  // checkInstantiationPolicy evaluates an instantiation policy against a signed proposal.
   182  func (vscc *Validator) checkInstantiationPolicy(chainName string, env *common.Envelope, instantiationPolicy []byte, payl *common.Payload) commonerrors.TxValidationError {
   183  	// get the signature header
   184  	shdr, err := protoutil.UnmarshalSignatureHeader(payl.Header.SignatureHeader)
   185  	if err != nil {
   186  		return policyErr(err)
   187  	}
   188  
   189  	// construct signed data we can evaluate the instantiation policy against
   190  	sd := []*protoutil.SignedData{{
   191  		Data:      env.Payload,
   192  		Identity:  shdr.Creator,
   193  		Signature: env.Signature,
   194  	}}
   195  	err = vscc.policyEvaluator.Evaluate(instantiationPolicy, sd)
   196  	if err != nil {
   197  		return policyErr(fmt.Errorf("chaincode instantiation policy violated, error %s", err))
   198  	}
   199  	return nil
   200  }
   201  
   202  func validateNewCollectionConfigs(newCollectionConfigs []*pb.CollectionConfig) error {
   203  	newCollectionsMap := make(map[string]bool, len(newCollectionConfigs))
   204  	// Process each collection config from a set of collection configs
   205  	for _, newCollectionConfig := range newCollectionConfigs {
   206  
   207  		newCollection := newCollectionConfig.GetStaticCollectionConfig()
   208  		if newCollection == nil {
   209  			return errors.New("unknown collection configuration type")
   210  		}
   211  
   212  		// Ensure that there are no duplicate collection names
   213  		collectionName := newCollection.GetName()
   214  
   215  		if err := validateCollectionName(collectionName); err != nil {
   216  			return err
   217  		}
   218  
   219  		if _, ok := newCollectionsMap[collectionName]; !ok {
   220  			newCollectionsMap[collectionName] = true
   221  		} else {
   222  			return fmt.Errorf("collection-name: %s -- found duplicate collection configuration", collectionName)
   223  		}
   224  
   225  		// Validate gossip related parameters present in the collection config
   226  		maximumPeerCount := newCollection.GetMaximumPeerCount()
   227  		requiredPeerCount := newCollection.GetRequiredPeerCount()
   228  		if maximumPeerCount < requiredPeerCount {
   229  			return fmt.Errorf("collection-name: %s -- maximum peer count (%d) cannot be less than the required peer count (%d)",
   230  				collectionName, maximumPeerCount, requiredPeerCount)
   231  
   232  		}
   233  		if requiredPeerCount < 0 {
   234  			return fmt.Errorf("collection-name: %s -- requiredPeerCount (%d) cannot be less than zero",
   235  				collectionName, requiredPeerCount)
   236  
   237  		}
   238  
   239  		// make sure that the signature policy is meaningful (only consists of ORs)
   240  		err := validateSpOrConcat(newCollection.MemberOrgsPolicy.GetSignaturePolicy().Rule)
   241  		if err != nil {
   242  			return errors.WithMessagef(err, "collection-name: %s -- error in member org policy", collectionName)
   243  		}
   244  	}
   245  	return nil
   246  }
   247  
   248  // validateSpOrConcat checks if the supplied signature policy is just an OR-concatenation of identities.
   249  func validateSpOrConcat(sp *common.SignaturePolicy) error {
   250  	if sp.GetNOutOf() == nil {
   251  		return nil
   252  	}
   253  	// check if N == 1 (OR concatenation)
   254  	if sp.GetNOutOf().N != 1 {
   255  		return errors.New(fmt.Sprintf("signature policy is not an OR concatenation, NOutOf %d", sp.GetNOutOf().N))
   256  	}
   257  	// recurse into all sub-rules
   258  	for _, rule := range sp.GetNOutOf().Rules {
   259  		err := validateSpOrConcat(rule)
   260  		if err != nil {
   261  			return err
   262  		}
   263  	}
   264  	return nil
   265  }
   266  
   267  func checkForMissingCollections(newCollectionsMap map[string]*pb.StaticCollectionConfig, oldCollectionConfigs []*pb.CollectionConfig,
   268  ) error {
   269  	var missingCollections []string
   270  
   271  	// In the new collection config package, ensure that there is one entry per old collection. Any
   272  	// number of new collections are allowed.
   273  	for _, oldCollectionConfig := range oldCollectionConfigs {
   274  
   275  		oldCollection := oldCollectionConfig.GetStaticCollectionConfig()
   276  		// It cannot be nil
   277  		if oldCollection == nil {
   278  			return policyErr(fmt.Errorf("unknown collection configuration type"))
   279  		}
   280  
   281  		// All old collection must exist in the new collection config package
   282  		oldCollectionName := oldCollection.GetName()
   283  		_, ok := newCollectionsMap[oldCollectionName]
   284  		if !ok {
   285  			missingCollections = append(missingCollections, oldCollectionName)
   286  		}
   287  	}
   288  
   289  	if len(missingCollections) > 0 {
   290  		return policyErr(fmt.Errorf("the following existing collections are missing in the new collection configuration package: %v",
   291  			missingCollections))
   292  	}
   293  
   294  	return nil
   295  }
   296  
   297  func checkForModifiedCollectionsBTL(newCollectionsMap map[string]*pb.StaticCollectionConfig, oldCollectionConfigs []*pb.CollectionConfig,
   298  ) error {
   299  	var modifiedCollectionsBTL []string
   300  
   301  	// In the new collection config package, ensure that the block to live value is not
   302  	// modified for the existing collections.
   303  	for _, oldCollectionConfig := range oldCollectionConfigs {
   304  
   305  		oldCollection := oldCollectionConfig.GetStaticCollectionConfig()
   306  		// It cannot be nil
   307  		if oldCollection == nil {
   308  			return policyErr(fmt.Errorf("unknown collection configuration type"))
   309  		}
   310  
   311  		oldCollectionName := oldCollection.GetName()
   312  		newCollection, _ := newCollectionsMap[oldCollectionName]
   313  		// BlockToLive cannot be changed
   314  		if newCollection.GetBlockToLive() != oldCollection.GetBlockToLive() {
   315  			modifiedCollectionsBTL = append(modifiedCollectionsBTL, oldCollectionName)
   316  		}
   317  	}
   318  
   319  	if len(modifiedCollectionsBTL) > 0 {
   320  		return policyErr(fmt.Errorf("the BlockToLive in the following existing collections must not be modified: %v",
   321  			modifiedCollectionsBTL))
   322  	}
   323  
   324  	return nil
   325  }
   326  
   327  func validateNewCollectionConfigsAgainstOld(newCollectionConfigs []*pb.CollectionConfig, oldCollectionConfigs []*pb.CollectionConfig,
   328  ) error {
   329  	newCollectionsMap := make(map[string]*pb.StaticCollectionConfig, len(newCollectionConfigs))
   330  
   331  	for _, newCollectionConfig := range newCollectionConfigs {
   332  		newCollection := newCollectionConfig.GetStaticCollectionConfig()
   333  		// Collection object itself is stored as value so that we can
   334  		// check whether the block to live is changed -- FAB-7810
   335  		newCollectionsMap[newCollection.GetName()] = newCollection
   336  	}
   337  
   338  	if err := checkForMissingCollections(newCollectionsMap, oldCollectionConfigs); err != nil {
   339  		return err
   340  	}
   341  
   342  	if err := checkForModifiedCollectionsBTL(newCollectionsMap, oldCollectionConfigs); err != nil {
   343  		return err
   344  	}
   345  
   346  	return nil
   347  }
   348  
   349  func validateCollectionName(collectionName string) error {
   350  	if collectionName == "" {
   351  		return fmt.Errorf("empty collection-name is not allowed")
   352  	}
   353  	match := validCollectionNameRegex.FindString(collectionName)
   354  	if len(match) != len(collectionName) {
   355  		return fmt.Errorf("collection-name: %s not allowed. A valid collection name follows the pattern: %s",
   356  			collectionName, AllowedCharsCollectionName)
   357  	}
   358  	return nil
   359  }
   360  
   361  // validateRWSetAndCollection performs validation of the rwset
   362  // of an LSCC deploy operation and then it validates any collection
   363  // configuration.
   364  func (vscc *Validator) validateRWSetAndCollection(
   365  	lsccrwset *kvrwset.KVRWSet,
   366  	cdRWSet *ccprovider.ChaincodeData,
   367  	lsccArgs [][]byte,
   368  	lsccFunc string,
   369  	ac vc.Capabilities,
   370  	channelName string,
   371  ) commonerrors.TxValidationError {
   372  	/********************************************/
   373  	/* security check 0.a - validation of rwset */
   374  	/********************************************/
   375  	// there can only be one or two writes
   376  	if len(lsccrwset.Writes) > 2 {
   377  		return policyErr(fmt.Errorf("LSCC can only issue one or two putState upon deploy"))
   378  	}
   379  
   380  	/**********************************************************/
   381  	/* security check 0.b - validation of the collection data */
   382  	/**********************************************************/
   383  	var collectionsConfigArg []byte
   384  	if len(lsccArgs) > 5 {
   385  		collectionsConfigArg = lsccArgs[5]
   386  	}
   387  
   388  	var collectionsConfigLedger []byte
   389  	if len(lsccrwset.Writes) == 2 {
   390  		key := privdata.BuildCollectionKVSKey(cdRWSet.Name)
   391  		if lsccrwset.Writes[1].Key != key {
   392  			return policyErr(fmt.Errorf("invalid key for the collection of chaincode %s:%s; expected '%s', received '%s'",
   393  				cdRWSet.Name, cdRWSet.Version, key, lsccrwset.Writes[1].Key))
   394  
   395  		}
   396  
   397  		collectionsConfigLedger = lsccrwset.Writes[1].Value
   398  	}
   399  
   400  	if !bytes.Equal(collectionsConfigArg, collectionsConfigLedger) {
   401  		return policyErr(fmt.Errorf("collection configuration arguments supplied for chaincode %s:%s do not match the configuration in the lscc writeset",
   402  			cdRWSet.Name, cdRWSet.Version))
   403  
   404  	}
   405  
   406  	channelState, err := vscc.stateFetcher.FetchState()
   407  	if err != nil {
   408  		return &commonerrors.VSCCExecutionFailureError{Err: fmt.Errorf("failed obtaining query executor: %v", err)}
   409  	}
   410  	defer channelState.Done()
   411  
   412  	state := &state{channelState}
   413  
   414  	// The following condition check added in v1.1 may not be needed as it is not possible to have the chaincodeName~collection key in
   415  	// the lscc namespace before a chaincode deploy. To avoid forks in v1.2, the following condition is retained.
   416  	if lsccFunc == lscc.DEPLOY {
   417  		colCriteria := privdata.CollectionCriteria{Channel: channelName, Namespace: cdRWSet.Name}
   418  		ccp, err := privdata.RetrieveCollectionConfigPackageFromState(colCriteria, state)
   419  		if err != nil {
   420  			// fail if we get any error other than NoSuchCollectionError
   421  			// because it means something went wrong while looking up the
   422  			// older collection
   423  			if _, ok := err.(privdata.NoSuchCollectionError); !ok {
   424  				return &commonerrors.VSCCExecutionFailureError{Err: fmt.Errorf("unable to check whether collection existed earlier for chaincode %s:%s",
   425  					cdRWSet.Name, cdRWSet.Version),
   426  				}
   427  			}
   428  		}
   429  		if ccp != nil {
   430  			return policyErr(fmt.Errorf("collection data should not exist for chaincode %s:%s", cdRWSet.Name, cdRWSet.Version))
   431  		}
   432  	}
   433  
   434  	// TODO: Once the new chaincode lifecycle is available (FAB-8724), the following validation
   435  	// and other validation performed in ValidateLSCCInvocation can be moved to LSCC itself.
   436  	newCollectionConfigPackage := &pb.CollectionConfigPackage{}
   437  
   438  	if collectionsConfigArg != nil {
   439  		err := proto.Unmarshal(collectionsConfigArg, newCollectionConfigPackage)
   440  		if err != nil {
   441  			return policyErr(fmt.Errorf("invalid collection configuration supplied for chaincode %s:%s",
   442  				cdRWSet.Name, cdRWSet.Version))
   443  		}
   444  	} else {
   445  		return nil
   446  	}
   447  
   448  	if ac.V1_2Validation() {
   449  		newCollectionConfigs := newCollectionConfigPackage.GetConfig()
   450  		if err := validateNewCollectionConfigs(newCollectionConfigs); err != nil {
   451  			return policyErr(err)
   452  		}
   453  
   454  		if lsccFunc == lscc.UPGRADE {
   455  
   456  			collectionCriteria := privdata.CollectionCriteria{Channel: channelName, Namespace: cdRWSet.Name}
   457  			// oldCollectionConfigPackage denotes the existing collection config package in the ledger
   458  			oldCollectionConfigPackage, err := privdata.RetrieveCollectionConfigPackageFromState(collectionCriteria, state)
   459  			if err != nil {
   460  				// fail if we get any error other than NoSuchCollectionError
   461  				// because it means something went wrong while looking up the
   462  				// older collection
   463  				if _, ok := err.(privdata.NoSuchCollectionError); !ok {
   464  					return &commonerrors.VSCCExecutionFailureError{Err: fmt.Errorf("unable to check whether collection existed earlier for chaincode %s:%s: %v",
   465  						cdRWSet.Name, cdRWSet.Version, err),
   466  					}
   467  				}
   468  			}
   469  
   470  			// oldCollectionConfigPackage denotes the existing collection config package in the ledger
   471  			if oldCollectionConfigPackage != nil {
   472  				oldCollectionConfigs := oldCollectionConfigPackage.GetConfig()
   473  				if err := validateNewCollectionConfigsAgainstOld(newCollectionConfigs, oldCollectionConfigs); err != nil {
   474  					return policyErr(err)
   475  				}
   476  
   477  			}
   478  		}
   479  	}
   480  
   481  	return nil
   482  }
   483  
   484  func (vscc *Validator) ValidateLSCCInvocation(
   485  	chid string,
   486  	env *common.Envelope,
   487  	cap *pb.ChaincodeActionPayload,
   488  	payl *common.Payload,
   489  	ac vc.Capabilities,
   490  ) commonerrors.TxValidationError {
   491  	cpp, err := protoutil.UnmarshalChaincodeProposalPayload(cap.ChaincodeProposalPayload)
   492  	if err != nil {
   493  		logger.Errorf("VSCC error: GetChaincodeProposalPayload failed, err %s", err)
   494  		return policyErr(err)
   495  	}
   496  
   497  	cis := &pb.ChaincodeInvocationSpec{}
   498  	err = proto.Unmarshal(cpp.Input, cis)
   499  	if err != nil {
   500  		logger.Errorf("VSCC error: Unmarshal ChaincodeInvocationSpec failed, err %s", err)
   501  		return policyErr(err)
   502  	}
   503  
   504  	if cis.ChaincodeSpec == nil ||
   505  		cis.ChaincodeSpec.Input == nil ||
   506  		cis.ChaincodeSpec.Input.Args == nil {
   507  		logger.Errorf("VSCC error: committing invalid vscc invocation")
   508  		return policyErr(fmt.Errorf("malformed chaincode invocation spec"))
   509  	}
   510  
   511  	lsccFunc := string(cis.ChaincodeSpec.Input.Args[0])
   512  	lsccArgs := cis.ChaincodeSpec.Input.Args[1:]
   513  
   514  	logger.Debugf("VSCC info: ValidateLSCCInvocation acting on %s %#v", lsccFunc, lsccArgs)
   515  
   516  	switch lsccFunc {
   517  	case lscc.UPGRADE, lscc.DEPLOY:
   518  		logger.Debugf("VSCC info: validating invocation of lscc function %s on arguments %#v", lsccFunc, lsccArgs)
   519  
   520  		if len(lsccArgs) < 2 {
   521  			return policyErr(fmt.Errorf("Wrong number of arguments for invocation lscc(%s): expected at least 2, received %d", lsccFunc, len(lsccArgs)))
   522  		}
   523  
   524  		if (!ac.PrivateChannelData() && len(lsccArgs) > 5) ||
   525  			(ac.PrivateChannelData() && len(lsccArgs) > 6) {
   526  			return policyErr(fmt.Errorf("Wrong number of arguments for invocation lscc(%s): received %d", lsccFunc, len(lsccArgs)))
   527  		}
   528  
   529  		cdsArgs, err := protoutil.UnmarshalChaincodeDeploymentSpec(lsccArgs[1])
   530  		if err != nil {
   531  			return policyErr(fmt.Errorf("GetChaincodeDeploymentSpec error %s", err))
   532  		}
   533  
   534  		if cdsArgs == nil || cdsArgs.ChaincodeSpec == nil || cdsArgs.ChaincodeSpec.ChaincodeId == nil ||
   535  			cap.Action == nil || cap.Action.ProposalResponsePayload == nil {
   536  			return policyErr(fmt.Errorf("VSCC error: invocation of lscc(%s) does not have appropriate arguments", lsccFunc))
   537  		}
   538  
   539  		switch cdsArgs.ChaincodeSpec.Type.String() {
   540  		case "GOLANG", "NODE", "JAVA", "CAR":
   541  		default:
   542  			return policyErr(fmt.Errorf("unexpected chaincode spec type: %s", cdsArgs.ChaincodeSpec.Type.String()))
   543  		}
   544  
   545  		// validate chaincode name
   546  		ccName := cdsArgs.ChaincodeSpec.ChaincodeId.Name
   547  		// it must comply with the lscc.ChaincodeNameRegExp
   548  		if !lscc.ChaincodeNameRegExp.MatchString(ccName) {
   549  			return policyErr(errors.Errorf("invalid chaincode name '%s'", ccName))
   550  		}
   551  		// it can't match the name of one of the system chaincodes
   552  		if _, in := systemChaincodeNames[ccName]; in {
   553  			return policyErr(errors.Errorf("chaincode name '%s' is reserved for system chaincodes", ccName))
   554  		}
   555  
   556  		// validate chaincode version
   557  		ccVersion := cdsArgs.ChaincodeSpec.ChaincodeId.Version
   558  		// it must comply with the lscc.ChaincodeVersionRegExp
   559  		if !lscc.ChaincodeVersionRegExp.MatchString(ccVersion) {
   560  			return policyErr(errors.Errorf("invalid chaincode version '%s'", ccVersion))
   561  		}
   562  
   563  		// get the rwset
   564  		pRespPayload, err := protoutil.UnmarshalProposalResponsePayload(cap.Action.ProposalResponsePayload)
   565  		if err != nil {
   566  			return policyErr(fmt.Errorf("GetProposalResponsePayload error %s", err))
   567  		}
   568  		if pRespPayload.Extension == nil {
   569  			return policyErr(fmt.Errorf("nil pRespPayload.Extension"))
   570  		}
   571  		respPayload, err := protoutil.UnmarshalChaincodeAction(pRespPayload.Extension)
   572  		if err != nil {
   573  			return policyErr(fmt.Errorf("GetChaincodeAction error %s", err))
   574  		}
   575  		txRWSet := &rwsetutil.TxRwSet{}
   576  		if err = txRWSet.FromProtoBytes(respPayload.Results); err != nil {
   577  			return policyErr(fmt.Errorf("txRWSet.FromProtoBytes error %s", err))
   578  		}
   579  
   580  		// extract the rwset for lscc
   581  		var lsccrwset *kvrwset.KVRWSet
   582  		for _, ns := range txRWSet.NsRwSets {
   583  			logger.Debugf("Namespace %s", ns.NameSpace)
   584  			if ns.NameSpace == "lscc" {
   585  				lsccrwset = ns.KvRwSet
   586  				break
   587  			}
   588  		}
   589  
   590  		// retrieve from the ledger the entry for the chaincode at hand
   591  		cdLedger, ccExistsOnLedger, err := vscc.getInstantiatedCC(chid, cdsArgs.ChaincodeSpec.ChaincodeId.Name)
   592  		if err != nil {
   593  			return &commonerrors.VSCCExecutionFailureError{Err: err}
   594  		}
   595  
   596  		/******************************************/
   597  		/* security check 0 - validation of rwset */
   598  		/******************************************/
   599  		// there has to be a write-set
   600  		if lsccrwset == nil {
   601  			return policyErr(fmt.Errorf("No read write set for lscc was found"))
   602  		}
   603  		// there must be at least one write
   604  		if len(lsccrwset.Writes) < 1 {
   605  			return policyErr(fmt.Errorf("LSCC must issue at least one single putState upon deploy/upgrade"))
   606  		}
   607  		// the first key name must be the chaincode id provided in the deployment spec
   608  		if lsccrwset.Writes[0].Key != cdsArgs.ChaincodeSpec.ChaincodeId.Name {
   609  			return policyErr(fmt.Errorf("expected key %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Name, lsccrwset.Writes[0].Key))
   610  		}
   611  		// the value must be a ChaincodeData struct
   612  		cdRWSet := &ccprovider.ChaincodeData{}
   613  		err = proto.Unmarshal(lsccrwset.Writes[0].Value, cdRWSet)
   614  		if err != nil {
   615  			return policyErr(fmt.Errorf("unmarhsalling of ChaincodeData failed, error %s", err))
   616  		}
   617  		// the chaincode name in the lsccwriteset must match the chaincode name in the deployment spec
   618  		if cdRWSet.Name != cdsArgs.ChaincodeSpec.ChaincodeId.Name {
   619  			return policyErr(fmt.Errorf("expected cc name %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Name, cdRWSet.Name))
   620  		}
   621  		// the chaincode version in the lsccwriteset must match the chaincode version in the deployment spec
   622  		if cdRWSet.Version != cdsArgs.ChaincodeSpec.ChaincodeId.Version {
   623  			return policyErr(fmt.Errorf("expected cc version %s, found %s", cdsArgs.ChaincodeSpec.ChaincodeId.Version, cdRWSet.Version))
   624  		}
   625  		// it must only write to 2 namespaces: LSCC's and the cc that we are deploying/upgrading
   626  		for _, ns := range txRWSet.NsRwSets {
   627  			if ns.NameSpace != "lscc" && ns.NameSpace != cdRWSet.Name && len(ns.KvRwSet.Writes) > 0 {
   628  				return policyErr(fmt.Errorf("LSCC invocation is attempting to write to namespace %s", ns.NameSpace))
   629  			}
   630  		}
   631  
   632  		logger.Debugf("Validating %s for cc %s version %s", lsccFunc, cdRWSet.Name, cdRWSet.Version)
   633  
   634  		switch lsccFunc {
   635  		case lscc.DEPLOY:
   636  
   637  			/******************************************************************/
   638  			/* security check 1 - cc not in the LCCC table of instantiated cc */
   639  			/******************************************************************/
   640  			if ccExistsOnLedger {
   641  				return policyErr(fmt.Errorf("Chaincode %s is already instantiated", cdsArgs.ChaincodeSpec.ChaincodeId.Name))
   642  			}
   643  
   644  			/****************************************************************************/
   645  			/* security check 2 - validation of rwset (and of collections if enabled) */
   646  			/****************************************************************************/
   647  			if ac.PrivateChannelData() {
   648  				// do extra validation for collections
   649  				err := vscc.validateRWSetAndCollection(lsccrwset, cdRWSet, lsccArgs, lsccFunc, ac, chid)
   650  				if err != nil {
   651  					return err
   652  				}
   653  			} else {
   654  				// there can only be a single ledger write
   655  				if len(lsccrwset.Writes) != 1 {
   656  					return policyErr(fmt.Errorf("LSCC can only issue a single putState upon deploy"))
   657  				}
   658  			}
   659  
   660  			/*****************************************************/
   661  			/* security check 3 - check the instantiation policy */
   662  			/*****************************************************/
   663  			pol := cdRWSet.InstantiationPolicy
   664  			if pol == nil {
   665  				return policyErr(fmt.Errorf("no instantiation policy was specified"))
   666  			}
   667  			// FIXME: could we actually pull the cds package from the
   668  			// file system to verify whether the policy that is specified
   669  			// here is the same as the one on disk?
   670  			// PROS: we prevent attacks where the policy is replaced
   671  			// CONS: this would be a point of non-determinism
   672  			err := vscc.checkInstantiationPolicy(chid, env, pol, payl)
   673  			if err != nil {
   674  				return err
   675  			}
   676  
   677  		case lscc.UPGRADE:
   678  			/**************************************************************/
   679  			/* security check 1 - cc in the LCCC table of instantiated cc */
   680  			/**************************************************************/
   681  			if !ccExistsOnLedger {
   682  				return policyErr(fmt.Errorf("Upgrading non-existent chaincode %s", cdsArgs.ChaincodeSpec.ChaincodeId.Name))
   683  			}
   684  
   685  			/**********************************************************/
   686  			/* security check 2 - existing cc's version was different */
   687  			/**********************************************************/
   688  			if cdLedger.Version == cdsArgs.ChaincodeSpec.ChaincodeId.Version {
   689  				return policyErr(fmt.Errorf("Existing version of the cc on the ledger (%s) should be different from the upgraded one", cdsArgs.ChaincodeSpec.ChaincodeId.Version))
   690  			}
   691  
   692  			/****************************************************************************/
   693  			/* security check 3 validation of rwset (and of collections if enabled) */
   694  			/****************************************************************************/
   695  			// Only in v1.2, a collection can be updated during a chaincode upgrade
   696  			if ac.V1_2Validation() {
   697  				// do extra validation for collections
   698  				err := vscc.validateRWSetAndCollection(lsccrwset, cdRWSet, lsccArgs, lsccFunc, ac, chid)
   699  				if err != nil {
   700  					return err
   701  				}
   702  			} else {
   703  				// there can only be a single ledger write
   704  				if len(lsccrwset.Writes) != 1 {
   705  					return policyErr(fmt.Errorf("LSCC can only issue a single putState upon upgrade"))
   706  				}
   707  			}
   708  
   709  			/*****************************************************/
   710  			/* security check 4 - check the instantiation policy */
   711  			/*****************************************************/
   712  			pol := cdLedger.InstantiationPolicy
   713  			if pol == nil {
   714  				return policyErr(fmt.Errorf("No instantiation policy was specified"))
   715  			}
   716  			// FIXME: could we actually pull the cds package from the
   717  			// file system to verify whether the policy that is specified
   718  			// here is the same as the one on disk?
   719  			// PROS: we prevent attacks where the policy is replaced
   720  			// CONS: this would be a point of non-determinism
   721  			err := vscc.checkInstantiationPolicy(chid, env, pol, payl)
   722  			if err != nil {
   723  				return err
   724  			}
   725  
   726  			/******************************************************************/
   727  			/* security check 5 - check the instantiation policy in the rwset */
   728  			/******************************************************************/
   729  			if ac.V1_1Validation() {
   730  				polNew := cdRWSet.InstantiationPolicy
   731  				if polNew == nil {
   732  					return policyErr(fmt.Errorf("No instantiation policy was specified"))
   733  				}
   734  
   735  				// no point in checking it again if they are the same policy
   736  				if !bytes.Equal(polNew, pol) {
   737  					err = vscc.checkInstantiationPolicy(chid, env, polNew, payl)
   738  					if err != nil {
   739  						return err
   740  					}
   741  				}
   742  			}
   743  		}
   744  
   745  		// all is good!
   746  		return nil
   747  	default:
   748  		return policyErr(fmt.Errorf("VSCC error: committing an invocation of function %s of lscc is invalid", lsccFunc))
   749  	}
   750  }
   751  
   752  func (vscc *Validator) getInstantiatedCC(chid, ccid string) (cd *ccprovider.ChaincodeData, exists bool, err error) {
   753  	qe, err := vscc.stateFetcher.FetchState()
   754  	if err != nil {
   755  		err = fmt.Errorf("could not retrieve QueryExecutor for channel %s, error %s", chid, err)
   756  		return
   757  	}
   758  	defer qe.Done()
   759  	channelState := &state{qe}
   760  	bytes, err := channelState.GetState("lscc", ccid)
   761  	if err != nil {
   762  		err = fmt.Errorf("could not retrieve state for chaincode %s on channel %s, error %s", ccid, chid, err)
   763  		return
   764  	}
   765  
   766  	if bytes == nil {
   767  		return
   768  	}
   769  
   770  	cd = &ccprovider.ChaincodeData{}
   771  	err = proto.Unmarshal(bytes, cd)
   772  	if err != nil {
   773  		err = fmt.Errorf("unmarshalling ChaincodeQueryResponse failed, error %s", err)
   774  		return
   775  	}
   776  
   777  	exists = true
   778  	return
   779  }
   780  
   781  func (vscc *Validator) deduplicateIdentity(cap *pb.ChaincodeActionPayload) ([]*protoutil.SignedData, error) {
   782  	// this is the first part of the signed message
   783  	prespBytes := cap.Action.ProposalResponsePayload
   784  
   785  	// build the signature set for the evaluation
   786  	signatureSet := []*protoutil.SignedData{}
   787  	signatureMap := make(map[string]struct{})
   788  	// loop through each of the endorsements and build the signature set
   789  	for _, endorsement := range cap.Action.Endorsements {
   790  		//unmarshal endorser bytes
   791  		serializedIdentity := &msp.SerializedIdentity{}
   792  		if err := proto.Unmarshal(endorsement.Endorser, serializedIdentity); err != nil {
   793  			logger.Errorf("Unmarshal endorser error: %s", err)
   794  			return nil, policyErr(fmt.Errorf("Unmarshal endorser error: %s", err))
   795  		}
   796  		identity := serializedIdentity.Mspid + string(serializedIdentity.IdBytes)
   797  		if _, ok := signatureMap[identity]; ok {
   798  			// Endorsement with the same identity has already been added
   799  			logger.Warningf("Ignoring duplicated identity, Mspid: %s, pem:\n%s", serializedIdentity.Mspid, serializedIdentity.IdBytes)
   800  			continue
   801  		}
   802  		data := make([]byte, len(prespBytes)+len(endorsement.Endorser))
   803  		copy(data, prespBytes)
   804  		copy(data[len(prespBytes):], endorsement.Endorser)
   805  		signatureSet = append(signatureSet, &protoutil.SignedData{
   806  			// set the data that is signed; concatenation of proposal response bytes and endorser ID
   807  			Data: data,
   808  			// set the identity that signs the message: it's the endorser
   809  			Identity: endorsement.Endorser,
   810  			// set the signature
   811  			Signature: endorsement.Signature})
   812  		signatureMap[identity] = struct{}{}
   813  	}
   814  
   815  	logger.Debugf("Signature set is of size %d out of %d endorsement(s)", len(signatureSet), len(cap.Action.Endorsements))
   816  	return signatureSet, nil
   817  }
   818  
   819  type state struct {
   820  	vs.State
   821  }
   822  
   823  // GetState retrieves the value for the given key in the given namespace.
   824  func (s *state) GetState(namespace string, key string) ([]byte, error) {
   825  	values, err := s.GetStateMultipleKeys(namespace, []string{key})
   826  	if err != nil {
   827  		return nil, err
   828  	}
   829  	if len(values) == 0 {
   830  		return nil, nil
   831  	}
   832  	return values[0], nil
   833  }
   834  
   835  func policyErr(err error) *commonerrors.VSCCEndorsementPolicyError {
   836  	return &commonerrors.VSCCEndorsementPolicyError{
   837  		Err: err,
   838  	}
   839  }