github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/peer/lifecycle/chaincode/client_connections.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  	"crypto/tls"
    11  
    12  	"github.com/hechain20/hechain/bccsp"
    13  	"github.com/hechain20/hechain/internal/peer/common"
    14  	"github.com/hechain20/hechain/internal/pkg/identity"
    15  	pb "github.com/hyperledger/fabric-protos-go/peer"
    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  	TargetPeer            string
    43  	TLSEnabled            bool
    44  }
    45  
    46  // NewClientConnections creates a new set of client connections based on the
    47  // input parameters.
    48  func NewClientConnections(input *ClientConnectionsInput, cryptoProvider bccsp.BCCSP) (*ClientConnections, error) {
    49  	signer, err := common.GetDefaultSigner()
    50  	if err != nil {
    51  		return nil, errors.WithMessage(err, "failed to retrieve default signer")
    52  	}
    53  
    54  	c := &ClientConnections{
    55  		Signer:         signer,
    56  		CryptoProvider: cryptoProvider,
    57  	}
    58  
    59  	if input.EndorserRequired {
    60  		err := c.setPeerClients(input)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  	}
    65  
    66  	if input.OrdererRequired {
    67  		err := c.setOrdererClient()
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  	}
    72  
    73  	return c, nil
    74  }
    75  
    76  func (c *ClientConnections) setPeerClients(input *ClientConnectionsInput) error {
    77  	var endorserClients []pb.EndorserClient
    78  	var deliverClients []pb.DeliverClient
    79  
    80  	if err := c.validatePeerConnectionParameters(input); err != nil {
    81  		return errors.WithMessage(err, "failed to validate peer connection parameters")
    82  	}
    83  
    84  	for i, address := range input.PeerAddresses {
    85  		var tlsRootCertFile string
    86  		if input.TLSRootCertFiles != nil {
    87  			tlsRootCertFile = input.TLSRootCertFiles[i]
    88  		}
    89  		endorserClient, err := common.GetEndorserClient(address, tlsRootCertFile)
    90  		if err != nil {
    91  			return errors.WithMessagef(err, "failed to retrieve endorser client for %s", input.CommandName)
    92  		}
    93  		endorserClients = append(endorserClients, endorserClient)
    94  		deliverClient, err := common.GetPeerDeliverClient(address, tlsRootCertFile)
    95  		if err != nil {
    96  			return errors.WithMessagef(err, "failed to retrieve deliver client for %s", input.CommandName)
    97  		}
    98  		deliverClients = append(deliverClients, deliverClient)
    99  	}
   100  	if len(endorserClients) == 0 {
   101  		// this should only be empty due to a programming bug
   102  		return errors.New("no endorser clients retrieved")
   103  	}
   104  
   105  	err := c.setCertificate()
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	c.EndorserClients = endorserClients
   111  	c.DeliverClients = deliverClients
   112  
   113  	return nil
   114  }
   115  
   116  func (c *ClientConnections) validatePeerConnectionParameters(input *ClientConnectionsInput) error {
   117  	if input.ConnectionProfilePath != "" {
   118  		err := input.parseConnectionProfile()
   119  		if err != nil {
   120  			return err
   121  		}
   122  	}
   123  
   124  	// currently only support multiple peer addresses for _lifecycle
   125  	// for approveformyorg and commit
   126  	multiplePeersAllowed := map[string]bool{
   127  		"approveformyorg": true,
   128  		"commit":          true,
   129  	}
   130  	if !multiplePeersAllowed[input.CommandName] && len(input.PeerAddresses) > 1 {
   131  		return errors.Errorf("'%s' command supports one peer. %d peers provided", input.CommandName, len(input.PeerAddresses))
   132  	}
   133  
   134  	if !input.TLSEnabled {
   135  		input.TLSRootCertFiles = nil
   136  		return nil
   137  	}
   138  	if len(input.TLSRootCertFiles) != len(input.PeerAddresses) {
   139  		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))
   140  	}
   141  
   142  	return nil
   143  }
   144  
   145  func (c *ClientConnectionsInput) parseConnectionProfile() error {
   146  	networkConfig, err := common.GetConfig(c.ConnectionProfilePath)
   147  	if err != nil {
   148  		return err
   149  	}
   150  
   151  	c.PeerAddresses = []string{}
   152  	c.TLSRootCertFiles = []string{}
   153  
   154  	if c.ChannelID == "" {
   155  		if c.TargetPeer == "" {
   156  			return errors.New("--targetPeer must be specified for channel-less operation using connection profile")
   157  		}
   158  		return c.appendPeerConfig(networkConfig, c.TargetPeer)
   159  	}
   160  
   161  	if len(networkConfig.Channels[c.ChannelID].Peers) == 0 {
   162  		return nil
   163  	}
   164  
   165  	for peer, peerChannelConfig := range networkConfig.Channels[c.ChannelID].Peers {
   166  		if peerChannelConfig.EndorsingPeer {
   167  			err := c.appendPeerConfig(networkConfig, peer)
   168  			if err != nil {
   169  				return err
   170  			}
   171  		}
   172  	}
   173  
   174  	return nil
   175  }
   176  
   177  func (c *ClientConnectionsInput) appendPeerConfig(n *common.NetworkConfig, peer string) error {
   178  	peerConfig, ok := n.Peers[peer]
   179  	if !ok {
   180  		return errors.Errorf("peer '%s' doesn't have associated peer config", peer)
   181  	}
   182  	c.PeerAddresses = append(c.PeerAddresses, peerConfig.URL)
   183  	c.TLSRootCertFiles = append(c.TLSRootCertFiles, peerConfig.TLSCACerts.Path)
   184  
   185  	return nil
   186  }
   187  
   188  func (c *ClientConnections) setCertificate() error {
   189  	certificate, err := common.GetClientCertificate()
   190  	if err != nil {
   191  		return errors.WithMessage(err, "failed to retrieve client cerificate")
   192  	}
   193  
   194  	c.Certificate = certificate
   195  
   196  	return nil
   197  }
   198  
   199  func (c *ClientConnections) setOrdererClient() error {
   200  	oe := viper.GetString("orderer.address")
   201  	if oe == "" {
   202  		// if we're here we didn't get an orderer endpoint from the command line
   203  		// so we'll attempt to get one from cscc - bless it
   204  		if c.Signer == nil {
   205  			return errors.New("cannot obtain orderer endpoint, no signer was configured")
   206  		}
   207  
   208  		if len(c.EndorserClients) == 0 {
   209  			return errors.New("cannot obtain orderer endpoint, empty endorser list")
   210  		}
   211  
   212  		orderingEndpoints, err := common.GetOrdererEndpointOfChainFnc(channelID, c.Signer, c.EndorserClients[0], c.CryptoProvider)
   213  		if err != nil {
   214  			return errors.WithMessagef(err, "error getting channel (%s) orderer endpoint", channelID)
   215  		}
   216  		if len(orderingEndpoints) == 0 {
   217  			return errors.Errorf("no orderer endpoints retrieved for channel %s, pass orderer endpoint with -o flag instead", channelID)
   218  		}
   219  
   220  		logger.Infof("Retrieved channel (%s) orderer endpoint: %s", channelID, orderingEndpoints[0])
   221  		// override viper env
   222  		viper.Set("orderer.address", orderingEndpoints[0])
   223  	}
   224  
   225  	broadcastClient, err := common.GetBroadcastClient()
   226  	if err != nil {
   227  		return errors.WithMessage(err, "failed to retrieve broadcast client")
   228  	}
   229  
   230  	c.BroadcastClient = broadcastClient
   231  
   232  	return nil
   233  }