/// <returns>null if don't have, ques it if not qued</returns> public Block GetBlock(uint256 hash) { using (BlocksFolderLock.Lock()) { foreach (var filePath in Directory.EnumerateFiles(BlocksFolderPath)) { var fileName = Path.GetFileName(filePath); if (hash == new uint256(fileName)) { var blockBytes = File.ReadAllBytes(filePath); var block = new Block(blockBytes); return(block); } } } QueToDownload(hash); return(default);
public void QueToDownload(uint256 hash) { using (BlocksFolderLock.Lock()) using (BlocksToDownloadLock.Lock()) { var filePaths = Directory.EnumerateFiles(BlocksFolderPath); var fileNames = filePaths.Select(x => Path.GetFileName(x)); var hashes = fileNames.Select(x => new uint256(x)); if (!hashes.Contains(hash)) { if (!BlocksToDownload.Contains(hash)) { BlocksToDownload.Add(hash); } } } }
/// <remarks> /// Use it at reorgs. /// </remarks> public void TryRemove(uint256 hash) { using (BlocksFolderLock.Lock()) using (BlocksToDownloadLock.Lock()) { if (BlocksToDownload.Contains(hash)) { BlocksToDownload.Remove(hash); } var filePaths = Directory.EnumerateFiles(BlocksFolderPath); var fileNames = filePaths.Select(x => Path.GetFileName(x)); var hashes = fileNames.Select(x => new uint256(x)); if (hashes.Contains(hash)) { File.Delete(Path.Combine(BlocksFolderPath, hash.ToString())); } } }
public void Start() { Interlocked.Exchange(ref _running, 1); Task.Run(async() => { while (IsRunning) { try { // If stop was requested return. if (IsRunning == false) { return; } // If no connection, wait then continue. if (Nodes.ConnectedNodes.Count == 0) { await Task.Delay(10); continue; } if (IsRunning == false) { return; } uint256 hash = null; // If nothing to download, wait then continue. using (BlocksToDownloadLock.Lock()) { if (BlocksToDownload.Count == 0) { await Task.Delay(100); continue; } else { hash = BlocksToDownload.First(); } } if (IsRunning == false) { return; } Node node = Nodes.ConnectedNodes.RandomElement(); if (node == default(Node)) { await Task.Delay(10); continue; } if (!node.IsConnected) { await Task.Delay(10); continue; } Block block = null; try { using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(32))) // ADSL 512 kbit/s 00:00:32 { block = node.GetBlocks(new uint256[] { hash }, cts.Token)?.Single(); } if (block == null) { Logger.LogInfo <BlockDownloader>($"Disconnected node, because couldn't parse received block."); node.DisconnectAsync("Couldn't parse block."); continue; } if (!block.Check()) { Logger.LogInfo <BlockDownloader>($"Disconnected node, because block invalid block received."); node.DisconnectAsync("Invalid block received."); continue; } } catch (TimeoutException) { Logger.LogInfo <BlockDownloader>($"Disconnected node, because block download took too long."); node.DisconnectAsync("Block download took too long."); continue; } catch (OperationCanceledException) { Logger.LogInfo <BlockDownloader>($"Disconnected node, because block download took too long."); node.DisconnectAsync("Block download took too long."); continue; } catch (Exception ex) { Logger.LogDebug <BlockDownloader>(ex); Logger.LogInfo <BlockDownloader>($"Disconnected node, because block download failed: {ex.Message}"); node.DisconnectAsync("Block download failed."); continue; } using (BlocksFolderLock.Lock()) using (BlocksToDownloadLock.Lock()) { BlocksToDownload.Remove(hash); var path = Path.Combine(BlocksFolderPath, hash.ToString()); await File.WriteAllBytesAsync(path, block.ToBytes()); } } catch (Exception ex) { Logger.LogDebug <BlockDownloader>(ex); } } } ); }