github.com/true-sqn/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  }