public async Task <Dictionary <string, SDChaindcode> > DiscoverEndorserEndpointsAsync(TransactionContext tContext, List <List <ServiceDiscoveryChaincodeCalls> > chaincodeNames, CancellationToken token = default(CancellationToken)) { if (null == chaincodeNames) { logger.Warn("Discover of chaincode names was null."); return(new Dictionary <string, SDChaindcode>()); } if (chaincodeNames.Count == 0) { logger.Warn("Discover of chaincode names was empty."); return(new Dictionary <string, SDChaindcode>()); } if (IS_DEBUG_LEVEL) { StringBuilder cns = new StringBuilder(1000); string sep = ""; cns.Append("["); foreach (List <ServiceDiscoveryChaincodeCalls> s in chaincodeNames) { ServiceDiscoveryChaincodeCalls n = s[0]; cns.Append(sep).Append(n.Write(s.GetRange(1, s.Count - 1))); sep = ", "; } cns.Append("]"); logger.Debug($"Channel {channelName} doing discovery for chaincodes: {cns}"); } List <Peer> speers = serviceDiscoveryPeers.Shuffle().ToList(); Dictionary <string, SDChaindcode> ret = new Dictionary <string, SDChaindcode>(); sdNetwork = await NetworkDiscoveryAsync(tContext, false, token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); ServiceDiscoveryException serviceDiscoveryException = null; foreach (Peer serviceDiscoveryPeer in speers) { serviceDiscoveryException = null; try { logger.Debug($"Channel {channelName} doing discovery for chaincodes on peer: {serviceDiscoveryPeer}"); TransactionContext ltransactionContext = tContext.RetryTransactionSameContext(); byte[] clientTLSCertificateDigest = serviceDiscoveryPeer.GetClientTLSCertificateDigest(); if (null == clientTLSCertificateDigest) { logger.Warn($"Channel {channelName} peer {serviceDiscoveryPeer} requires mutual tls for service discovery."); continue; } ByteString clientIdent = ltransactionContext.Identity.ToByteString(); ByteString tlshash = ByteString.CopyFrom(clientTLSCertificateDigest); AuthInfo authentication = new AuthInfo(); authentication.ClientIdentity = clientIdent; authentication.ClientTlsCertHash = tlshash; List <Query> fq = new List <Query>(chaincodeNames.Count); foreach (List <ServiceDiscoveryChaincodeCalls> chaincodeName in chaincodeNames) { if (ret.ContainsKey(chaincodeName[0].Name)) { continue; } List <ChaincodeCall> chaincodeCalls = new List <ChaincodeCall>(); chaincodeName.ForEach(serviceDiscoveryChaincodeCalls => chaincodeCalls.Add(serviceDiscoveryChaincodeCalls.Build())); List <ChaincodeInterest> cinn = new List <ChaincodeInterest>(1); //chaincodeName.ForEach(ServiceDiscoveryChaincodeCalls.Build); ChaincodeInterest cci = new ChaincodeInterest(); cci.Chaincodes.Add(chaincodeCalls); cinn.Add(cci); ChaincodeQuery chaincodeQuery = new ChaincodeQuery(); chaincodeQuery.Interests.AddRange(cinn); Query q = new Query(); q.Channel = channelName; q.CcQuery = chaincodeQuery; fq.Add(q); } if (fq.Count == 0) { //this would be odd but lets take care of it. break; } Request request = new Request(); request.Queries.AddRange(fq); request.Authentication = authentication; ByteString payloadBytes = request.ToByteString(); ByteString signatureBytes = ltransactionContext.SignByteStrings(payloadBytes); SignedRequest sr = new SignedRequest(); sr.Payload = payloadBytes; sr.Signature = signatureBytes; if (IS_TRACE_LEVEL && null != diagnosticFileDumper) // dump protobuf we sent { logger.Trace($"Service discovery channel {channelName} {serviceDiscoveryPeer} service chaincode query sent {diagnosticFileDumper.CreateDiagnosticProtobufFile(sr.ToByteArray())}"); } logger.Debug($"Channel {channelName} peer {serviceDiscoveryPeer} sending chaincode query request"); Response response = await serviceDiscoveryPeer.SendDiscoveryRequestAsync(sr, SERVICE_DISCOVERY_WAITTIME, token).ConfigureAwait(false); if (IS_TRACE_LEVEL && null != diagnosticFileDumper) // dump protobuf we get { logger.Trace($"Service discovery channel {channelName} {serviceDiscoveryPeer} query returned {diagnosticFileDumper.CreateDiagnosticProtobufFile(response.ToByteArray())}"); } logger.Debug($"Channel {channelName} peer {serviceDiscoveryPeer} completed chaincode query request"); //serviceDiscoveryPeer.HasConnected(); foreach (QueryResult queryResult in response.Results) { if (queryResult.ResultCase == QueryResult.ResultOneofCase.Error) { ServiceDiscoveryException discoveryException = new ServiceDiscoveryException($"Error {queryResult.Error.Content}"); logger.Error(discoveryException.Message); continue; } if (queryResult.ResultCase != QueryResult.ResultOneofCase.CcQueryRes) { ServiceDiscoveryException discoveryException = new ServiceDiscoveryException($"Error expected chaincode endorsement query but got {queryResult.ResultCase.ToString()}"); logger.Error(discoveryException.Message); continue; } ChaincodeQueryResult ccQueryRes = queryResult.CcQueryRes; if (ccQueryRes.Content.Count == 0) { throw new ServiceDiscoveryException($"Error {queryResult.Error.Content}"); } foreach (EndorsementDescriptor es in ccQueryRes.Content) { string chaincode = es.Chaincode; List <SDLayout> layouts = new List <SDLayout>(); foreach (Layout layout in es.Layouts) { SDLayout sdLayout = null; Dictionary <string, uint> quantitiesByGroupMap = layout.QuantitiesByGroup.ToDictionary(a => a.Key, a => a.Value); foreach (string key in quantitiesByGroupMap.Keys) { uint quantity = quantitiesByGroupMap[key]; if (quantity < 1) { continue; } Peers peers = es.EndorsersByGroups.GetOrNull(key); if (peers == null || peers.Peers_.Count == 0) { continue; } List <SDEndorser> sdEndorsers = new List <SDEndorser>(); foreach (Protos.Discovery.Peer pp in peers.Peers_) { SDEndorser ppp = new SDEndorser(channel, pp, null, null); string endPoint = ppp.Endpoint; SDEndorser nppp = sdNetwork.GetEndorserByEndpoint(endPoint); if (null == nppp) { sdNetwork = await NetworkDiscoveryAsync(tContext, true, token).ConfigureAwait(false); if (null == sdNetwork) { throw new ServiceDiscoveryException("Failed to discover network resources."); } nppp = sdNetwork.GetEndorserByEndpoint(ppp.Endpoint); if (null == nppp) { throw new ServiceDiscoveryException($"Failed to discover peer endpoint information {ppp.Endpoint} for chaincode {chaincode}"); } } sdEndorsers.Add(nppp); } if (sdLayout == null) { sdLayout = new SDLayout(); layouts.Add(sdLayout); } sdLayout.AddGroup(key, (int)quantity, sdEndorsers); } } if (layouts.Count == 0) { logger.Warn($"Channel {channelName} chaincode {chaincode} discovered no layouts!"); } else { if (IS_DEBUG_LEVEL) { StringBuilder sb = new StringBuilder(1000); sb.Append("Channel ").Append(channelName).Append(" found ").Append(layouts.Count).Append(" layouts for chaincode: ").Append(es.Chaincode); sb.Append(", layouts: ["); string sep = ""; foreach (SDLayout layout in layouts) { sb.Append(sep).Append(layout); sep = ", "; } sb.Append("]"); logger.Debug(sb.ToString()); } ret[chaincode] = new SDChaindcode(es.Chaincode, layouts); } } } if (ret.Count == chaincodeNames.Count) { break; // found them all. } } catch (ServiceDiscoveryException e) { logger.Warn($"Service discovery error on peer {serviceDiscoveryPeer}. Error: {e.Message}"); serviceDiscoveryException = e; } catch (Exception e) { logger.Warn($"Service discovery error on peer {serviceDiscoveryPeer}. Error: {e.Message}"); serviceDiscoveryException = new ServiceDiscoveryException(e.Message, e); } } if (null != serviceDiscoveryException) { throw serviceDiscoveryException; } if (ret.Count != chaincodeNames.Count()) { logger.Warn($"Channel {channelName} failed to find all layouts for chaincodes. Expected: {chaincodeNames.Count} and found: {ret.Count}"); } return(ret); }
public async Task <SDNetwork> NetworkDiscoveryAsync(TransactionContext ltransactionContext, bool force, CancellationToken token = default(CancellationToken)) { using (await discoverLock.LockAsync(token).ConfigureAwait(false)) { logger.Trace($"Network discovery force: {force}"); List <Peer> speers = serviceDiscoveryPeers.Shuffle().ToList(); SDNetwork ret = sdNetwork; if (!force && null != ret && !ret.TimeElapsed) { return(ret); } ret = null; foreach (Peer serviceDiscoveryPeer in speers) { try { SDNetwork lsdNetwork = new SDNetwork(SERVICE_DISCOVER_FREQ_SECONDS); byte[] clientTLSCertificateDigest = serviceDiscoveryPeer.GetClientTLSCertificateDigest(); logger.Info($"Channel {channelName} doing discovery with peer: {serviceDiscoveryPeer}"); if (null == clientTLSCertificateDigest) { throw new ArgumentException($"Channel {channelName}, peer {serviceDiscoveryPeer} requires mutual tls for service discovery."); } ByteString clientIdent = ltransactionContext.Identity.ToByteString(); ByteString tlshash = ByteString.CopyFrom(clientTLSCertificateDigest); AuthInfo authentication = new AuthInfo(); authentication.ClientIdentity = clientIdent; authentication.ClientTlsCertHash = tlshash; List <Query> fq = new List <Query>(2); Query cq = new Query(); Query pq = new Query(); cq.Channel = channelName; pq.Channel = channelName; cq.ConfigQuery = new ConfigQuery(); pq.PeerQuery = new PeerMembershipQuery(); fq.Add(cq); fq.Add(pq); Request request = new Request(); request.Queries.AddRange(fq); request.Authentication = authentication; ByteString payloadBytes = request.ToByteString(); ByteString signatureBytes = ltransactionContext.SignByteStrings(payloadBytes); SignedRequest sr = new SignedRequest(); sr.Payload = payloadBytes; sr.Signature = signatureBytes; if (IS_TRACE_LEVEL && null != diagnosticFileDumper) // dump protobuf we sent { logger.Trace($"Service discovery channel {channelName} {serviceDiscoveryPeer} service chaincode query sent {diagnosticFileDumper.CreateDiagnosticProtobufFile(sr.ToByteArray())}"); } Response response = await serviceDiscoveryPeer.SendDiscoveryRequestAsync(sr, SERVICE_DISCOVERY_WAITTIME, token).ConfigureAwait(false); if (IS_TRACE_LEVEL && null != diagnosticFileDumper) // dump protobuf we get { logger.Trace($"Service discovery channel {channelName} {serviceDiscoveryPeer} service discovery returned {diagnosticFileDumper.CreateDiagnosticProtobufFile(response.ToByteArray())}"); } //serviceDiscoveryPeer.HasConnected; ??? List <QueryResult> resultsList = response.Results.ToList(); QueryResult queryResult = resultsList[0]; //configquery if (queryResult.ResultCase == QueryResult.ResultOneofCase.Error) { logger.Warn($"Channel {channelName} peer: {serviceDiscoveryPeer} error during service discovery {queryResult.Error.Content}"); continue; } QueryResult queryResult2 = resultsList[1]; if (queryResult2.ResultCase == QueryResult.ResultOneofCase.Error) { logger.Warn($"Channel {channelName} peer: {serviceDiscoveryPeer} error during service discovery {queryResult2.Error.Content}"); continue; } ConfigResult configResult = queryResult.ConfigResult; Dictionary <string, FabricMSPConfig> msps = configResult.Msps.ToDictionary(a => a.Key, a => a.Value); HashSet <ByteString> cbbs = new HashSet <ByteString>(); foreach (string i in msps.Keys) { FabricMSPConfig value = msps[i]; string mspid = value.Name; cbbs.AddRange(value.RootCerts); cbbs.AddRange(value.IntermediateCerts); value.RootCerts.ToList().ForEach(a => lsdNetwork.AddTlsCert(mspid, a.ToByteArray())); value.TlsIntermediateCerts.ToList().ForEach(a => lsdNetwork.AddTlsIntermCert(mspid, a.ToByteArray())); } List <byte[]> toaddCerts = new List <byte[]>(); AddCerts(cbbs, toaddCerts); if (toaddCerts.Count > 0) // add them to crypto store. { toaddCerts.ForEach(a => channel.Client.CryptoSuite.Store.AddCertificate(a.ToUTF8String())); } Dictionary <string, SDOrderer> ordererEndpoints = new Dictionary <string, SDOrderer>(); Dictionary <string, Endpoints> orderersMap = configResult.Orderers.ToDictionary(a => a.Key, a => a.Value); foreach (string mspid in orderersMap.Keys) { Endpoints value = orderersMap[mspid]; foreach (Protos.Discovery.Endpoint l in value.Endpoint) { string endpoint = l.Host + ":" + l.Port.ToString().ToLowerInvariant().Trim(); logger.Trace($"Channel {channelName} discovered orderer MSPID: {mspid}, endpoint: {endpoint}"); SDOrderer sdOrderer = new SDOrderer(channel, mspid, endpoint, lsdNetwork.GetTlsCerts(mspid), lsdNetwork.GetTlsIntermediateCerts(mspid)); ordererEndpoints[sdOrderer.Endpoint] = sdOrderer; } } lsdNetwork.SetOrdererEndpoints(ordererEndpoints); PeerMembershipResult membership = queryResult2.Members; Dictionary <string, SDEndorser> endorsers = new Dictionary <string, SDEndorser>(); foreach (string mspId in membership.PeersByOrg.Keys) { Peers peer = membership.PeersByOrg[mspId]; foreach (Protos.Discovery.Peer pp in peer.Peers_) { SDEndorser ppp = new SDEndorser(channel, pp, lsdNetwork.GetTlsCerts(mspId), lsdNetwork.GetTlsIntermediateCerts(mspId)); logger.Trace($"Channel {channelName} discovered peer MSPID: {mspId}, endpoint: {ppp.Endpoint}"); endorsers[ppp.Endpoint] = ppp; } } lsdNetwork.SetEndorsers(endorsers); lsdNetwork.End(); sdNetwork = lsdNetwork; ret = lsdNetwork; break; } catch (Exception e) { logger.Warn($"Channel {channelName} peer {serviceDiscoveryPeer} service discovery error {e.Message}"); } } logger.Debug($"Channel {channelName} service discovery completed: {ret != null}"); return(ret); } }