github.com/anjalikarhana/fabric@v2.1.1+incompatible/internal/peer/lifecycle/chaincode/client_connections.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  	"crypto/tls"
    11  
    12  	pb "github.com/hyperledger/fabric-protos-go/peer"
    13  	"github.com/hyperledger/fabric/bccsp"
    14  	"github.com/hyperledger/fabric/internal/peer/common"
    15  	"github.com/hyperledger/fabric/internal/pkg/identity"
    16  	"github.com/pkg/errors"
    17  	"github.com/spf13/viper"
    18  )
    19  
    20  // ClientConnections holds the clients for connecting to the various
    21  // endpoints in a Fabric network.
    22  type ClientConnections struct {
    23  	BroadcastClient common.BroadcastClient
    24  	DeliverClients  []pb.DeliverClient
    25  	EndorserClients []pb.EndorserClient
    26  	Certificate     tls.Certificate
    27  	Signer          identity.SignerSerializer
    28  	CryptoProvider  bccsp.BCCSP
    29  }
    30  
    31  // ClientConnectionsInput holds the input parameters for creating
    32  // client connections.
    33  type ClientConnectionsInput struct {
    34  	CommandName           string
    35  	EndorserRequired      bool
    36  	OrdererRequired       bool
    37  	OrderingEndpoint      string
    38  	ChannelID             string
    39  	PeerAddresses         []string
    40  	TLSRootCertFiles      []string
    41  	ConnectionProfilePath string
    42  	TLSEnabled            bool
    43  }
    44  
    45  // NewClientConnections creates a new set of client connections based on the
    46  // input parameters.
    47  func NewClientConnections(input *ClientConnectionsInput, cryptoProvider bccsp.BCCSP) (*ClientConnections, error) {
    48  	signer, err := common.GetDefaultSigner()
    49  	if err != nil {
    50  		return nil, errors.WithMessage(err, "failed to retrieve default signer")
    51  	}
    52  
    53  	c := &ClientConnections{
    54  		Signer:         signer,
    55  		CryptoProvider: cryptoProvider,
    56  	}
    57  
    58  	if input.EndorserRequired {
    59  		err := c.setPeerClients(input)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  	}
    64  
    65  	if input.OrdererRequired {
    66  		err := c.setOrdererClient()
    67  		if err != nil {
    68  			return nil, err
    69  		}
    70  	}
    71  
    72  	return c, nil
    73  }
    74  
    75  func (c *ClientConnections) setPeerClients(input *ClientConnectionsInput) error {
    76  	var endorserClients []pb.EndorserClient
    77  	var deliverClients []pb.DeliverClient
    78  
    79  	if err := c.validatePeerConnectionParameters(input); err != nil {
    80  		return errors.WithMessage(err, "failed to validate peer connection parameters")
    81  	}
    82  
    83  	for i, address := range input.PeerAddresses {
    84  		var tlsRootCertFile string
    85  		if input.TLSRootCertFiles != nil {
    86  			tlsRootCertFile = input.TLSRootCertFiles[i]
    87  		}
    88  		endorserClient, err := common.GetEndorserClient(address, tlsRootCertFile)
    89  		if err != nil {
    90  			return errors.WithMessagef(err, "failed to retrieve endorser client for %s", input.CommandName)
    91  		}
    92  		endorserClients = append(endorserClients, endorserClient)
    93  		deliverClient, err := common.GetPeerDeliverClient(address, tlsRootCertFile)
    94  		if err != nil {
    95  			return errors.WithMessagef(err, "failed to retrieve deliver client for %s", input.CommandName)
    96  		}
    97  		deliverClients = append(deliverClients, deliverClient)
    98  	}
    99  	if len(endorserClients) == 0 {
   100  		// this should only be empty due to a programming bug
   101  		return errors.New("no endorser clients retrieved")
   102  	}
   103  
   104  	err := c.setCertificate()
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	c.EndorserClients = endorserClients
   110  	c.DeliverClients = deliverClients
   111  
   112  	return nil
   113  }
   114  
   115  func (c *ClientConnections) validatePeerConnectionParameters(input *ClientConnectionsInput) error {
   116  	if input.ConnectionProfilePath != "" {
   117  		networkConfig, err := common.GetConfig(input.ConnectionProfilePath)
   118  		if err != nil {
   119  			return err
   120  		}
   121  		if len(networkConfig.Channels[input.ChannelID].Peers) != 0 {
   122  			input.PeerAddresses = []string{}
   123  			input.TLSRootCertFiles = []string{}
   124  			for peer, peerChannelConfig := range networkConfig.Channels[input.ChannelID].Peers {
   125  				if peerChannelConfig.EndorsingPeer {
   126  					peerConfig, ok := networkConfig.Peers[peer]
   127  					if !ok {
   128  						return errors.Errorf("peer '%s' is defined in the channel config but doesn't have associated peer config", peer)
   129  					}
   130  					input.PeerAddresses = append(input.PeerAddresses, peerConfig.URL)
   131  					input.TLSRootCertFiles = append(input.TLSRootCertFiles, peerConfig.TLSCACerts.Path)
   132  				}
   133  			}
   134  		}
   135  	}
   136  
   137  	// currently only support multiple peer addresses for _lifecycle
   138  	// for approveformyorg and commit
   139  	multiplePeersAllowed := map[string]bool{
   140  		"approveformyorg": true,
   141  		"commit":          true,
   142  	}
   143  	if !multiplePeersAllowed[input.CommandName] && len(input.PeerAddresses) > 1 {
   144  		return errors.Errorf("'%s' command supports one peer. %d peers provided", input.CommandName, len(input.PeerAddresses))
   145  	}
   146  
   147  	if !input.TLSEnabled {
   148  		input.TLSRootCertFiles = nil
   149  		return nil
   150  	}
   151  	if len(input.TLSRootCertFiles) != len(input.PeerAddresses) {
   152  		return errors.Errorf("number of peer addresses (%d) does not match the number of TLS root cert files (%d)", len(input.PeerAddresses), len(input.TLSRootCertFiles))
   153  	}
   154  
   155  	return nil
   156  }
   157  
   158  func (c *ClientConnections) setCertificate() error {
   159  	certificate, err := common.GetCertificate()
   160  	if err != nil {
   161  		return errors.WithMessage(err, "failed to retrieve client cerificate")
   162  	}
   163  
   164  	c.Certificate = certificate
   165  
   166  	return nil
   167  }
   168  
   169  func (c *ClientConnections) setOrdererClient() error {
   170  	oe := viper.GetString("orderer.address")
   171  	if oe == "" {
   172  		// if we're here we didn't get an orderer endpoint from the command line
   173  		// so we'll attempt to get one from cscc - bless it
   174  		if c.Signer == nil {
   175  			return errors.New("cannot obtain orderer endpoint, no signer was configured")
   176  		}
   177  
   178  		if len(c.EndorserClients) == 0 {
   179  			return errors.New("cannot obtain orderer endpoint, empty endorser list")
   180  		}
   181  
   182  		orderingEndpoints, err := common.GetOrdererEndpointOfChainFnc(channelID, c.Signer, c.EndorserClients[0], c.CryptoProvider)
   183  		if err != nil {
   184  			return errors.WithMessagef(err, "error getting channel (%s) orderer endpoint", channelID)
   185  		}
   186  		if len(orderingEndpoints) == 0 {
   187  			return errors.Errorf("no orderer endpoints retrieved for channel %s", channelID)
   188  		}
   189  
   190  		logger.Infof("Retrieved channel (%s) orderer endpoint: %s", channelID, orderingEndpoints[0])
   191  		// override viper env
   192  		viper.Set("orderer.address", orderingEndpoints[0])
   193  	}
   194  
   195  	broadcastClient, err := common.GetBroadcastClient()
   196  	if err != nil {
   197  		return errors.WithMessage(err, "failed to retrieve broadcast client")
   198  	}
   199  
   200  	c.BroadcastClient = broadcastClient
   201  
   202  	return nil
   203  }