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