public async Task <SDChaindcode> DiscoverEndorserEndpointAsync(TransactionContext tContext, string name, CancellationToken token = default(CancellationToken)) { Dictionary <string, SDChaindcode> lchaindcodeMap = chaindcodeMap; // check if we have it already. SDChaindcode sd = lchaindcodeMap?.GetOrNull(name); if (sd != null) { return(sd); } ServiceDiscoveryChaincodeCalls serviceDiscoveryChaincodeCalls = new ServiceDiscoveryChaincodeCalls(name); List <ServiceDiscoveryChaincodeCalls> cc = new List <ServiceDiscoveryChaincodeCalls>(); cc.Add(serviceDiscoveryChaincodeCalls); List <List <ServiceDiscoveryChaincodeCalls> > ccl = new List <List <ServiceDiscoveryChaincodeCalls> >(); ccl.Add(cc); Dictionary <string, SDChaindcode> dchaindcodeMap = await DiscoverEndorserEndpointsAsync(tContext, ccl, token).ConfigureAwait(false); SDChaindcode sdChaindcode = dchaindcodeMap.GetOrNull(name); if (null == sdChaindcode) { throw new ServiceDiscoveryException($"Failed to find and endorsers for chaincode {name}. See logs for details"); } return(sdChaindcode); }
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); }