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