async Task OnBlockData(NodeBlockDataMessage message, NodeConnection connection) { var chainType = message.ChainType; var blockId = message.BlockId; var chainId = message.ChainId; var chainIndex = message.ChainIndex; var chain = _chainManager.GetChain(chainType, chainId, chainIndex); if (chain == null || blockId <= chain.BlockStorage.LastStoredBlockId) { return; } if (message.BlockData != null) { await _node.SyncManager.HandleBlockData(message.BlockData, new HashSet <NodeConnection> { connection }); } else { if (connection.NodeInfo.IsPublicEndPoint || connection.AutoConnect != null) { var client = new NodeClient(connection.NodeInfo.IsPublicEndPoint ? connection.NodeInfo.PublicEndPoint : connection.AutoConnect.EndPoint); var blockData = (await client.DownloadBlockData(chainType, chainId, chainIndex, blockId)).Data; if (blockData != null) { await _node.SyncManager.HandleBlockData(blockData, new HashSet <NodeConnection> { connection }); return; } } _ = connection.Send(new NodeBlockDataRequestMessage(chainType, blockId, chain.ChainId, chainIndex) { SignKey = _node.NodeConfiguration.LocaleNodePrivateKey }); } }
async Task DownloadBlock(long blockId, ChainSyncItem chainSyncItem, HashSet <NodeConnection> nodeConnections, int tries = 0) { var retry = false; var sync = chainSyncItem.Sync; try { await sync.DownloadLock.WaitAsync(); SyncDownload download; lock (sync.Lock) { sync.NewBlocks.TryGetValue(blockId, out download); if (download == null) { return; } if (!download.TimedOut && download.Downloading) { return; } download.Downloading = true; download.DownloadTime = DateTime.UtcNow; } nodeConnections = nodeConnections ?? new HashSet <NodeConnection>(); foreach (var connection in nodeConnections) { var nodeInfo = connection.NodeInfo; if (nodeInfo.IsPublicEndPoint && nodeInfo.NodeId != _configuration.LocaleNodeInfo.NodeId) { var client = new NodeClient(nodeInfo.PublicEndPoint); var blockData = (await client.DownloadBlockData(chainSyncItem.ChainType, chainSyncItem.ChainId, chainSyncItem.ChainIndex, blockId)).Data; if (blockData != null) { download.UpdateBlockData(blockData); await HandleBlockData(blockData, nodeConnections); goto end; } else { retry = true; } } } foreach (var endPoint in chainSyncItem.Chain.AvailableEndpoints) { var client = new NodeClient(endPoint.EndPoint); if (endPoint.NodeInfo == null) { endPoint.NodeInfo = (await client.DownloadNodeInfo(_configuration.NetworkPublicKey)).Data; } if (endPoint.NodeInfo != null && endPoint.NodeInfo.NodeId != _configuration.LocaleNodeInfo.NodeId) { var blockData = (await client.DownloadBlockData(chainSyncItem.ChainType, chainSyncItem.ChainId, chainSyncItem.ChainIndex, blockId)).Data; if (blockData != null) { download.UpdateBlockData(blockData); await HandleBlockData(blockData, nodeConnections); goto end; } else { retry = true; } } } foreach (var connection in nodeConnections) { await connection.Send(new NodeBlockDataRequestMessage(chainSyncItem.ChainType, blockId, chainSyncItem.ChainId, chainSyncItem.ChainIndex) { SignKey = _configuration.LocaleNodePrivateKey }); await Task.Delay(50); } end: lock (sync.Lock) { download.Downloading = false; } } catch (Exception ex) { Log.HandleException(ex); } finally { sync.DownloadLock.Release(); } if (retry && tries < 10) { await Task.Delay(50 *(tries + 1)); TaskRunner.Run(() => DownloadBlock(blockId, chainSyncItem, nodeConnections, tries + 1)); } }