From 7ccd0fb6173916d0e8a344f09d2f518316b480d4 Mon Sep 17 00:00:00 2001 From: Shawn Date: Fri, 31 Jul 2020 14:40:50 +0800 Subject: [PATCH 01/12] add node health --- src/neo/Network/P2P/RemoteNode.cs | 18 ++++++++++++++++++ src/neo/Network/P2P/TaskManager.cs | 30 +++++++++++++++++++++--------- src/neo/Network/P2P/TaskSession.cs | 18 ++++++++++++++++-- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/neo/Network/P2P/RemoteNode.cs b/src/neo/Network/P2P/RemoteNode.cs index b1457a8522..382f77abbd 100644 --- a/src/neo/Network/P2P/RemoteNode.cs +++ b/src/neo/Network/P2P/RemoteNode.cs @@ -7,6 +7,7 @@ using Neo.Ledger; using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -24,6 +25,9 @@ internal class Relay { public IInventory Inventory; } private readonly Queue message_queue_low = new Queue(); private ByteString msg_buffer = ByteString.Empty; private bool ack = true; + private int message_count = 0; + private DateTime start_message_time; + private readonly double time_threshold = 1000; public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); public int ListenerTcpPort { get; private set; } = 0; @@ -112,7 +116,21 @@ protected override void OnData(ByteString data) msg_buffer = msg_buffer.Concat(data); for (Message message = TryParseMessage(); message != null; message = TryParseMessage()) + { + if (message_count == 0) + start_message_time = TimeProvider.Current.UtcNow; + else if (message_count > 1000) + { + message_count = 0; + if ((TimeProvider.Current.UtcNow - start_message_time).TotalMilliseconds < time_threshold) + { + Disconnect(true); + return; + } + } OnMessage(message); + message_count++; + } } protected override void OnReceive(object message) diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index 3eab30ba2e..c11961980f 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -52,10 +52,8 @@ private bool AssignSyncTask(uint index, TaskSession filterSession = null) { if (index <= Blockchain.Singleton.Height || sessions.Values.Any(p => p != filterSession && p.IndexTasks.ContainsKey(index))) return true; - Random rand = new Random(); - KeyValuePair remoteNode = sessions.Where(p => p.Value != filterSession && p.Value.LastBlockIndex >= index) - .OrderBy(p => p.Value.IndexTasks.Count) - .ThenBy(s => rand.Next()) + KeyValuePair remoteNode = sessions.Where(p => p.Value != filterSession && p.Value.LastBlockIndex >= index && p.Value.IndexTasks.Count < TaskSession.MaxTaskCountPerNode) + .OrderByDescending(p => p.Value.Weight) .FirstOrDefault(); if (remoteNode.Value == null) { @@ -64,6 +62,7 @@ private bool AssignSyncTask(uint index, TaskSession filterSession = null) } TaskSession session = remoteNode.Value; session.IndexTasks.TryAdd(index, TimeProvider.Current.UtcNow); + session.UpdateWeight(); remoteNode.Key.Tell(Message.Create(MessageCommand.GetBlockByIndex, GetBlockByIndexPayload.Create(index, 1))); failedSyncTasks.Remove(index); return true; @@ -73,7 +72,10 @@ private void OnBlock(Block block) { var session = sessions.Values.FirstOrDefault(p => p.IndexTasks.ContainsKey(block.Index)); if (session is null) return; + var newRTT = (TimeProvider.Current.UtcNow - session.IndexTasks[block.Index]).TotalMilliseconds; + session.UpdateRTT(newRTT); session.IndexTasks.Remove(block.Index); + session.UpdateWeight(); receivedBlockIndex.TryAdd(block.Index, session); RequestTasks(); } @@ -82,10 +84,15 @@ private void OnInvalidBlock(Block invalidBlock) { receivedBlockIndex.TryGetValue(invalidBlock.Index, out TaskSession session); if (session is null) return; - session.InvalidBlockCount++; - session.IndexTasks.Remove(invalidBlock.Index); + if (++session.InvalidBlockCount > 3) + OnTerminated(sessions.Where(p => p.Value == session).First().Key); + else + { + session.IndexTasks.Remove(invalidBlock.Index); + session.UpdateWeight(); + AssignSyncTask(invalidBlock.Index, session); + } receivedBlockIndex.Remove(invalidBlock.Index); - AssignSyncTask(invalidBlock.Index, session); } private void OnNewTasks(InvPayload payload) @@ -241,8 +248,13 @@ private void OnTimer() if (TimeProvider.Current.UtcNow - kvp.Value > TaskTimeout) { session.IndexTasks.Remove(kvp.Key); - session.TimeoutTimes++; - AssignSyncTask(kvp.Key, session); + if (++session.TimeoutTimes > 3) + OnTerminated(sessions.Where(p => p.Value == session).First().Key); + else + { + session.UpdateWeight(); + AssignSyncTask(kvp.Key, session); + } } } diff --git a/src/neo/Network/P2P/TaskSession.cs b/src/neo/Network/P2P/TaskSession.cs index 859f282d35..2688a06889 100644 --- a/src/neo/Network/P2P/TaskSession.cs +++ b/src/neo/Network/P2P/TaskSession.cs @@ -15,12 +15,26 @@ internal class TaskSession public uint LastBlockIndex { get; set; } public uint TimeoutTimes = 0; public uint InvalidBlockCount = 0; + public double RTT = 100.0; + public double Weight = 1000.0; + + public const int MaxTaskCountPerNode = 10; + + public void UpdateRTT(double newRTT) + { + RTT = 0.9 * RTT + 0.1 * newRTT; + } + + public void UpdateWeight() + { + Weight = RTT * (1.0 / Math.Pow(2, TimeoutTimes)) * (1.0 / Math.Pow(2, InvalidBlockCount)) * ((double)(MaxTaskCountPerNode + 1 - IndexTasks.Count) / (MaxTaskCountPerNode + 1)); + } public TaskSession(VersionPayload version) { var fullNode = version.Capabilities.OfType().FirstOrDefault(); - this.IsFullNode = fullNode != null; - this.LastBlockIndex = fullNode.StartHeight; + IsFullNode = fullNode != null; + LastBlockIndex = fullNode.StartHeight; } } } From b0810732f8b830ad3b2d6dba46e5b2359f48cf29 Mon Sep 17 00:00:00 2001 From: Shawn Date: Fri, 31 Jul 2020 14:44:39 +0800 Subject: [PATCH 02/12] format --- src/neo/Network/P2P/TaskSession.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/neo/Network/P2P/TaskSession.cs b/src/neo/Network/P2P/TaskSession.cs index 2688a06889..26e86b1001 100644 --- a/src/neo/Network/P2P/TaskSession.cs +++ b/src/neo/Network/P2P/TaskSession.cs @@ -13,13 +13,12 @@ internal class TaskSession public bool IsFullNode { get; } public uint LastBlockIndex { get; set; } + public const int MaxTaskCountPerNode = 10; public uint TimeoutTimes = 0; public uint InvalidBlockCount = 0; public double RTT = 100.0; public double Weight = 1000.0; - public const int MaxTaskCountPerNode = 10; - public void UpdateRTT(double newRTT) { RTT = 0.9 * RTT + 0.1 * newRTT; From e0779e65e5be9893a1dde0873c3d4750f8c08525 Mon Sep 17 00:00:00 2001 From: Shawn Date: Thu, 13 Aug 2020 14:17:54 +0800 Subject: [PATCH 03/12] fix node health --- src/neo/Network/P2P/LocalNode.cs | 4 ++++ src/neo/Network/P2P/Peer.cs | 12 +++++++--- src/neo/Network/P2P/RemoteNode.cs | 2 +- src/neo/Network/P2P/TaskManager.cs | 38 ++++++++++++++++++++---------- src/neo/Network/P2P/TaskSession.cs | 5 ++-- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/neo/Network/P2P/LocalNode.cs b/src/neo/Network/P2P/LocalNode.cs index c8bc937001..106f65f8c3 100644 --- a/src/neo/Network/P2P/LocalNode.cs +++ b/src/neo/Network/P2P/LocalNode.cs @@ -17,6 +17,7 @@ public class LocalNode : Peer { internal class RelayDirectly { public IInventory Inventory; } internal class SendDirectly { public IInventory Inventory; } + internal class BadActor { public IActorRef actor; } public const uint ProtocolVersion = 0; private const int MaxCountFromSeedList = 5; @@ -196,6 +197,9 @@ protected override void OnReceive(object message) case SendDirectly send: OnSendDirectly(send.Inventory); break; + case BadActor actor: + RemoveBadActor(actor.actor); + break; } } diff --git a/src/neo/Network/P2P/Peer.cs b/src/neo/Network/P2P/Peer.cs index 106f530b71..bbf76dc0c4 100644 --- a/src/neo/Network/P2P/Peer.cs +++ b/src/neo/Network/P2P/Peer.cs @@ -94,7 +94,6 @@ protected void ConnectToPeer(IPEndPoint endPoint, bool isTrusted = false) endPoint = endPoint.Unmap(); // If the address is the same, the ListenerTcpPort should be different, otherwise, return if (endPoint.Port == ListenerTcpPort && localAddresses.Contains(endPoint.Address)) return; - if (isTrusted) TrustedIpAddresses.Add(endPoint.Address); // If connections with the peer greater than or equal to MaxConnectionsPerAddress, return. if (ConnectedAddresses.TryGetValue(endPoint.Address, out int count) && count >= MaxConnectionsPerAddress) @@ -121,6 +120,15 @@ private static bool IsIntranetAddress(IPAddress address) /// Number of peers that are being requested. protected abstract void NeedMorePeers(int count); + public void RemoveBadActor(IActorRef actor) + { + if (ConnectedPeers.TryRemove(actor, out IPEndPoint ipEndPoint)) + { + UnconnectedPeers.Remove(ipEndPoint); + actor.Tell(Tcp.Abort.Instance); + } + } + protected override void OnReceive(object message) { switch (message) @@ -266,11 +274,9 @@ private void OnTimer() { // Check if the number of desired connections is already enough if (ConnectedPeers.Count >= MinDesiredConnections) return; - // If there aren't available UnconnectedPeers, it triggers an abstract implementation of NeedMorePeers if (UnconnectedPeers.Count == 0) NeedMorePeers(MinDesiredConnections - ConnectedPeers.Count); - Random rand = new Random(); IPEndPoint[] endpoints = UnconnectedPeers.OrderBy(u => rand.Next()).Take(MinDesiredConnections - ConnectedPeers.Count).ToArray(); ImmutableInterlocked.Update(ref UnconnectedPeers, p => p.Except(endpoints)); diff --git a/src/neo/Network/P2P/RemoteNode.cs b/src/neo/Network/P2P/RemoteNode.cs index 382f77abbd..e72c522e1c 100644 --- a/src/neo/Network/P2P/RemoteNode.cs +++ b/src/neo/Network/P2P/RemoteNode.cs @@ -27,7 +27,7 @@ internal class Relay { public IInventory Inventory; } private bool ack = true; private int message_count = 0; private DateTime start_message_time; - private readonly double time_threshold = 1000; + private readonly double time_threshold = 10; public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); public int ListenerTcpPort { get; private set; } = 0; diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index c11961980f..def693fc15 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -46,14 +46,16 @@ public TaskManager(NeoSystem system) this.knownHashes = new HashSetCache(Blockchain.Singleton.MemPool.Capacity * 2 / 5); this.lastTaskIndex = Blockchain.Singleton.Height; Context.System.EventStream.Subscribe(Self, typeof(Blockchain.PersistCompleted)); + Context.System.EventStream.Subscribe(Self, typeof(Blockchain.RelayResult)); } private bool AssignSyncTask(uint index, TaskSession filterSession = null) { if (index <= Blockchain.Singleton.Height || sessions.Values.Any(p => p != filterSession && p.IndexTasks.ContainsKey(index))) return true; - KeyValuePair remoteNode = sessions.Where(p => p.Value != filterSession && p.Value.LastBlockIndex >= index && p.Value.IndexTasks.Count < TaskSession.MaxTaskCountPerNode) - .OrderByDescending(p => p.Value.Weight) + var highestBlockIndex = sessions.Values.Max(p => p.LastBlockIndex); + KeyValuePair remoteNode = sessions.Where(p => p.Value != filterSession && p.Value.LastBlockIndex >= index && p.Value.IndexTasks.Count < p.Value.MaxTaskCountPerNode) + .OrderBy(p => p.Value.Weight) .FirstOrDefault(); if (remoteNode.Value == null) { @@ -82,17 +84,24 @@ private void OnBlock(Block block) private void OnInvalidBlock(Block invalidBlock) { - receivedBlockIndex.TryGetValue(invalidBlock.Index, out TaskSession session); - if (session is null) return; - if (++session.InvalidBlockCount > 3) - OnTerminated(sessions.Where(p => p.Value == session).First().Key); - else + receivedBlockIndex.Remove(invalidBlock.Index); + if (!receivedBlockIndex.TryGetValue(invalidBlock.Index, out TaskSession session)) { - session.IndexTasks.Remove(invalidBlock.Index); - session.UpdateWeight(); - AssignSyncTask(invalidBlock.Index, session); + AssignSyncTask(invalidBlock.Index); + return; } - receivedBlockIndex.Remove(invalidBlock.Index); + var actor = sessions.Where(p => p.Value == session).FirstOrDefault().Key; + if (actor != null) + { + system.LocalNode.Tell(new LocalNode.BadActor { actor = actor }); + OnTerminated(actor); + } + } + + private void OnValidBlock(Block validBlock) + { + if (receivedBlockIndex.TryGetValue(validBlock.Index, out TaskSession session) && session.MaxTaskCountPerNode < 10) + session.MaxTaskCountPerNode++; } private void OnNewTasks(InvPayload payload) @@ -155,6 +164,8 @@ protected override void OnReceive(object message) case Blockchain.RelayResult rr: if (rr.Inventory is Block invalidBlock && rr.Result == VerifyResult.Invalid) OnInvalidBlock(invalidBlock); + else if (rr.Inventory is Block validBlock && rr.Result == VerifyResult.Succeed) + OnValidBlock(validBlock); break; case Timer _: OnTimer(); @@ -236,6 +247,7 @@ private void OnTerminated(IActorRef actor) foreach (UInt256 hash in session.InvTasks.Keys) DecrementGlobalTask(hash); + //system.LocalNode.Tell(new Terminated(actor, false, false)); sessions.Remove(actor); } @@ -289,7 +301,7 @@ private void RequestTasks() while (failedSyncTasks.Count() > 0) { - var failedTask = failedSyncTasks.First(); + var failedTask = failedSyncTasks.OrderBy(p => p).First(); if (failedTask <= Blockchain.Singleton.Height) { failedSyncTasks.Remove(failedTask); @@ -302,7 +314,7 @@ private void RequestTasks() var highestBlockIndex = sessions.Values.Max(p => p.LastBlockIndex); for (; taskCounts < MaxSyncTasksCount; taskCounts++) { - if (lastTaskIndex >= highestBlockIndex) break; + if (lastTaskIndex >= highestBlockIndex || lastTaskIndex > Blockchain.Singleton.HeaderHeight + 2000) break; if (!AssignSyncTask(++lastTaskIndex)) break; } } diff --git a/src/neo/Network/P2P/TaskSession.cs b/src/neo/Network/P2P/TaskSession.cs index 26e86b1001..5173433f2e 100644 --- a/src/neo/Network/P2P/TaskSession.cs +++ b/src/neo/Network/P2P/TaskSession.cs @@ -13,9 +13,8 @@ internal class TaskSession public bool IsFullNode { get; } public uint LastBlockIndex { get; set; } - public const int MaxTaskCountPerNode = 10; + public int MaxTaskCountPerNode = 1; public uint TimeoutTimes = 0; - public uint InvalidBlockCount = 0; public double RTT = 100.0; public double Weight = 1000.0; @@ -26,7 +25,7 @@ public void UpdateRTT(double newRTT) public void UpdateWeight() { - Weight = RTT * (1.0 / Math.Pow(2, TimeoutTimes)) * (1.0 / Math.Pow(2, InvalidBlockCount)) * ((double)(MaxTaskCountPerNode + 1 - IndexTasks.Count) / (MaxTaskCountPerNode + 1)); + Weight = RTT * (1.0 / Math.Pow(2, TimeoutTimes)) * ((double)(MaxTaskCountPerNode + 1 - IndexTasks.Count) / (MaxTaskCountPerNode + 1)); } public TaskSession(VersionPayload version) From 2d2a0b92f1980daf80add4783a02213e63a424c6 Mon Sep 17 00:00:00 2001 From: Shawn Date: Thu, 13 Aug 2020 14:21:34 +0800 Subject: [PATCH 04/12] format --- src/neo/Network/P2P/Peer.cs | 3 +++ src/neo/Network/P2P/TaskManager.cs | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/neo/Network/P2P/Peer.cs b/src/neo/Network/P2P/Peer.cs index bbf76dc0c4..587b970a55 100644 --- a/src/neo/Network/P2P/Peer.cs +++ b/src/neo/Network/P2P/Peer.cs @@ -94,6 +94,7 @@ protected void ConnectToPeer(IPEndPoint endPoint, bool isTrusted = false) endPoint = endPoint.Unmap(); // If the address is the same, the ListenerTcpPort should be different, otherwise, return if (endPoint.Port == ListenerTcpPort && localAddresses.Contains(endPoint.Address)) return; + if (isTrusted) TrustedIpAddresses.Add(endPoint.Address); // If connections with the peer greater than or equal to MaxConnectionsPerAddress, return. if (ConnectedAddresses.TryGetValue(endPoint.Address, out int count) && count >= MaxConnectionsPerAddress) @@ -274,9 +275,11 @@ private void OnTimer() { // Check if the number of desired connections is already enough if (ConnectedPeers.Count >= MinDesiredConnections) return; + // If there aren't available UnconnectedPeers, it triggers an abstract implementation of NeedMorePeers if (UnconnectedPeers.Count == 0) NeedMorePeers(MinDesiredConnections - ConnectedPeers.Count); + Random rand = new Random(); IPEndPoint[] endpoints = UnconnectedPeers.OrderBy(u => rand.Next()).Take(MinDesiredConnections - ConnectedPeers.Count).ToArray(); ImmutableInterlocked.Update(ref UnconnectedPeers, p => p.Except(endpoints)); diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index def693fc15..8af50f4149 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -53,7 +53,6 @@ private bool AssignSyncTask(uint index, TaskSession filterSession = null) { if (index <= Blockchain.Singleton.Height || sessions.Values.Any(p => p != filterSession && p.IndexTasks.ContainsKey(index))) return true; - var highestBlockIndex = sessions.Values.Max(p => p.LastBlockIndex); KeyValuePair remoteNode = sessions.Where(p => p.Value != filterSession && p.Value.LastBlockIndex >= index && p.Value.IndexTasks.Count < p.Value.MaxTaskCountPerNode) .OrderBy(p => p.Value.Weight) .FirstOrDefault(); @@ -247,7 +246,6 @@ private void OnTerminated(IActorRef actor) foreach (UInt256 hash in session.InvTasks.Keys) DecrementGlobalTask(hash); - //system.LocalNode.Tell(new Terminated(actor, false, false)); sessions.Remove(actor); } From 272fb34d92c90e38af408792dc31f0d5b02649cb Mon Sep 17 00:00:00 2001 From: Shawn Date: Fri, 14 Aug 2020 16:38:11 +0800 Subject: [PATCH 05/12] format --- src/neo/Network/P2P/LocalNode.cs | 6 +++--- src/neo/Network/P2P/Peer.cs | 2 +- src/neo/Network/P2P/TaskManager.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/neo/Network/P2P/LocalNode.cs b/src/neo/Network/P2P/LocalNode.cs index 106f65f8c3..1b7f0388fd 100644 --- a/src/neo/Network/P2P/LocalNode.cs +++ b/src/neo/Network/P2P/LocalNode.cs @@ -17,7 +17,7 @@ public class LocalNode : Peer { internal class RelayDirectly { public IInventory Inventory; } internal class SendDirectly { public IInventory Inventory; } - internal class BadActor { public IActorRef actor; } + internal class MaliciousNode { public IActorRef actor; } public const uint ProtocolVersion = 0; private const int MaxCountFromSeedList = 5; @@ -197,8 +197,8 @@ protected override void OnReceive(object message) case SendDirectly send: OnSendDirectly(send.Inventory); break; - case BadActor actor: - RemoveBadActor(actor.actor); + case MaliciousNode actor: + RemoveMaliciousNode(actor.actor); break; } } diff --git a/src/neo/Network/P2P/Peer.cs b/src/neo/Network/P2P/Peer.cs index 587b970a55..f36ad67697 100644 --- a/src/neo/Network/P2P/Peer.cs +++ b/src/neo/Network/P2P/Peer.cs @@ -121,7 +121,7 @@ private static bool IsIntranetAddress(IPAddress address) /// Number of peers that are being requested. protected abstract void NeedMorePeers(int count); - public void RemoveBadActor(IActorRef actor) + public void RemoveMaliciousNode(IActorRef actor) { if (ConnectedPeers.TryRemove(actor, out IPEndPoint ipEndPoint)) { diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index 8af50f4149..13211ba39e 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -92,7 +92,7 @@ private void OnInvalidBlock(Block invalidBlock) var actor = sessions.Where(p => p.Value == session).FirstOrDefault().Key; if (actor != null) { - system.LocalNode.Tell(new LocalNode.BadActor { actor = actor }); + system.LocalNode.Tell(new LocalNode.MaliciousNode { actor = actor }); OnTerminated(actor); } } From 1fb0d2bd5efd3bec099076374ba67a45d60e88bc Mon Sep 17 00:00:00 2001 From: Shawn Date: Thu, 27 Aug 2020 16:17:24 +0800 Subject: [PATCH 06/12] modify nodehealth --- src/neo/Network/P2P/Peer.cs | 21 ++++++++++++- .../Network/P2P/RemoteNode.ProtocolHandler.cs | 16 +++++++++- src/neo/Network/P2P/TaskManager.cs | 30 +++++++++++-------- src/neo/Network/P2P/TaskSession.cs | 2 +- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/neo/Network/P2P/Peer.cs b/src/neo/Network/P2P/Peer.cs index f36ad67697..9e04385831 100644 --- a/src/neo/Network/P2P/Peer.cs +++ b/src/neo/Network/P2P/Peer.cs @@ -34,8 +34,10 @@ private class WsConnected { public WebSocket Socket; public IPEndPoint Remote; p private ICancelable timer; protected ActorSelection Connections => Context.ActorSelection("connection_*"); + private static readonly TimeSpan BlacklistTime = TimeSpan.FromMinutes(10); private static readonly HashSet localAddresses = new HashSet(); private readonly Dictionary ConnectedAddresses = new Dictionary(); + private readonly Dictionary IPAddressBlacklist = new Dictionary(); /// /// A dictionary that stores the connected nodes. /// @@ -89,12 +91,21 @@ protected void AddPeers(IEnumerable peers) } } + private void AddToBlacklist(IPEndPoint endPoint) + { + if (IPAddressBlacklist.ContainsKey(endPoint)) + IPAddressBlacklist[endPoint] = DateTime.Now; + else + IPAddressBlacklist.TryAdd(endPoint, DateTime.Now); + } + protected void ConnectToPeer(IPEndPoint endPoint, bool isTrusted = false) { endPoint = endPoint.Unmap(); // If the address is the same, the ListenerTcpPort should be different, otherwise, return if (endPoint.Port == ListenerTcpPort && localAddresses.Contains(endPoint.Address)) return; - + // If the address is in blacklist, return + if (IPAddressBlacklist.ContainsKey(endPoint)) return; if (isTrusted) TrustedIpAddresses.Add(endPoint.Address); // If connections with the peer greater than or equal to MaxConnectionsPerAddress, return. if (ConnectedAddresses.TryGetValue(endPoint.Address, out int count) && count >= MaxConnectionsPerAddress) @@ -125,6 +136,7 @@ public void RemoveMaliciousNode(IActorRef actor) { if (ConnectedPeers.TryRemove(actor, out IPEndPoint ipEndPoint)) { + AddToBlacklist(ipEndPoint); UnconnectedPeers.Remove(ipEndPoint); actor.Tell(Tcp.Abort.Instance); } @@ -273,6 +285,13 @@ private void OnTerminated(IActorRef actorRef) private void OnTimer() { + var now = DateTime.Now; + foreach (var item in IPAddressBlacklist.ToList()) + { + if (now - item.Value > BlacklistTime) + IPAddressBlacklist.Remove(item.Key); + } + // Check if the number of desired connections is already enough if (ConnectedPeers.Count >= MinDesiredConnections) return; diff --git a/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs b/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs index 9e73809cc1..e5fb5ee9e0 100644 --- a/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs +++ b/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs @@ -29,6 +29,7 @@ protected override UInt256 GetKeyForItem((UInt256, DateTime) item) private readonly PendingKnownHashesCollection pendingKnownHashes = new PendingKnownHashesCollection(); private readonly HashSetCache knownHashes = new HashSetCache(Blockchain.Singleton.MemPool.Capacity * 2 / 5); private readonly HashSetCache sentHashes = new HashSetCache(Blockchain.Singleton.MemPool.Capacity * 2 / 5); + private readonly HashSet receivedBlcokIndex = new HashSet(Blockchain.Singleton.MemPool.Capacity * 2 / 5); private bool verack = false; private BloomFilter bloom_filter; @@ -270,7 +271,7 @@ private void OnGetDataMessageReceived(InvPayload payload) private void OnGetHeadersMessageReceived(GetBlockByIndexPayload payload) { uint index = payload.IndexStart; - uint count = payload.Count == -1 ? HeadersPayload.MaxHeadersCount : (uint)payload.Count; + uint count = payload.Count == -1 ? HeadersPayload.MaxHeadersCount : Math.Min((uint)payload.Count, HeadersPayload.MaxHeadersCount); if (index > Blockchain.Singleton.HeaderHeight) return; List
headers = new List
(); @@ -286,6 +287,12 @@ private void OnGetHeadersMessageReceived(GetBlockByIndexPayload payload) private void OnInventoryReceived(IInventory inventory) { + if (inventory is Block block) + { + if (receivedBlcokIndex.Contains(block.Index)) return; + receivedBlcokIndex.Add(block.Index); + } + system.TaskManager.Tell(inventory); if (inventory is Transaction transaction) system.Consensus?.Tell(transaction); @@ -373,6 +380,13 @@ private void RefreshPendingKnownHashes() break; pendingKnownHashes.RemoveAt(0); } + + var height = Blockchain.Singleton.Height; + foreach (var item in receivedBlcokIndex.ToArray()) + { + if (item <= height) + receivedBlcokIndex.Remove(item); + } } private void UpdateLastBlockIndex(PingPayload payload) diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index 13211ba39e..391a2b6504 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -25,7 +25,7 @@ private class Timer { } private static readonly UInt256 MemPoolTaskHash = UInt256.Parse("0x0000000000000000000000000000000000000000000000000000000000000001"); private const int MaxConncurrentTasks = 3; - private const int MaxSyncTasksCount = 50; + private const int MaxSyncTasksCount = 500; private const int PingCoolingOffPeriod = 60_000; // in ms. private readonly NeoSystem system; @@ -53,7 +53,7 @@ private bool AssignSyncTask(uint index, TaskSession filterSession = null) { if (index <= Blockchain.Singleton.Height || sessions.Values.Any(p => p != filterSession && p.IndexTasks.ContainsKey(index))) return true; - KeyValuePair remoteNode = sessions.Where(p => p.Value != filterSession && p.Value.LastBlockIndex >= index && p.Value.IndexTasks.Count < p.Value.MaxTaskCountPerNode) + KeyValuePair remoteNode = sessions.Where(p => p.Value != filterSession && p.Value.LastBlockIndex >= index) .OrderBy(p => p.Value.Weight) .FirstOrDefault(); if (remoteNode.Value == null) @@ -83,23 +83,24 @@ private void OnBlock(Block block) private void OnInvalidBlock(Block invalidBlock) { - receivedBlockIndex.Remove(invalidBlock.Index); if (!receivedBlockIndex.TryGetValue(invalidBlock.Index, out TaskSession session)) { AssignSyncTask(invalidBlock.Index); return; } + receivedBlockIndex.Remove(invalidBlock.Index); var actor = sessions.Where(p => p.Value == session).FirstOrDefault().Key; if (actor != null) { - system.LocalNode.Tell(new LocalNode.MaliciousNode { actor = actor }); OnTerminated(actor); + system.LocalNode.Tell(new LocalNode.MaliciousNode { actor = actor }); + AssignSyncTask(invalidBlock.Index); } } private void OnValidBlock(Block validBlock) { - if (receivedBlockIndex.TryGetValue(validBlock.Index, out TaskSession session) && session.MaxTaskCountPerNode < 10) + if (receivedBlockIndex.TryGetValue(validBlock.Index, out TaskSession session) && session.MaxTaskCountPerNode < 50) session.MaxTaskCountPerNode++; } @@ -151,11 +152,8 @@ protected override void OnReceive(object message) case RestartTasks restart: OnRestartTasks(restart.Payload); break; - case Block block: - OnBlock(block); - break; case IInventory inventory: - OnTaskCompleted(inventory.Hash); + OnTaskCompleted(inventory); break; case Blockchain.PersistCompleted pc: OnPersistCompleted(pc.Block); @@ -202,8 +200,11 @@ private void OnRestartTasks(InvPayload payload) system.LocalNode.Tell(Message.Create(MessageCommand.GetData, group)); } - private void OnTaskCompleted(UInt256 hash) + private void OnTaskCompleted(IInventory inventory) { + if (inventory is Block block) + OnBlock(block); + var hash = inventory.Hash; knownHashes.Add(hash); globalTasks.Remove(hash); if (sessions.TryGetValue(Sender, out TaskSession session)) @@ -297,18 +298,23 @@ private void RequestTasks() SendPingMessage(); + int taskCounts = sessions.Values.Sum(p => p.IndexTasks.Count); + while (failedSyncTasks.Count() > 0) { + if (taskCounts >= MaxSyncTasksCount) return; var failedTask = failedSyncTasks.OrderBy(p => p).First(); if (failedTask <= Blockchain.Singleton.Height) { failedSyncTasks.Remove(failedTask); continue; } - if (!AssignSyncTask(failedTask)) return; + if (AssignSyncTask(failedTask)) + taskCounts++; + else + return; } - int taskCounts = sessions.Values.Sum(p => p.IndexTasks.Count); var highestBlockIndex = sessions.Values.Max(p => p.LastBlockIndex); for (; taskCounts < MaxSyncTasksCount; taskCounts++) { diff --git a/src/neo/Network/P2P/TaskSession.cs b/src/neo/Network/P2P/TaskSession.cs index 5173433f2e..902e6baee1 100644 --- a/src/neo/Network/P2P/TaskSession.cs +++ b/src/neo/Network/P2P/TaskSession.cs @@ -25,7 +25,7 @@ public void UpdateRTT(double newRTT) public void UpdateWeight() { - Weight = RTT * (1.0 / Math.Pow(2, TimeoutTimes)) * ((double)(MaxTaskCountPerNode + 1 - IndexTasks.Count) / (MaxTaskCountPerNode + 1)); + Weight = RTT * (1.0 / Math.Pow(2, TimeoutTimes)) * (IndexTasks.Count); } public TaskSession(VersionPayload version) From e5784c35275796544df972f1a57f8fbe12390a71 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 27 Aug 2020 12:32:27 +0200 Subject: [PATCH 07/12] Reduce checks --- src/neo/Network/P2P/TaskManager.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index 2bc1570653..0bb86baec3 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -152,8 +152,12 @@ protected override void OnReceive(object message) case RestartTasks restart: OnRestartTasks(restart.Payload); break; + case Block block: + OnBlock(block); + OnTaskCompleted(block.Hash); + break; case IInventory inventory: - OnTaskCompleted(inventory); + OnTaskCompleted(inventory.Hash); break; case Blockchain.PersistCompleted pc: OnPersistCompleted(pc.Block); @@ -201,11 +205,8 @@ private void OnRestartTasks(InvPayload payload) system.LocalNode.Tell(Message.Create(MessageCommand.GetData, group)); } - private void OnTaskCompleted(IInventory inventory) + private void OnTaskCompleted(UInt256 hash) { - if (inventory is Block block) - OnBlock(block); - var hash = inventory.Hash; knownHashes.Add(hash); globalTasks.Remove(hash); if (sessions.TryGetValue(Sender, out TaskSession session)) From 78e29d3671ee36990fe3e5c8affc2ae0eb622c77 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 27 Aug 2020 12:36:47 +0200 Subject: [PATCH 08/12] Reduce check Inventory type --- src/neo/Network/P2P/TaskManager.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index 0bb86baec3..3b2b74eba2 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -163,10 +163,13 @@ protected override void OnReceive(object message) OnPersistCompleted(pc.Block); break; case Blockchain.RelayResult rr: - if (rr.Inventory is Block invalidBlock && rr.Result == VerifyResult.Invalid) - OnInvalidBlock(invalidBlock); - else if (rr.Inventory is Block validBlock && rr.Result == VerifyResult.Succeed) - OnValidBlock(validBlock); + if (rr.Inventory is Block b) + { + if (rr.Result == VerifyResult.Invalid) + OnInvalidBlock(b); + else if (rr.Result == VerifyResult.Succeed) + OnValidBlock(b); + } break; case Timer _: OnTimer(); From 04fa0116c0c093b4794078616ab2f2689225807a Mon Sep 17 00:00:00 2001 From: Shawn Date: Thu, 27 Aug 2020 18:37:48 +0800 Subject: [PATCH 09/12] del max tasks per node --- src/neo/Network/P2P/TaskManager.cs | 8 -------- src/neo/Network/P2P/TaskSession.cs | 1 - 2 files changed, 9 deletions(-) diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index 2bc1570653..06235e6cec 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -98,12 +98,6 @@ private void OnInvalidBlock(Block invalidBlock) } } - private void OnValidBlock(Block validBlock) - { - if (receivedBlockIndex.TryGetValue(validBlock.Index, out TaskSession session) && session.MaxTaskCountPerNode < 50) - session.MaxTaskCountPerNode++; - } - private void OnNewTasks(InvPayload payload) { if (!sessions.TryGetValue(Sender, out TaskSession session)) @@ -161,8 +155,6 @@ protected override void OnReceive(object message) case Blockchain.RelayResult rr: if (rr.Inventory is Block invalidBlock && rr.Result == VerifyResult.Invalid) OnInvalidBlock(invalidBlock); - else if (rr.Inventory is Block validBlock && rr.Result == VerifyResult.Succeed) - OnValidBlock(validBlock); break; case Timer _: OnTimer(); diff --git a/src/neo/Network/P2P/TaskSession.cs b/src/neo/Network/P2P/TaskSession.cs index 560debbc82..cc315ea511 100644 --- a/src/neo/Network/P2P/TaskSession.cs +++ b/src/neo/Network/P2P/TaskSession.cs @@ -13,7 +13,6 @@ internal class TaskSession public bool IsFullNode { get; } public uint LastBlockIndex { get; set; } - public int MaxTaskCountPerNode = 1; public uint TimeoutTimes = 0; public DateTime ExpireTime = DateTime.MinValue; public double RTT = 100.0; From ad61739ef2a964b181ff0e9c26160341d9a22da1 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 27 Aug 2020 12:41:02 +0200 Subject: [PATCH 10/12] Change Date to UTC --- src/neo/Network/P2P/Peer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo/Network/P2P/Peer.cs b/src/neo/Network/P2P/Peer.cs index 9e04385831..e0e32a5885 100644 --- a/src/neo/Network/P2P/Peer.cs +++ b/src/neo/Network/P2P/Peer.cs @@ -94,9 +94,9 @@ protected void AddPeers(IEnumerable peers) private void AddToBlacklist(IPEndPoint endPoint) { if (IPAddressBlacklist.ContainsKey(endPoint)) - IPAddressBlacklist[endPoint] = DateTime.Now; + IPAddressBlacklist[endPoint] = TimeProvider.Current.UtcNow; else - IPAddressBlacklist.TryAdd(endPoint, DateTime.Now); + IPAddressBlacklist.TryAdd(endPoint, TimeProvider.Current.UtcNow); } protected void ConnectToPeer(IPEndPoint endPoint, bool isTrusted = false) From ad305b20c6c48dfd82729101dccd4d4f9a601d2b Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 31 Aug 2020 17:37:59 +0800 Subject: [PATCH 11/12] add a limit to get Tx --- src/neo/Consensus/ConsensusService.cs | 1 + .../Network/P2P/RemoteNode.ProtocolHandler.cs | 15 ++++- src/neo/Network/P2P/RemoteNode.cs | 7 ++- src/neo/Network/P2P/TaskManager.cs | 56 ++++++++++++++++++- src/neo/Network/P2P/TaskSession.cs | 4 +- 5 files changed, 75 insertions(+), 8 deletions(-) diff --git a/src/neo/Consensus/ConsensusService.cs b/src/neo/Consensus/ConsensusService.cs index 8054147eb5..9e33202299 100644 --- a/src/neo/Consensus/ConsensusService.cs +++ b/src/neo/Consensus/ConsensusService.cs @@ -657,6 +657,7 @@ private void SendPrepareRequest() if (context.TransactionHashes.Length > 0) { + taskManager.Tell(new TaskManager.InvHashes { Hashes = context.TransactionHashes }); foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes)) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } diff --git a/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs b/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs index 416b7ce0a4..25c8fa24ac 100644 --- a/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs +++ b/src/neo/Network/P2P/RemoteNode.ProtocolHandler.cs @@ -209,13 +209,24 @@ private void OnGetBlockByIndexMessageReceived(GetBlockByIndexPayload payload) } } + private void OnGetDataMessageReceived(InvPayload payload) + { + if (payload.Type is InventoryType.TX) + { + system.TaskManager.Tell(new TaskManager.GetDataHashes { Hashes = payload.Hashes }); + return; + } + else + OnGetData(payload); + } + /// /// Will be triggered when a MessageCommand.GetData message is received. /// The payload includes an array of hash values. /// For different payload.Type (Tx, Block, Consensus), get the corresponding (Txs, Blocks, Consensus) and tell them to RemoteNode actor. /// /// The payload containing the requested information. - private void OnGetDataMessageReceived(InvPayload payload) + private void OnGetData(InvPayload payload) { var notFound = new List(); foreach (UInt256 hash in payload.Hashes.Where(p => sentHashes.Add(p))) @@ -370,7 +381,7 @@ private void OnVersionMessageReceived(VersionPayload payload) SendMessage(Message.Create(MessageCommand.Verack)); } - private void RefreshPendingKnownHashes() + private void OnTimer() { while (pendingKnownHashes.Count > 0) { diff --git a/src/neo/Network/P2P/RemoteNode.cs b/src/neo/Network/P2P/RemoteNode.cs index e72c522e1c..807781e89b 100644 --- a/src/neo/Network/P2P/RemoteNode.cs +++ b/src/neo/Network/P2P/RemoteNode.cs @@ -27,7 +27,7 @@ internal class Relay { public IInventory Inventory; } private bool ack = true; private int message_count = 0; private DateTime start_message_time; - private readonly double time_threshold = 10; + private readonly double time_threshold = 100; public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); public int ListenerTcpPort { get; private set; } = 0; @@ -139,7 +139,7 @@ protected override void OnReceive(object message) switch (message) { case Timer _: - RefreshPendingKnownHashes(); + OnTimer(); break; case Message msg: EnqueueMessage(msg); @@ -153,6 +153,9 @@ protected override void OnReceive(object message) case StartProtocol _: OnStartProtocol(); break; + case InvPayload payload: + OnGetData(payload); + break; } } diff --git a/src/neo/Network/P2P/TaskManager.cs b/src/neo/Network/P2P/TaskManager.cs index 12f4b0ab43..a73965d4b3 100644 --- a/src/neo/Network/P2P/TaskManager.cs +++ b/src/neo/Network/P2P/TaskManager.cs @@ -18,10 +18,14 @@ public class Register { public VersionPayload Version; } public class Update { public uint LastBlockIndex; public bool RequestTasks; } public class NewTasks { public InvPayload Payload; } public class RestartTasks { public InvPayload Payload; } + public class InvHashes { public UInt256[] Hashes; } + public class GetDataHashes { public UInt256[] Hashes; } private class Timer { } private static readonly TimeSpan TimerInterval = TimeSpan.FromSeconds(30); private static readonly TimeSpan TaskTimeout = TimeSpan.FromMinutes(1); + private static readonly TimeSpan InvHashTimeout = TimeSpan.FromMinutes(30); + private static readonly TimeSpan ReduceTimeoutRecord = TimeSpan.FromDays(1); private static readonly UInt256 MemPoolTaskHash = UInt256.Parse("0x0000000000000000000000000000000000000000000000000000000000000001"); private const int MaxConncurrentTasks = 3; @@ -33,6 +37,7 @@ private class Timer { } /// A set of known hashes, of inventories or payloads, already received. /// private readonly HashSetCache knownHashes; + private readonly Dictionary sentInvHashes = new Dictionary(); private readonly Dictionary globalTasks = new Dictionary(); private readonly Dictionary receivedBlockIndex = new Dictionary(); private readonly HashSet failedSyncTasks = new HashSet(); @@ -160,6 +165,12 @@ protected override void OnReceive(object message) if (rr.Inventory is Block invalidBlock && rr.Result == VerifyResult.Invalid) OnInvalidBlock(invalidBlock); break; + case InvHashes invHashes: + OnInvHashes(invHashes.Hashes); + break; + case GetDataHashes getDataHashes: + OnGetDataHashes(getDataHashes.Hashes); + break; case Timer _: OnTimer(); break; @@ -205,6 +216,33 @@ private void OnTaskCompleted(UInt256 hash) session.InvTasks.Remove(hash); } + private void OnInvHashes(UInt256[] hashes) + { + foreach (var hash in hashes) + { + if (sentInvHashes.ContainsKey(hash)) + sentInvHashes[hash] = TimeProvider.Current.UtcNow; + else + sentInvHashes.TryAdd(hash, TimeProvider.Current.UtcNow); + } + } + + private void OnGetDataHashes(UInt256[] hashes) + { + var invalidHashesCount = 0; + + foreach (var hash in hashes) + { + if (!sentInvHashes.ContainsKey(hash)) + invalidHashesCount++; + } + + if (invalidHashesCount < 3) + Sender.Tell(InvPayload.Create(InventoryType.TX, hashes)); + else + system.LocalNode.Tell(new LocalNode.MaliciousNode { actor = Sender }); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private void DecrementGlobalTask(UInt256 hash) { @@ -253,7 +291,8 @@ private void OnTimer() if (TimeProvider.Current.UtcNow - kvp.Value > TaskTimeout) { session.IndexTasks.Remove(kvp.Key); - if (++session.TimeoutTimes > 3) + session.TimeoutRecord.Add(TimeProvider.Current.UtcNow); + if (session.TimeoutRecord.Count > 3) OnTerminated(sessions.Where(p => p.Value == session).First().Key); else { @@ -265,13 +304,26 @@ private void OnTimer() foreach (var task in session.InvTasks.ToArray()) { - if (DateTime.UtcNow - task.Value > TaskTimeout) + if (TimeProvider.Current.UtcNow - task.Value > TaskTimeout) { if (session.InvTasks.Remove(task.Key)) DecrementGlobalTask(task.Key); } } + + for (var i = session.TimeoutRecord.Count; i > 0; i--) + { + if (TimeProvider.Current.UtcNow - session.TimeoutRecord[i] > ReduceTimeoutRecord) + session.TimeoutRecord.RemoveAt(i); + } } + + foreach (var hash in sentInvHashes) + { + if (TimeProvider.Current.UtcNow - hash.Value > InvHashTimeout) + sentInvHashes.Remove(hash.Key); + } + RequestTasks(); } diff --git a/src/neo/Network/P2P/TaskSession.cs b/src/neo/Network/P2P/TaskSession.cs index cc315ea511..2ebe153903 100644 --- a/src/neo/Network/P2P/TaskSession.cs +++ b/src/neo/Network/P2P/TaskSession.cs @@ -10,10 +10,10 @@ internal class TaskSession { public readonly Dictionary InvTasks = new Dictionary(); public readonly Dictionary IndexTasks = new Dictionary(); + public List TimeoutRecord = new List(); public bool IsFullNode { get; } public uint LastBlockIndex { get; set; } - public uint TimeoutTimes = 0; public DateTime ExpireTime = DateTime.MinValue; public double RTT = 100.0; public double Weight = 1000.0; @@ -25,7 +25,7 @@ public void UpdateRTT(double newRTT) public void UpdateWeight() { - Weight = RTT * (1.0 / Math.Pow(2, TimeoutTimes)) * (IndexTasks.Count); + Weight = RTT * (1.0 / Math.Pow(2, TimeoutRecord.Count)) * (IndexTasks.Count); } public TaskSession(VersionPayload version) From d26dc47651237ac728be8790e636605e8796629c Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 31 Aug 2020 17:45:14 +0800 Subject: [PATCH 12/12] fix UT --- tests/neo.UnitTests/Network/P2P/UT_TaskSession.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/neo.UnitTests/Network/P2P/UT_TaskSession.cs b/tests/neo.UnitTests/Network/P2P/UT_TaskSession.cs index 6afb2fa368..b01c6d36de 100644 --- a/tests/neo.UnitTests/Network/P2P/UT_TaskSession.cs +++ b/tests/neo.UnitTests/Network/P2P/UT_TaskSession.cs @@ -21,7 +21,7 @@ public void CreateTest() Assert.AreEqual((uint)123, ses.LastBlockIndex); Assert.AreEqual(0, ses.IndexTasks.Count); Assert.AreEqual(0, ses.InvTasks.Count); - Assert.AreEqual((uint)0, ses.TimeoutTimes); + Assert.AreEqual((int)0, ses.TimeoutRecord.Count); ses = new TaskSession(new VersionPayload() { Capabilities = new NodeCapability[0] }); @@ -29,7 +29,7 @@ public void CreateTest() Assert.AreEqual((uint)0, ses.LastBlockIndex); Assert.AreEqual(0, ses.IndexTasks.Count); Assert.AreEqual(0, ses.InvTasks.Count); - Assert.AreEqual((uint)0, ses.TimeoutTimes); + Assert.AreEqual((int)0, ses.TimeoutRecord.Count); } } }