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 }