github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/scc/lscc/lscc.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package lscc
    18  
    19  import (
    20  	"fmt"
    21  	"regexp"
    22  
    23  	"github.com/golang/protobuf/proto"
    24  	"github.com/hyperledger/fabric/common/cauthdsl"
    25  	"github.com/hyperledger/fabric/common/flogging"
    26  	"github.com/hyperledger/fabric/common/policies"
    27  	"github.com/hyperledger/fabric/core/chaincode/shim"
    28  	"github.com/hyperledger/fabric/core/common/ccprovider"
    29  	"github.com/hyperledger/fabric/core/common/sysccprovider"
    30  	"github.com/hyperledger/fabric/core/peer"
    31  	"github.com/hyperledger/fabric/core/policy"
    32  	"github.com/hyperledger/fabric/core/policyprovider"
    33  	"github.com/hyperledger/fabric/msp/mgmt"
    34  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    35  	"github.com/hyperledger/fabric/protos/common"
    36  	pb "github.com/hyperledger/fabric/protos/peer"
    37  	"github.com/hyperledger/fabric/protos/utils"
    38  )
    39  
    40  //The life cycle system chaincode manages chaincodes deployed
    41  //on this peer. It manages chaincodes via Invoke proposals.
    42  //     "Args":["deploy",<ChaincodeDeploymentSpec>]
    43  //     "Args":["upgrade",<ChaincodeDeploymentSpec>]
    44  //     "Args":["stop",<ChaincodeInvocationSpec>]
    45  //     "Args":["start",<ChaincodeInvocationSpec>]
    46  
    47  var logger = flogging.MustGetLogger("lscc")
    48  
    49  const (
    50  	//CHAINCODETABLE prefix for chaincode tables
    51  	CHAINCODETABLE = "chaincodes"
    52  
    53  	//chaincode lifecyle commands
    54  
    55  	//INSTALL install command
    56  	INSTALL = "install"
    57  
    58  	//DEPLOY deploy command
    59  	DEPLOY = "deploy"
    60  
    61  	//UPGRADE upgrade chaincode
    62  	UPGRADE = "upgrade"
    63  
    64  	//GETCCINFO get chaincode
    65  	GETCCINFO = "getid"
    66  
    67  	//GETDEPSPEC get ChaincodeDeploymentSpec
    68  	GETDEPSPEC = "getdepspec"
    69  
    70  	//GETCCDATA get ChaincodeData
    71  	GETCCDATA = "getccdata"
    72  
    73  	//GETCHAINCODES gets the instantiated chaincodes on a channel
    74  	GETCHAINCODES = "getchaincodes"
    75  
    76  	//GETINSTALLEDCHAINCODES gets the installed chaincodes on a peer
    77  	GETINSTALLEDCHAINCODES = "getinstalledchaincodes"
    78  
    79  	allowedCharsChaincodeName = "[A-Za-z0-9_-]+"
    80  	allowedCharsVersion       = "[A-Za-z0-9_.-]+"
    81  )
    82  
    83  //---------- the LSCC -----------------
    84  
    85  // LifeCycleSysCC implements chaincode lifecycle and policies around it
    86  type LifeCycleSysCC struct {
    87  	// sccprovider is the interface with which we call
    88  	// methods of the system chaincode package without
    89  	// import cycles
    90  	sccprovider sysccprovider.SystemChaincodeProvider
    91  
    92  	// policyChecker is the interface used to perform
    93  	// access control
    94  	policyChecker policy.PolicyChecker
    95  }
    96  
    97  //----------------errors---------------
    98  
    99  //AlreadyRegisteredErr Already registered error
   100  type AlreadyRegisteredErr string
   101  
   102  func (f AlreadyRegisteredErr) Error() string {
   103  	return fmt.Sprintf("%s already registered", string(f))
   104  }
   105  
   106  //InvalidFunctionErr invalid function error
   107  type InvalidFunctionErr string
   108  
   109  func (f InvalidFunctionErr) Error() string {
   110  	return fmt.Sprintf("invalid function to lscc %s", string(f))
   111  }
   112  
   113  //InvalidArgsLenErr invalid arguments length error
   114  type InvalidArgsLenErr int
   115  
   116  func (i InvalidArgsLenErr) Error() string {
   117  	return fmt.Sprintf("invalid number of argument to lscc %d", int(i))
   118  }
   119  
   120  //InvalidArgsErr invalid arguments error
   121  type InvalidArgsErr int
   122  
   123  func (i InvalidArgsErr) Error() string {
   124  	return fmt.Sprintf("invalid argument (%d) to lscc", int(i))
   125  }
   126  
   127  //TXExistsErr transaction exists error
   128  type TXExistsErr string
   129  
   130  func (t TXExistsErr) Error() string {
   131  	return fmt.Sprintf("transaction exists %s", string(t))
   132  }
   133  
   134  //TXNotFoundErr transaction not found error
   135  type TXNotFoundErr string
   136  
   137  func (t TXNotFoundErr) Error() string {
   138  	return fmt.Sprintf("transaction not found %s", string(t))
   139  }
   140  
   141  //InvalidDeploymentSpecErr invalide chaincode deployment spec error
   142  type InvalidDeploymentSpecErr string
   143  
   144  func (f InvalidDeploymentSpecErr) Error() string {
   145  	return fmt.Sprintf("invalid deployment spec : %s", string(f))
   146  }
   147  
   148  //ExistsErr chaincode exists error
   149  type ExistsErr string
   150  
   151  func (t ExistsErr) Error() string {
   152  	return fmt.Sprintf("chaincode exists %s", string(t))
   153  }
   154  
   155  //NotFoundErr chaincode not registered with LSCC error
   156  type NotFoundErr string
   157  
   158  func (t NotFoundErr) Error() string {
   159  	return fmt.Sprintf("could not find chaincode with name '%s'", string(t))
   160  }
   161  
   162  //InvalidChainNameErr invalid chain name error
   163  type InvalidChainNameErr string
   164  
   165  func (f InvalidChainNameErr) Error() string {
   166  	return fmt.Sprintf("invalid chain name %s", string(f))
   167  }
   168  
   169  //InvalidChaincodeNameErr invalid chaincode name error
   170  type InvalidChaincodeNameErr string
   171  
   172  func (f InvalidChaincodeNameErr) Error() string {
   173  	return fmt.Sprintf("invalid chaincode name '%s'. Names can only consist of alphanumerics, '_', and '-'", string(f))
   174  }
   175  
   176  //EmptyChaincodeNameErr trying to upgrade to same version of Chaincode
   177  type EmptyChaincodeNameErr string
   178  
   179  func (f EmptyChaincodeNameErr) Error() string {
   180  	return fmt.Sprint("chaincode name not provided")
   181  }
   182  
   183  //InvalidVersionErr invalid version error
   184  type InvalidVersionErr string
   185  
   186  func (f InvalidVersionErr) Error() string {
   187  	return fmt.Sprintf("invalid chaincode version '%s'. Versions can only consist of alphanumerics, '_',  '-', and '.'", string(f))
   188  }
   189  
   190  //ChaincodeMismatchErr chaincode name from two places don't match
   191  type ChaincodeMismatchErr string
   192  
   193  func (f ChaincodeMismatchErr) Error() string {
   194  	return fmt.Sprintf("chaincode name mismatch %s", string(f))
   195  }
   196  
   197  //EmptyVersionErr empty version error
   198  type EmptyVersionErr string
   199  
   200  func (f EmptyVersionErr) Error() string {
   201  	return fmt.Sprintf("version not provided for chaincode with name '%s'", string(f))
   202  }
   203  
   204  //MarshallErr error marshaling/unmarshalling
   205  type MarshallErr string
   206  
   207  func (m MarshallErr) Error() string {
   208  	return fmt.Sprintf("error while marshalling %s", string(m))
   209  }
   210  
   211  //IdenticalVersionErr trying to upgrade to same version of Chaincode
   212  type IdenticalVersionErr string
   213  
   214  func (f IdenticalVersionErr) Error() string {
   215  	return fmt.Sprintf("version already exists for chaincode with name '%s'", string(f))
   216  }
   217  
   218  //InvalidCCOnFSError error due to mismatch between fingerprint on lscc and installed CC
   219  type InvalidCCOnFSError string
   220  
   221  func (f InvalidCCOnFSError) Error() string {
   222  	return fmt.Sprintf("chaincode fingerprint mismatch %s", string(f))
   223  }
   224  
   225  //InstantiationPolicyViolatedErr when chaincode instantiation policy has been violated on instantiate or upgrade
   226  type InstantiationPolicyViolatedErr string
   227  
   228  func (f InstantiationPolicyViolatedErr) Error() string {
   229  	return fmt.Sprintf("chaincode instantiation policy violated(%s)", string(f))
   230  }
   231  
   232  //InstantiationPolicyMissing when no existing instantiation policy is found when upgrading CC
   233  type InstantiationPolicyMissing string
   234  
   235  func (f InstantiationPolicyMissing) Error() string {
   236  	return "instantiation policy missing"
   237  }
   238  
   239  //-------------- helper functions ------------------
   240  //create the chaincode on the given chain
   241  func (lscc *LifeCycleSysCC) createChaincode(stub shim.ChaincodeStubInterface, cd *ccprovider.ChaincodeData) error {
   242  	return lscc.putChaincodeData(stub, cd)
   243  }
   244  
   245  //upgrade the chaincode on the given chain
   246  func (lscc *LifeCycleSysCC) upgradeChaincode(stub shim.ChaincodeStubInterface, cd *ccprovider.ChaincodeData) error {
   247  	return lscc.putChaincodeData(stub, cd)
   248  }
   249  
   250  //create the chaincode on the given chain
   251  func (lscc *LifeCycleSysCC) putChaincodeData(stub shim.ChaincodeStubInterface, cd *ccprovider.ChaincodeData) error {
   252  	// check that escc and vscc are real system chaincodes
   253  	if !lscc.sccprovider.IsSysCC(string(cd.Escc)) {
   254  		return fmt.Errorf("%s is not a valid endorsement system chaincode", string(cd.Escc))
   255  	}
   256  	if !lscc.sccprovider.IsSysCC(string(cd.Vscc)) {
   257  		return fmt.Errorf("%s is not a valid validation system chaincode", string(cd.Vscc))
   258  	}
   259  
   260  	cdbytes, err := proto.Marshal(cd)
   261  	if err != nil {
   262  		return err
   263  	}
   264  
   265  	if cdbytes == nil {
   266  		return MarshallErr(cd.Name)
   267  	}
   268  
   269  	err = stub.PutState(cd.Name, cdbytes)
   270  
   271  	return err
   272  }
   273  
   274  //checks for existence of chaincode on the given channel
   275  func (lscc *LifeCycleSysCC) getCCInstance(stub shim.ChaincodeStubInterface, ccname string) ([]byte, error) {
   276  	cdbytes, err := stub.GetState(ccname)
   277  	if err != nil {
   278  		return nil, TXNotFoundErr(err.Error())
   279  	}
   280  	if cdbytes == nil {
   281  		return nil, NotFoundErr(ccname)
   282  	}
   283  
   284  	return cdbytes, nil
   285  }
   286  
   287  //gets the cd out of the bytes
   288  func (lscc *LifeCycleSysCC) getChaincodeData(ccname string, cdbytes []byte) (*ccprovider.ChaincodeData, error) {
   289  	cd := &ccprovider.ChaincodeData{}
   290  	err := proto.Unmarshal(cdbytes, cd)
   291  	if err != nil {
   292  		return nil, MarshallErr(ccname)
   293  	}
   294  
   295  	//this should not happen but still a sanity check is not a bad thing
   296  	if cd.Name != ccname {
   297  		return nil, ChaincodeMismatchErr(fmt.Sprintf("%s!=%s", ccname, cd.Name))
   298  	}
   299  
   300  	return cd, nil
   301  }
   302  
   303  //checks for existence of chaincode on the given chain
   304  func (lscc *LifeCycleSysCC) getCCCode(ccname string, cdbytes []byte) (*ccprovider.ChaincodeData, *pb.ChaincodeDeploymentSpec, []byte, error) {
   305  	cd, err := lscc.getChaincodeData(ccname, cdbytes)
   306  	if err != nil {
   307  		return nil, nil, nil, err
   308  	}
   309  
   310  	ccpack, err := ccprovider.GetChaincodeFromFS(ccname, cd.Version)
   311  	if err != nil {
   312  		return nil, nil, nil, InvalidDeploymentSpecErr(err.Error())
   313  	}
   314  
   315  	//this is the big test and the reason every launch should go through
   316  	//getChaincode call. We validate the chaincode entry against the
   317  	//the chaincode in FS
   318  	if err = ccpack.ValidateCC(cd); err != nil {
   319  		return nil, nil, nil, InvalidCCOnFSError(err.Error())
   320  	}
   321  
   322  	//these are guaranteed to be non-nil because we got a valid ccpack
   323  	depspec := ccpack.GetDepSpec()
   324  	depspecbytes := ccpack.GetDepSpecBytes()
   325  
   326  	return cd, depspec, depspecbytes, nil
   327  }
   328  
   329  // getChaincodes returns all chaincodes instantiated on this LSCC's channel
   330  func (lscc *LifeCycleSysCC) getChaincodes(stub shim.ChaincodeStubInterface) pb.Response {
   331  	// get all rows from LSCC
   332  	itr, err := stub.GetStateByRange("", "")
   333  
   334  	if err != nil {
   335  		return shim.Error(err.Error())
   336  	}
   337  	defer itr.Close()
   338  
   339  	// array to store metadata for all chaincode entries from LSCC
   340  	var ccInfoArray []*pb.ChaincodeInfo
   341  
   342  	for itr.HasNext() {
   343  		response, err := itr.Next()
   344  		if err != nil {
   345  			return shim.Error(err.Error())
   346  		}
   347  
   348  		ccdata := &ccprovider.ChaincodeData{}
   349  		if err = proto.Unmarshal(response.Value, ccdata); err != nil {
   350  			return shim.Error(err.Error())
   351  		}
   352  
   353  		var path string
   354  		var input string
   355  
   356  		//if chaincode is not installed on the system we won't have
   357  		//data beyond name and version
   358  		ccpack, err := ccprovider.GetChaincodeFromFS(ccdata.Name, ccdata.Version)
   359  		if err == nil {
   360  			path = ccpack.GetDepSpec().GetChaincodeSpec().ChaincodeId.Path
   361  			input = ccpack.GetDepSpec().GetChaincodeSpec().Input.String()
   362  		}
   363  
   364  		ccInfo := &pb.ChaincodeInfo{Name: ccdata.Name, Version: ccdata.Version, Path: path, Input: input, Escc: ccdata.Escc, Vscc: ccdata.Vscc}
   365  
   366  		// add this specific chaincode's metadata to the array of all chaincodes
   367  		ccInfoArray = append(ccInfoArray, ccInfo)
   368  	}
   369  	// add array with info about all instantiated chaincodes to the query
   370  	// response proto
   371  	cqr := &pb.ChaincodeQueryResponse{Chaincodes: ccInfoArray}
   372  
   373  	cqrbytes, err := proto.Marshal(cqr)
   374  	if err != nil {
   375  		return shim.Error(err.Error())
   376  	}
   377  
   378  	return shim.Success(cqrbytes)
   379  }
   380  
   381  // getInstalledChaincodes returns all chaincodes installed on the peer
   382  func (lscc *LifeCycleSysCC) getInstalledChaincodes() pb.Response {
   383  	// get chaincode query response proto which contains information about all
   384  	// installed chaincodes
   385  	cqr, err := ccprovider.GetInstalledChaincodes()
   386  	if err != nil {
   387  		return shim.Error(err.Error())
   388  	}
   389  
   390  	cqrbytes, err := proto.Marshal(cqr)
   391  	if err != nil {
   392  		return shim.Error(err.Error())
   393  	}
   394  
   395  	return shim.Success(cqrbytes)
   396  }
   397  
   398  //do access control
   399  func (lscc *LifeCycleSysCC) acl(stub shim.ChaincodeStubInterface, chainname string, cds *pb.ChaincodeDeploymentSpec) error {
   400  	return nil
   401  }
   402  
   403  //check validity of chain name
   404  func (lscc *LifeCycleSysCC) isValidChainName(chainname string) bool {
   405  	//TODO we probably need more checks
   406  	if chainname == "" {
   407  		return false
   408  	}
   409  	return true
   410  }
   411  
   412  // isValidChaincodeName checks the validity of chaincode name. Chaincode names
   413  // should never be blank and should only consist of alphanumerics, '_', and '-'
   414  func (lscc *LifeCycleSysCC) isValidChaincodeName(chaincodeName string) error {
   415  	if chaincodeName == "" {
   416  		return EmptyChaincodeNameErr("")
   417  	}
   418  
   419  	if !isValidCCNameOrVersion(chaincodeName, allowedCharsChaincodeName) {
   420  		return InvalidChaincodeNameErr(chaincodeName)
   421  	}
   422  
   423  	return nil
   424  }
   425  
   426  // isValidChaincodeVersion checks the validity of chaincode version. Versions
   427  // should never be blank and should only consist of alphanumerics, '_',  '-',
   428  // and '.'
   429  func (lscc *LifeCycleSysCC) isValidChaincodeVersion(chaincodeName string, version string) error {
   430  	if version == "" {
   431  		return EmptyVersionErr(chaincodeName)
   432  	}
   433  
   434  	if !isValidCCNameOrVersion(version, allowedCharsVersion) {
   435  		return InvalidVersionErr(version)
   436  	}
   437  
   438  	return nil
   439  }
   440  
   441  func isValidCCNameOrVersion(ccNameOrVersion string, regExp string) bool {
   442  	re, _ := regexp.Compile(regExp)
   443  
   444  	matched := re.FindString(ccNameOrVersion)
   445  	if len(matched) != len(ccNameOrVersion) {
   446  		return false
   447  	}
   448  
   449  	return true
   450  }
   451  
   452  // executeInstall implements the "install" Invoke transaction
   453  func (lscc *LifeCycleSysCC) executeInstall(stub shim.ChaincodeStubInterface, ccbytes []byte) error {
   454  	ccpack, err := ccprovider.GetCCPackage(ccbytes)
   455  	if err != nil {
   456  		return err
   457  	}
   458  
   459  	cds := ccpack.GetDepSpec()
   460  
   461  	if cds == nil {
   462  		return fmt.Errorf("nil deployment spec from from the CC package")
   463  	}
   464  
   465  	if err = lscc.isValidChaincodeName(cds.ChaincodeSpec.ChaincodeId.Name); err != nil {
   466  		return err
   467  	}
   468  
   469  	if err = lscc.isValidChaincodeVersion(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version); err != nil {
   470  		return err
   471  	}
   472  
   473  	//everything checks out..lets write the package to the FS
   474  	if err = ccpack.PutChaincodeToFS(); err != nil {
   475  		return fmt.Errorf("Error installing chaincode code %s:%s(%s)", cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, err)
   476  	}
   477  
   478  	return err
   479  }
   480  
   481  // getInstantiationPolicy retrieves the instantiation policy from a SignedCDSPackage
   482  func (lscc *LifeCycleSysCC) getInstantiationPolicy(channel string, ccpack ccprovider.CCPackage) ([]byte, error) {
   483  	var ip []byte
   484  	var err error
   485  	// if ccpack is a SignedCDSPackage, return its IP, otherwise use a default IP
   486  	sccpack, isSccpack := ccpack.(*ccprovider.SignedCDSPackage)
   487  	if isSccpack {
   488  		ip = sccpack.GetInstantiationPolicy()
   489  		if ip == nil {
   490  			return nil, fmt.Errorf("Instantiation policy cannot be null for a SignedCCDeploymentSpec")
   491  		}
   492  	} else {
   493  		// the default instantiation policy allows any of the channel MSP admins
   494  		// to be able to instantiate
   495  		mspids := peer.GetMSPIDs(channel)
   496  
   497  		p := cauthdsl.SignedByAnyAdmin(mspids)
   498  		ip, err = utils.Marshal(p)
   499  		if err != nil {
   500  			return nil, fmt.Errorf("Error marshalling default instantiation policy")
   501  		}
   502  
   503  	}
   504  	return ip, nil
   505  }
   506  
   507  // checkInstantiationPolicy evaluates an instantiation policy against a signed proposal
   508  func (lscc *LifeCycleSysCC) checkInstantiationPolicy(stub shim.ChaincodeStubInterface, chainName string, instantiationPolicy []byte) error {
   509  	// create a policy object from the policy bytes
   510  	mgr := mspmgmt.GetManagerForChain(chainName)
   511  	if mgr == nil {
   512  		return fmt.Errorf("Error checking chaincode instantiation policy: MSP manager for chain %s not found", chainName)
   513  	}
   514  	npp := cauthdsl.NewPolicyProvider(mgr)
   515  	instPol, _, err := npp.NewPolicy(instantiationPolicy)
   516  	if err != nil {
   517  		return err
   518  	}
   519  	// get the signed instantiation proposal
   520  	signedProp, err := stub.GetSignedProposal()
   521  	if err != nil {
   522  		return err
   523  	}
   524  	proposal, err := utils.GetProposal(signedProp.ProposalBytes)
   525  	if err != nil {
   526  		return err
   527  	}
   528  	// get the signature header of the proposal
   529  	header, err := utils.GetHeader(proposal.Header)
   530  	if err != nil {
   531  		return err
   532  	}
   533  	shdr, err := utils.GetSignatureHeader(header.SignatureHeader)
   534  	if err != nil {
   535  		return err
   536  	}
   537  	// construct signed data we can evaluate the instantiation policy against
   538  	sd := []*common.SignedData{&common.SignedData{
   539  		Data:      signedProp.ProposalBytes,
   540  		Identity:  shdr.Creator,
   541  		Signature: signedProp.Signature,
   542  	}}
   543  	err = instPol.Evaluate(sd)
   544  	if err != nil {
   545  		return InstantiationPolicyViolatedErr(err.Error())
   546  	}
   547  	return nil
   548  }
   549  
   550  // executeDeploy implements the "instantiate" Invoke transaction
   551  func (lscc *LifeCycleSysCC) executeDeploy(stub shim.ChaincodeStubInterface, chainname string, depSpec []byte, policy []byte, escc []byte, vscc []byte) (*ccprovider.ChaincodeData, error) {
   552  	cds, err := utils.GetChaincodeDeploymentSpec(depSpec)
   553  
   554  	if err != nil {
   555  		return nil, err
   556  	}
   557  
   558  	if err = lscc.isValidChaincodeName(cds.ChaincodeSpec.ChaincodeId.Name); err != nil {
   559  		return nil, err
   560  	}
   561  
   562  	if err = lscc.isValidChaincodeVersion(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version); err != nil {
   563  		return nil, err
   564  	}
   565  
   566  	if err = lscc.acl(stub, chainname, cds); err != nil {
   567  		return nil, err
   568  	}
   569  
   570  	//just test for existence of the chaincode in the LSCC
   571  	_, err = lscc.getCCInstance(stub, cds.ChaincodeSpec.ChaincodeId.Name)
   572  	if err == nil {
   573  		return nil, ExistsErr(cds.ChaincodeSpec.ChaincodeId.Name)
   574  	}
   575  
   576  	//get the chaincode from the FS
   577  	ccpack, err := ccprovider.GetChaincodeFromFS(cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version)
   578  	if err != nil {
   579  		return nil, fmt.Errorf("cannot get package for the chaincode to be instantiated (%s:%s)-%s", cds.ChaincodeSpec.ChaincodeId.Name, cds.ChaincodeSpec.ChaincodeId.Version, err)
   580  	}
   581  
   582  	//this is guarantees to be not nil
   583  	cd := ccpack.GetChaincodeData()
   584  
   585  	//retain chaincode specific data and fill channel specific ones
   586  	cd.Escc = string(escc)
   587  	cd.Vscc = string(vscc)
   588  	cd.Policy = policy
   589  
   590  	// retrieve and evaluate instantiation policy
   591  	cd.InstantiationPolicy, err = lscc.getInstantiationPolicy(chainname, ccpack)
   592  	if err != nil {
   593  		return nil, err
   594  	}
   595  	err = lscc.checkInstantiationPolicy(stub, chainname, cd.InstantiationPolicy)
   596  	if err != nil {
   597  		return nil, err
   598  	}
   599  
   600  	err = lscc.createChaincode(stub, cd)
   601  
   602  	return cd, err
   603  }
   604  
   605  // executeUpgrade implements the "upgrade" Invoke transaction.
   606  func (lscc *LifeCycleSysCC) executeUpgrade(stub shim.ChaincodeStubInterface, chainName string, depSpec []byte, policy []byte, escc []byte, vscc []byte) (*ccprovider.ChaincodeData, error) {
   607  	cds, err := utils.GetChaincodeDeploymentSpec(depSpec)
   608  	if err != nil {
   609  		return nil, err
   610  	}
   611  
   612  	if err = lscc.acl(stub, chainName, cds); err != nil {
   613  		return nil, err
   614  	}
   615  
   616  	chaincodeName := cds.ChaincodeSpec.ChaincodeId.Name
   617  	if err = lscc.isValidChaincodeName(chaincodeName); err != nil {
   618  		return nil, err
   619  	}
   620  
   621  	if err = lscc.isValidChaincodeVersion(chaincodeName, cds.ChaincodeSpec.ChaincodeId.Version); err != nil {
   622  		return nil, err
   623  	}
   624  
   625  	// check for existence of chaincode instance only (it has to exist on the channel)
   626  	// we dont care about the old chaincode on the FS. In particular, user may even
   627  	// have deleted it
   628  	cdbytes, _ := lscc.getCCInstance(stub, chaincodeName)
   629  	if cdbytes == nil {
   630  		return nil, NotFoundErr(chainName)
   631  	}
   632  
   633  	//we need the cd to compare the version
   634  	cd, err := lscc.getChaincodeData(chaincodeName, cdbytes)
   635  	if err != nil {
   636  		return nil, err
   637  	}
   638  
   639  	//do not upgrade if same version
   640  	if cd.Version == cds.ChaincodeSpec.ChaincodeId.Version {
   641  		return nil, IdenticalVersionErr(cds.ChaincodeSpec.ChaincodeId.Name)
   642  	}
   643  
   644  	//do not upgrade if instantiation policy is violated
   645  	if cd.InstantiationPolicy == nil {
   646  		return nil, InstantiationPolicyMissing("")
   647  	}
   648  	err = lscc.checkInstantiationPolicy(stub, chainName, cd.InstantiationPolicy)
   649  	if err != nil {
   650  		return nil, err
   651  	}
   652  
   653  	ccpack, err := ccprovider.GetChaincodeFromFS(chaincodeName, cds.ChaincodeSpec.ChaincodeId.Version)
   654  	if err != nil {
   655  		return nil, fmt.Errorf("cannot get package for the chaincode to be upgraded (%s:%s)-%s", chaincodeName, cds.ChaincodeSpec.ChaincodeId.Version, err)
   656  	}
   657  
   658  	//get the new cd to upgrade to this is guaranteed to be not nil
   659  	cd = ccpack.GetChaincodeData()
   660  
   661  	//retain chaincode specific data and fill channel specific ones
   662  	cd.Escc = string(escc)
   663  	cd.Vscc = string(vscc)
   664  	cd.Policy = policy
   665  
   666  	// retrieve and evaluate new instantiation policy
   667  	cd.InstantiationPolicy, err = lscc.getInstantiationPolicy(chainName, ccpack)
   668  	if err != nil {
   669  		return nil, err
   670  	}
   671  	err = lscc.checkInstantiationPolicy(stub, chainName, cd.InstantiationPolicy)
   672  	if err != nil {
   673  		return nil, err
   674  	}
   675  
   676  	err = lscc.upgradeChaincode(stub, cd)
   677  	if err != nil {
   678  		return nil, err
   679  	}
   680  
   681  	return cd, nil
   682  }
   683  
   684  //-------------- the chaincode stub interface implementation ----------
   685  
   686  //Init only initializes the system chaincode provider
   687  func (lscc *LifeCycleSysCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
   688  	lscc.sccprovider = sysccprovider.GetSystemChaincodeProvider()
   689  
   690  	// Init policy checker for access control
   691  	lscc.policyChecker = policyprovider.GetPolicyChecker()
   692  
   693  	return shim.Success(nil)
   694  }
   695  
   696  // Invoke implements lifecycle functions "deploy", "start", "stop", "upgrade".
   697  // Deploy's arguments -  {[]byte("deploy"), []byte(<chainname>), <unmarshalled pb.ChaincodeDeploymentSpec>}
   698  //
   699  // Invoke also implements some query-like functions
   700  // Get chaincode arguments -  {[]byte("getid"), []byte(<chainname>), []byte(<chaincodename>)}
   701  func (lscc *LifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
   702  	args := stub.GetArgs()
   703  	if len(args) < 1 {
   704  		return shim.Error(InvalidArgsLenErr(len(args)).Error())
   705  	}
   706  
   707  	function := string(args[0])
   708  
   709  	// Handle ACL:
   710  	// 1. get the signed proposal
   711  	sp, err := stub.GetSignedProposal()
   712  	if err != nil {
   713  		return shim.Error(fmt.Sprintf("Failed retrieving signed proposal on executing %s with error %s", function, err))
   714  	}
   715  
   716  	switch function {
   717  	case INSTALL:
   718  		if len(args) < 2 {
   719  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   720  		}
   721  
   722  		// 2. check local MSP Admins policy
   723  		if err = lscc.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp); err != nil {
   724  			return shim.Error(fmt.Sprintf("Authorization for INSTALL has been denied (error-%s)", err))
   725  		}
   726  
   727  		depSpec := args[1]
   728  
   729  		err := lscc.executeInstall(stub, depSpec)
   730  		if err != nil {
   731  			return shim.Error(err.Error())
   732  		}
   733  		return shim.Success([]byte("OK"))
   734  	case DEPLOY:
   735  		if len(args) < 3 || len(args) > 6 {
   736  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   737  		}
   738  
   739  		// TODO: add access control check
   740  		// once the instantiation process will be completed.
   741  
   742  		//chain the chaincode shoud be associated with. It
   743  		//should be created with a register call
   744  		chainname := string(args[1])
   745  
   746  		if !lscc.isValidChainName(chainname) {
   747  			return shim.Error(InvalidChainNameErr(chainname).Error())
   748  		}
   749  
   750  		depSpec := args[2]
   751  
   752  		// optional arguments here (they can each be nil and may or may not be present)
   753  		// args[3] is a marshalled SignaturePolicyEnvelope representing the endorsement policy
   754  		// args[4] is the name of escc
   755  		// args[5] is the name of vscc
   756  		var policy []byte
   757  		if len(args) > 3 && len(args[3]) > 0 {
   758  			policy = args[3]
   759  		} else {
   760  			p := cauthdsl.SignedByAnyMember(peer.GetMSPIDs(chainname))
   761  			policy, err = utils.Marshal(p)
   762  			if err != nil {
   763  				return shim.Error(err.Error())
   764  			}
   765  		}
   766  
   767  		var escc []byte
   768  		if len(args) > 4 && args[4] != nil {
   769  			escc = args[4]
   770  		} else {
   771  			escc = []byte("escc")
   772  		}
   773  
   774  		var vscc []byte
   775  		if len(args) > 5 && args[5] != nil {
   776  			vscc = args[5]
   777  		} else {
   778  			vscc = []byte("vscc")
   779  		}
   780  
   781  		cd, err := lscc.executeDeploy(stub, chainname, depSpec, policy, escc, vscc)
   782  		if err != nil {
   783  			return shim.Error(err.Error())
   784  		}
   785  		cdbytes, err := proto.Marshal(cd)
   786  		if err != nil {
   787  			return shim.Error(err.Error())
   788  		}
   789  		return shim.Success(cdbytes)
   790  	case UPGRADE:
   791  		if len(args) < 3 || len(args) > 6 {
   792  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   793  		}
   794  
   795  		chainname := string(args[1])
   796  		if !lscc.isValidChainName(chainname) {
   797  			return shim.Error(InvalidChainNameErr(chainname).Error())
   798  		}
   799  
   800  		// TODO: add access control check
   801  		// once the instantiation process will be completed.
   802  
   803  		depSpec := args[2]
   804  
   805  		// optional arguments here (they can each be nil and may or may not be present)
   806  		// args[3] is a marshalled SignaturePolicyEnvelope representing the endorsement policy
   807  		// args[4] is the name of escc
   808  		// args[5] is the name of vscc
   809  		var policy []byte
   810  		if len(args) > 3 && len(args[3]) > 0 {
   811  			policy = args[3]
   812  		} else {
   813  			p := cauthdsl.SignedByAnyMember(peer.GetMSPIDs(chainname))
   814  			policy, err = utils.Marshal(p)
   815  			if err != nil {
   816  				return shim.Error(err.Error())
   817  			}
   818  		}
   819  
   820  		var escc []byte
   821  		if len(args) > 4 && args[4] != nil {
   822  			escc = args[4]
   823  		} else {
   824  			escc = []byte("escc")
   825  		}
   826  
   827  		var vscc []byte
   828  		if len(args) > 5 && args[5] != nil {
   829  			vscc = args[5]
   830  		} else {
   831  			vscc = []byte("vscc")
   832  		}
   833  
   834  		cd, err := lscc.executeUpgrade(stub, chainname, depSpec, policy, escc, vscc)
   835  		if err != nil {
   836  			return shim.Error(err.Error())
   837  		}
   838  		cdbytes, err := proto.Marshal(cd)
   839  		if err != nil {
   840  			return shim.Error(err.Error())
   841  		}
   842  		return shim.Success(cdbytes)
   843  	case GETCCINFO, GETDEPSPEC, GETCCDATA:
   844  		if len(args) != 3 {
   845  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   846  		}
   847  
   848  		chain := string(args[1])
   849  		ccname := string(args[2])
   850  
   851  		// 2. check local Channel Readers policy
   852  		// Notice that this information are already available on the ledger
   853  		// therefore we enforce here that the caller is reader of the channel.
   854  		if err = lscc.policyChecker.CheckPolicy(chain, policies.ChannelApplicationReaders, sp); err != nil {
   855  			return shim.Error(fmt.Sprintf("Authorization for %s on channel %s has been denied with error %s", function, args[1], err))
   856  		}
   857  
   858  		cdbytes, err := lscc.getCCInstance(stub, ccname)
   859  		if err != nil {
   860  			logger.Errorf("error getting chaincode %s on channel: %s(err:%s)", ccname, chain, err)
   861  			return shim.Error(err.Error())
   862  		}
   863  
   864  		switch function {
   865  		case GETCCINFO:
   866  			cd, err := lscc.getChaincodeData(ccname, cdbytes)
   867  			if err != nil {
   868  				return shim.Error(err.Error())
   869  			}
   870  			return shim.Success([]byte(cd.Name))
   871  		case GETCCDATA:
   872  			return shim.Success(cdbytes)
   873  		default:
   874  			_, _, depspecbytes, err := lscc.getCCCode(ccname, cdbytes)
   875  			if err != nil {
   876  				return shim.Error(err.Error())
   877  			}
   878  			return shim.Success(depspecbytes)
   879  		}
   880  	case GETCHAINCODES:
   881  		if len(args) != 1 {
   882  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   883  		}
   884  
   885  		// 2. check local MSP Admins policy
   886  		if err = lscc.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp); err != nil {
   887  			return shim.Error(fmt.Sprintf("Authorization for GETCHAINCODES on channel %s has been denied with error %s", args[0], err))
   888  		}
   889  
   890  		return lscc.getChaincodes(stub)
   891  	case GETINSTALLEDCHAINCODES:
   892  		if len(args) != 1 {
   893  			return shim.Error(InvalidArgsLenErr(len(args)).Error())
   894  		}
   895  
   896  		// 2. check local MSP Admins policy
   897  		if err = lscc.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp); err != nil {
   898  			return shim.Error(fmt.Sprintf("Authorization for GETINSTALLEDCHAINCODES on channel %s has been denied with error %s", args[0], err))
   899  		}
   900  
   901  		return lscc.getInstalledChaincodes()
   902  	}
   903  
   904  	return shim.Error(InvalidFunctionErr(function).Error())
   905  }