github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/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 installCmdName = "install" 39 40 const installDesc = "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(installDesc), 47 Long: fmt.Sprint(installDesc), 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 flagList := []string{ 58 "lang", 59 "ctor", 60 "path", 61 "name", 62 "version", 63 } 64 attachFlags(chaincodeInstallCmd, flagList) 65 66 return chaincodeInstallCmd 67 } 68 69 //install the depspec to "peer.address" 70 func install(msg proto.Message, cf *ChaincodeCmdFactory) error { 71 creator, err := cf.Signer.Serialize() 72 if err != nil { 73 return fmt.Errorf("Error serializing identity for %s: %s", cf.Signer.GetIdentifier(), err) 74 } 75 76 prop, _, err := utils.CreateInstallProposalFromCDS(msg, creator) 77 if err != nil { 78 return fmt.Errorf("Error creating proposal %s: %s", chainFuncName, err) 79 } 80 81 var signedProp *pb.SignedProposal 82 signedProp, err = utils.GetSignedProposal(prop, cf.Signer) 83 if err != nil { 84 return fmt.Errorf("Error creating signed proposal %s: %s", chainFuncName, err) 85 } 86 87 proposalResponse, err := cf.EndorserClient.ProcessProposal(context.Background(), signedProp) 88 if err != nil { 89 return fmt.Errorf("Error endorsing %s: %s", chainFuncName, err) 90 } 91 92 if proposalResponse != nil { 93 logger.Debugf("Installed remotely %v", proposalResponse) 94 } 95 96 return nil 97 } 98 99 //genChaincodeDeploymentSpec creates ChaincodeDeploymentSpec as the package to install 100 func genChaincodeDeploymentSpec(cmd *cobra.Command, chaincodeName, chaincodeVersion string) (*pb.ChaincodeDeploymentSpec, error) { 101 if existed, _ := ccprovider.ChaincodePackageExists(chaincodeName, chaincodeVersion); existed { 102 return nil, fmt.Errorf("chaincode %s:%s already exists", chaincodeName, chaincodeVersion) 103 } 104 105 spec, err := getChaincodeSpec(cmd) 106 if err != nil { 107 return nil, err 108 } 109 110 cds, err := getChaincodeDeploymentSpec(spec, true) 111 if err != nil { 112 return nil, fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err) 113 } 114 115 return cds, nil 116 } 117 118 //getPackageFromFile get the chaincode package from file and the extracted ChaincodeDeploymentSpec 119 func getPackageFromFile(ccpackfile string) (proto.Message, *pb.ChaincodeDeploymentSpec, error) { 120 b, err := ioutil.ReadFile(ccpackfile) 121 if err != nil { 122 return nil, nil, err 123 } 124 125 //the bytes should be a valid package (CDS or SigedCDS) 126 ccpack, err := ccprovider.GetCCPackage(b) 127 if err != nil { 128 return nil, nil, err 129 } 130 131 //either CDS or Envelope 132 o, err := ccpack.GetPackageObject(), nil 133 if err != nil { 134 return nil, nil, err 135 } 136 137 //try CDS first 138 cds, ok := o.(*pb.ChaincodeDeploymentSpec) 139 if !ok || cds == nil { 140 //try Envelope next 141 env, ok := o.(*pcommon.Envelope) 142 if !ok || env == nil { 143 return nil, nil, fmt.Errorf("error extracting valid chaincode package") 144 } 145 146 //this will check for a valid package Envelope 147 _, sCDS, err := ccpackage.ExtractSignedCCDepSpec(env) 148 if err != nil { 149 return nil, nil, fmt.Errorf("error extracting valid signed chaincode package(%s)", err) 150 } 151 152 //...and get the CDS at last 153 cds, err = utils.GetChaincodeDeploymentSpec(sCDS.ChaincodeDeploymentSpec) 154 if err != nil { 155 return nil, nil, fmt.Errorf("error extracting chaincode deployment spec(%s)", err) 156 } 157 } 158 159 return o, cds, nil 160 } 161 162 // chaincodeInstall installs the chaincode. If remoteinstall, does it via a lscc call 163 func chaincodeInstall(cmd *cobra.Command, ccpackfile string, cf *ChaincodeCmdFactory) error { 164 var err error 165 if cf == nil { 166 cf, err = InitCmdFactory(true, false) 167 if err != nil { 168 return err 169 } 170 } 171 172 var ccpackmsg proto.Message 173 if ccpackfile == "" { 174 if chaincodePath == common.UndefinedParamValue || chaincodeVersion == common.UndefinedParamValue || chaincodeName == common.UndefinedParamValue { 175 return fmt.Errorf("Must supply value for %s name, path and version parameters.", chainFuncName) 176 } 177 //generate a raw ChaincodeDeploymentSpec 178 ccpackmsg, err = genChaincodeDeploymentSpec(cmd, chaincodeName, chaincodeVersion) 179 if err != nil { 180 return err 181 } 182 } else { 183 //read in a package generated by the "package" sub-command (and perhaps signed 184 //by multiple owners with the "signpackage" sub-command) 185 var cds *pb.ChaincodeDeploymentSpec 186 ccpackmsg, cds, err = getPackageFromFile(ccpackfile) 187 188 if err != nil { 189 return err 190 } 191 192 //get the chaincode details from cds 193 cName := cds.ChaincodeSpec.ChaincodeId.Name 194 cVersion := cds.ChaincodeSpec.ChaincodeId.Version 195 196 //if user provided chaincodeName, use it for validation 197 if chaincodeName != "" && chaincodeName != cName { 198 return fmt.Errorf("chaincode name %s does not match name %s in package", chaincodeName, cName) 199 } 200 201 //if user provided chaincodeVersion, use it for validation 202 if chaincodeVersion != "" && chaincodeVersion != cVersion { 203 return fmt.Errorf("chaincode version %s does not match version %s in packages", chaincodeVersion, cVersion) 204 } 205 } 206 207 err = install(ccpackmsg, cf) 208 209 return err 210 }