github.com/kaituanwang/hyperledger@v2.0.1+incompatible/core/scc/lscc/lscc.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lscc
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"regexp"
    13  	"sync"
    14  
    15  	"github.com/golang/protobuf/proto"
    16  	"github.com/hyperledger/fabric-chaincode-go/shim"
    17  	mb "github.com/hyperledger/fabric-protos-go/msp"
    18  	pb "github.com/hyperledger/fabric-protos-go/peer"
    19  	"github.com/hyperledger/fabric/bccsp"
    20  	"github.com/hyperledger/fabric/common/cauthdsl"
    21  	"github.com/hyperledger/fabric/common/channelconfig"
    22  	"github.com/hyperledger/fabric/common/flogging"
    23  	"github.com/hyperledger/fabric/common/policies"
    24  	"github.com/hyperledger/fabric/core/aclmgmt"
    25  	"github.com/hyperledger/fabric/core/aclmgmt/resources"
    26  	"github.com/hyperledger/fabric/core/chaincode/lifecycle"
    27  	"github.com/hyperledger/fabric/core/common/ccprovider"
    28  	"github.com/hyperledger/fabric/core/common/privdata"
    29  	"github.com/hyperledger/fabric/core/common/sysccprovider"
    30  	"github.com/hyperledger/fabric/core/container"
    31  	"github.com/hyperledger/fabric/core/container/externalbuilder"
    32  	"github.com/hyperledger/fabric/core/ledger"
    33  	"github.com/hyperledger/fabric/core/ledger/cceventmgmt"
    34  	"github.com/hyperledger/fabric/core/peer"
    35  	"github.com/hyperledger/fabric/core/policy"
    36  	"github.com/hyperledger/fabric/core/scc"
    37  	"github.com/hyperledger/fabric/internal/ccmetadata"
    38  	"github.com/hyperledger/fabric/msp"
    39  	"github.com/hyperledger/fabric/msp/mgmt"
    40  	"github.com/hyperledger/fabric/protoutil"
    41  	"github.com/pkg/errors"
    42  )
    43  
    44  // The lifecycle system chaincode manages chaincodes deployed
    45  // on this peer. It manages chaincodes via Invoke proposals.
    46  //     "Args":["deploy",<ChaincodeDeploymentSpec>]
    47  //     "Args":["upgrade",<ChaincodeDeploymentSpec>]
    48  //     "Args":["stop",<ChaincodeInvocationSpec>]
    49  //     "Args":["start",<ChaincodeInvocationSpec>]
    50  
    51  var (
    52  	logger = flogging.MustGetLogger("lscc")
    53  	// NOTE these regular expressions should stay in sync with those defined in
    54  	// core/chaincode/lifecycle/scc.go until LSCC has been removed.
    55  	ChaincodeNameRegExp    = regexp.MustCompile("^[a-zA-Z0-9]+([-_][a-zA-Z0-9]+)*$")
    56  	ChaincodeVersionRegExp = regexp.MustCompile("^[A-Za-z0-9_.+-]+$")
    57  )
    58  
    59  const (
    60  	// chaincode lifecycle commands
    61  
    62  	// INSTALL install command
    63  	INSTALL = "install"
    64  
    65  	// DEPLOY deploy command
    66  	DEPLOY = "deploy"
    67  
    68  	// UPGRADE upgrade chaincode
    69  	UPGRADE = "upgrade"
    70  
    71  	// CCEXISTS get chaincode
    72  	CCEXISTS = "getid"
    73  
    74  	// CHAINCODEEXISTS get chaincode alias
    75  	CHAINCODEEXISTS = "ChaincodeExists"
    76  
    77  	// GETDEPSPEC get ChaincodeDeploymentSpec
    78  	GETDEPSPEC = "getdepspec"
    79  
    80  	// GETDEPLOYMENTSPEC get ChaincodeDeploymentSpec alias
    81  	GETDEPLOYMENTSPEC = "GetDeploymentSpec"
    82  
    83  	// GETCCDATA get ChaincodeData
    84  	GETCCDATA = "getccdata"
    85  
    86  	// GETCHAINCODEDATA get ChaincodeData alias
    87  	GETCHAINCODEDATA = "GetChaincodeData"
    88  
    89  	// GETCHAINCODES gets the instantiated chaincodes on a channel
    90  	GETCHAINCODES = "getchaincodes"
    91  
    92  	// GETCHAINCODESALIAS gets the instantiated chaincodes on a channel
    93  	GETCHAINCODESALIAS = "GetChaincodes"
    94  
    95  	// GETINSTALLEDCHAINCODES gets the installed chaincodes on a peer
    96  	GETINSTALLEDCHAINCODES = "getinstalledchaincodes"
    97  
    98  	// GETINSTALLEDCHAINCODESALIAS gets the installed chaincodes on a peer
    99  	GETINSTALLEDCHAINCODESALIAS = "GetInstalledChaincodes"
   100  
   101  	// GETCOLLECTIONSCONFIG gets the collections config for a chaincode
   102  	GETCOLLECTIONSCONFIG = "GetCollectionsConfig"
   103  
   104  	// GETCOLLECTIONSCONFIGALIAS gets the collections config for a chaincode
   105  	GETCOLLECTIONSCONFIGALIAS = "getcollectionsconfig"
   106  )
   107  
   108  // FilesystemSupport contains functions that LSCC requires to execute its tasks
   109  type FilesystemSupport interface {
   110  	// PutChaincodeToLocalStorage stores the supplied chaincode
   111  	// package to local storage (i.e. the file system)
   112  	PutChaincodeToLocalStorage(ccprovider.CCPackage) error
   113  
   114  	// GetChaincodeFromLocalStorage retrieves the chaincode package
   115  	// for the requested chaincode, specified by name and version
   116  	GetChaincodeFromLocalStorage(ccNameVersion string) (ccprovider.CCPackage, error)
   117  
   118  	// GetChaincodesFromLocalStorage returns an array of all chaincode
   119  	// data that have previously been persisted to local storage
   120  	GetChaincodesFromLocalStorage() (*pb.ChaincodeQueryResponse, error)
   121  
   122  	// GetInstantiationPolicy returns the instantiation policy for the
   123  	// supplied chaincode (or the channel's default if none was specified)
   124  	GetInstantiationPolicy(channel string, ccpack ccprovider.CCPackage) ([]byte, error)
   125  
   126  	// CheckInstantiationPolicy checks whether the supplied signed proposal
   127  	// complies with the supplied instantiation policy
   128  	CheckInstantiationPolicy(signedProposal *pb.SignedProposal, chainName string, instantiationPolicy []byte) error
   129  }
   130  
   131  type ChaincodeBuilder interface {
   132  	Build(ccid string) error
   133  }
   134  
   135  // MSPsIDGetter is used to get the MSP IDs for a channel.
   136  type MSPIDsGetter func(string) []string
   137  
   138  //---------- the LSCC -----------------
   139  
   140  // SCC implements chaincode lifecycle and policies around it
   141  type SCC struct {
   142  	// aclProvider is responsible for access control evaluation
   143  	ACLProvider aclmgmt.ACLProvider
   144  
   145  	BuiltinSCCs scc.BuiltinSCCs
   146  
   147  	// SCCProvider is the interface which is passed into system chaincodes
   148  	// to access other parts of the system
   149  	SCCProvider sysccprovider.SystemChaincodeProvider
   150  
   151  	// PolicyChecker is the interface used to perform
   152  	// access control
   153  	PolicyChecker policy.PolicyChecker
   154  
   155  	// Support provides the implementation of several
   156  	// static functions
   157  	Support FilesystemSupport
   158  
   159  	GetMSPIDs MSPIDsGetter
   160  
   161  	BuildRegistry *container.BuildRegistry
   162  
   163  	ChaincodeBuilder ChaincodeBuilder
   164  
   165  	EbMetadataProvider *externalbuilder.MetadataProvider
   166  
   167  	// BCCSP instance
   168  	BCCSP bccsp.BCCSP
   169  
   170  	PackageCache PackageCache
   171  }
   172  
   173  // PeerShim adapts the peer instance for use with LSCC by providing methods
   174  // previously provided by the scc provider.  If the lscc code weren't all getting
   175  // deleted soon, it would probably be worth rewriting it to use these APIs directly
   176  // rather that go through this shim, but it will be gone soon.
   177  type PeerShim struct {
   178  	Peer *peer.Peer
   179  }
   180  
   181  // GetQueryExecutorForLedger returns a query executor for the specified channel
   182  func (p *PeerShim) GetQueryExecutorForLedger(cid string) (ledger.QueryExecutor, error) {
   183  	l := p.Peer.GetLedger(cid)
   184  	if l == nil {
   185  		return nil, fmt.Errorf("Could not retrieve ledger for channel %s", cid)
   186  	}
   187  
   188  	return l.NewQueryExecutor()
   189  }
   190  
   191  // GetApplicationConfig returns the configtxapplication.SharedConfig for the channel
   192  // and whether the Application config exists
   193  func (p *PeerShim) GetApplicationConfig(cid string) (channelconfig.Application, bool) {
   194  	return p.Peer.GetApplicationConfig(cid)
   195  }
   196  
   197  // Returns the policy manager associated to the passed channel
   198  // and whether the policy manager exists
   199  func (p *PeerShim) PolicyManager(channelID string) (policies.Manager, bool) {
   200  	m := p.Peer.GetPolicyManager(channelID)
   201  	return m, (m != nil)
   202  }
   203  
   204  func (lscc *SCC) Name() string              { return "lscc" }
   205  func (lscc *SCC) Chaincode() shim.Chaincode { return lscc }
   206  
   207  type PackageCache struct {
   208  	Mutex             sync.RWMutex
   209  	ValidatedPackages map[string]*ccprovider.ChaincodeData
   210  }
   211  
   212  type LegacySecurity struct {
   213  	Support      FilesystemSupport
   214  	PackageCache *PackageCache
   215  }
   216  
   217  func (ls *LegacySecurity) SecurityCheckLegacyChaincode(cd *ccprovider.ChaincodeData) error {
   218  	ccid := cd.ChaincodeID()
   219  
   220  	ls.PackageCache.Mutex.RLock()
   221  	fsData, ok := ls.PackageCache.ValidatedPackages[ccid]
   222  	ls.PackageCache.Mutex.RUnlock()
   223  
   224  	if !ok {
   225  		ls.PackageCache.Mutex.Lock()
   226  		defer ls.PackageCache.Mutex.Unlock()
   227  		fsData, ok = ls.PackageCache.ValidatedPackages[ccid]
   228  		if !ok {
   229  			ccpack, err := ls.Support.GetChaincodeFromLocalStorage(cd.ChaincodeID())
   230  			if err != nil {
   231  				return InvalidDeploymentSpecErr(err.Error())
   232  			}
   233  
   234  			// This is 'the big security check', though it's no clear what's being accomplished
   235  			// here.  Basically, it seems to try to verify that the chaincode defintion matches
   236  			// what's on the filesystem, which, might include instanatiation policy, but it's
   237  			// not obvious from the code, and was being checked separately, so we check it
   238  			// explicitly below.
   239  			if err = ccpack.ValidateCC(cd); err != nil {
   240  				return InvalidCCOnFSError(err.Error())
   241  			}
   242  
   243  			if ls.PackageCache.ValidatedPackages == nil {
   244  				ls.PackageCache.ValidatedPackages = map[string]*ccprovider.ChaincodeData{}
   245  			}
   246  
   247  			fsData = ccpack.GetChaincodeData()
   248  			ls.PackageCache.ValidatedPackages[ccid] = fsData
   249  		}
   250  	}
   251  
   252  	// we have the info from the fs, check that the policy
   253  	// matches the one on the file system if one was specified;
   254  	// this check is required because the admin of this peer
   255  	// might have specified instantiation policies for their
   256  	// chaincode, for example to make sure that the chaincode
   257  	// is only instantiated on certain channels; a malicious
   258  	// peer on the other hand might have created a deploy
   259  	// transaction that attempts to bypass the instantiation
   260  	// policy. This check is there to ensure that this will not
   261  	// happen, i.e. that the peer will refuse to invoke the
   262  	// chaincode under these conditions. More info on
   263  	// https://jira.hyperledger.org/browse/FAB-3156
   264  	if fsData.InstantiationPolicy != nil {
   265  		if !bytes.Equal(fsData.InstantiationPolicy, cd.InstantiationPolicy) {
   266  			return fmt.Errorf("Instantiation policy mismatch for cc %s", cd.ChaincodeID())
   267  		}
   268  	}
   269  
   270  	return nil
   271  }
   272  
   273  func (lscc *SCC) ChaincodeEndorsementInfo(channelID, chaincodeName string, qe ledger.SimpleQueryExecutor) (*lifecycle.ChaincodeEndorsementInfo, error) {
   274  	chaincodeDataBytes, err := qe.GetState("lscc", chaincodeName)
   275  	if err != nil {
   276  		return nil, errors.Wrapf(err, "could not retrieve state for chaincode %s", chaincodeName)
   277  	}
   278  
   279  	if chaincodeDataBytes == nil {
   280  		return nil, errors.Errorf("chaincode %s not found", chaincodeName)
   281  	}
   282  
   283  	chaincodeData := &ccprovider.ChaincodeData{}
   284  	err = proto.Unmarshal(chaincodeDataBytes, chaincodeData)
   285  	if err != nil {
   286  		return nil, errors.Wrapf(err, "chaincode %s has bad definition", chaincodeName)
   287  	}
   288  
   289  	ls := &LegacySecurity{
   290  		Support:      lscc.Support,
   291  		PackageCache: &lscc.PackageCache,
   292  	}
   293  
   294  	err = ls.SecurityCheckLegacyChaincode(chaincodeData)
   295  	if err != nil {
   296  		return nil, errors.WithMessage(err, "failed security checks")
   297  	}
   298  
   299  	return &lifecycle.ChaincodeEndorsementInfo{
   300  		Version:           chaincodeData.Version,
   301  		EndorsementPlugin: chaincodeData.Escc,
   302  		ChaincodeID:       chaincodeData.Name + ":" + chaincodeData.Version,
   303  	}, nil
   304  }
   305  
   306  // ValidationInfo returns name&arguments of the validation plugin for the supplied chaincode.
   307  // The function returns two types of errors, unexpected errors and validation errors. The
   308  // reason for this is that this function is to be called from the validation code, which
   309  // needs to tell apart the two types of error to halt processing on the channel if the
   310  // unexpected error is not nil and mark the transaction as invalid if the validation error
   311  // is not nil.
   312  func (lscc *SCC) ValidationInfo(channelID, chaincodeName string, qe ledger.SimpleQueryExecutor) (plugin string, args []byte, unexpectedErr error, validationErr error) {
   313  	chaincodeDataBytes, err := qe.GetState("lscc", chaincodeName)
   314  	if err != nil {
   315  		// failure to access the ledger is clearly an unexpected
   316  		// error since we expect the ledger to be reachable
   317  		unexpectedErr = errors.Wrapf(err, "could not retrieve state for chaincode %s", chaincodeName)
   318  		return
   319  	}
   320  
   321  	if chaincodeDataBytes == nil {
   322  		// no chaincode definition is a validation error since
   323  		// we're trying to retrieve chaincode definitions for a non-existent chaincode
   324  		validationErr = errors.Errorf("chaincode %s not found", chaincodeName)
   325  		return
   326  	}
   327  
   328  	chaincodeData := &ccprovider.ChaincodeData{}
   329  	err = proto.Unmarshal(chaincodeDataBytes, chaincodeData)
   330  	if err != nil {
   331  		// this kind of data corruption is unexpected since our code
   332  		// always marshals ChaincodeData into these keys
   333  		unexpectedErr = errors.Wrapf(err, "chaincode %s has bad definition", chaincodeName)
   334  		return
   335  	}
   336  
   337  	plugin = chaincodeData.Vscc
   338  	args = chaincodeData.Policy
   339  	return
   340  }
   341  
   342  //create the chaincode on the given chain
   343  func (lscc *SCC) putChaincodeData(stub shim.ChaincodeStubInterface, cd *ccprovider.ChaincodeData) error {
   344  	cdbytes, err := proto.Marshal(cd)
   345  	if err != nil {
   346  		return err
   347  	}
   348  
   349  	if cdbytes == nil {
   350  		return MarshallErr(cd.Name)
   351  	}
   352  
   353  	err = stub.PutState(cd.Name, cdbytes)
   354  
   355  	return err
   356  }
   357  
   358  // checkCollectionMemberPolicy checks whether the supplied collection configuration
   359  // complies to the given msp configuration and performs semantic validation.
   360  // Channel config may change afterwards (i.e., after endorsement or commit of this transaction).
   361  // Fabric will deal with the situation where some collection configs are no longer meaningful.
   362  // Therefore, the use of channel config for verifying during endorsement is more
   363  // towards catching manual errors in the config as oppose to any attempt of serializability.
   364  func checkCollectionMemberPolicy(collectionConfig *pb.CollectionConfig, mspmgr msp.MSPManager) error {
   365  	if mspmgr == nil {
   366  		return fmt.Errorf("msp manager not set")
   367  	}
   368  	msps, err := mspmgr.GetMSPs()
   369  	if err != nil {
   370  		return errors.Wrapf(err, "error getting channel msp")
   371  	}
   372  	if collectionConfig == nil {
   373  		return fmt.Errorf("collection configuration is not set")
   374  	}
   375  	coll := collectionConfig.GetStaticCollectionConfig()
   376  	if coll == nil {
   377  		return fmt.Errorf("collection configuration is empty")
   378  	}
   379  	if coll.MemberOrgsPolicy == nil {
   380  		return fmt.Errorf("collection member policy is not set")
   381  	}
   382  	if coll.MemberOrgsPolicy.GetSignaturePolicy() == nil {
   383  		return fmt.Errorf("collection member org policy is empty")
   384  	}
   385  	// make sure that the orgs listed are actually part of the channel
   386  	// check all principals in the signature policy
   387  	for _, principal := range coll.MemberOrgsPolicy.GetSignaturePolicy().Identities {
   388  		found := false
   389  		var orgID string
   390  		// the member org policy only supports certain principal types
   391  		switch principal.PrincipalClassification {
   392  
   393  		case mb.MSPPrincipal_ROLE:
   394  			msprole := &mb.MSPRole{}
   395  			err := proto.Unmarshal(principal.Principal, msprole)
   396  			if err != nil {
   397  				return errors.Wrapf(err, "collection-name: %s -- cannot unmarshal identities", coll.GetName())
   398  			}
   399  			orgID = msprole.MspIdentifier
   400  			// the msp map is indexed using msp IDs - this behavior is implementation specific, making the following check a bit of a hack
   401  			for mspid := range msps {
   402  				if mspid == orgID {
   403  					found = true
   404  					break
   405  				}
   406  			}
   407  
   408  		case mb.MSPPrincipal_ORGANIZATION_UNIT:
   409  			mspou := &mb.OrganizationUnit{}
   410  			err := proto.Unmarshal(principal.Principal, mspou)
   411  			if err != nil {
   412  				return errors.Wrapf(err, "collection-name: %s -- cannot unmarshal identities", coll.GetName())
   413  			}
   414  			orgID = mspou.MspIdentifier
   415  			// the msp map is indexed using msp IDs - this behavior is implementation specific, making the following check a bit of a hack
   416  			for mspid := range msps {
   417  				if mspid == orgID {
   418  					found = true
   419  					break
   420  				}
   421  			}
   422  
   423  		case mb.MSPPrincipal_IDENTITY:
   424  			orgID = "identity principal"
   425  			for _, msp := range msps {
   426  				_, err := msp.DeserializeIdentity(principal.Principal)
   427  				if err == nil {
   428  					found = true
   429  					break
   430  				}
   431  			}
   432  		default:
   433  			return fmt.Errorf("collection-name: %s -- principal type %v is not supported", coll.GetName(), principal.PrincipalClassification)
   434  		}
   435  		if !found {
   436  			logger.Warningf("collection-name: %s collection member %s is not part of the channel", coll.GetName(), orgID)
   437  		}
   438  	}
   439  
   440  	// Call the constructor for SignaturePolicyEnvelope evaluators to perform extra semantic validation.
   441  	// Among other things, this validation catches any out-of-range references to the identities array.
   442  	policyProvider := &cauthdsl.EnvelopeBasedPolicyProvider{Deserializer: mspmgr}
   443  	if _, err := policyProvider.NewPolicy(coll.MemberOrgsPolicy.GetSignaturePolicy()); err != nil {
   444  		logger.Errorf("Invalid member org policy for collection '%s', error: %s", coll.Name, err)
   445  		return errors.WithMessage(err, fmt.Sprintf("invalid member org policy for collection '%s'", coll.Name))
   446  	}
   447  
   448  	return nil
   449  }
   450  
   451  // putChaincodeCollectionData adds collection data for the chaincode
   452  func (lscc *SCC) putChaincodeCollectionData(stub shim.ChaincodeStubInterface, cd *ccprovider.ChaincodeData, collectionConfigBytes []byte) error {
   453  	if cd == nil {
   454  		return errors.New("nil ChaincodeData")
   455  	}
   456  
   457  	if len(collectionConfigBytes) == 0 {
   458  		logger.Debug("No collection configuration specified")
   459  		return nil
   460  	}
   461  
   462  	collections := &pb.CollectionConfigPackage{}
   463  	err := proto.Unmarshal(collectionConfigBytes, collections)
   464  	if err != nil {
   465  		return errors.Errorf("invalid collection configuration supplied for chaincode %s:%s", cd.Name, cd.Version)
   466  	}
   467  
   468  	mspmgr := mgmt.GetManagerForChain(stub.GetChannelID())
   469  	if mspmgr == nil {
   470  		return fmt.Errorf("could not get MSP manager for channel %s", stub.GetChannelID())
   471  	}
   472  	for _, collectionConfig := range collections.Config {
   473  		err = checkCollectionMemberPolicy(collectionConfig, mspmgr)
   474  		if err != nil {
   475  			return errors.Wrapf(err, "collection member policy check failed")
   476  		}
   477  	}
   478  
   479  	key := privdata.BuildCollectionKVSKey(cd.Name)
   480  
   481  	err = stub.PutState(key, collectionConfigBytes)
   482  	if err != nil {
   483  		return errors.WithMessagef(err, "error putting collection for chaincode %s:%s", cd.Name, cd.Version)
   484  	}
   485  
   486  	return nil
   487  }
   488  
   489  // getChaincodeCollectionData retrieve collections config.
   490  func (lscc *SCC) getChaincodeCollectionData(stub shim.ChaincodeStubInterface, chaincodeName string) pb.Response {
   491  	key := privdata.BuildCollectionKVSKey(chaincodeName)
   492  	collectionsConfigBytes, err := stub.GetState(key)
   493  	if err != nil {
   494  		return shim.Error(err.Error())
   495  	}
   496  	if len(collectionsConfigBytes) == 0 {
   497  		return shim.Error(fmt.Sprintf("collections config not defined for chaincode %s", chaincodeName))
   498  	}
   499  	return shim.Success(collectionsConfigBytes)
   500  }
   501  
   502  //checks for existence of chaincode on the given channel
   503  func (lscc *SCC) getCCInstance(stub shim.ChaincodeStubInterface, ccname string) ([]byte, error) {
   504  	cdbytes, err := stub.GetState(ccname)
   505  	if err != nil {
   506  		return nil, TXNotFoundErr(err.Error())
   507  	}
   508  	if cdbytes == nil {
   509  		return nil, NotFoundErr(ccname)
   510  	}
   511  
   512  	return cdbytes, nil
   513  }
   514  
   515  //gets the cd out of the bytes
   516  func (lscc *SCC) getChaincodeData(ccname string, cdbytes []byte) (*ccprovider.ChaincodeData, error) {
   517  	cd := &ccprovider.ChaincodeData{}
   518  	err := proto.Unmarshal(cdbytes, cd)
   519  	if err != nil {
   520  		return nil, MarshallErr(ccname)
   521  	}
   522  
   523  	//this should not happen but still a sanity check is not a bad thing
   524  	if cd.Name != ccname {
   525  		return nil, ChaincodeMismatchErr(fmt.Sprintf("%s!=%s", ccname, cd.Name))
   526  	}
   527  
   528  	return cd, nil
   529  }
   530  
   531  //checks for existence of chaincode on the given chain
   532  func (lscc *SCC) getCCCode(ccname string, cdbytes []byte) (*pb.ChaincodeDeploymentSpec, []byte, error) {
   533  	cd, err := lscc.getChaincodeData(ccname, cdbytes)
   534  	if err != nil {
   535  		return nil, nil, err
   536  	}
   537  
   538  	ccpack, err := lscc.Support.GetChaincodeFromLocalStorage(cd.ChaincodeID())
   539  	if err != nil {
   540  		return nil, nil, InvalidDeploymentSpecErr(err.Error())
   541  	}
   542  
   543  	//this is the big test and the reason every launch should go through
   544  	//getChaincode call. We validate the chaincode entry against the
   545  	//the chaincode in FS
   546  	if err = ccpack.ValidateCC(cd); err != nil {
   547  		return nil, nil, InvalidCCOnFSError(err.Error())
   548  	}
   549  
   550  	//these are guaranteed to be non-nil because we got a valid ccpack
   551  	depspec := ccpack.GetDepSpec()
   552  	depspecbytes := ccpack.GetDepSpecBytes()
   553  
   554  	return depspec, depspecbytes, nil
   555  }
   556  
   557  // getChaincodes returns all chaincodes instantiated on this LSCC's channel
   558  func (lscc *SCC) getChaincodes(stub shim.ChaincodeStubInterface) pb.Response {
   559  	// get all rows from LSCC
   560  	itr, err := stub.GetStateByRange("", "")
   561  
   562  	if err != nil {
   563  		return shim.Error(err.Error())
   564  	}
   565  	defer itr.Close()
   566  
   567  	// array to store metadata for all chaincode entries from LSCC
   568  	var ccInfoArray []*pb.ChaincodeInfo
   569  
   570  	for itr.HasNext() {
   571  		response, err := itr.Next()
   572  		if err != nil {
   573  			return shim.Error(err.Error())
   574  		}
   575  
   576  		// CollectionConfig isn't ChaincodeData
   577  		if privdata.IsCollectionConfigKey(response.Key) {
   578  			continue
   579  		}
   580  
   581  		ccdata := &ccprovider.ChaincodeData{}
   582  		if err = proto.Unmarshal(response.Value, ccdata); err != nil {
   583  			return shim.Error(err.Error())
   584  		}
   585  
   586  		var path string
   587  		var input string
   588  
   589  		// if chaincode is not installed on the system we won't have
   590  		// data beyond name and version
   591  		ccpack, err := lscc.Support.GetChaincodeFromLocalStorage(ccdata.ChaincodeID())
   592  		if err == nil {
   593  			path = ccpack.GetDepSpec().GetChaincodeSpec().ChaincodeId.Path
   594  			input = ccpack.GetDepSpec().GetChaincodeSpec().Input.String()
   595  		}
   596  
   597  		// add this specific chaincode's metadata to the array of all chaincodes
   598  		ccInfo := &pb.ChaincodeInfo{Name: ccdata.Name, Version: ccdata.Version, Path: path, Input: input, Escc: ccdata.Escc, Vscc: ccdata.Vscc}
   599  		ccInfoArray = append(ccInfoArray, ccInfo)
   600  	}
   601  	// add array with info about all instantiated chaincodes to the query
   602  	// response proto
   603  	cqr := &pb.ChaincodeQueryResponse{Chaincodes: ccInfoArray}
   604  
   605  	cqrbytes, err := proto.Marshal(cqr)
   606  	if err != nil {
   607  		return shim.Error(err.Error())
   608  	}
   609  
   610  	return shim.Success(cqrbytes)
   611  }
   612  
   613  // getInstalledChaincodes returns all chaincodes installed on the peer
   614  func (lscc *SCC) getInstalledChaincodes() pb.Response {
   615  	// get chaincode query response proto which contains information about all
   616  	// installed chaincodes
   617  	cqr, err := lscc.Support.GetChaincodesFromLocalStorage()
   618  	if err != nil {
   619  		return shim.Error(err.Error())
   620  	}
   621  
   622  	cqrbytes, err := proto.Marshal(cqr)
   623  	if err != nil {
   624  		return shim.Error(err.Error())
   625  	}
   626  
   627  	return shim.Success(cqrbytes)
   628  }
   629  
   630  // check validity of channel name
   631  func (lscc *SCC) isValidChannelName(channel string) bool {
   632  	// TODO we probably need more checks
   633  	if channel == "" {
   634  		return false
   635  	}
   636  	return true
   637  }
   638  
   639  // isValidChaincodeName checks the validity of chaincode name. Chaincode names
   640  // should never be blank and should only consist of alphanumerics, '_', and '-'
   641  func (lscc *SCC) isValidChaincodeName(chaincodeName string) error {
   642  	if !ChaincodeNameRegExp.MatchString(chaincodeName) {
   643  		return InvalidChaincodeNameErr(chaincodeName)
   644  	}
   645  
   646  	return nil
   647  }
   648  
   649  // isValidChaincodeVersion checks the validity of chaincode version. Versions
   650  // should never be blank and should only consist of alphanumerics, '_',  '-',
   651  // '+', and '.'
   652  func (lscc *SCC) isValidChaincodeVersion(chaincodeName string, version string) error {
   653  	if !ChaincodeVersionRegExp.MatchString(version) {
   654  		return InvalidVersionErr(version)
   655  	}
   656  
   657  	return nil
   658  }
   659  
   660  func isValidStatedbArtifactsTar(statedbArtifactsTar []byte) error {
   661  	// Extract the metadata files from the archive
   662  	// Passing an empty string for the databaseType will validate all artifacts in
   663  	// the archive
   664  	archiveFiles, err := ccprovider.ExtractFileEntries(statedbArtifactsTar, "")
   665  	if err != nil {
   666  		return err
   667  	}
   668  	// iterate through the files and validate
   669  	for _, archiveDirectoryFiles := range archiveFiles {
   670  		for _, fileEntry := range archiveDirectoryFiles {
   671  			indexData := fileEntry.FileContent
   672  			// Validation is based on the passed file name, e.g. META-INF/statedb/couchdb/indexes/indexname.json
   673  			err = ccmetadata.ValidateMetadataFile(fileEntry.FileHeader.Name, indexData)
   674  			if err != nil {
   675  				return err
   676  			}
   677  		}
   678  	}
   679  
   680  	return nil
   681  }
   682  
   683  // executeInstall implements the "install" Invoke transaction
   684  func (lscc *SCC) executeInstall(stub shim.ChaincodeStubInterface, ccbytes []byte) error {
   685  	ccpack, err := ccprovider.GetCCPackage(ccbytes, lscc.BCCSP)
   686  	if err != nil {
   687  		return err
   688  	}
   689  
   690  	cds := ccpack.GetDepSpec()
   691  
   692  	if cds == nil {
   693  		return fmt.Errorf("nil deployment spec from the CC package")
   694  	}
   695  
   696  	if err = lscc.isValidChaincodeName(cds.ChaincodeSpec.ChaincodeId.Name); err != nil {
   697  		return err
   698  	}
   699  
   700  	if err = lscc.isValidChaincodeVersion(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version); err != nil {
   701  		return err
   702  	}
   703  
   704  	if lscc.BuiltinSCCs.IsSysCC(cds.ChaincodeSpec.ChaincodeId.Name) {
   705  		return errors.Errorf("cannot install: %s is the name of a system chaincode", cds.ChaincodeSpec.ChaincodeId.Name)
   706  	}
   707  
   708  	// We must put the chaincode package on the filesystem prior to building it.
   709  	// This creates a race for endorsements coming in and executing the chaincode
   710  	// prior to indexes being installed, but, such is life, and this case is already
   711  	// present when an already installed chaincode is instantiated.
   712  	if err = lscc.Support.PutChaincodeToLocalStorage(ccpack); err != nil {
   713  		return err
   714  	}
   715  
   716  	ccid := ccpack.GetChaincodeData().Name + ":" + ccpack.GetChaincodeData().Version
   717  	buildStatus, building := lscc.BuildRegistry.BuildStatus(ccid)
   718  	if !building {
   719  		err := lscc.ChaincodeBuilder.Build(ccid)
   720  		buildStatus.Notify(err)
   721  	}
   722  	<-buildStatus.Done()
   723  	if err := buildStatus.Err(); err != nil {
   724  		return errors.WithMessage(err, "could not build chaincode")
   725  	}
   726  
   727  	md, err := lscc.EbMetadataProvider.PackageMetadata(ccid)
   728  	if err != nil {
   729  		return errors.WithMessage(err, "external builder release metadata found, but could not be packaged")
   730  	}
   731  
   732  	if md == nil {
   733  		// Get any statedb artifacts from the chaincode package, e.g. couchdb index definitions
   734  		md, err = ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)
   735  		if err != nil {
   736  			return err
   737  		}
   738  	}
   739  
   740  	if err = isValidStatedbArtifactsTar(md); err != nil {
   741  		return InvalidStatedbArtifactsErr(err.Error())
   742  	}
   743  
   744  	chaincodeDefinition := &cceventmgmt.ChaincodeDefinition{
   745  		Name:    ccpack.GetChaincodeData().Name,
   746  		Version: ccpack.GetChaincodeData().Version,
   747  		Hash:    ccpack.GetId()} // Note - The chaincode 'id' is the hash of chaincode's (CodeHash || MetaDataHash), aka fingerprint
   748  
   749  	// HandleChaincodeInstall will apply any statedb artifacts (e.g. couchdb indexes) to
   750  	// any channel's statedb where the chaincode is already instantiated
   751  	// Note - this step is done prior to PutChaincodeToLocalStorage() since this step is idempotent and harmless until endorsements start,
   752  	// that is, if there are errors deploying the indexes the chaincode install can safely be re-attempted later.
   753  	err = cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, md)
   754  	defer func() {
   755  		cceventmgmt.GetMgr().ChaincodeInstallDone(err == nil)
   756  	}()
   757  	if err != nil {
   758  		return err
   759  	}
   760  
   761  	logger.Infof("Installed Chaincode [%s] Version [%s] to peer", ccpack.GetChaincodeData().Name, ccpack.GetChaincodeData().Version)
   762  
   763  	return nil
   764  }
   765  
   766  // executeDeployOrUpgrade routes the code path either to executeDeploy or executeUpgrade
   767  // depending on its function argument
   768  func (lscc *SCC) executeDeployOrUpgrade(
   769  	stub shim.ChaincodeStubInterface,
   770  	chainname string,
   771  	cds *pb.ChaincodeDeploymentSpec,
   772  	policy, escc, vscc, collectionConfigBytes []byte,
   773  	function string,
   774  ) (*ccprovider.ChaincodeData, error) {
   775  
   776  	chaincodeName := cds.ChaincodeSpec.ChaincodeId.Name
   777  	chaincodeVersion := cds.ChaincodeSpec.ChaincodeId.Version
   778  
   779  	if err := lscc.isValidChaincodeName(chaincodeName); err != nil {
   780  		return nil, err
   781  	}
   782  
   783  	if err := lscc.isValidChaincodeVersion(chaincodeName, chaincodeVersion); err != nil {
   784  		return nil, err
   785  	}
   786  
   787  	chaincodeNameVersion := chaincodeName + ":" + chaincodeVersion
   788  
   789  	ccpack, err := lscc.Support.GetChaincodeFromLocalStorage(chaincodeNameVersion)
   790  	if err != nil {
   791  		retErrMsg := fmt.Sprintf("cannot get package for chaincode (%s)", chaincodeNameVersion)
   792  		logger.Errorf("%s-err:%s", retErrMsg, err)
   793  		return nil, fmt.Errorf("%s", retErrMsg)
   794  	}
   795  	cd := ccpack.GetChaincodeData()
   796  
   797  	switch function {
   798  	case DEPLOY:
   799  		return lscc.executeDeploy(stub, chainname, cds, policy, escc, vscc, cd, ccpack, collectionConfigBytes)
   800  	case UPGRADE:
   801  		return lscc.executeUpgrade(stub, chainname, cds, policy, escc, vscc, cd, ccpack, collectionConfigBytes)
   802  	default:
   803  		logger.Panicf("Programming error, unexpected function '%s'", function)
   804  		panic("") // unreachable code
   805  	}
   806  }
   807  
   808  // executeDeploy implements the "instantiate" Invoke transaction
   809  func (lscc *SCC) executeDeploy(
   810  	stub shim.ChaincodeStubInterface,
   811  	chainname string,
   812  	cds *pb.ChaincodeDeploymentSpec,
   813  	policy []byte,
   814  	escc []byte,
   815  	vscc []byte,
   816  	cdfs *ccprovider.ChaincodeData,
   817  	ccpackfs ccprovider.CCPackage,
   818  	collectionConfigBytes []byte,
   819  ) (*ccprovider.ChaincodeData, error) {
   820  	//just test for existence of the chaincode in the LSCC
   821  	chaincodeName := cds.ChaincodeSpec.ChaincodeId.Name
   822  	_, err := lscc.getCCInstance(stub, chaincodeName)
   823  	if err == nil {
   824  		return nil, ExistsErr(chaincodeName)
   825  	}
   826  
   827  	//retain chaincode specific data and fill channel specific ones
   828  	cdfs.Escc = string(escc)
   829  	cdfs.Vscc = string(vscc)
   830  	cdfs.Policy = policy
   831  
   832  	// retrieve and evaluate instantiation policy
   833  	cdfs.InstantiationPolicy, err = lscc.Support.GetInstantiationPolicy(chainname, ccpackfs)
   834  	if err != nil {
   835  		return nil, err
   836  	}
   837  	// get the signed instantiation proposal
   838  	signedProp, err := stub.GetSignedProposal()
   839  	if err != nil {
   840  		return nil, err
   841  	}
   842  	err = lscc.Support.CheckInstantiationPolicy(signedProp, chainname, cdfs.InstantiationPolicy)
   843  	if err != nil {
   844  		return nil, err
   845  	}
   846  
   847  	err = lscc.putChaincodeData(stub, cdfs)
   848  	if err != nil {
   849  		return nil, err
   850  	}
   851  
   852  	err = lscc.putChaincodeCollectionData(stub, cdfs, collectionConfigBytes)
   853  	if err != nil {
   854  		return nil, err
   855  	}
   856  
   857  	return cdfs, nil
   858  }
   859  
   860  // executeUpgrade implements the "upgrade" Invoke transaction.
   861  func (lscc *SCC) executeUpgrade(stub shim.ChaincodeStubInterface, chainName string, cds *pb.ChaincodeDeploymentSpec, policy []byte, escc []byte, vscc []byte, cdfs *ccprovider.ChaincodeData, ccpackfs ccprovider.CCPackage, collectionConfigBytes []byte) (*ccprovider.ChaincodeData, error) {
   862  
   863  	chaincodeName := cds.ChaincodeSpec.ChaincodeId.Name
   864  
   865  	// check for existence of chaincode instance only (it has to exist on the channel)
   866  	// we dont care about the old chaincode on the FS. In particular, user may even
   867  	// have deleted it
   868  	cdbytes, _ := lscc.getCCInstance(stub, chaincodeName)
   869  	if cdbytes == nil {
   870  		return nil, NotFoundErr(chaincodeName)
   871  	}
   872  
   873  	//we need the cd to compare the version
   874  	cdLedger, err := lscc.getChaincodeData(chaincodeName, cdbytes)
   875  	if err != nil {
   876  		return nil, err
   877  	}
   878  
   879  	//do not upgrade if same version
   880  	if cdLedger.Version == cds.ChaincodeSpec.ChaincodeId.Version {
   881  		return nil, IdenticalVersionErr(chaincodeName)
   882  	}
   883  
   884  	//do not upgrade if instantiation policy is violated
   885  	if cdLedger.InstantiationPolicy == nil {
   886  		return nil, InstantiationPolicyMissing("")
   887  	}
   888  	// get the signed instantiation proposal
   889  	signedProp, err := stub.GetSignedProposal()
   890  	if err != nil {
   891  		return nil, err
   892  	}
   893  	err = lscc.Support.CheckInstantiationPolicy(signedProp, chainName, cdLedger.InstantiationPolicy)
   894  	if err != nil {
   895  		return nil, err
   896  	}
   897  
   898  	//retain chaincode specific data and fill channel specific ones
   899  	cdfs.Escc = string(escc)
   900  	cdfs.Vscc = string(vscc)
   901  	cdfs.Policy = policy
   902  
   903  	// retrieve and evaluate new instantiation policy
   904  	cdfs.InstantiationPolicy, err = lscc.Support.GetInstantiationPolicy(chainName, ccpackfs)
   905  	if err != nil {
   906  		return nil, err
   907  	}
   908  	err = lscc.Support.CheckInstantiationPolicy(signedProp, chainName, cdfs.InstantiationPolicy)
   909  	if err != nil {
   910  		return nil, err
   911  	}
   912  
   913  	err = lscc.putChaincodeData(stub, cdfs)
   914  	if err != nil {
   915  		return nil, err
   916  	}
   917  
   918  	ac, exists := lscc.SCCProvider.GetApplicationConfig(chainName)
   919  	if !exists {
   920  		logger.Panicf("programming error, non-existent appplication config for channel '%s'", chainName)
   921  	}
   922  
   923  	if ac.Capabilities().CollectionUpgrade() {
   924  		err = lscc.putChaincodeCollectionData(stub, cdfs, collectionConfigBytes)
   925  		if err != nil {
   926  			return nil, err
   927  		}
   928  	} else {
   929  		if collectionConfigBytes != nil {
   930  			return nil, errors.New(CollectionsConfigUpgradesNotAllowed("").Error())
   931  		}
   932  	}
   933  
   934  	lifecycleEvent := &pb.LifecycleEvent{ChaincodeName: chaincodeName}
   935  	lifecycleEventBytes := protoutil.MarshalOrPanic(lifecycleEvent)
   936  	stub.SetEvent(UPGRADE, lifecycleEventBytes)
   937  	return cdfs, nil
   938  }
   939  
   940  //-------------- the chaincode stub interface implementation ----------
   941  
   942  //Init is mostly useless for SCC
   943  func (lscc *SCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
   944  	return shim.Success(nil)
   945  }
   946  
   947  // Invoke implements lifecycle functions "deploy", "start", "stop", "upgrade".
   948  // Deploy's arguments -  {[]byte("deploy"), []byte(<chainname>), <unmarshalled pb.ChaincodeDeploymentSpec>}
   949  //
   950  // Invoke also implements some query-like functions
   951  // Get chaincode arguments -  {[]byte("getid"), []byte(<chainname>), []byte(<chaincodename>)}
   952  func (lscc *SCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
   953  	args := stub.GetArgs()
   954  	if len(args) < 1 {
   955  		return shim.Error(InvalidArgsLenErr(len(args)).Error())
   956  	}
   957  
   958  	function := string(args[0])
   959  
   960  	// Handle ACL:
   961  	// 1. get the signed proposal
   962  	sp, err := stub.GetSignedProposal()
   963  	if err != nil {
   964  		return shim.Error(fmt.Sprintf("Failed retrieving signed proposal on executing %s with error %s", function, err))
   965  	}
   966  
   967  	switch function {
   968  	case INSTALL:
   969  		if len(args) < 2 {
   970  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   971  		}
   972  
   973  		// 2. check install policy
   974  		if err = lscc.ACLProvider.CheckACL(resources.Lscc_Install, "", sp); err != nil {
   975  			return shim.Error(fmt.Sprintf("access denied for [%s]: %s", function, err))
   976  		}
   977  
   978  		depSpec := args[1]
   979  
   980  		err := lscc.executeInstall(stub, depSpec)
   981  		if err != nil {
   982  			return shim.Error(err.Error())
   983  		}
   984  		return shim.Success([]byte("OK"))
   985  	case DEPLOY, UPGRADE:
   986  		// we expect a minimum of 3 arguments, the function
   987  		// name, the chain name and deployment spec
   988  		if len(args) < 3 {
   989  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   990  		}
   991  
   992  		// channel the chaincode should be associated with. It
   993  		// should be created with a register call
   994  		channel := string(args[1])
   995  
   996  		if !lscc.isValidChannelName(channel) {
   997  			return shim.Error(InvalidChannelNameErr(channel).Error())
   998  		}
   999  
  1000  		ac, exists := lscc.SCCProvider.GetApplicationConfig(channel)
  1001  		if !exists {
  1002  			logger.Panicf("programming error, non-existent appplication config for channel '%s'", channel)
  1003  		}
  1004  
  1005  		if ac.Capabilities().LifecycleV20() {
  1006  			return shim.Error(fmt.Sprintf("Channel '%s' has been migrated to the new lifecycle, LSCC is now read-only", channel))
  1007  		}
  1008  
  1009  		// the maximum number of arguments depends on the capability of the channel
  1010  		if !ac.Capabilities().PrivateChannelData() && len(args) > 6 {
  1011  			return shim.Error(PrivateChannelDataNotAvailable("").Error())
  1012  		}
  1013  		if ac.Capabilities().PrivateChannelData() && len(args) > 7 {
  1014  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1015  		}
  1016  
  1017  		depSpec := args[2]
  1018  		cds := &pb.ChaincodeDeploymentSpec{}
  1019  		err := proto.Unmarshal(depSpec, cds)
  1020  		if err != nil {
  1021  			return shim.Error(fmt.Sprintf("error unmarshaling ChaincodeDeploymentSpec: %s", err))
  1022  		}
  1023  
  1024  		// optional arguments here (they can each be nil and may or may not be present)
  1025  		// args[3] is a marshalled SignaturePolicyEnvelope representing the endorsement policy
  1026  		// args[4] is the name of escc
  1027  		// args[5] is the name of vscc
  1028  		// args[6] is a marshalled CollectionConfigPackage struct
  1029  		var EP []byte
  1030  		if len(args) > 3 && len(args[3]) > 0 {
  1031  			EP = args[3]
  1032  		} else {
  1033  			mspIDs := lscc.GetMSPIDs(channel)
  1034  			p := cauthdsl.SignedByAnyMember(mspIDs)
  1035  			EP, err = protoutil.Marshal(p)
  1036  			if err != nil {
  1037  				return shim.Error(err.Error())
  1038  			}
  1039  		}
  1040  
  1041  		var escc []byte
  1042  		if len(args) > 4 && len(args[4]) > 0 {
  1043  			escc = args[4]
  1044  		} else {
  1045  			escc = []byte("escc")
  1046  		}
  1047  
  1048  		var vscc []byte
  1049  		if len(args) > 5 && len(args[5]) > 0 {
  1050  			vscc = args[5]
  1051  		} else {
  1052  			vscc = []byte("vscc")
  1053  		}
  1054  
  1055  		var collectionsConfig []byte
  1056  		// we proceed with a non-nil collection configuration only if
  1057  		// we Support the PrivateChannelData capability
  1058  		if ac.Capabilities().PrivateChannelData() && len(args) > 6 {
  1059  			collectionsConfig = args[6]
  1060  		}
  1061  
  1062  		cd, err := lscc.executeDeployOrUpgrade(stub, channel, cds, EP, escc, vscc, collectionsConfig, function)
  1063  		if err != nil {
  1064  			return shim.Error(err.Error())
  1065  		}
  1066  		cdbytes, err := proto.Marshal(cd)
  1067  		if err != nil {
  1068  			return shim.Error(err.Error())
  1069  		}
  1070  		return shim.Success(cdbytes)
  1071  	case CCEXISTS, CHAINCODEEXISTS, GETDEPSPEC, GETDEPLOYMENTSPEC, GETCCDATA, GETCHAINCODEDATA:
  1072  		if len(args) != 3 {
  1073  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1074  		}
  1075  
  1076  		channel := string(args[1])
  1077  		ccname := string(args[2])
  1078  
  1079  		// 2. check policy for ACL resource
  1080  		var resource string
  1081  		switch function {
  1082  		case CCEXISTS, CHAINCODEEXISTS:
  1083  			resource = resources.Lscc_ChaincodeExists
  1084  		case GETDEPSPEC, GETDEPLOYMENTSPEC:
  1085  			resource = resources.Lscc_GetDeploymentSpec
  1086  		case GETCCDATA, GETCHAINCODEDATA:
  1087  			resource = resources.Lscc_GetChaincodeData
  1088  		}
  1089  		if err = lscc.ACLProvider.CheckACL(resource, channel, sp); err != nil {
  1090  			return shim.Error(fmt.Sprintf("access denied for [%s][%s]: %s", function, channel, err))
  1091  		}
  1092  
  1093  		cdbytes, err := lscc.getCCInstance(stub, ccname)
  1094  		if err != nil {
  1095  			logger.Errorf("error getting chaincode %s on channel [%s]: %s", ccname, channel, err)
  1096  			return shim.Error(err.Error())
  1097  		}
  1098  
  1099  		switch function {
  1100  		case CCEXISTS, CHAINCODEEXISTS:
  1101  			cd, err := lscc.getChaincodeData(ccname, cdbytes)
  1102  			if err != nil {
  1103  				return shim.Error(err.Error())
  1104  			}
  1105  			return shim.Success([]byte(cd.Name))
  1106  		case GETCCDATA, GETCHAINCODEDATA:
  1107  			return shim.Success(cdbytes)
  1108  		case GETDEPSPEC, GETDEPLOYMENTSPEC:
  1109  			_, depspecbytes, err := lscc.getCCCode(ccname, cdbytes)
  1110  			if err != nil {
  1111  				return shim.Error(err.Error())
  1112  			}
  1113  			return shim.Success(depspecbytes)
  1114  		default:
  1115  			panic("unreachable")
  1116  		}
  1117  	case GETCHAINCODES, GETCHAINCODESALIAS:
  1118  		if len(args) != 1 {
  1119  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1120  		}
  1121  
  1122  		if err = lscc.ACLProvider.CheckACL(resources.Lscc_GetInstantiatedChaincodes, stub.GetChannelID(), sp); err != nil {
  1123  			return shim.Error(fmt.Sprintf("access denied for [%s][%s]: %s", function, stub.GetChannelID(), err))
  1124  		}
  1125  
  1126  		return lscc.getChaincodes(stub)
  1127  	case GETINSTALLEDCHAINCODES, GETINSTALLEDCHAINCODESALIAS:
  1128  		if len(args) != 1 {
  1129  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1130  		}
  1131  
  1132  		// 2. check Lscc_GetInstalledChaincodes policy
  1133  		if err = lscc.ACLProvider.CheckACL(resources.Lscc_GetInstalledChaincodes, "", sp); err != nil {
  1134  			return shim.Error(fmt.Sprintf("access denied for [%s]: %s", function, err))
  1135  		}
  1136  
  1137  		return lscc.getInstalledChaincodes()
  1138  	case GETCOLLECTIONSCONFIG, GETCOLLECTIONSCONFIGALIAS:
  1139  		if len(args) != 2 {
  1140  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1141  		}
  1142  
  1143  		chaincodeName := string(args[1])
  1144  
  1145  		logger.Debugf("GetCollectionsConfig, chaincodeName:%s, start to check ACL for current identity policy", chaincodeName)
  1146  		if err = lscc.ACLProvider.CheckACL(resources.Lscc_GetCollectionsConfig, stub.GetChannelID(), sp); err != nil {
  1147  			logger.Debugf("ACL Check Failed for channel:%s, chaincode:%s", stub.GetChannelID(), chaincodeName)
  1148  			return shim.Error(fmt.Sprintf("access denied for [%s]: %s", function, err))
  1149  		}
  1150  
  1151  		return lscc.getChaincodeCollectionData(stub, chaincodeName)
  1152  	}
  1153  
  1154  	return shim.Error(InvalidFunctionErr(function).Error())
  1155  }