github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/peer/chaincode/package.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 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 chaincode
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"io/ioutil"
    23  
    24  	"github.com/golang/protobuf/proto"
    25  	"github.com/spf13/cobra"
    26  
    27  	"github.com/hyperledger/fabric/common/cauthdsl"
    28  	"github.com/hyperledger/fabric/core/common/ccpackage"
    29  	"github.com/hyperledger/fabric/msp"
    30  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    31  	pcommon "github.com/hyperledger/fabric/protos/common"
    32  	pb "github.com/hyperledger/fabric/protos/peer"
    33  	"github.com/hyperledger/fabric/protos/utils"
    34  )
    35  
    36  var chaincodePackageCmd *cobra.Command
    37  var createSignedCCDepSpec bool
    38  var signCCDepSpec bool
    39  var instantiationPolicy string
    40  
    41  const package_cmdname = "package"
    42  const package_desc = "Package the specified chaincode into a deployment spec."
    43  
    44  type ccDepSpecFactory func(spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error)
    45  
    46  func defaultCDSFactory(spec *pb.ChaincodeSpec) (*pb.ChaincodeDeploymentSpec, error) {
    47  	return getChaincodeDeploymentSpec(spec, true)
    48  }
    49  
    50  // deployCmd returns the cobra command for Chaincode Deploy
    51  func packageCmd(cf *ChaincodeCmdFactory, cdsFact ccDepSpecFactory) *cobra.Command {
    52  	chaincodePackageCmd = &cobra.Command{
    53  		Use:       "package",
    54  		Short:     package_desc,
    55  		Long:      package_desc,
    56  		ValidArgs: []string{"1"},
    57  		RunE: func(cmd *cobra.Command, args []string) error {
    58  			if len(args) != 1 {
    59  				return fmt.Errorf("output file not specified or invalid number of args (filename should be the only arg)")
    60  			}
    61  			//UT will supply its own mock factory
    62  			if cdsFact == nil {
    63  				cdsFact = defaultCDSFactory
    64  			}
    65  			return chaincodePackage(cmd, args, cdsFact, cf)
    66  		},
    67  	}
    68  
    69  	chaincodePackageCmd.Flags().BoolVarP(&createSignedCCDepSpec, "cc-package", "s", false, "create CC deployment spec for owner endorsements instead of raw CC deployment spec")
    70  	chaincodePackageCmd.Flags().BoolVarP(&signCCDepSpec, "sign", "S", false, "if creating CC deployment spec package for owner endorsements, also sign it with local MSP")
    71  	chaincodePackageCmd.Flags().StringVarP(&instantiationPolicy, "instantiate-policy", "i", "", "instatiation policy for the chaincode")
    72  
    73  	return chaincodePackageCmd
    74  }
    75  
    76  func getInstantiationPolicy(policy string) (*pcommon.SignaturePolicyEnvelope, error) {
    77  	p, err := cauthdsl.FromString(policy)
    78  	if err != nil {
    79  		return nil, fmt.Errorf("Invalid policy %s", policy)
    80  	}
    81  	return p, nil
    82  }
    83  
    84  //getChaincodeInstallPackage returns either a raw ChaincodeDeploymentSpec or
    85  //a Envelope with ChaincodeDeploymentSpec and (optional) signature
    86  func getChaincodeInstallPackage(cds *pb.ChaincodeDeploymentSpec, cf *ChaincodeCmdFactory) ([]byte, error) {
    87  	//this can be raw ChaincodeDeploymentSpec or Envelope with signatures
    88  	var objToWrite proto.Message
    89  
    90  	//start with default cds
    91  	objToWrite = cds
    92  
    93  	var err error
    94  
    95  	var owner msp.SigningIdentity
    96  
    97  	//create a chaincode package...
    98  	if createSignedCCDepSpec {
    99  		//...and optionally get the signer so the package can be signed
   100  		//by the local MSP.  This package can be given to other owners
   101  		//to sign using "peer chaincode sign <package file>"
   102  		if signCCDepSpec {
   103  			if cf.Signer == nil {
   104  				return nil, fmt.Errorf("Error getting signer")
   105  			}
   106  			owner = cf.Signer
   107  		}
   108  	}
   109  
   110  	ip := instantiationPolicy
   111  	if ip == "" {
   112  		//if an instantiation policy is not given, default
   113  		//to "admin  must sign chaincode instantiation proposals"
   114  		mspid, err := mspmgmt.GetLocalMSP().GetIdentifier()
   115  		if err != nil {
   116  			return nil, err
   117  		}
   118  		ip = "AND('" + mspid + ".admin')"
   119  	}
   120  
   121  	sp, err := getInstantiationPolicy(ip)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	//we get the Envelope of type CHAINCODE_PACKAGE
   127  	objToWrite, err = ccpackage.OwnerCreateSignedCCDepSpec(cds, sp, owner)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  
   132  	//convert the proto object to bytes
   133  	bytesToWrite, err := proto.Marshal(objToWrite)
   134  	if err != nil {
   135  		return nil, fmt.Errorf("Error marshalling chaincode package : %s", err)
   136  	}
   137  
   138  	return bytesToWrite, nil
   139  }
   140  
   141  // chaincodePackage creates the chaincode packge. On success, the chaincode name
   142  // (hash) is printed to STDOUT for use by subsequent chaincode-related CLI
   143  // commands.
   144  func chaincodePackage(cmd *cobra.Command, args []string, cdsFact ccDepSpecFactory, cf *ChaincodeCmdFactory) error {
   145  	if cdsFact == nil {
   146  		return fmt.Errorf("Error chaincode deployment spec factory not specified")
   147  	}
   148  
   149  	var err error
   150  	if cf == nil {
   151  		cf, err = InitCmdFactory(false, false)
   152  		if err != nil {
   153  			return err
   154  		}
   155  	}
   156  	spec, err := getChaincodeSpec(cmd)
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	cds, err := cdsFact(spec)
   162  	if err != nil {
   163  		return fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err)
   164  	}
   165  
   166  	var bytesToWrite []byte
   167  	if createSignedCCDepSpec {
   168  		bytesToWrite, err = getChaincodeInstallPackage(cds, cf)
   169  		if err != nil {
   170  			return err
   171  		}
   172  	} else {
   173  		bytesToWrite = utils.MarshalOrPanic(cds)
   174  	}
   175  
   176  	logger.Debugf("Packaged chaincode into deployment spec of size <%d>, with args = %v", len(bytesToWrite), args)
   177  	fileToWrite := args[0]
   178  	err = ioutil.WriteFile(fileToWrite, bytesToWrite, 0700)
   179  	if err != nil {
   180  		logger.Errorf("Failed writing deployment spec to file [%s]: [%s]", fileToWrite, err)
   181  		return err
   182  	}
   183  
   184  	return err
   185  }