github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/peer/lifecycle/chaincode/getinstalledpackage.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package chaincode 8 9 import ( 10 "context" 11 "path/filepath" 12 13 "github.com/golang/protobuf/proto" 14 "github.com/hechain20/hechain/bccsp" 15 "github.com/hechain20/hechain/core/chaincode/persistence" 16 "github.com/hechain20/hechain/protoutil" 17 cb "github.com/hyperledger/fabric-protos-go/common" 18 pb "github.com/hyperledger/fabric-protos-go/peer" 19 lb "github.com/hyperledger/fabric-protos-go/peer/lifecycle" 20 "github.com/pkg/errors" 21 "github.com/spf13/cobra" 22 "github.com/spf13/viper" 23 ) 24 25 // InstalledPackageGetter holds the dependencies needed to retrieve 26 // an installed chaincode package from a peer. 27 type InstalledPackageGetter struct { 28 Command *cobra.Command 29 Input *GetInstalledPackageInput 30 EndorserClient EndorserClient 31 Signer Signer 32 Writer Writer 33 } 34 35 // GetInstalledPackageInput holds all of the input parameters for 36 // getting an installed chaincode package from a peer. 37 type GetInstalledPackageInput struct { 38 PackageID string 39 OutputDirectory string 40 } 41 42 // Validate checks that the required parameters are provided. 43 func (i *GetInstalledPackageInput) Validate() error { 44 if i.PackageID == "" { 45 return errors.New("The required parameter 'package-id' is empty. Rerun the command with --package-id flag") 46 } 47 48 return nil 49 } 50 51 // GetInstalledPackageCmd returns the cobra command for getting an 52 // installed chaincode package from a peer. 53 func GetInstalledPackageCmd(i *InstalledPackageGetter, cryptoProvider bccsp.BCCSP) *cobra.Command { 54 chaincodeGetInstalledPackageCmd := &cobra.Command{ 55 Use: "getinstalledpackage [outputfile]", 56 Short: "Get an installed chaincode package from a peer.", 57 Long: "Get an installed chaincode package from a peer.", 58 RunE: func(cmd *cobra.Command, args []string) error { 59 if i == nil { 60 ccInput := &ClientConnectionsInput{ 61 CommandName: cmd.Name(), 62 EndorserRequired: true, 63 PeerAddresses: peerAddresses, 64 TLSRootCertFiles: tlsRootCertFiles, 65 ConnectionProfilePath: connectionProfilePath, 66 TargetPeer: targetPeer, 67 TLSEnabled: viper.GetBool("peer.tls.enabled"), 68 } 69 70 cc, err := NewClientConnections(ccInput, cryptoProvider) 71 if err != nil { 72 return err 73 } 74 75 gipInput := &GetInstalledPackageInput{ 76 PackageID: packageID, 77 OutputDirectory: outputDirectory, 78 } 79 80 // getinstalledpackage only supports one peer connection, 81 // which is why we only wire in the first endorser 82 // client 83 i = &InstalledPackageGetter{ 84 Command: cmd, 85 EndorserClient: cc.EndorserClients[0], 86 Input: gipInput, 87 Signer: cc.Signer, 88 Writer: &persistence.FilesystemIO{}, 89 } 90 } 91 return i.Get() 92 }, 93 } 94 95 flagList := []string{ 96 "peerAddresses", 97 "tlsRootCertFiles", 98 "connectionProfile", 99 "targetPeer", 100 "package-id", 101 "output-directory", 102 } 103 attachFlags(chaincodeGetInstalledPackageCmd, flagList) 104 105 return chaincodeGetInstalledPackageCmd 106 } 107 108 // Get retrieves the installed chaincode package from a peer. 109 func (i *InstalledPackageGetter) Get() error { 110 if i.Command != nil { 111 // Parsing of the command line is done so silence cmd usage 112 i.Command.SilenceUsage = true 113 } 114 115 if err := i.Input.Validate(); err != nil { 116 return err 117 } 118 119 proposal, err := i.createProposal() 120 if err != nil { 121 return errors.WithMessage(err, "failed to create proposal") 122 } 123 124 signedProposal, err := signProposal(proposal, i.Signer) 125 if err != nil { 126 return errors.WithMessage(err, "failed to create signed proposal") 127 } 128 129 proposalResponse, err := i.EndorserClient.ProcessProposal(context.Background(), signedProposal) 130 if err != nil { 131 return errors.WithMessage(err, "failed to endorse proposal") 132 } 133 134 if proposalResponse == nil { 135 return errors.New("received nil proposal response") 136 } 137 138 if proposalResponse.Response == nil { 139 return errors.New("received proposal response with nil response") 140 } 141 142 if proposalResponse.Response.Status != int32(cb.Status_SUCCESS) { 143 return errors.Errorf("proposal failed with status: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message) 144 } 145 146 return i.writePackage(proposalResponse) 147 } 148 149 func (i *InstalledPackageGetter) writePackage(proposalResponse *pb.ProposalResponse) error { 150 result := &lb.GetInstalledChaincodePackageResult{} 151 err := proto.Unmarshal(proposalResponse.Response.Payload, result) 152 if err != nil { 153 return errors.Wrap(err, "failed to unmarshal proposal response's response payload") 154 } 155 156 outputFile := filepath.Join(i.Input.OutputDirectory, i.Input.PackageID+".tar.gz") 157 158 dir, name := filepath.Split(outputFile) 159 // translate dir into absolute path 160 if dir, err = filepath.Abs(dir); err != nil { 161 return err 162 } 163 164 err = i.Writer.WriteFile(dir, name, result.ChaincodeInstallPackage) 165 if err != nil { 166 err = errors.Wrapf(err, "failed to write chaincode package to %s", outputFile) 167 logger.Error(err.Error()) 168 return err 169 } 170 171 return nil 172 } 173 174 func (i *InstalledPackageGetter) createProposal() (*pb.Proposal, error) { 175 args := &lb.GetInstalledChaincodePackageArgs{ 176 PackageId: i.Input.PackageID, 177 } 178 179 argsBytes, err := proto.Marshal(args) 180 if err != nil { 181 return nil, errors.Wrap(err, "failed to marshal args") 182 } 183 184 ccInput := &pb.ChaincodeInput{ 185 Args: [][]byte{[]byte("GetInstalledChaincodePackage"), argsBytes}, 186 } 187 188 cis := &pb.ChaincodeInvocationSpec{ 189 ChaincodeSpec: &pb.ChaincodeSpec{ 190 ChaincodeId: &pb.ChaincodeID{Name: lifecycleName}, 191 Input: ccInput, 192 }, 193 } 194 195 signerSerialized, err := i.Signer.Serialize() 196 if err != nil { 197 return nil, errors.WithMessage(err, "failed to serialize identity") 198 } 199 200 proposal, _, err := protoutil.CreateProposalFromCIS(cb.HeaderType_ENDORSER_TRANSACTION, "", cis, signerSerialized) 201 if err != nil { 202 return nil, errors.WithMessage(err, "failed to create ChaincodeInvocationSpec proposal") 203 } 204 205 return proposal, nil 206 }