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