github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/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 packageCmdName = "package"
    42  const packageDesc = "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:     packageDesc,
    55  		Long:      packageDesc,
    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  	flagList := []string{
    69  		"lang",
    70  		"ctor",
    71  		"path",
    72  		"name",
    73  		"version",
    74  	}
    75  	attachFlags(chaincodePackageCmd, flagList)
    76  
    77  	chaincodePackageCmd.Flags().BoolVarP(&createSignedCCDepSpec, "cc-package", "s", false, "create CC deployment spec for owner endorsements instead of raw CC deployment spec")
    78  	chaincodePackageCmd.Flags().BoolVarP(&signCCDepSpec, "sign", "S", false, "if creating CC deployment spec package for owner endorsements, also sign it with local MSP")
    79  	chaincodePackageCmd.Flags().StringVarP(&instantiationPolicy, "instantiate-policy", "i", "", "instantiation policy for the chaincode")
    80  
    81  	return chaincodePackageCmd
    82  }
    83  
    84  func getInstantiationPolicy(policy string) (*pcommon.SignaturePolicyEnvelope, error) {
    85  	p, err := cauthdsl.FromString(policy)
    86  	if err != nil {
    87  		return nil, fmt.Errorf("Invalid policy %s, err %s", policy, err)
    88  	}
    89  	return p, nil
    90  }
    91  
    92  //getChaincodeInstallPackage returns either a raw ChaincodeDeploymentSpec or
    93  //a Envelope with ChaincodeDeploymentSpec and (optional) signature
    94  func getChaincodeInstallPackage(cds *pb.ChaincodeDeploymentSpec, cf *ChaincodeCmdFactory) ([]byte, error) {
    95  	//this can be raw ChaincodeDeploymentSpec or Envelope with signatures
    96  	var objToWrite proto.Message
    97  
    98  	//start with default cds
    99  	objToWrite = cds
   100  
   101  	var err error
   102  
   103  	var owner msp.SigningIdentity
   104  
   105  	//create a chaincode package...
   106  	if createSignedCCDepSpec {
   107  		//...and optionally get the signer so the package can be signed
   108  		//by the local MSP.  This package can be given to other owners
   109  		//to sign using "peer chaincode sign <package file>"
   110  		if signCCDepSpec {
   111  			if cf.Signer == nil {
   112  				return nil, fmt.Errorf("Error getting signer")
   113  			}
   114  			owner = cf.Signer
   115  		}
   116  	}
   117  
   118  	ip := instantiationPolicy
   119  	if ip == "" {
   120  		//if an instantiation policy is not given, default
   121  		//to "admin  must sign chaincode instantiation proposals"
   122  		mspid, err := mspmgmt.GetLocalMSP().GetIdentifier()
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  		ip = "AND('" + mspid + ".admin')"
   127  	}
   128  
   129  	sp, err := getInstantiationPolicy(ip)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	//we get the Envelope of type CHAINCODE_PACKAGE
   135  	objToWrite, err = ccpackage.OwnerCreateSignedCCDepSpec(cds, sp, owner)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	//convert the proto object to bytes
   141  	bytesToWrite, err := proto.Marshal(objToWrite)
   142  	if err != nil {
   143  		return nil, fmt.Errorf("Error marshalling chaincode package : %s", err)
   144  	}
   145  
   146  	return bytesToWrite, nil
   147  }
   148  
   149  // chaincodePackage creates the chaincode package. On success, the chaincode name
   150  // (hash) is printed to STDOUT for use by subsequent chaincode-related CLI
   151  // commands.
   152  func chaincodePackage(cmd *cobra.Command, args []string, cdsFact ccDepSpecFactory, cf *ChaincodeCmdFactory) error {
   153  	if cdsFact == nil {
   154  		return fmt.Errorf("Error chaincode deployment spec factory not specified")
   155  	}
   156  
   157  	var err error
   158  	if cf == nil {
   159  		cf, err = InitCmdFactory(false, false)
   160  		if err != nil {
   161  			return err
   162  		}
   163  	}
   164  	spec, err := getChaincodeSpec(cmd)
   165  	if err != nil {
   166  		return err
   167  	}
   168  
   169  	cds, err := cdsFact(spec)
   170  	if err != nil {
   171  		return fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err)
   172  	}
   173  
   174  	var bytesToWrite []byte
   175  	if createSignedCCDepSpec {
   176  		bytesToWrite, err = getChaincodeInstallPackage(cds, cf)
   177  		if err != nil {
   178  			return err
   179  		}
   180  	} else {
   181  		bytesToWrite = utils.MarshalOrPanic(cds)
   182  	}
   183  
   184  	logger.Debugf("Packaged chaincode into deployment spec of size <%d>, with args = %v", len(bytesToWrite), args)
   185  	fileToWrite := args[0]
   186  	err = ioutil.WriteFile(fileToWrite, bytesToWrite, 0700)
   187  	if err != nil {
   188  		logger.Errorf("Failed writing deployment spec to file [%s]: [%s]", fileToWrite, err)
   189  		return err
   190  	}
   191  
   192  	return err
   193  }