/// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private async Task <FullNetworkBlockHeightMessage> FullNetworkBlockHeight()
        {
            var list = new List <NodeBlockCountProto>();

            try
            {
                var responses = await httpService.Dial(DialType.Get, "height");

                foreach (var response in responses)
                {
                    if (response.IsSuccessStatusCode)
                    {
                        var fullNodeIdentity = httpService.GetFullNodeIdentity(response);

                        var jToken = Util.ReadJToken(response, "height");
                        list.Add(new NodeBlockCountProto {
                            Address = fullNodeIdentity.Value, BlockCount = jToken.Value <ulong>(), Node = fullNodeIdentity.Key
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error($"<<< NetworkProvider.FullNetworkBlockHeight >>>: {ex.ToString()}");
            }

            return(new FullNetworkBlockHeightMessage {
                NodeBlockCounts = list
            });
        }
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private async Task <ConcurrentDictionary <ulong, BlockGraphProto> > PullRemote()
        {
            var allTasks = new List <Task <HttpResponseMessage> >();
            var blocks   = new ConcurrentDictionary <ulong, BlockGraphProto>();

            var jobs = await unitOfWork.Job.GetWhere(x => x.Status == JobState.Queued);

            foreach (var job in jobs)
            {
                await MarkAs(job, JobState.Dialling);

                foreach (var member in httpService.Members)
                {
                    allTasks.Add(Task.Run(async() =>
                    {
                        HttpResponseMessage response = null;

                        response = await httpService.Dial(DialType.Get, member.Value, $"mempool/{job.BlockGraph.Block.Hash}/{job.BlockGraph.Block.Round}");
                        response.EnsureSuccessStatusCode();

                        var jToken    = Util.ReadJToken(response, "protobuf");
                        var byteArray = Convert.FromBase64String(jToken.Value <string>());

                        if (byteArray.Length > 0)
                        {
                            var scheme    = response.RequestMessage.RequestUri.Scheme;
                            var authority = response.RequestMessage.RequestUri.Authority;
                            var identity  = httpService.Members.FirstOrDefault(k => k.Value.Equals($"{scheme}://{authority}"));

                            blocks.TryAdd(identity.Key, Util.DeserializeProto <BlockGraphProto>(byteArray));
                        }

                        return(response);
                    }));
                }
            }

            try
            {
                await Task.WhenAll(allTasks.ToArray());
            }
            catch { }


            return(blocks);
        }
Esempio n. 3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="throttler"></param>
        /// <param name="member"></param>
        /// <param name="batch"></param>
        /// <returns></returns>
        private Task <HttpResponseMessage> Replies(SemaphoreSlim throttler, string member, IEnumerable <BlockGraphProto> batch)
        {
            return(Task.Run(async() =>
            {
                HttpResponseMessage response = null;

                try
                {
                    var sending = batch.Select(i => i);
                    var currentBlockGraphs = Util.SerializeProto(sending);
                    var uri = new Uri(new Uri(member), "blockgraphs");

                    response = await httpService.Dial(uri.AbsoluteUri, currentBlockGraphs);
                    response.EnsureSuccessStatusCode();

                    var jToken = Util.ReadJToken(response, "protobufs");
                    var byteArray = Convert.FromBase64String(jToken.Value <string>());

                    if (byteArray.Length > 0)
                    {
                        var blockInfos = Util.DeserializeListProto <BlockInfoProto>(byteArray);
                        if (blockInfos.Any())
                        {
                            await MarkMultipleStatesAs(blockInfos, JobState.Queued);
                            await MarkMultipleRepliesAs(blockInfos, true);
                        }
                    }
                }
                catch
                {
                    var blockLookup = batch.ToLookup(i => i.Block.Hash);
                    var blockInfos = blockLookup.Select(h => new BlockInfoProto {
                        Hash = h.Key
                    });
                    if (blockInfos.Any())
                    {
                        await MarkMultipleStatesAs(blockInfos, JobState.Dead);
                        await MarkMultipleRepliesAs(blockInfos, false);
                    }
                }
                finally
                {
                    throttler.Release();
                }

                return response;
            }));
        }
Esempio n. 4
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public async Task <IEnumerable <KeyValuePair <ulong, int> > > Synchronize(IEnumerable <NodeBlockCountProto> pool, ulong numberOfBlocks)
        {
            if (pool.Any() != true)
            {
                throw new InvalidOperationException("Sequence contains no elements");
            }

            var throttler = new SemaphoreSlim(int.MaxValue);
            var downloads = new ConcurrentDictionary <ulong, int>();

            try
            {
                var allTasks        = new List <Task>();
                var numberOfBatches = (int)Math.Ceiling((double)numberOfBlocks / numberOfBlocks);

                var series = new long[numberOfBatches];
                foreach (var n in series)
                {
                    await throttler.WaitAsync();

                    allTasks.Add(Task.Run(async() =>
                    {
                        try
                        {
                            Util.Shuffle(pool.ToArray());

                            var response = await httpService.Dial(DialType.Get, pool.First().Address, $"coins/{n * (long)numberOfBlocks}/{numberOfBlocks}");

                            var read          = Util.ReadJToken(response, "protobufs");
                            var byteArray     = Convert.FromBase64String(read.Value <string>());
                            var blockIdProtos = Util.DeserializeListProto <BlockIDProto>(byteArray);

                            logger.LogInformation($"<<< Synchronize >>>: Retrieved {byteArray.Length} bytes from {response.RequestMessage.RequestUri.Authority}");

                            var fullIdentity = httpService.GetFullNodeIdentity(response);

                            if (byteArray.Length > 0)
                            {
                                var blockIDs = blockIdProtos.Select(x => new Core.API.Consensus.BlockID(x.Hash, x.Node, x.Round, x.SignedBlock)).AsEnumerable();
                                var success  = await interpretActorProvider.Interpret(new Core.API.Messages.InterpretBlocksMessage(httpService.NodeIdentity, blockIDs));

                                downloads.TryAdd(fullIdentity.Key, blockIDs.Count());
                                return;
                            }

                            downloads.TryAdd(fullIdentity.Key, 0);
                        }
                        finally
                        {
                            throttler.Release();
                        }
                    }));
                }

                try
                {
                    await Task.WhenAll(allTasks);
                }
                catch { }
            }
            catch (Exception ex)
            {
                logger.LogError($"<<< SyncProvider.Synchronize >>>: Failed to synchronize node: {ex.ToString()}");
            }
            finally
            {
                throttler.Dispose();
            }

            return(downloads);
        }