public void ReportBreachOfProtocol(PeerInfo peerInfo, string details) { /* since the allocations can have the peers dynamically changed * it may be hard for the external classes to ensure that the peerInfo is not null at the time when they report * so we decide to check for null here and not consider the scenario to be exceptional */ if (peerInfo != null) { _stats.ReportSyncEvent(peerInfo.SyncPeer.Node, NodeStatsEventType.SyncFailed); peerInfo.SyncPeer.Disconnect(DisconnectReason.BreachOfProtocol, details); } }
public void ReportWeakPeer(PeerInfo weakPeer, AllocationContexts allocationContexts) { if (weakPeer == null) { /* it may have just got disconnected and in such case the allocation would be nullified * in such case there is no need to talk about whether the peer is good or bad */ return; } AllocationContexts sleeps = weakPeer.IncreaseWeakness(allocationContexts); if (sleeps != AllocationContexts.None) { weakPeer.PutToSleep(sleeps, DateTime.UtcNow); } }
public void Cancel() { PeerInfo current = Current; if (current == null) { return; } lock (_allocationLock) { current.Free(Contexts); Current = null; } AllocationChangeEventArgs args = new AllocationChangeEventArgs(current, null); Cancelled?.Invoke(this, args); }
public void AddPeer(ISyncPeer syncPeer) { if (_logger.IsDebug) { _logger.Debug($"Adding sync peer {syncPeer.Node:c}"); } if (!_isStarted) { if (_logger.IsDebug) { _logger.Debug($"Sync peer pool not started yet - adding peer is blocked: {syncPeer.Node:s}"); } return; } if (_peers.ContainsKey(syncPeer.Node.Id)) { if (_logger.IsDebug) { _logger.Debug($"Sync peer {syncPeer.Node:c} already in peers collection."); } return; } PeerInfo peerInfo = new PeerInfo(syncPeer); _peers.TryAdd(syncPeer.Node.Id, peerInfo); Metrics.SyncPeers = _peers.Count; if (_logger.IsDebug) { _logger.Debug($"Adding {syncPeer.Node:c} to refresh queue"); } if (NetworkDiagTracer.IsEnabled) { NetworkDiagTracer.ReportInterestingEvent(syncPeer.Node.Host, "adding node to refresh queue"); } _peerRefreshQueue.Add(new RefreshTotalDiffTask { SyncPeer = syncPeer }); }
public void AllocateBestPeer(IEnumerable <PeerInfo> peers, INodeStatsManager nodeStatsManager, IBlockTree blockTree) { PeerInfo current = Current; PeerInfo selected = _peerAllocationStrategy.Allocate(Current, peers, nodeStatsManager, blockTree); if (selected == current) { return; } AllocationChangeEventArgs args; lock (_allocationLock) { if (selected != null && selected.TryAllocate(Contexts)) { Current = selected; args = new AllocationChangeEventArgs(current, selected); current?.Free(Contexts); Replaced?.Invoke(this, args); } } }
public void ReportNoSyncProgress(PeerInfo peerInfo, AllocationContexts allocationContexts) { ReportWeakPeer(peerInfo, allocationContexts); }
internal void DropUselessPeers(bool force = false) { if (!force && DateTime.UtcNow - _lastUselessPeersDropTime < TimeSpan.FromSeconds(30)) { // give some time to monitoring nodes // (monitoring nodes are nodes that are investigating the network but are not synced themselves) return; } if (_logger.IsTrace) { _logger.Trace($"Reviewing {PeerCount} peer usefulness"); } int peersDropped = 0; _lastUselessPeersDropTime = DateTime.UtcNow; long ourNumber = _blockTree.BestSuggestedHeader?.Number ?? 0L; UInt256 ourDifficulty = _blockTree.BestSuggestedHeader?.TotalDifficulty ?? UInt256.Zero; foreach (PeerInfo peerInfo in AllPeers) { if (peerInfo.HeadNumber == 0 && peerInfo.IsInitialized && ourNumber != 0 && peerInfo.PeerClientType != PeerClientType.Nethermind) // we know that Nethermind reports 0 HeadNumber when it is in sync (and it can still serve a lot of data to other nodes) { if (!CanBeUsefulForFastBlocks(peerInfo.HeadNumber)) { peersDropped++; peerInfo.SyncPeer.Disconnect(DisconnectReason.UselessPeer, "PEER REVIEW / HEAD 0"); } } else if (peerInfo.HeadNumber == 1920000 && _blockTree.ChainId == ChainId.Mainnet) // mainnet, stuck Geth nodes { if (!CanBeUsefulForFastBlocks(peerInfo.HeadNumber)) { peersDropped++; peerInfo.SyncPeer.Disconnect(DisconnectReason.UselessPeer, "PEER REVIEW / 1920000"); } } else if (peerInfo.HeadNumber == 7280022 && _blockTree.ChainId == ChainId.Mainnet) // mainnet, stuck Geth nodes { if (!CanBeUsefulForFastBlocks(peerInfo.HeadNumber)) { peersDropped++; peerInfo.SyncPeer.Disconnect(DisconnectReason.UselessPeer, "PEER REVIEW / 7280022"); } } else if (peerInfo.HeadNumber > ourNumber + 1024L && peerInfo.TotalDifficulty < ourDifficulty) { if (!CanBeUsefulForFastBlocks(MainnetSpecProvider.Instance.DaoBlockNumber ?? 0)) { // probably Ethereum Classic nodes tht remain connected after we went pass the DAO // worth to find a better way to discard them at the right time peersDropped++; peerInfo.SyncPeer.Disconnect(DisconnectReason.UselessPeer, "STRAY PEER"); } } } if (PeerCount == PeerMaxCount) { long lowestBlockNumber = long.MaxValue; PeerInfo worstPeer = null; foreach (PeerInfo peerInfo in AllPeers) { if (peerInfo.HeadNumber < lowestBlockNumber) { lowestBlockNumber = peerInfo.HeadNumber; worstPeer = peerInfo; } } peersDropped++; worstPeer?.SyncPeer.Disconnect(DisconnectReason.TooManyPeers, "PEER REVIEW / LOWEST NUMBER"); } if (_logger.IsDebug) { _logger.Debug($"Dropped {peersDropped} useless peers"); } }
private void AddPeerInfo(PeerInfo peerInfo) { _stringBuilder.Append($" {peerInfo}[{_stats.GetOrAdd(peerInfo.SyncPeer.Node).GetAverageTransferSpeed(TransferSpeedType.Latency) ?? 0}|{_stats.GetOrAdd(peerInfo.SyncPeer.Node).GetAverageTransferSpeed(TransferSpeedType.Headers) ?? 0}|{_stats.GetOrAdd(peerInfo.SyncPeer.Node).GetAverageTransferSpeed(TransferSpeedType.Bodies) ?? 0}|{_stats.GetOrAdd(peerInfo.SyncPeer.Node).GetAverageTransferSpeed(TransferSpeedType.Receipts) ?? 0}|{_stats.GetOrAdd(peerInfo.SyncPeer.Node).GetAverageTransferSpeed(TransferSpeedType.NodeData) ?? 0}]"); }
public SyncPeerAllocation(PeerInfo peerInfo, AllocationContexts contexts) : this(new StaticStrategy(peerInfo), contexts) { }