public async Task <int> CountBlocksAsync() { using (await BlockFolderLock.LockAsync()) { return(Directory.EnumerateFiles(BlocksFolderPath).Count()); } }
/// <remarks> /// Use it at reorgs. /// </remarks> public async Task DeleteBlockAsync(uint256 hash) { using (await BlockFolderLock.LockAsync()) { 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())); } } }
/// <exception cref="OperationCanceledException"></exception> public async Task <Block> GetOrDownloadBlockAsync(uint256 hash, CancellationToken cancel) { // Try get the block using (await BlockFolderLock.LockAsync()) { foreach (var filePath in Directory.EnumerateFiles(BlocksFolderPath)) { var fileName = Path.GetFileName(filePath); if (hash == new uint256(fileName)) { var blockBytes = await File.ReadAllBytesAsync(filePath); return(Block.Load(blockBytes, IndexDownloader.Network)); } } } cancel.ThrowIfCancellationRequested(); // Download the block Block block = null; using (await BlockDownloadLock.LockAsync()) { while (true) { cancel.ThrowIfCancellationRequested(); try { // If no connection, wait then continue. while (Nodes.ConnectedNodes.Count == 0) { await Task.Delay(100); } Node node = Nodes.ConnectedNodes.RandomElement(); if (node == default(Node)) { await Task.Delay(100); continue; } if (!node.IsConnected && !(IndexDownloader.Network != Network.RegTest)) { await Task.Delay(100); continue; } 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 <WalletService>($"Disconnected node, because couldn't parse received block."); node.DisconnectAsync("Couldn't parse block."); continue; } if (!block.Check()) { Logger.LogInfo <WalletService>($"Disconnected node, because block invalid block received."); node.DisconnectAsync("Invalid block received."); continue; } } catch (TimeoutException) { Logger.LogInfo <WalletService>($"Disconnected node, because block download took too long."); node.DisconnectAsync("Block download took too long."); continue; } catch (OperationCanceledException) { Logger.LogInfo <WalletService>($"Disconnected node, because block download took too long."); node.DisconnectAsync("Block download took too long."); continue; } catch (Exception ex) { Logger.LogDebug <WalletService>(ex); Logger.LogInfo <WalletService>($"Disconnected node, because block download failed: {ex.Message}"); node.DisconnectAsync("Block download failed."); continue; } break; // If got this far break, then we have the block, it's valid. Break. } catch (Exception ex) { Logger.LogDebug <WalletService>(ex); } } } // Save the block using (await BlockFolderLock.LockAsync()) { var path = Path.Combine(BlocksFolderPath, hash.ToString()); await File.WriteAllBytesAsync(path, block.ToBytes()); } return(block); }