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 }