github.com/lzy4123/fabric@v2.1.1+incompatible/internal/peer/lifecycle/chaincode/queryinstalled.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package chaincode 8 9 import ( 10 "context" 11 "fmt" 12 "io" 13 "os" 14 "strings" 15 16 "github.com/golang/protobuf/proto" 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/hyperledger/fabric/bccsp" 21 "github.com/hyperledger/fabric/protoutil" 22 "github.com/pkg/errors" 23 "github.com/spf13/cobra" 24 "github.com/spf13/viper" 25 ) 26 27 // InstalledQuerier holds the dependencies needed to query 28 // the installed chaincodes 29 type InstalledQuerier struct { 30 Command *cobra.Command 31 Input *InstalledQueryInput 32 EndorserClient EndorserClient 33 Signer Signer 34 Writer io.Writer 35 } 36 37 type InstalledQueryInput struct { 38 OutputFormat string 39 } 40 41 // QueryInstalledCmd returns the cobra command for listing 42 // the installed chaincodes 43 func QueryInstalledCmd(i *InstalledQuerier, cryptoProvider bccsp.BCCSP) *cobra.Command { 44 chaincodeQueryInstalledCmd := &cobra.Command{ 45 Use: "queryinstalled", 46 Short: "Query the installed chaincodes on a peer.", 47 Long: "Query the installed chaincodes on a peer.", 48 RunE: func(cmd *cobra.Command, args []string) error { 49 if i == nil { 50 ccInput := &ClientConnectionsInput{ 51 CommandName: cmd.Name(), 52 EndorserRequired: true, 53 ChannelID: channelID, 54 PeerAddresses: peerAddresses, 55 TLSRootCertFiles: tlsRootCertFiles, 56 ConnectionProfilePath: connectionProfilePath, 57 TLSEnabled: viper.GetBool("peer.tls.enabled"), 58 } 59 60 cc, err := NewClientConnections(ccInput, cryptoProvider) 61 if err != nil { 62 return err 63 } 64 65 iqInput := &InstalledQueryInput{ 66 OutputFormat: output, 67 } 68 69 // queryinstalled only supports one peer connection, 70 // which is why we only wire in the first endorser 71 // client 72 i = &InstalledQuerier{ 73 Command: cmd, 74 EndorserClient: cc.EndorserClients[0], 75 Input: iqInput, 76 Signer: cc.Signer, 77 Writer: os.Stdout, 78 } 79 } 80 return i.Query() 81 }, 82 } 83 84 flagList := []string{ 85 "peerAddresses", 86 "tlsRootCertFiles", 87 "connectionProfile", 88 "output", 89 } 90 attachFlags(chaincodeQueryInstalledCmd, flagList) 91 92 return chaincodeQueryInstalledCmd 93 } 94 95 // Query returns the chaincodes installed on a peer 96 func (i *InstalledQuerier) Query() error { 97 if i.Command != nil { 98 // Parsing of the command line is done so silence cmd usage 99 i.Command.SilenceUsage = true 100 } 101 102 proposal, err := i.createProposal() 103 if err != nil { 104 return errors.WithMessage(err, "failed to create proposal") 105 } 106 107 signedProposal, err := signProposal(proposal, i.Signer) 108 if err != nil { 109 return errors.WithMessage(err, "failed to create signed proposal") 110 } 111 112 proposalResponse, err := i.EndorserClient.ProcessProposal(context.Background(), signedProposal) 113 if err != nil { 114 return errors.WithMessage(err, "failed to endorse proposal") 115 } 116 117 if proposalResponse == nil { 118 return errors.New("received nil proposal response") 119 } 120 121 if proposalResponse.Response == nil { 122 return errors.New("received proposal response with nil response") 123 } 124 125 if proposalResponse.Response.Status != int32(cb.Status_SUCCESS) { 126 return errors.Errorf("query failed with status: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message) 127 } 128 129 if strings.ToLower(i.Input.OutputFormat) == "json" { 130 return printResponseAsJSON(proposalResponse, &lb.QueryInstalledChaincodesResult{}, i.Writer) 131 } 132 return i.printResponse(proposalResponse) 133 } 134 135 // printResponse prints the information included in the response 136 // from the server. 137 func (i *InstalledQuerier) printResponse(proposalResponse *pb.ProposalResponse) error { 138 qicr := &lb.QueryInstalledChaincodesResult{} 139 err := proto.Unmarshal(proposalResponse.Response.Payload, qicr) 140 if err != nil { 141 return errors.Wrap(err, "failed to unmarshal proposal response's response payload") 142 } 143 fmt.Fprintln(i.Writer, "Installed chaincodes on peer:") 144 for _, chaincode := range qicr.InstalledChaincodes { 145 fmt.Fprintf(i.Writer, "Package ID: %s, Label: %s\n", chaincode.PackageId, chaincode.Label) 146 } 147 return nil 148 } 149 150 func (i *InstalledQuerier) createProposal() (*pb.Proposal, error) { 151 args := &lb.QueryInstalledChaincodesArgs{} 152 153 argsBytes, err := proto.Marshal(args) 154 if err != nil { 155 return nil, errors.Wrap(err, "failed to marshal args") 156 } 157 158 ccInput := &pb.ChaincodeInput{ 159 Args: [][]byte{[]byte("QueryInstalledChaincodes"), argsBytes}, 160 } 161 162 cis := &pb.ChaincodeInvocationSpec{ 163 ChaincodeSpec: &pb.ChaincodeSpec{ 164 ChaincodeId: &pb.ChaincodeID{Name: lifecycleName}, 165 Input: ccInput, 166 }, 167 } 168 169 signerSerialized, err := i.Signer.Serialize() 170 if err != nil { 171 return nil, errors.WithMessage(err, "failed to serialize identity") 172 } 173 174 proposal, _, err := protoutil.CreateProposalFromCIS(cb.HeaderType_ENDORSER_TRANSACTION, "", cis, signerSerialized) 175 if err != nil { 176 return nil, errors.WithMessage(err, "failed to create ChaincodeInvocationSpec proposal") 177 } 178 179 return proposal, nil 180 }