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