diff --git a/src/Neo/Network/P2P/Capabilities/UnknownCapability.cs b/src/Neo/Network/P2P/Capabilities/UnknownCapability.cs index 4447166abe..537c7d15bc 100644 --- a/src/Neo/Network/P2P/Capabilities/UnknownCapability.cs +++ b/src/Neo/Network/P2P/Capabilities/UnknownCapability.cs @@ -48,7 +48,7 @@ protected override void DeserializeWithoutType(ref MemoryReader reader) protected override void SerializeWithoutType(BinaryWriter writer) { - throw new InvalidOperationException("Unknown capability can't be serialized"); + writer.WriteVarBytes(Data.Span); } } } diff --git a/src/Neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/src/Neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index 0b7e0acc37..6b51f2e033 100644 --- a/src/Neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/src/Neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -75,7 +75,10 @@ void ISerializable.Deserialize(ref MemoryReader reader) Capabilities = new NodeCapability[reader.ReadVarInt(VersionPayload.MaxCapabilities)]; for (int x = 0, max = Capabilities.Length; x < max; x++) Capabilities[x] = NodeCapability.DeserializeFrom(ref reader); - if (Capabilities.Select(p => p.Type).Distinct().Count() != Capabilities.Length) + // Verify that no duplicating capabilities are included. Unknown capabilities are not + // taken into account but still preserved to be able to share through the network. + var capabilities = Capabilities.Where(c => c is not UnknownCapability); + if (capabilities.Select(p => p.Type).Distinct().Count() != capabilities.Count()) throw new FormatException(); } diff --git a/src/Neo/Network/P2P/Payloads/VersionPayload.cs b/src/Neo/Network/P2P/Payloads/VersionPayload.cs index 29e9bec994..3a585a6af6 100644 --- a/src/Neo/Network/P2P/Payloads/VersionPayload.cs +++ b/src/Neo/Network/P2P/Payloads/VersionPayload.cs @@ -99,8 +99,8 @@ void ISerializable.Deserialize(ref MemoryReader reader) Capabilities = new NodeCapability[reader.ReadVarInt(MaxCapabilities)]; for (int x = 0, max = Capabilities.Length; x < max; x++) Capabilities[x] = NodeCapability.DeserializeFrom(ref reader); - Capabilities = Capabilities.Where(c => c is not UnknownCapability).ToArray(); - if (Capabilities.Select(p => p.Type).Distinct().Count() != Capabilities.Length) + var capabilities = Capabilities.Where(c => c is not UnknownCapability); + if (capabilities.Select(p => p.Type).Distinct().Count() != capabilities.Count()) throw new FormatException(); } diff --git a/tests/Neo.UnitTests/Network/P2P/Capabilities/UT_UnknownCapability.cs b/tests/Neo.UnitTests/Network/P2P/Capabilities/UT_UnknownCapability.cs index a228c00782..7579229f37 100644 --- a/tests/Neo.UnitTests/Network/P2P/Capabilities/UT_UnknownCapability.cs +++ b/tests/Neo.UnitTests/Network/P2P/Capabilities/UT_UnknownCapability.cs @@ -30,7 +30,7 @@ public void DeserializeUnknown() var capab = (NodeCapability)NodeCapability.DeserializeFrom(ref br); Assert.IsTrue(capab is UnknownCapability); - Assert.ThrowsException(() => capab.ToArray()); + CollectionAssert.AreEqual(buffer, capab.ToArray()); } } } diff --git a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_NetworkAddressWithTime.cs b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_NetworkAddressWithTime.cs index 3e2c6c336c..e3196adf7a 100644 --- a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_NetworkAddressWithTime.cs +++ b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_NetworkAddressWithTime.cs @@ -10,6 +10,7 @@ // modifications are permitted. using FluentAssertions; +using FluentAssertions.Equivalency; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Extensions; using Neo.IO; @@ -40,7 +41,7 @@ public void SizeAndEndPoint_Get() [TestMethod] public void DeserializeAndSerialize() { - var test = NetworkAddressWithTime.Create(IPAddress.Any, 1, new NodeCapability[] { new ServerCapability(NodeCapabilityType.TcpServer, 22) }); + var test = NetworkAddressWithTime.Create(IPAddress.Any, 1, new NodeCapability[] { new ServerCapability(NodeCapabilityType.TcpServer, 22), new UnknownCapability(NodeCapabilityType.Extension0), new UnknownCapability(NodeCapabilityType.Extension0) }); var clone = test.ToArray().AsSerializable(); CollectionAssert.AreEqual(test.Capabilities.ToByteArray(), clone.Capabilities.ToByteArray()); diff --git a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_VersionPayload.cs b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_VersionPayload.cs index 551654d04b..fe23ae6a76 100644 --- a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_VersionPayload.cs +++ b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_VersionPayload.cs @@ -58,8 +58,8 @@ public void DeserializeAndSerialize() buf = buf.Concat(new byte[] { 0x10, 0x01, 0x00, 0x00, 0x00 }).ToArray(); // FullNode capability, 0x01 index. clone = buf.AsSerializable(); - Assert.AreEqual(2, clone.Capabilities.Length); - Assert.AreEqual(0, clone.Capabilities.OfType().Count()); + Assert.AreEqual(4, clone.Capabilities.Length); + Assert.AreEqual(2, clone.Capabilities.OfType().Count()); } } }