Пример #1
0
 public void RefreshTotalDifficulty(ISyncPeer syncPeer, Keccak blockHash)
 {
     _peerRefreshQueue.Add(new RefreshTotalDiffTask {
         SyncPeer = syncPeer, BlockHash = blockHash
     });
 }
Пример #2
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.NotifyOfNewBlock(block, SendBlockPriority.High);
                                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;
        }
Пример #3
0
 public SyncEventArgs(ISyncPeer peer, SyncEvent @event)
 {
     Peer      = peer;
     SyncEvent = @event;
 }
Пример #4
0
 public SyncingContext AfterPeerIsRemoved(ISyncPeer syncPeer)
 {
     _peers.Remove(syncPeer.ClientId);
     SyncPeerPool.RemovePeer(syncPeer, EthSyncPeerPool.PeerRemoveReason.SessionDisconnected);
     return(this);
 }
Пример #5
0
        private async Task ExecuteRequest(CancellationToken token, FastBlocksBatch batch)
        {
            SyncPeerAllocation nodeSyncAllocation = _syncPeerPool.Borrow(BorrowOptions.DoNotReplace | (batch.Prioritized ? BorrowOptions.None : BorrowOptions.LowPriority), "fast blocks", batch.MinNumber);

            foreach (PeerInfo peerInfo in _syncPeerPool.UsefulPeers)
            {
                if (peerInfo.HeadNumber < Math.Max(0, (batch.MinNumber ?? 0) - 1024))
                {
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Made {peerInfo} sleep for a while - no min number satisfied");
                    }
                    _syncPeerPool.ReportNoSyncProgress(peerInfo);
                }
            }

            try
            {
                ISyncPeer peer = nodeSyncAllocation?.Current?.SyncPeer;
                batch.Allocation = nodeSyncAllocation;
                if (peer != null)
                {
                    batch.MarkSent();
                    switch (batch.BatchType)
                    {
                    case FastBlocksBatchType.Headers:
                    {
                        Task <BlockHeader[]> getHeadersTask = peer.GetBlockHeaders(batch.Headers.StartNumber, batch.Headers.RequestSize, 0, token);
                        await getHeadersTask.ContinueWith(
                            t =>
                            {
                                if (t.IsCompletedSuccessfully)
                                {
                                    if (batch.RequestTime > 1000)
                                    {
                                        if (_logger.IsDebug)
                                        {
                                            _logger.Debug($"{batch} - peer is slow {batch.RequestTime:F2}");
                                        }
                                    }

                                    batch.Headers.Response = getHeadersTask.Result;
                                    ValidateHeaders(token, batch);
                                }
                                else
                                {
                                    _syncPeerPool.ReportInvalid(batch.Allocation);
                                }
                            }
                            );

                        break;
                    }

                    case FastBlocksBatchType.Bodies:
                    {
                        Task <BlockBody[]> getBodiesTask = peer.GetBlocks(batch.Bodies.Request, token);
                        await getBodiesTask.ContinueWith(
                            t =>
                            {
                                if (t.IsCompletedSuccessfully)
                                {
                                    if (batch.RequestTime > 1000)
                                    {
                                        if (_logger.IsDebug)
                                        {
                                            _logger.Debug($"{batch} - peer is slow {batch.RequestTime:F2}");
                                        }
                                    }

                                    batch.Bodies.Response = getBodiesTask.Result;
                                }
                                else
                                {
                                    _syncPeerPool.ReportInvalid(batch.Allocation);
                                }
                            }
                            );

                        break;
                    }

                    case FastBlocksBatchType.Receipts:
                    {
                        Task <TxReceipt[][]> getReceiptsTask = peer.GetReceipts(batch.Receipts.Request, token);
                        await getReceiptsTask.ContinueWith(
                            t =>
                            {
                                if (t.IsCompletedSuccessfully)
                                {
                                    if (batch.RequestTime > 1000)
                                    {
                                        if (_logger.IsDebug)
                                        {
                                            _logger.Debug($"{batch} - peer is slow {batch.RequestTime:F2}");
                                        }
                                    }

                                    batch.Receipts.Response = getReceiptsTask.Result;
                                }
                                else
                                {
                                    _syncPeerPool.ReportInvalid(batch.Allocation);
                                }
                            }
                            );

                        break;
                    }

                    default:
                    {
                        throw new InvalidOperationException($"{nameof(FastBlocksBatchType)} is {batch.BatchType}");
                    }
                    }
                }

                (BlocksDataHandlerResult Result, int ItemsSynced)result = (BlocksDataHandlerResult.InvalidFormat, 0);
                try
                {
                    if (batch.Bodies?.Response == null &&
                        batch.Headers?.Response == null &&
                        batch.Receipts?.Response == null)
                    {
                        // to avoid uncontrolled loop in case of a code error
                        await Task.Delay(10);
                    }

                    result = _fastBlocksFeed.HandleResponse(batch);
                }
                catch (Exception e)
                {
                    // possibly clear the response and handle empty response batch here (to avoid missing parts)
                    if (_logger.IsError)
                    {
                        _logger.Error($"Error when handling response", e);
                    }
                }

                Interlocked.Add(ref _downloadedHeaders, result.ItemsSynced);
                if (result.ItemsSynced == 0 && peer != null)
                {
                    _syncPeerPool.ReportNoSyncProgress(nodeSyncAllocation);
                }
            }
            finally
            {
                if (nodeSyncAllocation != null)
                {
                    _syncPeerPool.Free(nodeSyncAllocation);
                }
            }
        }
Пример #6
0
 public void RemovePeer(ISyncPeer syncPeer)
 {
 }
Пример #7
0
 public SyncingContext AfterPeerIsRemoved(ISyncPeer syncPeer)
 {
     _peers.Remove(syncPeer.ClientId);
     SyncPeerPool.RemovePeer(syncPeer);
     return(this);
 }
Пример #8
0
 public RefreshTotalDiffTask(ISyncPeer syncPeer)
 {
     SyncPeer = syncPeer;
 }
Пример #9
0
 public PeerHeadRefreshedEventArgs(ISyncPeer syncPeer, BlockHeader blockHeader)
 {
     SyncPeer = syncPeer;
     Header   = blockHeader;
 }
Пример #10
0
        protected override async Task Dispatch(PeerInfo peerInfo, SnapSyncBatch batch, CancellationToken cancellationToken)
        {
            ISyncPeer peer = peerInfo.SyncPeer;

            //TODO: replace with a constant "snap"
            if (peer.TryGetSatelliteProtocol <ISnapSyncPeer>("snap", out var handler))
            {
                if (batch.AccountRangeRequest is not null)
                {
                    Task <AccountsAndProofs> task = handler.GetAccountRange(batch.AccountRangeRequest, cancellationToken);

                    await task.ContinueWith(
                        (t, state) =>
                    {
                        if (t.IsFaulted)
                        {
                            if (Logger.IsTrace)
                            {
                                Logger.Error("DEBUG/ERROR Error after dispatching the snap sync request", t.Exception);
                            }
                        }

                        SnapSyncBatch batchLocal = (SnapSyncBatch)state !;
                        if (t.IsCompletedSuccessfully)
                        {
                            batchLocal.AccountRangeResponse = t.Result;
                        }
                    }, batch);
                }
                else if (batch.StorageRangeRequest is not null)
                {
                    Task <SlotsAndProofs> task = handler.GetStorageRange(batch.StorageRangeRequest, cancellationToken);

                    await task.ContinueWith(
                        (t, state) =>
                    {
                        if (t.IsFaulted)
                        {
                            if (Logger.IsTrace)
                            {
                                Logger.Error("DEBUG/ERROR Error after dispatching the snap sync request", t.Exception);
                            }
                        }

                        SnapSyncBatch batchLocal = (SnapSyncBatch)state !;
                        if (t.IsCompletedSuccessfully)
                        {
                            batchLocal.StorageRangeResponse = t.Result;
                        }
                    }, batch);
                }
                else if (batch.CodesRequest is not null)
                {
                    Task <byte[][]> task = handler.GetByteCodes(batch.CodesRequest, cancellationToken);

                    await task.ContinueWith(
                        (t, state) =>
                    {
                        if (t.IsFaulted)
                        {
                            if (Logger.IsTrace)
                            {
                                Logger.Error("DEBUG/ERROR Error after dispatching the snap sync request", t.Exception);
                            }
                        }

                        SnapSyncBatch batchLocal = (SnapSyncBatch)state !;
                        if (t.IsCompletedSuccessfully)
                        {
                            batchLocal.CodesResponse = t.Result;
                        }
                    }, batch);
                }
                else if (batch.AccountsToRefreshRequest is not null)
                {
                    Task <byte[][]> task = handler.GetTrieNodes(batch.AccountsToRefreshRequest, cancellationToken);

                    await task.ContinueWith(
                        (t, state) =>
                    {
                        if (t.IsFaulted)
                        {
                            if (Logger.IsTrace)
                            {
                                Logger.Error("DEBUG/ERROR Error after dispatching the snap sync request", t.Exception);
                            }
                        }

                        SnapSyncBatch batchLocal = (SnapSyncBatch)state !;
                        if (t.IsCompletedSuccessfully)
                        {
                            batchLocal.AccountsToRefreshResponse = t.Result;
                        }
                    }, batch);
                }
            }

            await Task.CompletedTask;
        }
Пример #11
0
        private async Task ExecuteRequest(CancellationToken token, StateSyncBatch batch)
        {
            SyncPeerAllocation nodeSyncAllocation = _syncPeerPool.Borrow(BorrowOptions.DoNotReplace, "node sync");

            try
            {
                ISyncPeer peer = nodeSyncAllocation?.Current?.SyncPeer;
                batch.AssignedPeer = nodeSyncAllocation;
                if (peer != null)
                {
                    var             hashes          = batch.RequestedNodes.Select(r => r.Hash).ToArray();
                    Task <byte[][]> getNodeDataTask = peer.GetNodeData(hashes, token);
                    await getNodeDataTask.ContinueWith(
                        t =>
                    {
                        if (t.IsCompletedSuccessfully)
                        {
                            batch.Responses = getNodeDataTask.Result;
                        }
                    }
                        );
                }
                else
                {
                    // _logger.Info("No alloc punishment enabled.");
                    _noAllocInARow++;
                    if (_noAllocInARow > 10)
                    {
                        _noAllocPunishment = true;
                        if (_logger.IsInfo)
                        {
                            _logger.Info("Adjusting useful peers");
                        }
                        _noAllocInARow = 0;
                    }
                }

                (NodeDataHandlerResult Result, int NodesConsumed)result = (NodeDataHandlerResult.InvalidFormat, 0);
                try
                {
                    result = _nodeDataFeed.HandleResponse(batch);
                    if (result.Result == NodeDataHandlerResult.BadQuality)
                    {
                        _syncPeerPool.ReportBadPeer(batch.AssignedPeer);
                    }
                }
                catch (Exception e)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error($"Error when handling response", e);
                    }
                }

                Interlocked.Add(ref _consumedNodesCount, result.NodesConsumed);
                if (result.NodesConsumed == 0 && peer != null)
                {
                    _syncPeerPool.ReportNoSyncProgress(nodeSyncAllocation);
                }
            }
            finally
            {
                if (nodeSyncAllocation != null)
                {
                    _syncPeerPool.Free(nodeSyncAllocation);
                }
            }
        }
Пример #12
0
        private async Task ExecuteRequest(CancellationToken token, FastBlocksBatch batch)
        {
            SyncPeerAllocation syncPeerAllocation = batch.Allocation;

            try
            {
                foreach (PeerInfo usefulPeer in _syncPeerPool.UsefulPeers)
                {
                    if (usefulPeer.HeadNumber < Math.Max(0, (batch.MinNumber ?? 0) - 1024))
                    {
                        if (_logger.IsDebug)
                        {
                            _logger.Debug($"Made {usefulPeer} sleep for a while - no min number satisfied");
                        }
                        _syncPeerPool.ReportNoSyncProgress(usefulPeer);
                    }
                }

                PeerInfo  peerInfo = syncPeerAllocation?.Current;
                ISyncPeer peer     = peerInfo?.SyncPeer;
                if (peer != null)
                {
                    batch.MarkSent();
                    switch (batch.BatchType)
                    {
                    case FastBlocksBatchType.Headers:
                    {
                        Task <BlockHeader[]> getHeadersTask = peer.GetBlockHeaders(batch.Headers.StartNumber, batch.Headers.RequestSize, 0, token);
                        await getHeadersTask.ContinueWith(
                            t =>
                            {
                                if (t.IsCompletedSuccessfully)
                                {
                                    if (batch.RequestTime > 1000)
                                    {
                                        if (_logger.IsDebug)
                                        {
                                            _logger.Debug($"{batch} - peer is slow {batch.RequestTime:F2}");
                                        }
                                    }

                                    batch.Headers.Response = getHeadersTask.Result;
                                }
                                else
                                {
                                    if (t.Exception.InnerExceptions.Any(e => e is TimeoutException))
                                    {
                                        _syncPeerPool.ReportInvalid(batch.Allocation, $"headers -> timeout");
                                    }
                                    else
                                    {
                                        _syncPeerPool.ReportInvalid(batch.Allocation, $"headers -> {t.Exception}");
                                    }
                                }
                            }
                            );

                        break;
                    }

                    case FastBlocksBatchType.Bodies:
                    {
                        Task <BlockBody[]> getBodiesTask = peer.GetBlockBodies(batch.Bodies.Request, token);
                        await getBodiesTask.ContinueWith(
                            t =>
                            {
                                if (t.IsCompletedSuccessfully)
                                {
                                    if (batch.RequestTime > 1000)
                                    {
                                        if (_logger.IsDebug)
                                        {
                                            _logger.Debug($"{batch} - peer is slow {batch.RequestTime:F2}");
                                        }
                                    }

                                    batch.Bodies.Response = getBodiesTask.Result;
                                }
                                else
                                {
                                    if (t.Exception.InnerExceptions.Any(e => e is TimeoutException))
                                    {
                                        _syncPeerPool.ReportInvalid(batch.Allocation, $"bodies -> timeout");
                                    }
                                    else
                                    {
                                        _syncPeerPool.ReportInvalid(batch.Allocation, $"bodies -> {t.Exception}");
                                    }
                                }
                            }
                            );

                        break;
                    }

                    case FastBlocksBatchType.Receipts:
                    {
                        Task <TxReceipt[][]> getReceiptsTask = peer.GetReceipts(batch.Receipts.Request, token);
                        await getReceiptsTask.ContinueWith(
                            t =>
                            {
                                if (t.IsCompletedSuccessfully)
                                {
                                    if (batch.RequestTime > 1000)
                                    {
                                        if (_logger.IsDebug)
                                        {
                                            _logger.Debug($"{batch} - peer is slow {batch.RequestTime:F2}");
                                        }
                                    }

                                    batch.Receipts.Response = getReceiptsTask.Result;
                                }
                                else
                                {
                                    if (t.Exception.InnerExceptions.Any(e => e is TimeoutException))
                                    {
                                        _syncPeerPool.ReportInvalid(batch.Allocation, $"receipts -> timeout");
                                    }
                                    else
                                    {
                                        _syncPeerPool.ReportInvalid(batch.Allocation, $"receipts -> {t.Exception}");
                                    }
                                }
                            }
                            );

                        break;
                    }

                    default:
                    {
                        throw new InvalidOperationException($"{nameof(FastBlocksBatchType)} is {batch.BatchType}");
                    }
                    }
                }

                (BlocksDataHandlerResult Result, int ItemsSynced)result = (BlocksDataHandlerResult.InvalidFormat, 0);
                try
                {
                    result = _fastBlocksFeed.HandleResponse(batch);
                }
                catch (Exception e)
                {
                    // possibly clear the response and handle empty response batch here (to avoid missing parts)
                    // this practically corrupts sync
                    if (_logger.IsError)
                    {
                        _logger.Error($"Error when handling response", e);
                    }
                }

                Interlocked.Add(ref _downloadedHeaders, result.ItemsSynced);
                if (result.ItemsSynced == 0 && peer != null)
                {
                    _syncPeerPool.ReportNoSyncProgress(peerInfo);
                }
            }
            finally
            {
                if (syncPeerAllocation != null)
                {
                    _syncPeerPool.Free(syncPeerAllocation);
                }
            }
        }
Пример #13
0
 public PeerInfo(ISyncPeer syncPeer)
 {
     SyncPeer        = syncPeer;
     TotalDifficulty = syncPeer.TotalDifficultyOnSessionStart;
 }
Пример #14
0
        private async Task ExecuteRefreshTask(RefreshTotalDiffTask refreshTotalDiffTask, CancellationToken token)
        {
            ISyncPeer syncPeer = refreshTotalDiffTask.SyncPeer;

            if (_logger.IsTrace)
            {
                _logger.Trace($"Requesting head block info from {syncPeer.Node:s}");
            }

            var getHeadHeaderTask = syncPeer.GetHeadBlockHeader(refreshTotalDiffTask.BlockHash ?? syncPeer.HeadHash, token);
            CancellationTokenSource delaySource  = new CancellationTokenSource();
            CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(delaySource.Token, token);
            Task delayTask       = Task.Delay(InitTimeout, linkedSource.Token);
            Task firstToComplete = await Task.WhenAny(getHeadHeaderTask, delayTask);

            await firstToComplete.ContinueWith(
                t =>
            {
                try
                {
                    if (firstToComplete == delayTask)
                    {
                        if (_logger.IsDebug)
                        {
                            _logger.Debug($"InitPeerInfo timed out for node: {syncPeer.Node:c}");
                        }
                        _stats.ReportSyncEvent(syncPeer.Node, syncPeer.IsInitialized ? NodeStatsEventType.SyncFailed : NodeStatsEventType.SyncInitFailed);
                        syncPeer.Disconnect(DisconnectReason.DisconnectRequested, "refresh peer info fault - timeout");
                    }
                    else if (firstToComplete.IsFaulted)
                    {
                        if (_logger.IsDebug)
                        {
                            _logger.Debug($"InitPeerInfo failed for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                        }
                        _stats.ReportSyncEvent(syncPeer.Node, syncPeer.IsInitialized ? NodeStatsEventType.SyncFailed : NodeStatsEventType.SyncInitFailed);
                        syncPeer.Disconnect(DisconnectReason.DisconnectRequested, "refresh peer info fault - timeout");
                    }
                    else if (firstToComplete.IsCanceled)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"InitPeerInfo canceled for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                        }
                        _stats.ReportSyncEvent(syncPeer.Node, syncPeer.IsInitialized ? NodeStatsEventType.SyncCancelled : NodeStatsEventType.SyncInitCancelled);
                        token.ThrowIfCancellationRequested();
                    }
                    else
                    {
                        delaySource.Cancel();
                        BlockHeader header = getHeadHeaderTask.Result;
                        if (header == null)
                        {
                            if (_logger.IsDebug)
                            {
                                _logger.Debug($"InitPeerInfo failed for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                            }
                            _stats.ReportSyncEvent(syncPeer.Node, syncPeer.IsInitialized ? NodeStatsEventType.SyncFailed : NodeStatsEventType.SyncInitFailed);
                            syncPeer.Disconnect(DisconnectReason.DisconnectRequested, "refresh peer info fault - null response");
                            return;
                        }

                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"Received head block info from {syncPeer.Node:c} with head block numer {header.Number}");
                        }
                        if (!syncPeer.IsInitialized)
                        {
                            _stats.ReportSyncEvent(syncPeer.Node, NodeStatsEventType.SyncInitCompleted);
                        }

                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"REFRESH Updating header of {syncPeer} from {syncPeer.HeadNumber} to {header.Number}");
                        }

                        BlockHeader parent = _blockTree.FindParentHeader(header, BlockTreeLookupOptions.None);
                        if (parent != null)
                        {
                            UInt256 newTotalDifficulty = (parent.TotalDifficulty ?? UInt256.Zero) + header.Difficulty;
                            if (newTotalDifficulty >= syncPeer.TotalDifficulty)
                            {
                                syncPeer.TotalDifficulty = newTotalDifficulty;
                                syncPeer.HeadNumber      = header.Number;
                                syncPeer.HeadHash        = header.Hash;
                            }
                        }
                        else if (header.Number > syncPeer.HeadNumber)
                        {
                            syncPeer.HeadNumber = header.Number;
                            syncPeer.HeadHash   = header.Hash;
                        }

                        syncPeer.IsInitialized = true;

                        SignalPeersChanged();
                    }
                }
                finally
                {
                    linkedSource.Dispose();
                    delaySource.Dispose();
                }
            }, token);
        }
Пример #15
0
 public SyncingContext AfterHintBlockMessage(Block block, ISyncPeer peer)
 {
     _logger.Info($"HINT BLOCK MESSAGE {block.Number}");
     SyncServer.HintBlock(block.Hash, block.Number, peer);
     return(this);
 }
Пример #16
0
 public PeerInfo(ISyncPeer syncPeer)
 {
     SyncPeer = syncPeer;
     RecognizeClientType(syncPeer);
 }
Пример #17
0
 public PeerInfo(ISyncPeer syncPeer)
 {
     SyncPeer = syncPeer;
 }
Пример #18
0
 public RefreshTotalDiffTask(Keccak blockHash, ISyncPeer syncPeer)
 {
     BlockHash = blockHash;
     SyncPeer  = syncPeer;
 }
Пример #19
0
        private async Task ExecuteRefreshTask(RefreshTotalDiffTask refreshTotalDiffTask, CancellationToken token)
        {
            PeerInfo peerInfo = refreshTotalDiffTask.PeerInfo;

            if (_logger.IsTrace)
            {
                _logger.Trace($"Requesting head block info from {peerInfo.SyncPeer.Node:s}");
            }

            ISyncPeer syncPeer                   = peerInfo.SyncPeer;
            var       getHeadHeaderTask          = peerInfo.SyncPeer.GetHeadBlockHeader(refreshTotalDiffTask.BlockHash ?? peerInfo.HeadHash, token);
            CancellationTokenSource delaySource  = new CancellationTokenSource();
            CancellationTokenSource linkedSource = CancellationTokenSource.CreateLinkedTokenSource(delaySource.Token, token);
            Task delayTask       = Task.Delay(InitTimeout, linkedSource.Token);
            Task firstToComplete = await Task.WhenAny(getHeadHeaderTask, delayTask);

            await firstToComplete.ContinueWith(
                t =>
            {
                try
                {
                    if (firstToComplete.IsFaulted || firstToComplete == delayTask)
                    {
                        if (_logger.IsDebug)
                        {
                            _logger.Debug($"InitPeerInfo failed for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                        }
                        _stats.ReportSyncEvent(syncPeer.Node, peerInfo.IsInitialized ? NodeStatsEventType.SyncFailed : NodeStatsEventType.SyncInitFailed);
                        syncPeer.Disconnect(DisconnectReason.DisconnectRequested, "refresh peer info fault - timeout");
                    }
                    else if (firstToComplete.IsCanceled)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"InitPeerInfo canceled for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                        }
                        _stats.ReportSyncEvent(syncPeer.Node, peerInfo.IsInitialized ? NodeStatsEventType.SyncCancelled : NodeStatsEventType.SyncInitCancelled);
                        token.ThrowIfCancellationRequested();
                    }
                    else
                    {
                        delaySource.Cancel();
                        BlockHeader header = getHeadHeaderTask.Result;
                        if (header == null)
                        {
                            if (_logger.IsDebug)
                            {
                                _logger.Debug($"InitPeerInfo failed for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                            }

                            _stats.ReportSyncEvent(syncPeer.Node, peerInfo.IsInitialized ? NodeStatsEventType.SyncFailed : NodeStatsEventType.SyncInitFailed);
                            syncPeer.Disconnect(DisconnectReason.DisconnectRequested, "refresh peer info fault - null response");
                            return;
                        }

                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"Received head block info from {syncPeer.Node:c} with head block numer {header.Number}");
                        }
                        if (!peerInfo.IsInitialized)
                        {
                            _stats.ReportSyncEvent(syncPeer.Node, NodeStatsEventType.SyncInitCompleted);
                        }

                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"REFRESH Updating header of {peerInfo} from {peerInfo.HeadNumber} to {header.Number}");
                        }

                        BlockHeader parent = _blockTree.FindHeader(header.ParentHash, BlockTreeLookupOptions.None);
                        if (parent != null)
                        {
                            UInt256 newTotalDifficulty = (parent.TotalDifficulty ?? UInt256.Zero) + header.Difficulty;
                            if (newTotalDifficulty >= peerInfo.TotalDifficulty)
                            {
                                peerInfo.TotalDifficulty = newTotalDifficulty;
                                peerInfo.HeadNumber      = header.Number;
                                peerInfo.HeadHash        = header.Hash;
                            }
                        }
                        else if (header.Number > peerInfo.HeadNumber)
                        {
                            peerInfo.HeadNumber = header.Number;
                            peerInfo.HeadHash   = header.Hash;
                        }

                        peerInfo.IsInitialized = true;
                        foreach ((SyncPeerAllocation allocation, object _) in _replaceableAllocations)
                        {
                            if (allocation.Current == peerInfo)
                            {
                                allocation.Refresh();
                            }
                        }

                        _signals.Set();
                        PeerAdded?.Invoke(this, EventArgs.Empty);
                    }
                }
                finally
                {
                    linkedSource.Dispose();
                    delaySource.Dispose();
                }
            }, token);
        }
Пример #20
0
 public PeerBlockNotificationEventArgs(ISyncPeer syncPeer, Block block)
 {
     SyncPeer = syncPeer;
     Block    = block;
 }
Пример #21
0
        public void RefreshTotalDifficulty(ISyncPeer syncPeer, Keccak blockHash)
        {
            RefreshTotalDiffTask task = new RefreshTotalDiffTask(blockHash, syncPeer);

            _peerRefreshQueue.Add(task);
        }
Пример #22
0
 public void RefreshTotalDifficulty(ISyncPeer syncPeer, Keccak hash)
 {
 }
Пример #23
0
        private async Task RefreshPeerInfo(PeerInfo peerInfo, CancellationToken token)
        {
            if (_logger.IsTrace)
            {
                _logger.Trace($"Requesting head block info from {peerInfo.SyncPeer.Node:s}");
            }

            ISyncPeer          syncPeer          = peerInfo.SyncPeer;
            Task <BlockHeader> getHeadHeaderTask = peerInfo.SyncPeer.GetHeadBlockHeader(peerInfo.HeadHash, token);
            Task delayTask       = Task.Delay(InitTimeout, token);
            Task firstToComplete = await Task.WhenAny(getHeadHeaderTask, delayTask);

            await firstToComplete.ContinueWith(
                t =>
            {
                if (firstToComplete.IsFaulted || firstToComplete == delayTask)
                {
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"InitPeerInfo failed for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                    }
                    _stats.ReportSyncEvent(syncPeer.Node, peerInfo.IsInitialized ? NodeStatsEventType.SyncFailed : NodeStatsEventType.SyncInitFailed);
                    syncPeer.Disconnect(DisconnectReason.DisconnectRequested, "refresh peer info fault");
                }
                else if (firstToComplete.IsCanceled)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"InitPeerInfo canceled for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                    }
                    _stats.ReportSyncEvent(syncPeer.Node, peerInfo.IsInitialized ? NodeStatsEventType.SyncCancelled : NodeStatsEventType.SyncInitCancelled);
                    token.ThrowIfCancellationRequested();
                }
                else
                {
                    BlockHeader header = getHeadHeaderTask.Result;
                    if (header == null)
                    {
                        if (_logger.IsDebug)
                        {
                            _logger.Debug($"InitPeerInfo failed for node: {syncPeer.Node:c}{Environment.NewLine}{t.Exception}");
                        }

                        _stats.ReportSyncEvent(syncPeer.Node, peerInfo.IsInitialized ? NodeStatsEventType.SyncFailed: NodeStatsEventType.SyncInitFailed);
                        syncPeer.Disconnect(DisconnectReason.DisconnectRequested, "refresh peer info fault");
                        return;
                    }

                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Received head block info from {syncPeer.Node:c} with head block numer {header.Number}");
                    }
                    if (!peerInfo.IsInitialized)
                    {
                        _stats.ReportSyncEvent(syncPeer.Node, NodeStatsEventType.SyncInitCompleted);
                    }

                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"REFRESH Updating header of {peerInfo} from {peerInfo.HeadNumber} to {header.Number}");
                    }
                    peerInfo.HeadNumber = header.Number;
                    peerInfo.HeadHash   = header.Hash;

                    BlockHeader parent = _blockTree.FindHeader(header.ParentHash);
                    if (parent != null)
                    {
                        peerInfo.TotalDifficulty = (parent.TotalDifficulty ?? UInt256.Zero) + header.Difficulty;
                    }

                    peerInfo.IsInitialized = true;
                    foreach ((SyncPeerAllocation allocation, object _) in _allocations)
                    {
                        if (allocation.Current == peerInfo)
                        {
                            allocation.Refresh();
                        }
                    }
                }
            }, token);
        }
Пример #24
0
 public void AddPeer(ISyncPeer peer)
 {
 }
Пример #25
0
 public PeerInfo(ISyncPeer syncPeer)
 {
     SyncPeer        = syncPeer;
     TotalDifficulty = syncPeer.TotalDifficultyOnSessionStart;
     RecognizeClientType(syncPeer);
 }