/// <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); }
/// <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; })); }
/// <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); }