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