Exemplo n.º 1
0
        private async Task RunRefreshPeerLoop()
        {
            foreach (RefreshTotalDiffTask refreshTask in _peerRefreshQueue.GetConsumingEnumerable(_refreshLoopCancellation.Token))
            {
                ISyncPeer syncPeer = refreshTask.SyncPeer;
                if (_logger.IsDebug)
                {
                    _logger.Debug($"Refreshing info for {syncPeer}.");
                }
                CancellationTokenSource initCancelSource = _refreshCancelTokens[syncPeer.Node.Id] = new CancellationTokenSource();
                CancellationTokenSource linkedSource     = CancellationTokenSource.CreateLinkedTokenSource(initCancelSource.Token, _refreshLoopCancellation.Token);

#pragma warning disable 4014
                ExecuteRefreshTask(refreshTask, linkedSource.Token).ContinueWith(t =>
#pragma warning restore 4014
                {
                    _refreshCancelTokens.TryRemove(syncPeer.Node.Id, out _);
                    if (t.IsFaulted)
                    {
                        if (t.Exception != null && t.Exception.InnerExceptions.Any(x => x.InnerException is TimeoutException))
                        {
                            if (_logger.IsTrace)
                            {
                                _logger.Trace($"Refreshing info for {syncPeer} failed due to timeout: {t.Exception.Message}");
                            }
                        }
                        else if (_logger.IsDebug)
                        {
                            _logger.Debug($"Refreshing info for {syncPeer} failed {t.Exception}");
                        }
                    }
                    else if (t.IsCanceled)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"Refresh peer info canceled: {syncPeer.Node:s}");
                        }
                    }
                    else
                    {
                        UpgradeAllocations("REFRESH");
                        // cases when we want other nodes to resolve the impasse (check Goerli discussion on 5 out of 9 validators)
                        if (syncPeer.TotalDifficulty == _blockTree.BestSuggestedHeader?.TotalDifficulty && syncPeer.HeadHash != _blockTree.BestSuggestedHeader?.Hash)
                        {
                            Block block = _blockTree.FindBlock(_blockTree.BestSuggestedHeader.Hash, BlockTreeLookupOptions.None);
                            if (block != null) // can be null if fast syncing headers only
                            {
                                syncPeer.SendNewBlock(block);
                                if (_logger.IsDebug)
                                {
                                    _logger.Debug($"Sending my best block {block} to {syncPeer}");
                                }
                            }
                        }
                    }

                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Refreshed peer info for {syncPeer}.");
                    }

                    initCancelSource.Dispose();
                    linkedSource.Dispose();
                });
            }

            if (_logger.IsInfo)
            {
                _logger.Info("Exiting sync peer refresh loop");
            }
            await Task.CompletedTask;
        }