github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/scc/lscc/lscc.go (about)

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