github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/peer/chaincode/install.go (about) 1 /* 2 Copyright IBM Corp. 2016-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 "io/ioutil" 22 23 "github.com/golang/protobuf/proto" 24 "golang.org/x/net/context" 25 26 "github.com/hyperledger/fabric/core/common/ccpackage" 27 "github.com/hyperledger/fabric/core/common/ccprovider" 28 "github.com/hyperledger/fabric/peer/common" 29 pcommon "github.com/hyperledger/fabric/protos/common" 30 pb "github.com/hyperledger/fabric/protos/peer" 31 "github.com/hyperledger/fabric/protos/utils" 32 33 "github.com/spf13/cobra" 34 ) 35 36 var chaincodeInstallCmd *cobra.Command 37 38 const install_cmdname = "install" 39 40 const install_desc = "Package the specified chaincode into a deployment spec and save it on the peer's path." 41 42 // installCmd returns the cobra command for Chaincode Deploy 43 func installCmd(cf *ChaincodeCmdFactory) *cobra.Command { 44 chaincodeInstallCmd = &cobra.Command{ 45 Use: "install", 46 Short: fmt.Sprint(install_desc), 47 Long: fmt.Sprint(install_desc), 48 ValidArgs: []string{"1"}, 49 RunE: func(cmd *cobra.Command, args []string) error { 50 var ccpackfile string 51 if len(args) > 0 { 52 ccpackfile = args[0] 53 } 54 return chaincodeInstall(cmd, ccpackfile, cf) 55 }, 56 } 57 58 return chaincodeInstallCmd 59 } 60 61 //install the depspec to "peer.address" 62 func install(msg proto.Message, cf *ChaincodeCmdFactory) error { 63 creator, err := cf.Signer.Serialize() 64 if err != nil { 65 return fmt.Errorf("Error serializing identity for %s: %s", cf.Signer.GetIdentifier(), err) 66 } 67 68 prop, _, err := utils.CreateInstallProposalFromCDS(msg, creator) 69 if err != nil { 70 return fmt.Errorf("Error creating proposal %s: %s", chainFuncName, err) 71 } 72 73 var signedProp *pb.SignedProposal 74 signedProp, err = utils.GetSignedProposal(prop, cf.Signer) 75 if err != nil { 76 return fmt.Errorf("Error creating signed proposal %s: %s", chainFuncName, err) 77 } 78 79 proposalResponse, err := cf.EndorserClient.ProcessProposal(context.Background(), signedProp) 80 if err != nil { 81 return fmt.Errorf("Error endorsing %s: %s", chainFuncName, err) 82 } 83 84 if proposalResponse != nil { 85 logger.Debugf("Installed remotely %v", proposalResponse) 86 } 87 88 return nil 89 } 90 91 //generateChaincode creates ChaincodeDeploymentSpec as the package to install 92 func generateChaincode(cmd *cobra.Command, chaincodeName, chaincodeVersion string) (*pb.ChaincodeDeploymentSpec, error) { 93 tmppkg, _ := ccprovider.GetChaincodePackage(chaincodeName, chaincodeVersion) 94 if tmppkg != nil { 95 return nil, fmt.Errorf("chaincode %s:%s exists", chaincodeName, chaincodeVersion) 96 } 97 98 spec, err := getChaincodeSpec(cmd) 99 if err != nil { 100 return nil, err 101 } 102 103 cds, err := getChaincodeDeploymentSpec(spec, true) 104 if err != nil { 105 return nil, fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err) 106 } 107 108 return cds, nil 109 } 110 111 //getPackageFromFile get the chaincode package from file and the extracted ChaincodeDeploymentSpec 112 func getPackageFromFile(ccpackfile string) (proto.Message, *pb.ChaincodeDeploymentSpec, error) { 113 b, err := ioutil.ReadFile(ccpackfile) 114 if err != nil { 115 return nil, nil, err 116 } 117 118 //the bytes should be a valid package (CDS or SigedCDS) 119 ccpack, err := ccprovider.GetCCPackage(b) 120 if err != nil { 121 return nil, nil, err 122 } 123 124 //either CDS or Envelope 125 o, err := ccpack.GetPackageObject(), nil 126 if err != nil { 127 return nil, nil, err 128 } 129 130 //try CDS first 131 cds, ok := o.(*pb.ChaincodeDeploymentSpec) 132 if !ok || cds == nil { 133 //try Envelope next 134 env, ok := o.(*pcommon.Envelope) 135 if !ok || env == nil { 136 return nil, nil, fmt.Errorf("error extracting valid chaincode package") 137 } 138 139 //this will check for a valid package Envelope 140 _, sCDS, err := ccpackage.ExtractSignedCCDepSpec(env) 141 if err != nil { 142 return nil, nil, fmt.Errorf("error extracting valid signed chaincode package(%s)", err) 143 } 144 145 //...and get the CDS at last 146 cds, err = utils.GetChaincodeDeploymentSpec(sCDS.ChaincodeDeploymentSpec) 147 if err != nil { 148 return nil, nil, fmt.Errorf("error extracting chaincode deployment spec(%s)", err) 149 } 150 } 151 152 return o, cds, nil 153 } 154 155 // chaincodeInstall installs the chaincode. If remoteinstall, does it via a lscc call 156 func chaincodeInstall(cmd *cobra.Command, ccpackfile string, cf *ChaincodeCmdFactory) error { 157 var err error 158 if cf == nil { 159 cf, err = InitCmdFactory(true, false) 160 if err != nil { 161 return err 162 } 163 } 164 165 var ccpackmsg proto.Message 166 if ccpackfile == "" { 167 if chaincodePath == common.UndefinedParamValue || chaincodeVersion == common.UndefinedParamValue { 168 return fmt.Errorf("Must supply value for %s path and version parameters.", chainFuncName) 169 } 170 //generate a raw ChaincodeDeploymentSpec 171 ccpackmsg, err = generateChaincode(cmd, chaincodeName, chaincodeVersion) 172 if err != nil { 173 return err 174 } 175 } else { 176 //read in a package generated by the "package" sub-command (and perhaps signed 177 //by multiple owners with the "signpackage" sub-command) 178 var cds *pb.ChaincodeDeploymentSpec 179 ccpackmsg, cds, err = getPackageFromFile(ccpackfile) 180 181 if err != nil { 182 return err 183 } 184 185 //get the chaincode details from cds 186 cName := cds.ChaincodeSpec.ChaincodeId.Name 187 cVersion := cds.ChaincodeSpec.ChaincodeId.Version 188 189 //if user provided chaincodeName, use it for validation 190 if chaincodeName != "" && chaincodeName != cName { 191 return fmt.Errorf("chaincode name %s does not match name %s in package", chaincodeName, cName) 192 } 193 194 //if user provided chaincodeVersion, use it for validation 195 if chaincodeVersion != "" && chaincodeVersion != cVersion { 196 return fmt.Errorf("chaincode version %s does not match version %s in packages", chaincodeVersion, cVersion) 197 } 198 } 199 200 err = install(ccpackmsg, cf) 201 202 return err 203 }