github.com/lzy4123/fabric@v2.1.1+incompatible/internal/peer/chaincode/list.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 "bytes" 11 "context" 12 "encoding/hex" 13 "fmt" 14 "reflect" 15 "strings" 16 17 "github.com/golang/protobuf/proto" 18 cb "github.com/hyperledger/fabric-protos-go/common" 19 pb "github.com/hyperledger/fabric-protos-go/peer" 20 "github.com/hyperledger/fabric/bccsp" 21 "github.com/hyperledger/fabric/protoutil" 22 "github.com/pkg/errors" 23 "github.com/spf13/cobra" 24 ) 25 26 var ( 27 chaincodeListCmd *cobra.Command 28 getInstalledChaincodes bool 29 getInstantiatedChaincodes bool 30 ) 31 32 // listCmd returns the cobra command for listing 33 // the installed or instantiated chaincodes 34 func listCmd(cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) *cobra.Command { 35 chaincodeListCmd = &cobra.Command{ 36 Use: "list", 37 Short: "Get the instantiated chaincodes on a channel or installed chaincodes on a peer.", 38 Long: "Get the instantiated chaincodes in the channel if specify channel, or get installed chaincodes on the peer", 39 RunE: func(cmd *cobra.Command, args []string) error { 40 return getChaincodes(cmd, cf, cryptoProvider) 41 }, 42 } 43 44 flagList := []string{ 45 "channelID", 46 "installed", 47 "instantiated", 48 "peerAddresses", 49 "tlsRootCertFiles", 50 "connectionProfile", 51 } 52 attachFlags(chaincodeListCmd, flagList) 53 54 return chaincodeListCmd 55 } 56 57 func getChaincodes(cmd *cobra.Command, cf *ChaincodeCmdFactory, cryptoProvider bccsp.BCCSP) error { 58 if getInstantiatedChaincodes && channelID == "" { 59 return errors.New("The required parameter 'channelID' is empty. Rerun the command with -C flag") 60 } 61 // Parsing of the command line is done so silence cmd usage 62 cmd.SilenceUsage = true 63 64 var err error 65 if cf == nil { 66 cf, err = InitCmdFactory(cmd.Name(), true, false, cryptoProvider) 67 if err != nil { 68 return err 69 } 70 } 71 72 creator, err := cf.Signer.Serialize() 73 if err != nil { 74 return fmt.Errorf("error serializing identity: %s", err) 75 } 76 77 var proposal *pb.Proposal 78 79 if getInstalledChaincodes == getInstantiatedChaincodes { 80 return errors.New("must explicitly specify \"--installed\" or \"--instantiated\"") 81 } 82 83 if getInstalledChaincodes { 84 proposal, _, err = protoutil.CreateGetInstalledChaincodesProposal(creator) 85 } 86 87 if getInstantiatedChaincodes { 88 proposal, _, err = protoutil.CreateGetChaincodesProposal(channelID, creator) 89 } 90 91 if err != nil { 92 return errors.WithMessage(err, "error creating proposal") 93 } 94 95 var signedProposal *pb.SignedProposal 96 signedProposal, err = protoutil.GetSignedProposal(proposal, cf.Signer) 97 if err != nil { 98 return errors.WithMessage(err, "error creating signed proposal") 99 } 100 101 // list is currently only supported for one peer 102 proposalResponse, err := cf.EndorserClients[0].ProcessProposal(context.Background(), signedProposal) 103 if err != nil { 104 return errors.WithMessage(err, "error endorsing proposal") 105 } 106 107 if proposalResponse.Response == nil { 108 return errors.Errorf("proposal response had nil response") 109 } 110 111 if proposalResponse.Response.Status != int32(cb.Status_SUCCESS) { 112 return errors.Errorf("bad response: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message) 113 } 114 115 return printResponse(getInstalledChaincodes, getInstantiatedChaincodes, proposalResponse) 116 } 117 118 // printResponse prints the information included in the response 119 // from the server. If getInstalledChaincodes is set to false, the 120 // proposal response will be interpreted as containing instantiated 121 // chaincode information. 122 func printResponse(getInstalledChaincodes, getInstantiatedChaincodes bool, proposalResponse *pb.ProposalResponse) error { 123 cqr := &pb.ChaincodeQueryResponse{} 124 err := proto.Unmarshal(proposalResponse.Response.Payload, cqr) 125 if err != nil { 126 return err 127 } 128 129 if getInstalledChaincodes { 130 fmt.Println("Get installed chaincodes on peer:") 131 } else { 132 fmt.Printf("Get instantiated chaincodes on channel %s:\n", channelID) 133 } 134 135 for _, chaincode := range cqr.Chaincodes { 136 fmt.Printf("%v\n", ccInfo{chaincode}.String()) 137 } 138 139 return nil 140 } 141 142 type ccInfo struct { 143 *pb.ChaincodeInfo 144 } 145 146 func (cci ccInfo) String() string { 147 b := bytes.Buffer{} 148 md := reflect.ValueOf(*cci.ChaincodeInfo) 149 md2 := reflect.Indirect(reflect.ValueOf(*cci.ChaincodeInfo)).Type() 150 for i := 0; i < md.NumField(); i++ { 151 f := md.Field(i) 152 val := f.String() 153 if isBytes(f) { 154 val = hex.EncodeToString(f.Bytes()) 155 } 156 if len(val) == 0 { 157 continue 158 } 159 // Skip the proto-internal generated fields 160 if strings.HasPrefix(md2.Field(i).Name, "XXX") { 161 continue 162 } 163 b.WriteString(fmt.Sprintf("%s: %s, ", md2.Field(i).Name, val)) 164 } 165 return b.String()[:len(b.String())-2] 166 167 } 168 169 func isBytes(v reflect.Value) bool { 170 return v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 171 }