github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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/osdi23p228/fabric/bccsp"
    20  	"github.com/osdi23p228/fabric/common/cauthdsl"
    21  	"github.com/osdi23p228/fabric/common/channelconfig"
    22  	"github.com/osdi23p228/fabric/common/flogging"
    23  	"github.com/osdi23p228/fabric/common/policies"
    24  	"github.com/osdi23p228/fabric/common/policydsl"
    25  	"github.com/osdi23p228/fabric/core/aclmgmt"
    26  	"github.com/osdi23p228/fabric/core/aclmgmt/resources"
    27  	"github.com/osdi23p228/fabric/core/chaincode/lifecycle"
    28  	"github.com/osdi23p228/fabric/core/common/ccprovider"
    29  	"github.com/osdi23p228/fabric/core/common/privdata"
    30  	"github.com/osdi23p228/fabric/core/common/sysccprovider"
    31  	"github.com/osdi23p228/fabric/core/container"
    32  	"github.com/osdi23p228/fabric/core/container/externalbuilder"
    33  	"github.com/osdi23p228/fabric/core/ledger"
    34  	"github.com/osdi23p228/fabric/core/ledger/cceventmgmt"
    35  	"github.com/osdi23p228/fabric/core/peer"
    36  	"github.com/osdi23p228/fabric/core/policy"
    37  	"github.com/osdi23p228/fabric/core/scc"
    38  	"github.com/osdi23p228/fabric/internal/ccmetadata"
    39  	"github.com/osdi23p228/fabric/msp"
    40  	"github.com/osdi23p228/fabric/msp/mgmt"
    41  	"github.com/osdi23p228/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 definition matches
   237  			// what's on the filesystem, which, might include instantiation 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  	return channel != ""
   635  }
   636  
   637  // isValidChaincodeName checks the validity of chaincode name. Chaincode names
   638  // should never be blank and should only consist of alphanumerics, '_', and '-'
   639  func (lscc *SCC) isValidChaincodeName(chaincodeName string) error {
   640  	if !ChaincodeNameRegExp.MatchString(chaincodeName) {
   641  		return InvalidChaincodeNameErr(chaincodeName)
   642  	}
   643  
   644  	return nil
   645  }
   646  
   647  // isValidChaincodeVersion checks the validity of chaincode version. Versions
   648  // should never be blank and should only consist of alphanumerics, '_',  '-',
   649  // '+', and '.'
   650  func (lscc *SCC) isValidChaincodeVersion(chaincodeName string, version string) error {
   651  	if !ChaincodeVersionRegExp.MatchString(version) {
   652  		return InvalidVersionErr(version)
   653  	}
   654  
   655  	return nil
   656  }
   657  
   658  func isValidStatedbArtifactsTar(statedbArtifactsTar []byte) error {
   659  	// Extract the metadata files from the archive
   660  	// Passing an empty string for the databaseType will validate all artifacts in
   661  	// the archive
   662  	archiveFiles, err := ccprovider.ExtractFileEntries(statedbArtifactsTar, "")
   663  	if err != nil {
   664  		return err
   665  	}
   666  	// iterate through the files and validate
   667  	for _, archiveDirectoryFiles := range archiveFiles {
   668  		for _, fileEntry := range archiveDirectoryFiles {
   669  			indexData := fileEntry.FileContent
   670  			// Validation is based on the passed file name, e.g. META-INF/statedb/couchdb/indexes/indexname.json
   671  			err = ccmetadata.ValidateMetadataFile(fileEntry.FileHeader.Name, indexData)
   672  			if err != nil {
   673  				return err
   674  			}
   675  		}
   676  	}
   677  
   678  	return nil
   679  }
   680  
   681  // executeInstall implements the "install" Invoke transaction
   682  func (lscc *SCC) executeInstall(stub shim.ChaincodeStubInterface, ccbytes []byte) error {
   683  	ccpack, err := ccprovider.GetCCPackage(ccbytes, lscc.BCCSP)
   684  	if err != nil {
   685  		return err
   686  	}
   687  
   688  	cds := ccpack.GetDepSpec()
   689  
   690  	if cds == nil {
   691  		return fmt.Errorf("nil deployment spec from the CC package")
   692  	}
   693  
   694  	if err = lscc.isValidChaincodeName(cds.ChaincodeSpec.ChaincodeId.Name); err != nil {
   695  		return err
   696  	}
   697  
   698  	if err = lscc.isValidChaincodeVersion(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version); err != nil {
   699  		return err
   700  	}
   701  
   702  	if lscc.BuiltinSCCs.IsSysCC(cds.ChaincodeSpec.ChaincodeId.Name) {
   703  		return errors.Errorf("cannot install: %s is the name of a system chaincode", cds.ChaincodeSpec.ChaincodeId.Name)
   704  	}
   705  
   706  	// We must put the chaincode package on the filesystem prior to building it.
   707  	// This creates a race for endorsements coming in and executing the chaincode
   708  	// prior to indexes being installed, but, such is life, and this case is already
   709  	// present when an already installed chaincode is instantiated.
   710  	if err = lscc.Support.PutChaincodeToLocalStorage(ccpack); err != nil {
   711  		return err
   712  	}
   713  
   714  	ccid := ccpack.GetChaincodeData().Name + ":" + ccpack.GetChaincodeData().Version
   715  	buildStatus, building := lscc.BuildRegistry.BuildStatus(ccid)
   716  	if !building {
   717  		err := lscc.ChaincodeBuilder.Build(ccid)
   718  		buildStatus.Notify(err)
   719  	}
   720  	<-buildStatus.Done()
   721  	if err := buildStatus.Err(); err != nil {
   722  		return errors.WithMessage(err, "chaincode installed to peer but could not build chaincode")
   723  	}
   724  
   725  	md, err := lscc.EbMetadataProvider.PackageMetadata(ccid)
   726  	if err != nil {
   727  		return errors.WithMessage(err, "external builder release metadata found, but could not be packaged")
   728  	}
   729  
   730  	if md == nil {
   731  		// Get any statedb artifacts from the chaincode package, e.g. couchdb index definitions
   732  		md, err = ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)
   733  		if err != nil {
   734  			return err
   735  		}
   736  	}
   737  
   738  	if err = isValidStatedbArtifactsTar(md); err != nil {
   739  		return InvalidStatedbArtifactsErr(err.Error())
   740  	}
   741  
   742  	chaincodeDefinition := &cceventmgmt.ChaincodeDefinition{
   743  		Name:    ccpack.GetChaincodeData().Name,
   744  		Version: ccpack.GetChaincodeData().Version,
   745  		Hash:    ccpack.GetId()} // Note - The chaincode 'id' is the hash of chaincode's (CodeHash || MetaDataHash), aka fingerprint
   746  
   747  	// HandleChaincodeInstall will apply any statedb artifacts (e.g. couchdb indexes) to
   748  	// any channel's statedb where the chaincode is already instantiated
   749  	// Note - this step is done prior to PutChaincodeToLocalStorage() since this step is idempotent and harmless until endorsements start,
   750  	// that is, if there are errors deploying the indexes the chaincode install can safely be re-attempted later.
   751  	err = cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, md)
   752  	defer func() {
   753  		cceventmgmt.GetMgr().ChaincodeInstallDone(err == nil)
   754  	}()
   755  	if err != nil {
   756  		return err
   757  	}
   758  
   759  	logger.Infof("Installed Chaincode [%s] Version [%s] to peer", ccpack.GetChaincodeData().Name, ccpack.GetChaincodeData().Version)
   760  
   761  	return nil
   762  }
   763  
   764  // executeDeployOrUpgrade routes the code path either to executeDeploy or executeUpgrade
   765  // depending on its function argument
   766  func (lscc *SCC) executeDeployOrUpgrade(
   767  	stub shim.ChaincodeStubInterface,
   768  	chainname string,
   769  	cds *pb.ChaincodeDeploymentSpec,
   770  	policy, escc, vscc, collectionConfigBytes []byte,
   771  	function string,
   772  ) (*ccprovider.ChaincodeData, error) {
   773  
   774  	chaincodeName := cds.ChaincodeSpec.ChaincodeId.Name
   775  	chaincodeVersion := cds.ChaincodeSpec.ChaincodeId.Version
   776  
   777  	if err := lscc.isValidChaincodeName(chaincodeName); err != nil {
   778  		return nil, err
   779  	}
   780  
   781  	if err := lscc.isValidChaincodeVersion(chaincodeName, chaincodeVersion); err != nil {
   782  		return nil, err
   783  	}
   784  
   785  	chaincodeNameVersion := chaincodeName + ":" + chaincodeVersion
   786  
   787  	ccpack, err := lscc.Support.GetChaincodeFromLocalStorage(chaincodeNameVersion)
   788  	if err != nil {
   789  		retErrMsg := fmt.Sprintf("cannot get package for chaincode (%s)", chaincodeNameVersion)
   790  		logger.Errorf("%s-err:%s", retErrMsg, err)
   791  		return nil, fmt.Errorf("%s", retErrMsg)
   792  	}
   793  	cd := ccpack.GetChaincodeData()
   794  
   795  	switch function {
   796  	case DEPLOY:
   797  		return lscc.executeDeploy(stub, chainname, cds, policy, escc, vscc, cd, ccpack, collectionConfigBytes)
   798  	case UPGRADE:
   799  		return lscc.executeUpgrade(stub, chainname, cds, policy, escc, vscc, cd, ccpack, collectionConfigBytes)
   800  	default:
   801  		logger.Panicf("Programming error, unexpected function '%s'", function)
   802  		panic("") // unreachable code
   803  	}
   804  }
   805  
   806  // executeDeploy implements the "instantiate" Invoke transaction
   807  func (lscc *SCC) executeDeploy(
   808  	stub shim.ChaincodeStubInterface,
   809  	chainname string,
   810  	cds *pb.ChaincodeDeploymentSpec,
   811  	policy []byte,
   812  	escc []byte,
   813  	vscc []byte,
   814  	cdfs *ccprovider.ChaincodeData,
   815  	ccpackfs ccprovider.CCPackage,
   816  	collectionConfigBytes []byte,
   817  ) (*ccprovider.ChaincodeData, error) {
   818  	//just test for existence of the chaincode in the LSCC
   819  	chaincodeName := cds.ChaincodeSpec.ChaincodeId.Name
   820  	_, err := lscc.getCCInstance(stub, chaincodeName)
   821  	if err == nil {
   822  		return nil, ExistsErr(chaincodeName)
   823  	}
   824  
   825  	//retain chaincode specific data and fill channel specific ones
   826  	cdfs.Escc = string(escc)
   827  	cdfs.Vscc = string(vscc)
   828  	cdfs.Policy = policy
   829  
   830  	// retrieve and evaluate instantiation policy
   831  	cdfs.InstantiationPolicy, err = lscc.Support.GetInstantiationPolicy(chainname, ccpackfs)
   832  	if err != nil {
   833  		return nil, err
   834  	}
   835  	// get the signed instantiation proposal
   836  	signedProp, err := stub.GetSignedProposal()
   837  	if err != nil {
   838  		return nil, err
   839  	}
   840  	err = lscc.Support.CheckInstantiationPolicy(signedProp, chainname, cdfs.InstantiationPolicy)
   841  	if err != nil {
   842  		return nil, err
   843  	}
   844  
   845  	err = lscc.putChaincodeData(stub, cdfs)
   846  	if err != nil {
   847  		return nil, err
   848  	}
   849  
   850  	err = lscc.putChaincodeCollectionData(stub, cdfs, collectionConfigBytes)
   851  	if err != nil {
   852  		return nil, err
   853  	}
   854  
   855  	return cdfs, nil
   856  }
   857  
   858  // executeUpgrade implements the "upgrade" Invoke transaction.
   859  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) {
   860  
   861  	chaincodeName := cds.ChaincodeSpec.ChaincodeId.Name
   862  
   863  	// check for existence of chaincode instance only (it has to exist on the channel)
   864  	// we dont care about the old chaincode on the FS. In particular, user may even
   865  	// have deleted it
   866  	cdbytes, _ := lscc.getCCInstance(stub, chaincodeName)
   867  	if cdbytes == nil {
   868  		return nil, NotFoundErr(chaincodeName)
   869  	}
   870  
   871  	//we need the cd to compare the version
   872  	cdLedger, err := lscc.getChaincodeData(chaincodeName, cdbytes)
   873  	if err != nil {
   874  		return nil, err
   875  	}
   876  
   877  	//do not upgrade if same version
   878  	if cdLedger.Version == cds.ChaincodeSpec.ChaincodeId.Version {
   879  		return nil, IdenticalVersionErr(chaincodeName)
   880  	}
   881  
   882  	//do not upgrade if instantiation policy is violated
   883  	if cdLedger.InstantiationPolicy == nil {
   884  		return nil, InstantiationPolicyMissing("")
   885  	}
   886  	// get the signed instantiation proposal
   887  	signedProp, err := stub.GetSignedProposal()
   888  	if err != nil {
   889  		return nil, err
   890  	}
   891  	err = lscc.Support.CheckInstantiationPolicy(signedProp, chainName, cdLedger.InstantiationPolicy)
   892  	if err != nil {
   893  		return nil, err
   894  	}
   895  
   896  	//retain chaincode specific data and fill channel specific ones
   897  	cdfs.Escc = string(escc)
   898  	cdfs.Vscc = string(vscc)
   899  	cdfs.Policy = policy
   900  
   901  	// retrieve and evaluate new instantiation policy
   902  	cdfs.InstantiationPolicy, err = lscc.Support.GetInstantiationPolicy(chainName, ccpackfs)
   903  	if err != nil {
   904  		return nil, err
   905  	}
   906  	err = lscc.Support.CheckInstantiationPolicy(signedProp, chainName, cdfs.InstantiationPolicy)
   907  	if err != nil {
   908  		return nil, err
   909  	}
   910  
   911  	err = lscc.putChaincodeData(stub, cdfs)
   912  	if err != nil {
   913  		return nil, err
   914  	}
   915  
   916  	ac, exists := lscc.SCCProvider.GetApplicationConfig(chainName)
   917  	if !exists {
   918  		logger.Panicf("programming error, non-existent appplication config for channel '%s'", chainName)
   919  	}
   920  
   921  	if ac.Capabilities().CollectionUpgrade() {
   922  		err = lscc.putChaincodeCollectionData(stub, cdfs, collectionConfigBytes)
   923  		if err != nil {
   924  			return nil, err
   925  		}
   926  	} else {
   927  		if collectionConfigBytes != nil {
   928  			return nil, errors.New(CollectionsConfigUpgradesNotAllowed("").Error())
   929  		}
   930  	}
   931  
   932  	lifecycleEvent := &pb.LifecycleEvent{ChaincodeName: chaincodeName}
   933  	lifecycleEventBytes := protoutil.MarshalOrPanic(lifecycleEvent)
   934  	stub.SetEvent(UPGRADE, lifecycleEventBytes)
   935  	return cdfs, nil
   936  }
   937  
   938  //-------------- the chaincode stub interface implementation ----------
   939  
   940  //Init is mostly useless for SCC
   941  func (lscc *SCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
   942  	return shim.Success(nil)
   943  }
   944  
   945  // Invoke implements lifecycle functions "deploy", "start", "stop", "upgrade".
   946  // Deploy's arguments -  {[]byte("deploy"), []byte(<chainname>), <unmarshalled pb.ChaincodeDeploymentSpec>}
   947  //
   948  // Invoke also implements some query-like functions
   949  // Get chaincode arguments -  {[]byte("getid"), []byte(<chainname>), []byte(<chaincodename>)}
   950  func (lscc *SCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
   951  	args := stub.GetArgs()
   952  	if len(args) < 1 {
   953  		return shim.Error(InvalidArgsLenErr(len(args)).Error())
   954  	}
   955  
   956  	function := string(args[0])
   957  
   958  	// Handle ACL:
   959  	// 1. get the signed proposal
   960  	sp, err := stub.GetSignedProposal()
   961  	if err != nil {
   962  		return shim.Error(fmt.Sprintf("Failed retrieving signed proposal on executing %s with error %s", function, err))
   963  	}
   964  
   965  	switch function {
   966  	case INSTALL:
   967  		if len(args) < 2 {
   968  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   969  		}
   970  
   971  		// 2. check install policy
   972  		if err = lscc.ACLProvider.CheckACL(resources.Lscc_Install, "", sp); err != nil {
   973  			return shim.Error(fmt.Sprintf("access denied for [%s]: %s", function, err))
   974  		}
   975  
   976  		depSpec := args[1]
   977  
   978  		err := lscc.executeInstall(stub, depSpec)
   979  		if err != nil {
   980  			return shim.Error(err.Error())
   981  		}
   982  		return shim.Success([]byte("OK"))
   983  	case DEPLOY, UPGRADE:
   984  		// we expect a minimum of 3 arguments, the function
   985  		// name, the chain name and deployment spec
   986  		if len(args) < 3 {
   987  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   988  		}
   989  
   990  		// channel the chaincode should be associated with. It
   991  		// should be created with a register call
   992  		channel := string(args[1])
   993  
   994  		if !lscc.isValidChannelName(channel) {
   995  			return shim.Error(InvalidChannelNameErr(channel).Error())
   996  		}
   997  
   998  		ac, exists := lscc.SCCProvider.GetApplicationConfig(channel)
   999  		if !exists {
  1000  			logger.Panicf("programming error, non-existent appplication config for channel '%s'", channel)
  1001  		}
  1002  
  1003  		if ac.Capabilities().LifecycleV20() {
  1004  			return shim.Error(fmt.Sprintf("Channel '%s' has been migrated to the new lifecycle, LSCC is now read-only", channel))
  1005  		}
  1006  
  1007  		// the maximum number of arguments depends on the capability of the channel
  1008  		if !ac.Capabilities().PrivateChannelData() && len(args) > 6 {
  1009  			return shim.Error(PrivateChannelDataNotAvailable("").Error())
  1010  		}
  1011  		if ac.Capabilities().PrivateChannelData() && len(args) > 7 {
  1012  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1013  		}
  1014  
  1015  		depSpec := args[2]
  1016  		cds := &pb.ChaincodeDeploymentSpec{}
  1017  		err := proto.Unmarshal(depSpec, cds)
  1018  		if err != nil {
  1019  			return shim.Error(fmt.Sprintf("error unmarshaling ChaincodeDeploymentSpec: %s", err))
  1020  		}
  1021  
  1022  		// optional arguments here (they can each be nil and may or may not be present)
  1023  		// args[3] is a marshalled SignaturePolicyEnvelope representing the endorsement policy
  1024  		// args[4] is the name of escc
  1025  		// args[5] is the name of vscc
  1026  		// args[6] is a marshalled CollectionConfigPackage struct
  1027  		var EP []byte
  1028  		if len(args) > 3 && len(args[3]) > 0 {
  1029  			EP = args[3]
  1030  		} else {
  1031  			mspIDs := lscc.GetMSPIDs(channel)
  1032  			p := policydsl.SignedByAnyMember(mspIDs)
  1033  			EP, err = protoutil.Marshal(p)
  1034  			if err != nil {
  1035  				return shim.Error(err.Error())
  1036  			}
  1037  		}
  1038  
  1039  		var escc []byte
  1040  		if len(args) > 4 && len(args[4]) > 0 {
  1041  			escc = args[4]
  1042  		} else {
  1043  			escc = []byte("escc")
  1044  		}
  1045  
  1046  		var vscc []byte
  1047  		if len(args) > 5 && len(args[5]) > 0 {
  1048  			vscc = args[5]
  1049  		} else {
  1050  			vscc = []byte("vscc")
  1051  		}
  1052  
  1053  		var collectionsConfig []byte
  1054  		// we proceed with a non-nil collection configuration only if
  1055  		// we Support the PrivateChannelData capability
  1056  		if ac.Capabilities().PrivateChannelData() && len(args) > 6 {
  1057  			collectionsConfig = args[6]
  1058  		}
  1059  
  1060  		cd, err := lscc.executeDeployOrUpgrade(stub, channel, cds, EP, escc, vscc, collectionsConfig, function)
  1061  		if err != nil {
  1062  			return shim.Error(err.Error())
  1063  		}
  1064  		cdbytes, err := proto.Marshal(cd)
  1065  		if err != nil {
  1066  			return shim.Error(err.Error())
  1067  		}
  1068  		return shim.Success(cdbytes)
  1069  	case CCEXISTS, CHAINCODEEXISTS, GETDEPSPEC, GETDEPLOYMENTSPEC, GETCCDATA, GETCHAINCODEDATA:
  1070  		if len(args) != 3 {
  1071  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1072  		}
  1073  
  1074  		channel := string(args[1])
  1075  		ccname := string(args[2])
  1076  
  1077  		// 2. check policy for ACL resource
  1078  		var resource string
  1079  		switch function {
  1080  		case CCEXISTS, CHAINCODEEXISTS:
  1081  			resource = resources.Lscc_ChaincodeExists
  1082  		case GETDEPSPEC, GETDEPLOYMENTSPEC:
  1083  			resource = resources.Lscc_GetDeploymentSpec
  1084  		case GETCCDATA, GETCHAINCODEDATA:
  1085  			resource = resources.Lscc_GetChaincodeData
  1086  		}
  1087  		if err = lscc.ACLProvider.CheckACL(resource, channel, sp); err != nil {
  1088  			return shim.Error(fmt.Sprintf("access denied for [%s][%s]: %s", function, channel, err))
  1089  		}
  1090  
  1091  		cdbytes, err := lscc.getCCInstance(stub, ccname)
  1092  		if err != nil {
  1093  			logger.Errorf("error getting chaincode %s on channel [%s]: %s", ccname, channel, err)
  1094  			return shim.Error(err.Error())
  1095  		}
  1096  
  1097  		switch function {
  1098  		case CCEXISTS, CHAINCODEEXISTS:
  1099  			cd, err := lscc.getChaincodeData(ccname, cdbytes)
  1100  			if err != nil {
  1101  				return shim.Error(err.Error())
  1102  			}
  1103  			return shim.Success([]byte(cd.Name))
  1104  		case GETCCDATA, GETCHAINCODEDATA:
  1105  			return shim.Success(cdbytes)
  1106  		case GETDEPSPEC, GETDEPLOYMENTSPEC:
  1107  			_, depspecbytes, err := lscc.getCCCode(ccname, cdbytes)
  1108  			if err != nil {
  1109  				return shim.Error(err.Error())
  1110  			}
  1111  			return shim.Success(depspecbytes)
  1112  		default:
  1113  			panic("unreachable")
  1114  		}
  1115  	case GETCHAINCODES, GETCHAINCODESALIAS:
  1116  		if len(args) != 1 {
  1117  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1118  		}
  1119  
  1120  		if err = lscc.ACLProvider.CheckACL(resources.Lscc_GetInstantiatedChaincodes, stub.GetChannelID(), sp); err != nil {
  1121  			return shim.Error(fmt.Sprintf("access denied for [%s][%s]: %s", function, stub.GetChannelID(), err))
  1122  		}
  1123  
  1124  		return lscc.getChaincodes(stub)
  1125  	case GETINSTALLEDCHAINCODES, GETINSTALLEDCHAINCODESALIAS:
  1126  		if len(args) != 1 {
  1127  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1128  		}
  1129  
  1130  		// 2. check Lscc_GetInstalledChaincodes policy
  1131  		if err = lscc.ACLProvider.CheckACL(resources.Lscc_GetInstalledChaincodes, "", sp); err != nil {
  1132  			return shim.Error(fmt.Sprintf("access denied for [%s]: %s", function, err))
  1133  		}
  1134  
  1135  		return lscc.getInstalledChaincodes()
  1136  	case GETCOLLECTIONSCONFIG, GETCOLLECTIONSCONFIGALIAS:
  1137  		if len(args) != 2 {
  1138  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
  1139  		}
  1140  
  1141  		chaincodeName := string(args[1])
  1142  
  1143  		logger.Debugf("GetCollectionsConfig, chaincodeName:%s, start to check ACL for current identity policy", chaincodeName)
  1144  		if err = lscc.ACLProvider.CheckACL(resources.Lscc_GetCollectionsConfig, stub.GetChannelID(), sp); err != nil {
  1145  			logger.Debugf("ACL Check Failed for channel:%s, chaincode:%s", stub.GetChannelID(), chaincodeName)
  1146  			return shim.Error(fmt.Sprintf("access denied for [%s]: %s", function, err))
  1147  		}
  1148  
  1149  		return lscc.getChaincodeCollectionData(stub, chaincodeName)
  1150  	}
  1151  
  1152  	return shim.Error(InvalidFunctionErr(function).Error())
  1153  }