Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
            }
        }