diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/ReceiptDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/ReceiptDecoderTests.cs
index fee9591bd1b..96002756623 100644
--- a/src/Nethermind/Nethermind.Core.Test/Encoding/ReceiptDecoderTests.cs
+++ b/src/Nethermind/Nethermind.Core.Test/Encoding/ReceiptDecoderTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -33,7 +33,7 @@ public void Can_do_roundtrip_storage([Values(true, false)] bool encodeWithTxHash
TxReceipt GetExpected()
{
ReceiptBuilder receiptBuilder = Build.A.Receipt.WithAllFieldsFilled;
-
+
if ((encodeBehaviors & RlpBehaviors.Eip658Receipts) != 0)
{
receiptBuilder.WithState(null);
@@ -47,7 +47,7 @@ TxReceipt GetExpected()
{
receiptBuilder.WithTransactionHash(null);
}
-
+
if (!withError)
{
receiptBuilder.WithError(string.Empty);
@@ -71,7 +71,7 @@ TxReceipt BuildReceipt()
ReceiptStorageDecoder encoder = new(encodeWithTxHash);
Rlp rlp = encoder.Encode(txReceipt, encodeBehaviors);
-
+
ReceiptStorageDecoder decoder = new();
TxReceipt deserialized;
if (valueDecoder)
@@ -184,7 +184,7 @@ public void Can_do_roundtrip_none_rlp_stream()
AssertMessageReceipt(txReceipt, deserialized);
}
-
+
[Test]
public void Can_do_roundtrip_with_receipt_message_and_tx_type_access_list()
{
@@ -197,9 +197,9 @@ public void Can_do_roundtrip_with_receipt_message_and_tx_type_access_list()
ReceiptMessageDecoder decoder = new();
- byte[] rlpStreamResult = decoder.Encode(txReceipt).Bytes;
+ byte[] rlpStreamResult = decoder.EncodeNew(txReceipt, RlpBehaviors.None);
TxReceipt deserialized = decoder.Decode(new RlpStream(rlpStreamResult));
-
+
AssertMessageReceipt(txReceipt, deserialized);
}
@@ -227,7 +227,7 @@ public void Can_do_roundtrip_with_storage_receipt_and_tx_type_access_list()
AssertStorageReceipt(txReceipt, deserialized);
}
-
+
public static IEnumerable<(TxReceipt, string)> TestCaseSource()
{
Bloom bloom = new();
@@ -237,7 +237,7 @@ public void Can_do_roundtrip_with_storage_receipt_and_tx_type_access_list()
yield return (Build.A.Receipt.WithBloom(bloom).WithGasUsedTotal(500).WithState(TestItem.KeccakA).WithTxType(TxType.AccessList).TestObject, "access list");
yield return (Build.A.Receipt.WithBloom(bloom).WithGasUsedTotal(100).WithState(TestItem.KeccakH).WithTxType(TxType.EIP1559).TestObject, "eip 1559");
}
-
+
[TestCaseSource(nameof(TestCaseSource))]
public void Can_do_roundtrip_with_storage_receipt((TxReceipt TxReceipt, string Description) testCase)
{
@@ -249,7 +249,7 @@ public void Can_do_roundtrip_with_storage_receipt((TxReceipt TxReceipt, string D
AssertStorageReceipt(txReceipt, deserialized);
}
-
+
[TestCaseSource(nameof(TestCaseSource))]
public void Can_do_roundtrip_with_receipt_message((TxReceipt TxReceipt, string Description) testCase)
{
@@ -257,12 +257,12 @@ public void Can_do_roundtrip_with_receipt_message((TxReceipt TxReceipt, string D
ReceiptMessageDecoder decoder = new();
- byte[] rlpStreamResult = decoder.Encode(txReceipt).Bytes;
+ byte[] rlpStreamResult = decoder.EncodeNew(txReceipt);
TxReceipt deserialized = decoder.Decode(new RlpStream(rlpStreamResult));
AssertMessageReceipt(txReceipt, deserialized);
}
-
+
private void AssertMessageReceipt(TxReceipt txReceipt, TxReceipt deserialized)
{
Assert.AreEqual(txReceipt.Bloom, deserialized.Bloom, "bloom");
diff --git a/src/Nethermind/Nethermind.Network.Benchmark/InFlowBenchmarks.cs b/src/Nethermind/Nethermind.Network.Benchmark/InFlowBenchmarks.cs
index 1f50704a04a..6c3311addbc 100644
--- a/src/Nethermind/Nethermind.Network.Benchmark/InFlowBenchmarks.cs
+++ b/src/Nethermind/Nethermind.Network.Benchmark/InFlowBenchmarks.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2018 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -53,7 +53,7 @@ public void Setup()
{
throw new Exception("decoder buffer");
}
-
+
SetupAll();
IterationSetup();
Current();
@@ -65,7 +65,7 @@ public void Setup()
SetupAll();
IterationSetup();
}
-
+
[IterationSetup]
public void IterationSetup()
{
@@ -149,7 +149,7 @@ public void Current()
IByteBuffer decoded = _zeroDecoder.Decode(_decoderBuffer);
IByteBuffer merged = _zeroMerger.Decode(decoded);
merged.ReadByte();
- _outputMessage = _newBlockMessageSerializer.Deserialize(merged.ReadAllBytes());
+ _outputMessage = _newBlockMessageSerializer.Deserialize(merged.ReadAllBytesAsArray());
}
}
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery.Test/DiscoveryMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Discovery.Test/DiscoveryMessageSerializerTests.cs
index 6c798ff5f22..4462ef06334 100644
--- a/src/Nethermind/Nethermind.Network.Discovery.Test/DiscoveryMessageSerializerTests.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery.Test/DiscoveryMessageSerializerTests.cs
@@ -1,20 +1,21 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System.Net;
+using DotNetty.Buffers;
using Nethermind.Core;
using Nethermind.Core.Extensions;
using Nethermind.Core.Test.Builders;
@@ -58,7 +59,7 @@ public void PingMessageTest()
new(_privateKey.PublicKey, 60 + _timestamper.UnixTime.MillisecondsLong, _farAddress, _nearAddress,
new byte[32]) { FarAddress = _farAddress };
- byte[] data = _messageSerializationService.Serialize(message);
+ IByteBuffer data = _messageSerializationService.ZeroSerialize(message);
PingMsg deserializedMessage = _messageSerializationService.Deserialize(data);
Assert.AreEqual(message.MsgType, deserializedMessage.MsgType);
@@ -84,7 +85,7 @@ public void PongMessageTest()
FarAddress = _farAddress
};
- byte[] data = _messageSerializationService.Serialize(message);
+ IByteBuffer data = _messageSerializationService.ZeroSerialize(message);
PongMsg deserializedMessage = _messageSerializationService.Deserialize(data);
Assert.AreEqual(message.MsgType, deserializedMessage.MsgType);
@@ -99,21 +100,21 @@ public void Ping_with_enr_there_and_back()
{
PingMsg pingMsg = new (TestItem.PublicKeyA, long.MaxValue, TestItem.IPEndPointA, TestItem.IPEndPointB, new byte[32]);
pingMsg.EnrSequence = 3;
- byte[] serialized = _messageSerializationService.Serialize(pingMsg);
+ IByteBuffer serialized = _messageSerializationService.ZeroSerialize(pingMsg);
pingMsg = _messageSerializationService.Deserialize(serialized);
Assert.AreEqual(3, pingMsg.EnrSequence);
}
-
+
[Test]
public void Enr_request_there_and_back()
{
EnrRequestMsg msg = new(TestItem.PublicKeyA, long.MaxValue);
- byte[] serialized = _messageSerializationService.Serialize(msg);
+ IByteBuffer serialized = _messageSerializationService.ZeroSerialize(msg);
EnrRequestMsg deserialized = _messageSerializationService.Deserialize(serialized);
Assert.AreEqual(msg.ExpirationTime, deserialized.ExpirationTime);
Assert.AreEqual(deserialized.FarPublicKey, _privateKey.PublicKey);
}
-
+
[Test]
public void Enr_response_there_and_back()
{
@@ -124,7 +125,7 @@ public void Enr_response_there_and_back()
signer.Sign(nodeRecord);
EnrResponseMsg msg = new(TestItem.PublicKeyA, nodeRecord, TestItem.KeccakA);
- byte[] serialized = _messageSerializationService.Serialize(msg);
+ IByteBuffer serialized = _messageSerializationService.ZeroSerialize(msg);
EnrResponseMsg deserialized = _messageSerializationService.Deserialize(serialized);
Assert.AreEqual(msg.NodeRecord.EnrSequence, deserialized.NodeRecord.EnrSequence);
Assert.AreEqual(msg.RequestKeccak, deserialized.RequestKeccak);
@@ -161,7 +162,7 @@ public void FindNodeMessageTest()
FarAddress = _farAddress
};
- byte[] data = _messageSerializationService.Serialize(message);
+ IByteBuffer data = _messageSerializationService.ZeroSerialize(message);
FindNodeMsg deserializedMessage = _messageSerializationService.Deserialize(data);
Assert.AreEqual(message.MsgType, deserializedMessage.MsgType);
@@ -186,7 +187,7 @@ public void NeighborsMessageTest()
FarAddress = _farAddress
};
- byte[] data = _messageSerializationService.Serialize(message);
+ byte[] data = _messageSerializationService.ZeroSerialize(message).ReadAllBytesAsArray();
NeighborsMsg deserializedMessage = _messageSerializationService.Deserialize(data);
Assert.AreEqual(message.MsgType, deserializedMessage.MsgType);
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Messages/INodeIdResolver.cs b/src/Nethermind/Nethermind.Network.Discovery/Messages/INodeIdResolver.cs
index 60b5e6d9669..5af8ae34030 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Messages/INodeIdResolver.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Messages/INodeIdResolver.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -20,5 +20,5 @@ namespace Nethermind.Network.Discovery.Messages;
public interface INodeIdResolver
{
- PublicKey GetNodeId(byte[] signature, int recoveryId, Span typeAndData);
+ PublicKey GetNodeId(ReadOnlySpan signature, int recoveryId, Span typeAndData);
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Messages/NodeIdResolver.cs b/src/Nethermind/Nethermind.Network.Discovery/Messages/NodeIdResolver.cs
index 0ae89d7974b..73335a2fabf 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Messages/NodeIdResolver.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Messages/NodeIdResolver.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -28,8 +28,8 @@ public NodeIdResolver(IEcdsa ecdsa)
_ecdsa = ecdsa;
}
- public PublicKey GetNodeId(byte[] signature, int recoveryId, Span typeAndData)
+ public PublicKey GetNodeId(ReadOnlySpan signature, int recoveryId, Span typeAndData)
{
- return _ecdsa.RecoverPublicKey(new Signature(signature, recoveryId), Keccak.Compute(typeAndData));
+ return _ecdsa.RecoverPublicKey(new Signature(signature, recoveryId), Keccak.Compute(typeAndData));
}
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryHandler.cs b/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryHandler.cs
index 9dc3a44bdaa..cc0e0e4ef65 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryHandler.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/NettyDiscoveryHandler.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -80,12 +80,11 @@ public override void ChannelReadComplete(IChannelHandlerContext context)
public async void SendMsg(DiscoveryMsg discoveryMsg)
{
- byte[] msgBytes;
-
+ IByteBuffer msgBuffer;
try
{
if (_logger.IsTrace) _logger.Trace($"Sending message: {discoveryMsg}");
- msgBytes = Serialize(discoveryMsg);
+ msgBuffer = Serialize(discoveryMsg, ByteBufferAllocator.UnpooledByteBufferAllocator);
}
catch (Exception e)
{
@@ -93,14 +92,13 @@ public async void SendMsg(DiscoveryMsg discoveryMsg)
return;
}
- if (msgBytes.Length > 1280)
+ if (msgBuffer.ReadableBytes > 1280)
{
if (_logger.IsWarn) _logger.Warn($"Attempting to send message larger than 1280 bytes. This is out of spec and may not work for all client. Msg: ${discoveryMsg}");
}
- IByteBuffer copiedBuffer = Unpooled.CopiedBuffer(msgBytes);
- IAddressedEnvelope packet = new DatagramPacket(copiedBuffer, discoveryMsg.FarAddress);
-
+ IAddressedEnvelope packet = new DatagramPacket(msgBuffer, discoveryMsg.FarAddress);
+
await _channel.WriteAndFlushAsync(packet).ContinueWith(t =>
{
if (t.IsFaulted)
@@ -109,7 +107,7 @@ await _channel.WriteAndFlushAsync(packet).ContinueWith(t =>
}
});
- Interlocked.Add(ref Metrics.DiscoveryBytesSent, msgBytes.Length);
+ Interlocked.Add(ref Metrics.DiscoveryBytesSent, msgBuffer.ReadableBytes);
}
protected override void ChannelRead0(IChannelHandlerContext ctx, DatagramPacket packet)
{
@@ -118,7 +116,7 @@ protected override void ChannelRead0(IChannelHandlerContext ctx, DatagramPacket
byte[] msgBytes = new byte[content.ReadableBytes];
content.ReadBytes(msgBytes);
-
+
Interlocked.Add(ref Metrics.DiscoveryBytesReceived, msgBytes.Length);
if (msgBytes.Length < 98)
@@ -179,16 +177,16 @@ private DiscoveryMsg Deserialize(MsgType type, byte[] msg)
};
}
- private byte[] Serialize(DiscoveryMsg msg)
+ private IByteBuffer Serialize(DiscoveryMsg msg, ByteBufferAllocator allocator)
{
return msg.MsgType switch
{
- MsgType.Ping => _msgSerializationService.Serialize((PingMsg) msg),
- MsgType.Pong => _msgSerializationService.Serialize((PongMsg) msg),
- MsgType.FindNode => _msgSerializationService.Serialize((FindNodeMsg) msg),
- MsgType.Neighbors => _msgSerializationService.Serialize((NeighborsMsg) msg),
- MsgType.EnrRequest => _msgSerializationService.Serialize((EnrRequestMsg) msg),
- MsgType.EnrResponse => _msgSerializationService.Serialize((EnrResponseMsg) msg),
+ MsgType.Ping => _msgSerializationService.ZeroSerialize((PingMsg)msg, allocator),
+ MsgType.Pong => _msgSerializationService.ZeroSerialize((PongMsg)msg, allocator),
+ MsgType.FindNode => _msgSerializationService.ZeroSerialize((FindNodeMsg)msg, allocator),
+ MsgType.Neighbors => _msgSerializationService.ZeroSerialize((NeighborsMsg)msg, allocator),
+ MsgType.EnrRequest => _msgSerializationService.ZeroSerialize((EnrRequestMsg)msg, allocator),
+ MsgType.EnrResponse => _msgSerializationService.ZeroSerialize((EnrResponseMsg)msg, allocator),
_ => throw new Exception($"Unsupported messageType: {msg.MsgType}")
};
}
@@ -202,7 +200,7 @@ private bool ValidateMsg(DiscoveryMsg msg, MsgType type, EndPoint address, IChan
if (_logger.IsDebug) _logger.Debug($"Received a discovery message that has expired {-timeToExpire} seconds ago, type: {type}, sender: {address}, message: {msg}");
return false;
}
-
+
if (msg.FarAddress == null)
{
if (NetworkDiagTracer.IsEnabled) NetworkDiagTracer.ReportIncomingMessage(msg.FarAddress, "HANDLER disc v4", $"{msg.MsgType.ToString()} has null far address");
@@ -226,18 +224,18 @@ private bool ValidateMsg(DiscoveryMsg msg, MsgType type, EndPoint address, IChan
return true;
}
-
+
private static void ReportMsgByType(DiscoveryMsg msg)
{
if (msg is PingMsg pingMsg)
{
- if(NetworkDiagTracer.IsEnabled) NetworkDiagTracer.ReportIncomingMessage(pingMsg.FarAddress, "HANDLER disc v4", $"PING {pingMsg.SourceAddress.Address} -> {pingMsg.DestinationAddress?.Address}");
+ if(NetworkDiagTracer.IsEnabled) NetworkDiagTracer.ReportIncomingMessage(pingMsg.FarAddress, "HANDLER disc v4", $"PING {pingMsg.SourceAddress.Address} -> {pingMsg.DestinationAddress?.Address}");
}
else
{
- if(NetworkDiagTracer.IsEnabled) NetworkDiagTracer.ReportIncomingMessage(msg.FarAddress, "HANDLER disc v4", msg.MsgType.ToString());
+ if(NetworkDiagTracer.IsEnabled) NetworkDiagTracer.ReportIncomingMessage(msg.FarAddress, "HANDLER disc v4", msg.MsgType.ToString());
}
}
-
+
public event EventHandler? OnChannelActivated;
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/DiscoveryMsgSerializerBase.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/DiscoveryMsgSerializerBase.cs
index 13ecd1356d0..6e582857599 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/DiscoveryMsgSerializerBase.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/DiscoveryMsgSerializerBase.cs
@@ -1,24 +1,26 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System.Net;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
using Nethermind.Crypto;
using Nethermind.Network.Discovery.Messages;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Discovery.Serializers;
@@ -39,68 +41,85 @@ protected DiscoveryMsgSerializerBase(IEcdsa ecdsa,
_nodeIdResolver = nodeIdResolver ?? throw new ArgumentNullException(nameof(nodeIdResolver));
}
- protected byte[] Serialize(byte type, Span data)
+ protected void Serialize(byte type, Span data, IByteBuffer byteBuffer)
{
- byte[] result = new byte[32 + 1 + data.Length + 64 + 1];
- Span resultSpan = result.AsSpan();
+ int length = 32 + 1 + data.Length + 64 + 1;
+ byteBuffer.EnsureWritable(length);
+ Span resultSpan = stackalloc byte[length];
resultSpan[32 + 65] = type;
data.CopyTo(resultSpan.Slice(32 + 65 + 1, data.Length));
-
+
Span payload = resultSpan.Slice(32 + 65);
Keccak toSign = Keccak.Compute(payload);
Signature signature = _ecdsa.Sign(_privateKey, toSign);
signature.Bytes.AsSpan().CopyTo(resultSpan.Slice(32, 64));
resultSpan[32 + 64] = signature.RecoveryId;
-
+
Span forMdc = resultSpan.Slice(32);
ValueKeccak mdc = ValueKeccak.Compute(forMdc);
mdc.BytesAsSpan.CopyTo(resultSpan.Slice(0,32));
- return result;
+ byteBuffer.EnsureWritable(resultSpan.Length);
+ byteBuffer.WriteBytes(resultSpan);
}
- protected (PublicKey FarPublicKey, byte[] Mdc, byte[] Data) PrepareForDeserialization(byte[] msg)
+ protected (PublicKey FarPublicKey, Memory Mdc, IByteBuffer Data) PrepareForDeserialization(IByteBuffer msg)
{
- if (msg.Length < 98)
+ if (msg.ReadableBytes < 98)
{
throw new NetworkingException("Incorrect message", NetworkExceptionType.Validation);
}
-
- byte[] mdc = msg.Slice(0, 32);
- Span signature = msg.AsSpan(32, 65);
- // var type = new[] { msg[97] };
- byte[] data = msg.Slice(98, msg.Length - 98);
- Span computedMdc = ValueKeccak.Compute(msg.AsSpan(32)).BytesAsSpan;
-
- if (!Bytes.AreEqual(mdc, computedMdc))
+ IByteBuffer data = msg.Slice(98, msg.ReadableBytes - 98);
+ Memory msgBytes = msg.ReadAllBytesAsMemory();
+ Memory mdc = msgBytes.Slice(0, 32);
+ Span sigAndData = msgBytes.Span.Slice(32);
+ Span computedMdc = ValueKeccak.Compute(sigAndData).BytesAsSpan;
+
+ if (!Bytes.AreEqual(mdc.Span, computedMdc))
{
throw new NetworkingException("Invalid MDC", NetworkExceptionType.Validation);
}
-
- PublicKey nodeId = _nodeIdResolver.GetNodeId(signature.Slice(0, 64).ToArray(), signature[64], msg.AsSpan(97, msg.Length - 97));
+
+ PublicKey nodeId = _nodeIdResolver.GetNodeId(sigAndData.Slice(0, 64), sigAndData[64], sigAndData.Slice(65, sigAndData.Length - 65));
return (nodeId, mdc, data);
}
- protected static Rlp Encode(IPEndPoint address)
+ protected static void Encode(RlpStream stream, IPEndPoint address, int length)
+ {
+ stream.StartSequence(length);
+ stream.Encode(address.Address.GetAddressBytes());
+ //tcp port
+ stream.Encode(address.Port);
+ //udp port
+ stream.Encode(address.Port);
+ }
+
+ protected static int GetIPEndPointLength(IPEndPoint address)
+ {
+ int length = Rlp.LengthOf(address.Address.GetAddressBytes());
+ length += Rlp.LengthOf(address.Port);
+ length += Rlp.LengthOf(address.Port);
+ return length;
+ }
+
+ protected static void SerializeNode(RlpStream stream, IPEndPoint address, byte[] id)
{
- return Rlp.Encode(
- Rlp.Encode(address.Address.GetAddressBytes()),
- //tcp port
- Rlp.Encode(address.Port),
- //udp port
- Rlp.Encode(address.Port)
- );
+ int length = GetLengthSerializeNode(address, id);
+ stream.StartSequence(length);
+ stream.Encode(address.Address.GetAddressBytes());
+ //tcp port
+ stream.Encode(address.Port);
+ //udp port
+ stream.Encode(address.Port);
+ stream.Encode(id);
}
- protected static Rlp SerializeNode(IPEndPoint address, byte[] id)
+ protected static int GetLengthSerializeNode(IPEndPoint address, byte[] id)
{
- return Rlp.Encode(
- Rlp.Encode(address.Address.GetAddressBytes()),
- //tcp port
- Rlp.Encode(address.Port),
- //udp port
- Rlp.Encode(address.Port),
- Rlp.Encode(id)
- );
+ int length = Rlp.LengthOf(address.Address.GetAddressBytes());
+ length += Rlp.LengthOf(address.Port);
+ length += Rlp.LengthOf(address.Port);
+ length += Rlp.LengthOf(id);
+ return length;
}
protected static IPEndPoint GetAddress(ReadOnlySpan ip, int port)
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrRequestMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrRequestMsgSerializer.cs
index 0c579bfa217..8547d55c13b 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrRequestMsgSerializer.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrRequestMsgSerializer.cs
@@ -1,46 +1,55 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using System.Buffers;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Crypto;
using Nethermind.Network.Discovery.Messages;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Discovery.Serializers;
-public class EnrRequestMsgSerializer : DiscoveryMsgSerializerBase, IMessageSerializer
+public class EnrRequestMsgSerializer : DiscoveryMsgSerializerBase, IZeroInnerMessageSerializer
{
public EnrRequestMsgSerializer(IEcdsa ecdsa, IPrivateKeyGenerator nodeKey, INodeIdResolver nodeIdResolver)
: base(ecdsa, nodeKey, nodeIdResolver) { }
- public byte[] Serialize(EnrRequestMsg msg)
+ public void Serialize(IByteBuffer byteBuffer, EnrRequestMsg msg)
{
- // TODO: optimize
- byte[] data = Rlp.Encode(
- Rlp.Encode(msg.ExpirationTime)
- ).Bytes;
-
- byte[] serializedMsg = Serialize((byte) msg.MsgType, data);
- return serializedMsg;
+ int length = GetLength(msg, out int contentLength);
+ byte[] array = ArrayPool.Shared.Rent(length);
+ try
+ {
+ RlpStream stream = new(array);
+ stream.StartSequence(contentLength);
+ stream.Encode(msg.ExpirationTime);
+ Serialize((byte)msg.MsgType, stream.Data.AsSpan(0, length), byteBuffer);
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(array);
+ }
}
- public EnrRequestMsg Deserialize(byte[] msgBytes)
+ public EnrRequestMsg Deserialize(IByteBuffer msgBytes)
{
- (PublicKey FarPublicKey, byte[] Mdc, byte[] Data) results = PrepareForDeserialization(msgBytes);
- RlpStream rlpStream = results.Data.AsRlpStream();
+ (PublicKey FarPublicKey, Memory Mdc, IByteBuffer Data) results = PrepareForDeserialization(msgBytes);
+ NettyRlpStream rlpStream = new(results.Data);
rlpStream.ReadSequenceLength();
long expirationTime = rlpStream.DecodeLong();
@@ -48,4 +57,10 @@ public EnrRequestMsg Deserialize(byte[] msgBytes)
EnrRequestMsg msg = new (results.FarPublicKey, expirationTime);
return msg;
}
+
+ public int GetLength(EnrRequestMsg message, out int contentLength)
+ {
+ contentLength = Rlp.LengthOf(message.ExpirationTime);
+ return Rlp.LengthOfSequence(contentLength);
+ }
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrResponseMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrResponseMsgSerializer.cs
index afde35c125a..48284856cc8 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrResponseMsgSerializer.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/EnrResponseMsgSerializer.cs
@@ -1,29 +1,32 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using System.Buffers;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
using Nethermind.Crypto;
using Nethermind.Network.Discovery.Messages;
using Nethermind.Network.Enr;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Discovery.Serializers;
-public class EnrResponseMsgSerializer : DiscoveryMsgSerializerBase, IMessageSerializer
+public class EnrResponseMsgSerializer : DiscoveryMsgSerializerBase, IZeroInnerMessageSerializer
{
private readonly NodeRecordSigner _nodeRecordSigner;
@@ -33,25 +36,31 @@ public EnrResponseMsgSerializer(IEcdsa ecdsa, IPrivateKeyGenerator nodeKey, INod
_nodeRecordSigner = new NodeRecordSigner(ecdsa, nodeKey.Generate());
}
- public byte[] Serialize(EnrResponseMsg msg)
+ public void Serialize(IByteBuffer byteBuffer, EnrResponseMsg msg)
{
int contentLength = Rlp.LengthOfKeccakRlp;
contentLength += msg.NodeRecord.GetRlpLengthWithSignature();
int totalLength = Rlp.LengthOfSequence(contentLength);
- RlpStream rlpStream = new (totalLength);
- rlpStream.StartSequence(contentLength);
- rlpStream.Encode(msg.RequestKeccak);
- msg.NodeRecord.Encode(rlpStream);
-
- byte[] serializedMsg = Serialize((byte)msg.MsgType, rlpStream.Data);
- return serializedMsg;
+ byte[] array = ArrayPool.Shared.Rent(totalLength);
+ try
+ {
+ RlpStream rlpStream = new(array);
+ rlpStream.StartSequence(contentLength);
+ rlpStream.Encode(msg.RequestKeccak);
+ msg.NodeRecord.Encode(rlpStream);
+ Serialize((byte)msg.MsgType, rlpStream.Data.AsSpan(0, totalLength), byteBuffer);
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(array);
+ }
}
- public EnrResponseMsg Deserialize(byte[] msgBytes)
+ public EnrResponseMsg Deserialize(IByteBuffer msgBytes)
{
- (PublicKey? farPublicKey, _, byte[]? data) = PrepareForDeserialization(msgBytes);
- RlpStream rlpStream = data.AsRlpStream();
+ (PublicKey? farPublicKey, _, IByteBuffer? data) = PrepareForDeserialization(msgBytes);
+ NettyRlpStream rlpStream = new(data);
rlpStream.ReadSequenceLength();
Keccak? requestKeccak = rlpStream.DecodeKeccak(); // skip (not sure if needed to verify)
@@ -59,11 +68,18 @@ public EnrResponseMsg Deserialize(byte[] msgBytes)
NodeRecord nodeRecord = _nodeRecordSigner.Deserialize(rlpStream);
if (!_nodeRecordSigner.Verify(nodeRecord))
{
- string resHex = data.Slice(positionForHex).ToHexString();
+ string resHex = data.ReadBytes(positionForHex).ReadAllHex();
throw new NetworkingException($"Invalid ENR signature: {resHex}", NetworkExceptionType.Discovery);
}
-
+
EnrResponseMsg msg = new(farPublicKey, nodeRecord, requestKeccak!);
return msg;
}
+
+ public int GetLength(EnrResponseMsg msg, out int contentLength)
+ {
+ contentLength = Rlp.LengthOfKeccakRlp;
+ contentLength += msg.NodeRecord.GetRlpLengthWithSignature();
+ return Rlp.LengthOfSequence(contentLength);
+ }
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/FindNodeMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/FindNodeMsgSerializer.cs
index e2cbca0bf09..edc6bef1687 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/FindNodeMsgSerializer.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/FindNodeMsgSerializer.cs
@@ -1,48 +1,56 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using System.Buffers;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Crypto;
using Nethermind.Network.Discovery.Messages;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Discovery.Serializers;
-public class FindNodeMsgSerializer : DiscoveryMsgSerializerBase, IMessageSerializer
+public class FindNodeMsgSerializer : DiscoveryMsgSerializerBase, IZeroInnerMessageSerializer
{
public FindNodeMsgSerializer(IEcdsa ecdsa, IPrivateKeyGenerator nodeKey, INodeIdResolver nodeIdResolver)
: base(ecdsa, nodeKey, nodeIdResolver) { }
- public byte[] Serialize(FindNodeMsg msg)
+ public void Serialize(IByteBuffer byteBuffer, FindNodeMsg msg)
{
- byte[] data = Rlp.Encode(
- Rlp.Encode(msg.SearchedNodeId),
- //verify if encoding is correct
- Rlp.Encode(msg.ExpirationTime)
- ).Bytes;
-
- byte[] serializedMsg = Serialize((byte) msg.MsgType, data);
- return serializedMsg;
+ int length = GetLength(msg, out int contentLength);
+ byte[] array = ArrayPool.Shared.Rent(length);
+ try
+ {
+ RlpStream stream = new(array);
+ stream.StartSequence(contentLength);
+ stream.Encode(msg.SearchedNodeId);
+ stream.Encode(msg.ExpirationTime);
+ Serialize((byte)msg.MsgType, stream.Data.AsSpan(0, length), byteBuffer);
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(array);
+ }
}
- public FindNodeMsg Deserialize(byte[] msgBytes)
+ public FindNodeMsg Deserialize(IByteBuffer msgBytes)
{
- (PublicKey FarPublicKey, byte[] Mdc, byte[] Data) results = PrepareForDeserialization(msgBytes);
- RlpStream rlpStream = results.Data.AsRlpStream();
-
+ (PublicKey FarPublicKey, Memory Mdc, IByteBuffer Data) results = PrepareForDeserialization(msgBytes);
+ NettyRlpStream rlpStream = new(results.Data);
rlpStream.ReadSequenceLength();
byte[] searchedNodeId = rlpStream.DecodeByteArray();
long expirationTime = rlpStream.DecodeLong();
@@ -50,4 +58,12 @@ public FindNodeMsg Deserialize(byte[] msgBytes)
FindNodeMsg findNodeMsg = new (results.FarPublicKey, expirationTime, searchedNodeId);
return findNodeMsg;
}
+
+ public int GetLength(FindNodeMsg msg, out int contentLength)
+ {
+ contentLength = Rlp.LengthOf(msg.SearchedNodeId);
+ contentLength += Rlp.LengthOf(msg.ExpirationTime);
+
+ return Rlp.LengthOfSequence(contentLength);
+ }
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/NeighborsMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/NeighborsMsgSerializer.cs
index 7787a9990ac..557487e5862 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/NeighborsMsgSerializer.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/NeighborsMsgSerializer.cs
@@ -1,29 +1,32 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using System.Buffers;
using System.Net;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Crypto;
using Nethermind.Network.Discovery.Messages;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
using Nethermind.Stats.Model;
namespace Nethermind.Network.Discovery.Serializers;
-public class NeighborsMsgSerializer : DiscoveryMsgSerializerBase, IMessageSerializer
+public class NeighborsMsgSerializer : DiscoveryMsgSerializerBase, IZeroInnerMessageSerializer
{
public NeighborsMsgSerializer(IEcdsa ecdsa,
IPrivateKeyGenerator nodeKey,
@@ -31,34 +34,44 @@ public NeighborsMsgSerializer(IEcdsa ecdsa,
{
}
- public byte[] Serialize(NeighborsMsg msg)
+ public void Serialize(IByteBuffer byteBuffer, NeighborsMsg msg)
{
- Rlp[]? nodes = null;
- if (msg.Nodes.Any())
+ (int totalLength, int contentLength, int nodesContentLength) = GetLength(msg);
+
+ byte[] array = ArrayPool.Shared.Rent(totalLength);
+ try
{
- nodes = new Rlp[msg.Nodes.Length];
- for (int i = 0; i < msg.Nodes.Length; i++)
+ RlpStream stream = new(array);
+ stream.StartSequence(contentLength);
+ if (msg.Nodes.Any())
{
- Node node = msg.Nodes[i];
- Rlp serializedNode = SerializeNode(node.Address, node.Id.Bytes);
- nodes[i] = serializedNode;
+ stream.StartSequence(nodesContentLength);
+ for (int i = 0; i < msg.Nodes.Length; i++)
+ {
+ Node node = msg.Nodes[i];
+ SerializeNode(stream, node.Address, node.Id.Bytes);
+ }
+ }
+ else
+ {
+ stream.Encode(Rlp.OfEmptySequence);
}
- }
- byte[] data = Rlp.Encode(
- nodes == null ? Rlp.OfEmptySequence : Rlp.Encode(nodes),
- Rlp.Encode(msg.ExpirationTime)
- ).Bytes;
+ stream.Encode(msg.ExpirationTime);
- byte[] serializedMsg = Serialize((byte) msg.MsgType, data);
- return serializedMsg;
+ Serialize((byte)msg.MsgType, stream.Data.AsSpan(0, totalLength), byteBuffer);
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(array);
+ }
}
- public NeighborsMsg Deserialize(byte[] msgBytes)
+ public NeighborsMsg Deserialize(IByteBuffer msgBytes)
{
- (PublicKey FarPublicKey, byte[] Mdc, byte[] Data) results = PrepareForDeserialization(msgBytes);
+ (PublicKey FarPublicKey, Memory Mdc, IByteBuffer Data) results = PrepareForDeserialization(msgBytes);
- RlpStream rlp = results.Data.AsRlpStream();
+ NettyRlpStream rlp = new(results.Data);
rlp.ReadSequenceLength();
Node[] nodes = DeserializeNodes(rlp) as Node[];
@@ -85,4 +98,39 @@ public NeighborsMsg Deserialize(byte[] msgBytes)
return new Node(new PublicKey(id), address);
});
}
+
+ private int GetNodesLength(Node[] nodes, out int contentLength)
+ {
+ contentLength = 0;
+ for (int i = 0; i < nodes.Length; i++)
+ {
+ Node node = nodes[i];
+ contentLength += Rlp.LengthOfSequence(GetLengthSerializeNode(node.Address, node.Id.Bytes));
+ }
+ return Rlp.LengthOfSequence(contentLength);
+ }
+
+ public int GetLength(NeighborsMsg msg, out int contentLength)
+ {
+ (int totalLength, contentLength, int _) = GetLength(msg);
+ return totalLength;
+ }
+
+ private (int totalLength, int contentLength, int nodesContentLength) GetLength(NeighborsMsg msg)
+ {
+ int nodesContentLength = 0;
+ int contentLength = 0;
+ if (msg.Nodes.Any())
+ {
+ contentLength += GetNodesLength(msg.Nodes, out nodesContentLength);
+ }
+ else
+ {
+ contentLength += Rlp.OfEmptySequence.Bytes.Length;
+ }
+
+ contentLength += Rlp.LengthOf(msg.ExpirationTime);
+
+ return (Rlp.LengthOfSequence(contentLength), contentLength, nodesContentLength);
+ }
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/PingMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/PingMsgSerializer.cs
index 2f327be7ae5..7471a22b60e 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/PingMsgSerializer.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/PingMsgSerializer.cs
@@ -1,82 +1,85 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using System.Buffers;
using System.Net;
+using DotNetty.Buffers;
using DotNetty.Common.Utilities;
using Nethermind.Core.Crypto;
using Nethermind.Crypto;
using Nethermind.Network.Discovery.Messages;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Discovery.Serializers;
-public class PingMsgSerializer : DiscoveryMsgSerializerBase, IMessageSerializer
+public class PingMsgSerializer : DiscoveryMsgSerializerBase, IZeroInnerMessageSerializer
{
public PingMsgSerializer(IEcdsa ecdsa, IPrivateKeyGenerator nodeKey, INodeIdResolver nodeIdResolver)
: base(ecdsa, nodeKey, nodeIdResolver)
{
}
- public byte[] Serialize(PingMsg msg)
+ public void Serialize(IByteBuffer byteBuffer, PingMsg msg)
{
- byte typeByte = (byte)msg.MsgType;
- Rlp source = Encode(msg.SourceAddress);
- Rlp destination = Encode(msg.DestinationAddress);
+ (int totalLength, int contentLength, int sourceAddressLength, int destinationAddressLength) = GetLength(msg);
- byte[] data;
- if (msg.EnrSequence.HasValue)
+ byte[] array = ArrayPool.Shared.Rent(totalLength);
+ try
{
- data = Rlp.Encode(
- Rlp.Encode(msg.Version),
- source,
- destination,
- //verify if encoding is correct
- Rlp.Encode(msg.ExpirationTime),
- Rlp.Encode(msg.EnrSequence.Value)).Bytes;
+ RlpStream stream = new(array);
+
+ byte typeByte = (byte)msg.MsgType;
+
+ stream.StartSequence(contentLength);
+ stream.Encode(msg.Version);
+ Encode(stream, msg.SourceAddress, sourceAddressLength);
+ Encode(stream, msg.DestinationAddress, destinationAddressLength);
+ stream.Encode(msg.ExpirationTime);
+
+ if (msg.EnrSequence.HasValue)
+ {
+ stream.Encode(msg.EnrSequence.Value);
+ }
+
+ Serialize(typeByte, stream.Data.AsSpan(0, totalLength), byteBuffer);
+ byteBuffer.MarkReaderIndex();
+ msg.Mdc = byteBuffer.Slice(0, 32).ReadAllBytesAsArray();
+ byteBuffer.ResetReaderIndex();
}
- else
+ finally
{
- data = Rlp.Encode(
- Rlp.Encode(msg.Version),
- source,
- destination,
- //verify if encoding is correct
- Rlp.Encode(msg.ExpirationTime)).Bytes;
+ ArrayPool.Shared.Return(array);
}
-
- byte[] serializedMsg = Serialize(typeByte, data);
- msg.Mdc = serializedMsg.Slice(0, 32);
-
- return serializedMsg;
}
- public PingMsg Deserialize(byte[] msgBytes)
+ public PingMsg Deserialize(IByteBuffer msgBytes)
{
- (PublicKey FarPublicKey, byte[] Mdc, byte[] Data) results = PrepareForDeserialization(msgBytes);
- RlpStream rlp = results.Data.AsRlpStream();
+ (PublicKey FarPublicKey, Memory Mdc, IByteBuffer Data) results = PrepareForDeserialization(msgBytes);
+ NettyRlpStream rlp = new (results.Data);
rlp.ReadSequenceLength();
int version = rlp.DecodeInt();
rlp.ReadSequenceLength();
ReadOnlySpan sourceAddress = rlp.DecodeByteArraySpan();
-
+
// TODO: please note that we decode only one field for port and if the UDP is different from TCP then
// our discovery messages will not be routed correctly (the fix will not be part of this commit)
rlp.DecodeInt(); // UDP port
- int tcpPort = rlp.DecodeInt(); // we assume here that UDP and TCP port are same
+ int tcpPort = rlp.DecodeInt(); // we assume here that UDP and TCP port are same
IPEndPoint source = GetAddress(sourceAddress, tcpPort);
rlp.ReadSequenceLength();
@@ -85,9 +88,8 @@ public PingMsg Deserialize(byte[] msgBytes)
rlp.DecodeInt(); // UDP port
long expireTime = rlp.DecodeLong();
- PingMsg msg = new(results.FarPublicKey, expireTime, source, destination, results.Mdc);
-
- msg.Version = version;
+ PingMsg msg = new(results.FarPublicKey, expireTime, source, destination, results.Mdc.ToArray()) { Version = version };
+
if (version == 4)
{
if (!rlp.HasBeenRead)
@@ -103,4 +105,30 @@ public PingMsg Deserialize(byte[] msgBytes)
return msg;
}
+
+ public int GetLength(PingMsg msg, out int contentLength)
+ {
+ (int totalLength, contentLength, int _, int _) =
+ GetLength(msg);
+ return totalLength;
+ }
+
+
+ private (int totalLength, int contentLength, int sourceAddressLength, int destinationAddressLength) GetLength(PingMsg msg)
+ {
+ int sourceAddressLength = GetIPEndPointLength(msg.SourceAddress);
+ int destinationAddressLength = GetIPEndPointLength(msg.DestinationAddress);
+
+ int contentLength = Rlp.LengthOf(msg.Version)
+ + Rlp.LengthOfSequence(sourceAddressLength)
+ + Rlp.LengthOfSequence(destinationAddressLength)
+ + Rlp.LengthOf(msg.ExpirationTime);
+
+ if (msg.EnrSequence.HasValue)
+ {
+ contentLength += Rlp.LengthOf(msg.EnrSequence.Value);
+ }
+
+ return (Rlp.LengthOfSequence(contentLength), contentLength, sourceAddressLength, destinationAddressLength);
+ }
}
diff --git a/src/Nethermind/Nethermind.Network.Discovery/Serializers/PongMsgSerializer.cs b/src/Nethermind/Nethermind.Network.Discovery/Serializers/PongMsgSerializer.cs
index a2cb9150475..0e2960a687f 100644
--- a/src/Nethermind/Nethermind.Network.Discovery/Serializers/PongMsgSerializer.cs
+++ b/src/Nethermind/Nethermind.Network.Discovery/Serializers/PongMsgSerializer.cs
@@ -1,55 +1,67 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using System.Buffers;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Crypto;
using Nethermind.Network.Discovery.Messages;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Discovery.Serializers;
-public class PongMsgSerializer : DiscoveryMsgSerializerBase, IMessageSerializer
+public class PongMsgSerializer : DiscoveryMsgSerializerBase, IZeroInnerMessageSerializer
{
public PongMsgSerializer(IEcdsa ecdsa, IPrivateKeyGenerator nodeKey, INodeIdResolver nodeIdResolver) : base(ecdsa, nodeKey, nodeIdResolver)
{
}
- public byte[] Serialize(PongMsg msg)
+ public void Serialize(IByteBuffer byteBuffer, PongMsg msg)
{
if (msg.FarAddress is null)
{
- throw new NetworkingException($"Sending discovery message without {nameof(msg.FarAddress)} set.",
- NetworkExceptionType.Discovery);
+ throw new NetworkingException($"Sending discovery message without {nameof(msg.FarAddress)} set.", NetworkExceptionType.Discovery);
+ }
+
+ (int totalLength, int contentLength, int farAddressLength) = GetLength(msg);
+ byteBuffer.EnsureWritable(totalLength);
+
+ byte[] array = ArrayPool.Shared.Rent(totalLength);
+ try
+ {
+ RlpStream stream = new(array);
+ stream.StartSequence(contentLength);
+ Encode(stream, msg.FarAddress, farAddressLength);
+ stream.Encode(msg.PingMdc);
+ stream.Encode(msg.ExpirationTime);
+
+ Serialize((byte)msg.MsgType, stream.Data.AsSpan(0, totalLength), byteBuffer);
+ }
+ finally
+ {
+ ArrayPool.Shared.Return(array);
}
-
- byte[] data = Rlp.Encode(
- Encode(msg.FarAddress),
- Rlp.Encode(msg.PingMdc),
- Rlp.Encode(msg.ExpirationTime)
- ).Bytes;
-
- byte[] serializedMsg = Serialize((byte) msg.MsgType, data);
- return serializedMsg;
}
- public PongMsg Deserialize(byte[] msgBytes)
+ public PongMsg Deserialize(IByteBuffer msgBytes)
{
- (PublicKey FarPublicKey, byte[] Mdc, byte[] Data) results = PrepareForDeserialization(msgBytes);
+ (PublicKey FarPublicKey, Memory Mdc, IByteBuffer Data) results = PrepareForDeserialization(msgBytes);
- RlpStream rlp = results.Data.AsRlpStream();
+ NettyRlpStream rlp = new(results.Data);
rlp.ReadSequenceLength();
rlp.ReadSequenceLength();
@@ -64,4 +76,26 @@ public PongMsg Deserialize(byte[] msgBytes)
PongMsg msg = new(results.FarPublicKey, expirationTime, token);
return msg;
}
+
+ public int GetLength(PongMsg message, out int contentLength)
+ {
+ (int totalLength, contentLength, int _) = GetLength(message);
+ return totalLength;
+ }
+
+ private (int totalLength, int contentLength, int farAddressLength) GetLength(PongMsg message)
+ {
+ if (message.FarAddress is null)
+ {
+ throw new NetworkingException($"Sending discovery message without {nameof(message.FarAddress)} set.",
+ NetworkExceptionType.Discovery);
+ }
+
+ int farAddressLength = GetIPEndPointLength(message.FarAddress);
+ int contentLength = Rlp.LengthOfSequence(farAddressLength);
+ contentLength += Rlp.LengthOf(message.PingMdc);
+ contentLength += Rlp.LengthOf(message.ExpirationTime);
+
+ return (Rlp.LengthOfSequence(contentLength), contentLength, farAddressLength);
+ }
}
diff --git a/src/Nethermind/Nethermind.Network.Test/Builders/SerializationBuilder.cs b/src/Nethermind/Nethermind.Network.Test/Builders/SerializationBuilder.cs
index 9637cbc68da..1092135b411 100644
--- a/src/Nethermind/Nethermind.Network.Test/Builders/SerializationBuilder.cs
+++ b/src/Nethermind/Nethermind.Network.Test/Builders/SerializationBuilder.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -37,12 +37,6 @@ public SerializationBuilder(ITimestamper timestamper = null)
TestObject = new MessageSerializationService();
}
- public SerializationBuilder With(IMessageSerializer serializer) where T : MessageBase
- {
- TestObject.Register(serializer);
- return this;
- }
-
public SerializationBuilder With(IZeroMessageSerializer serializer) where T : MessageBase
{
TestObject.Register(serializer);
@@ -84,7 +78,7 @@ public SerializationBuilder WithEth65()
.With(new GetPooledTransactionsMessageSerializer())
.With(new PooledTransactionsMessageSerializer());
}
-
+
public SerializationBuilder WithEth66()
{
return WithEth65()
diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolHandlerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolHandlerTests.cs
index 3541691bb82..f7c62ff73b8 100644
--- a/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolHandlerTests.cs
+++ b/src/Nethermind/Nethermind.Network.Test/P2P/P2PProtocolHandlerTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -45,7 +45,7 @@ public void Setup()
private Packet CreatePacket(P2PMessage message)
{
- return new(message.Protocol, message.PacketType, _serializer.Serialize(message));
+ return new(message.Protocol, message.PacketType, _serializer.ZeroSerialize(message).ReadAllBytesAsArray());
}
private const int ListenPort = 8003;
@@ -59,7 +59,7 @@ private P2PProtocolHandler CreateSession()
return new P2PProtocolHandler(
_session,
TestItem.PublicKeyA,
- new NodeStatsManager(timerFactory, LimboLogs.Instance),
+ new NodeStatsManager(timerFactory, LimboLogs.Instance),
_serializer,
LimboLogs.Instance);
}
@@ -72,7 +72,7 @@ public void On_init_sends_a_hello_message()
_session.Received(1).DeliverMessage(Arg.Any());
}
-
+
[Test]
public void On_init_sends_a_hello_message_with_capabilities()
{
diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/PacketSenderTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/PacketSenderTests.cs
index c2e80917cd7..bcbf0bfeac1 100644
--- a/src/Nethermind/Nethermind.Network.Test/P2P/PacketSenderTests.cs
+++ b/src/Nethermind/Nethermind.Network.Test/P2P/PacketSenderTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -31,32 +31,32 @@ public class PacketSenderTests
[Test]
public void Does_send_on_active_channel()
{
- byte[] serialized = new byte[2];
+ IByteBuffer serialized = PooledByteBufferAllocator.Default.Buffer(2);
var serializer = Substitute.For();
- serializer.Serialize(PingMessage.Instance).Returns(serialized);
+ serializer.ZeroSerialize(PingMessage.Instance).Returns(serialized);
IChannelHandlerContext context = Substitute.For();
IChannel channel = Substitute.For();
channel.Active.Returns(true);
context.Channel.Returns(channel);
-
+
PacketSender packetSender = new(serializer, LimboLogs.Instance);
packetSender.HandlerAdded(context);
packetSender.Enqueue(PingMessage.Instance);
context.Received(1).WriteAndFlushAsync(Arg.Any());
}
-
+
[Test]
public void Does_not_try_to_send_on_inactive_channel()
{
- byte[] serialized = new byte[2];
+ IByteBuffer serialized = PooledByteBufferAllocator.Default.Buffer(2);
var serializer = Substitute.For();
- serializer.Serialize(PingMessage.Instance).Returns(serialized);
+ serializer.ZeroSerialize(PingMessage.Instance).Returns(serialized);
IChannelHandlerContext context = Substitute.For();
IChannel channel = Substitute.For();
channel.Active.Returns(false);
context.Channel.Returns(channel);
-
+
PacketSender packetSender = new(serializer ,LimboLogs.Instance);
packetSender.HandlerAdded(context);
packetSender.Enqueue(PingMessage.Instance);
diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/SerializerTester.cs b/src/Nethermind/Nethermind.Network.Test/P2P/SerializerTester.cs
index 91cdc191053..41578b0c9e3 100644
--- a/src/Nethermind/Nethermind.Network.Test/P2P/SerializerTester.cs
+++ b/src/Nethermind/Nethermind.Network.Test/P2P/SerializerTester.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -27,19 +27,6 @@ namespace Nethermind.Network.Test.P2P
{
public static class SerializerTester
{
- public static void Test(IMessageSerializer serializer, T message, string expectedData = null) where T : P2PMessage
- {
- byte[] serialized = serializer.Serialize(message);
- T deserialized = serializer.Deserialize(serialized);
- deserialized.Should().BeEquivalentTo(message);
- byte[] serializedAgain = serializer.Serialize(deserialized);
- Assert.AreEqual(serialized.ToHexString(), serializedAgain.ToHexString(), "test old way");
-
- if (expectedData != null)
- {
- Assert.AreEqual(expectedData, serialized.ToHexString());
- }
- }
public static void TestZero(IZeroMessageSerializer serializer, T message, string expectedData = null) where T : P2PMessage
{
@@ -49,18 +36,18 @@ public static void TestZero(IZeroMessageSerializer serializer, T message,
{
serializer.Serialize(buffer, message);
T deserialized = serializer.Deserialize(buffer);
-
+
// RlpLength is calculated explicitly when serializing an object by Calculate method. It's null after deserialization.
deserialized.Should().BeEquivalentTo(message, options => options.Excluding(c => c.Name == "RlpLength"));
-
+
Assert.AreEqual(0, buffer.ReadableBytes, "readable bytes");
-
+
serializer.Serialize(buffer2, deserialized);
buffer.SetReaderIndex(0);
string allHex = buffer.ReadAllHex();
Assert.AreEqual(allHex, buffer2.ReadAllHex(), "test zero");
-
+
if (expectedData != null)
{
allHex.Should().BeEquivalentTo(expectedData);
diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/ZeroNewBlockMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/ZeroNewBlockMessageSerializerTests.cs
index 1f48b9cce24..9f8194c0690 100644
--- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/ZeroNewBlockMessageSerializerTests.cs
+++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V62/ZeroNewBlockMessageSerializerTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -41,7 +41,7 @@ public void Roundtrip()
NewBlockMessageSerializer serializer = new();
serializer.Serialize(byteBuffer, newBlockMessage);
byte[] expectedBytes = Bytes.FromHexString("f90243f9023ff901f9a0ff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a01afbbda2cfebd56d2d0d1288617084931eb82bc346c678cac5eeff7c7a078e36a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830f424080833d090080830f424083010203a02ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e28800000000000003e8f840df80018252089400000000000000000000000000000000000000000180808080df80018252089400000000000000000000000000000000000000000180808080c080");
- byte[] bytes = byteBuffer.ReadAllBytes();
+ byte[] bytes = byteBuffer.ReadAllBytesAsArray();
Assert.AreEqual(expectedBytes.ToHexString(), bytes.ToHexString(), "bytes");
}
@@ -67,7 +67,7 @@ public void Roundtrip2()
serializer.Serialize(byteBuffer, newBlockMessage);
byte[] expectedBytes = Bytes.FromHexString("f90243f9023ff901f9a0ff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a01afbbda2cfebd56d2d0d1288617084931eb82bc346c678cac5eeff7c7a078e36a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830f424080833d090080830f424083010203a02ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e28800000000000003e8f840df80018252089400000000000000000000000000000000000000000180808080df80018252089400000000000000000000000000000000000000000180808080c080");
- byte[] bytes = byteBuffer.ReadAllBytes();
+ byte[] bytes = byteBuffer.ReadAllBytesAsArray();
Assert.AreEqual(expectedBytes.ToHexString(), bytes.ToHexString(), "bytes");
}
diff --git a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/ReceiptsMessageSerializerTests.cs b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/ReceiptsMessageSerializerTests.cs
index 59644bddc2d..d71a79d57bc 100644
--- a/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/ReceiptsMessageSerializerTests.cs
+++ b/src/Nethermind/Nethermind.Network.Test/P2P/Subprotocols/Eth/V63/ReceiptsMessageSerializerTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -69,26 +69,29 @@ private static void Test(TxReceipt[][] txReceipts)
Assert.AreEqual(0L, deserialized.TxReceipts[i][j].BlockNumber, $"receipts[{i}][{j}].BlockNumber");
Assert.Null(deserialized.TxReceipts[i][j].ContractAddress, $"receipts[{i}][{j}].ContractAddress");
Assert.AreEqual(0L, deserialized.TxReceipts[i][j].GasUsed, $"receipts[{i}][{j}].GasUsed");
- Assert.AreEqual(txReceipts[i][j].BlockNumber < RopstenSpecProvider.ByzantiumBlockNumber ? 0 : txReceipts[i][j].StatusCode, deserialized.TxReceipts[i][j].StatusCode, $"receipts[{i}][{j}].StatusCode");
Assert.AreEqual(txReceipts[i][j].GasUsedTotal, deserialized.TxReceipts[i][j].GasUsedTotal, $"receipts[{i}][{j}].GasUsedTotal");
- Assert.AreEqual(txReceipts[i][j].BlockNumber < RopstenSpecProvider.ByzantiumBlockNumber ? txReceipts[i][j].PostTransactionState : null, deserialized.TxReceipts[i][j].PostTransactionState, $"receipts[{i}][{j}].PostTransactionState");
+ if (!txReceipts[i][j].SkipStateAndStatusInRlp)
+ {
+ Assert.AreEqual(txReceipts[i][j].BlockNumber < RopstenSpecProvider.ByzantiumBlockNumber ? 0 : txReceipts[i][j].StatusCode, deserialized.TxReceipts[i][j].StatusCode, $"receipts[{i}][{j}].StatusCode");
+ Assert.AreEqual(txReceipts[i][j].BlockNumber < RopstenSpecProvider.ByzantiumBlockNumber ? txReceipts[i][j].PostTransactionState : null, deserialized.TxReceipts[i][j].PostTransactionState, $"receipts[{i}][{j}].PostTransactionState");
+ }
}
}
}
}
}
}
-
+
[Test]
public void Roundtrip()
- {
+ {
TxReceipt[][] data = {new[] {Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.WithBlockNumber(0).TestObject}, new[] {Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject}};
Test(data);
}
-
+
[Test]
public void Roundtrip_with_IgnoreOutputs()
- {
+ {
TxReceipt[][] data = {new[] {Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.WithBlockNumber(0).TestObject}, new[] {Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject}};
foreach (TxReceipt[] receipts in data)
{
@@ -96,10 +99,10 @@ public void Roundtrip_with_IgnoreOutputs()
}
Test(data);
}
-
+
[Test]
public void Roundtrip_with_eip658()
- {
+ {
TxReceipt[][] data = {new[] {Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject}, new[] {Build.A.Receipt.WithAllFieldsFilled.WithBlockNumber(RopstenSpecProvider.ConstantinopleBlockNumber).TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject}};
Test(data);
}
@@ -116,14 +119,14 @@ public void Roundtrip_with_nulls()
TxReceipt[][] data = {new[] {Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject}, null, new[] {null, Build.A.Receipt.WithAllFieldsFilled.TestObject}};
Test(data);
}
-
+
[Test]
public void Deserialize_empty()
{
ReceiptsMessageSerializer serializer = new(RopstenSpecProvider.Instance);
serializer.Deserialize(new byte[0]).TxReceipts.Should().HaveCount(0);
}
-
+
[Test]
public void Roundtrip_mainnet_sample()
{
@@ -132,18 +135,18 @@ public void Roundtrip_mainnet_sample()
ReceiptsMessage message = serializer.Deserialize(bytes);
byte[] serialized = serializer.Serialize(message);
Assert.AreEqual(bytes, serialized);
- }
-
+ }
+
[Test]
public void Roundtrip_one_receipt_with_accessList()
- {
+ {
TxReceipt[][] data = {new[] {Build.A.Receipt.WithAllFieldsFilled.WithTxType(TxType.AccessList).TestObject }};
Test(data);
}
-
+
[Test]
public void Roundtrip_with_both_txTypes_of_receipt()
- {
+ {
TxReceipt[][] data = {new[] {Build.A.Receipt.WithAllFieldsFilled.TestObject, Build.A.Receipt.WithAllFieldsFilled.WithBlockNumber(0).WithTxType(TxType.AccessList).TestObject}, new[] {Build.A.Receipt.WithAllFieldsFilled.WithTxType(TxType.AccessList).TestObject, Build.A.Receipt.WithAllFieldsFilled.TestObject}};
Test(data);
}
diff --git a/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs b/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs
index a8953f48aa0..abb2893a3c2 100644
--- a/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs
+++ b/src/Nethermind/Nethermind.Network.Test/ProtocolsManagerTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -183,7 +183,11 @@ public Context VerifyDisconnected()
public Context ReceiveDisconnect()
{
DisconnectMessage message = new(DisconnectReason.Other);
- _currentSession.ReceiveMessage(new Packet("p2p", P2PMessageCode.Disconnect, _serializer.Serialize(message)));
+ IByteBuffer disconnectPacket = _serializer.ZeroSerialize(message);
+
+ // to account for AdaptivePacketType byte
+ disconnectPacket.ReadByte();
+ _currentSession.ReceiveMessage(new ZeroPacket(disconnectPacket){ PacketType = P2PMessageCode.Disconnect });
return this;
}
@@ -213,7 +217,7 @@ public Context ReceiveStatus()
msg.GenesisHash = _blockTree.Genesis.Hash;
msg.BestHash = _blockTree.Genesis.Hash;
msg.ProtocolVersion = 63;
-
+
return ReceiveStatus(msg);
}
@@ -243,6 +247,17 @@ public Context VerifySyncPeersRemoved()
return this;
}
+ private Context ReceiveHello(HelloMessage msg)
+ {
+ IByteBuffer helloPacket = _serializer.ZeroSerialize(msg);
+ // to account for AdaptivePacketType byte
+ helloPacket.ReadByte();
+
+ _currentSession.ReceiveMessage(new ZeroPacket(helloPacket){ PacketType = P2PMessageCode.Hello });
+ return this;
+ }
+
+
public Context ReceiveHello(byte p2pVersion = 5)
{
HelloMessage msg = new();
@@ -251,10 +266,10 @@ public Context ReceiveHello(byte p2pVersion = 5)
msg.ClientId = "other client v1";
msg.P2PVersion = p2pVersion;
msg.ListenPort = 30314;
- _currentSession.ReceiveMessage(new Packet("p2p", P2PMessageCode.Hello, _serializer.Serialize(msg)));
- return this;
+
+ return ReceiveHello(msg);
}
-
+
public Context ReceiveHelloNoEth()
{
HelloMessage msg = new();
@@ -263,10 +278,9 @@ public Context ReceiveHelloNoEth()
msg.ClientId = "other client v1";
msg.P2PVersion = 5;
msg.ListenPort = 30314;
- _currentSession.ReceiveMessage(new Packet("p2p", P2PMessageCode.Hello, _serializer.Serialize(msg)));
- return this;
+ return ReceiveHello(msg);
}
-
+
public Context ReceiveHelloEth(int protocolVersion)
{
HelloMessage msg = new();
@@ -275,11 +289,10 @@ public Context ReceiveHelloEth(int protocolVersion)
msg.ClientId = "other client v1";
msg.P2PVersion = 5;
msg.ListenPort = 30314;
- _currentSession.ReceiveMessage(new Packet("p2p", P2PMessageCode.Hello, _serializer.Serialize(msg)));
- return this;
+ return ReceiveHello(msg);
}
-
+
public Context ReceiveHelloWrongEth()
{
return ReceiveHelloEth(61);
@@ -412,7 +425,7 @@ public void Disconnects_on_missing_eth()
.ReceiveHelloNoEth()
.VerifyDisconnected();
}
-
+
[Test]
public void Disconnects_on_wrong_eth()
{
@@ -439,7 +452,7 @@ public void Disconnects_on_wrong_chain_id()
.ReceiveStatusWrongChain()
.VerifyDisconnected();
}
-
+
[Test]
public void Disconnects_on_wrong_genesis_hash()
{
@@ -453,7 +466,7 @@ public void Disconnects_on_wrong_genesis_hash()
.ReceiveStatusWrongGenesis()
.VerifyDisconnected();
}
-
+
[Test]
public void Initialized_with_eth66_only()
{
diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EciesCipherTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EciesCipherTests.cs
index 0636bf265d0..891b75928e6 100644
--- a/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EciesCipherTests.cs
+++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/Handshake/EciesCipherTests.cs
@@ -1,20 +1,21 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
using Nethermind.Core.Test.Builders;
@@ -91,9 +92,8 @@ public void Can_decrypt_auth_message()
Assert.AreEqual(authMessage.IsTokenUsed, false);
Assert.NotNull(authMessage.Signature);
- byte[] data = _messageSerializationService.Serialize(authMessage);
- Array.Resize(ref data, deciphered.Length);
- Assert.AreEqual(deciphered, data, "serialization");
+ IByteBuffer data = _messageSerializationService.ZeroSerialize(authMessage);
+ Assert.AreEqual(deciphered, data.ReadAllBytesAsArray(), "serialization");
}
[Test]
@@ -124,10 +124,9 @@ public void Can_decrypt_auth_eip8_message()
Assert.AreEqual(authMessage.Version, 4);
Assert.NotNull(authMessage.Signature);
- byte[] data = _messageSerializationService.Serialize(authMessage);
- Array.Resize(ref data, deciphered.Length);
+ IByteBuffer data = _messageSerializationService.ZeroSerialize(authMessage);
- Assert.AreEqual(deciphered.Slice(0, 169), data.Slice(0, 169), "serialization");
+ Assert.AreEqual(deciphered.Slice(0, 169), data.Slice(0, 169).ReadAllBytesAsArray(), "serialization");
}
[Test]
@@ -147,9 +146,8 @@ public void Can_decrypt_ack()
Assert.AreEqual(ackMessage.Nonce, NetTestVectors.NonceB);
Assert.AreEqual(ackMessage.IsTokenUsed, false);
- byte[] data = _messageSerializationService.Serialize(ackMessage);
- Array.Resize(ref data, deciphered.Length);
- Assert.AreEqual(deciphered, data, "serialization");
+ IByteBuffer data = _messageSerializationService.ZeroSerialize(ackMessage);
+ Assert.AreEqual(deciphered, data.ReadAllBytesAsArray(), "serialization");
}
[Test]
@@ -181,11 +179,10 @@ public void Can_decrypt_ack_eip8_message()
Assert.AreEqual(ackMessage.Nonce, NetTestVectors.NonceB);
Assert.AreEqual(ackMessage.Version, 4);
- byte[] data = _messageSerializationService.Serialize(ackMessage);
- Array.Resize(ref data, deciphered.Length);
+ IByteBuffer data = _messageSerializationService.ZeroSerialize(ackMessage);
// TODO: check 102
- Assert.AreEqual(deciphered.Slice(0, 102), data.Slice(0, 102), "serialization");
+ Assert.AreEqual(deciphered.Slice(0, 102), data.ReadAllBytesAsArray().Slice(0, 102), "serialization");
}
[Test]
diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/SnappyTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/SnappyTests.cs
index 140a8398c2a..6a20b9a2c94 100644
--- a/src/Nethermind/Nethermind.Network.Test/Rlpx/SnappyTests.cs
+++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/SnappyTests.cs
@@ -58,7 +58,7 @@ public byte[] TestEncode(byte[] input)
{
var result = UnpooledByteBufferAllocator.Default.Buffer();
Encode(null, input.ToUnpooledByteBuffer(), result);
- return result.ReadAllBytes();
+ return result.ReadAllBytesAsArray();
}
}
diff --git a/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyFrameMergerTests.cs b/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyFrameMergerTests.cs
index 0ee477dd22a..ac89aca4c3d 100644
--- a/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyFrameMergerTests.cs
+++ b/src/Nethermind/Nethermind.Network.Test/Rlpx/ZeroNettyFrameMergerTests.cs
@@ -174,7 +174,7 @@ public void Can_decode_neth_message()
Assert.AreEqual(0, output.PacketType);
- byte[] outputBytes = output.Content.ReadAllBytes();
+ byte[] outputBytes = output.Content.ReadAllBytesAsArray();
HelloMessageSerializer serializer = new();
HelloMessage helloMessage = serializer.Deserialize(outputBytes);
@@ -204,7 +204,7 @@ public void Can_merge_big_frame()
Assert.NotNull(output);
Assert.AreEqual(32, output.PacketType);
- output.Content.ReadAllBytes();
+ output.Content.ReadAllBytesAsArray();
}
finally
{
diff --git a/src/Nethermind/Nethermind.Network/ByteBufferExtensions.cs b/src/Nethermind/Nethermind.Network/ByteBufferExtensions.cs
new file mode 100644
index 00000000000..d3fb0ac163b
--- /dev/null
+++ b/src/Nethermind/Nethermind.Network/ByteBufferExtensions.cs
@@ -0,0 +1,70 @@
+// Copyright (c) 2021 Demerzel Solutions Limited
+// This file is part of the Nethermind library.
+//
+// The Nethermind library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Nethermind library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Nethermind. If not, see .
+
+using System;
+using DotNetty.Buffers;
+using Nethermind.Core.Extensions;
+
+namespace Nethermind.Network
+{
+ public static class ByteBufferExtensions
+ {
+ public static byte[] ReadAllBytesAsArray(this IByteBuffer buffer)
+ {
+ byte[] bytes = new byte[buffer.ReadableBytes];
+ buffer.ReadBytes(bytes);
+ return bytes;
+ }
+
+ public static Span ReadAllBytesAsSpan(this IByteBuffer buffer)
+ {
+ if (buffer.HasArray)
+ {
+ Span bytes = buffer.Array.AsSpan(buffer.ArrayOffset + buffer.ReaderIndex, buffer.ReadableBytes);
+ buffer.SetReaderIndex(buffer.WriterIndex);
+ return bytes;
+ }
+ else
+ {
+ return buffer.ReadAllBytesAsArray().AsSpan();
+ }
+ }
+
+ public static Memory ReadAllBytesAsMemory(this IByteBuffer buffer)
+ {
+ if (buffer.HasArray)
+ {
+ Memory bytes = buffer.Array.AsMemory(buffer.ArrayOffset + buffer.ReaderIndex, buffer.ReadableBytes);
+ buffer.SetReaderIndex(buffer.WriterIndex);
+ return bytes;
+ }
+ else
+ {
+ return buffer.ReadAllBytesAsArray().AsMemory();
+ }
+ }
+
+ public static string ReadAllHex(this IByteBuffer buffer) => buffer.ReadAllBytesAsSpan().ToHexString();
+
+ public static void WriteBytes(this IByteBuffer buffer, ReadOnlySpan bytes)
+ {
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ buffer.WriteByte(bytes[i]);
+ }
+ }
+ }
+}
diff --git a/src/Nethermind/Nethermind.Network/IByteArrayExtensions.cs b/src/Nethermind/Nethermind.Network/IByteArrayExtensions.cs
deleted file mode 100644
index c486f61f8d8..00000000000
--- a/src/Nethermind/Nethermind.Network/IByteArrayExtensions.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2021 Demerzel Solutions Limited
-// This file is part of the Nethermind library.
-//
-// The Nethermind library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The Nethermind library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the Nethermind. If not, see .
-
-using DotNetty.Buffers;
-using Nethermind.Core.Extensions;
-
-namespace Nethermind.Network
-{
- public static class IByteBufferExtensions
- {
- public static byte[] ReadAllBytes(this IByteBuffer buffer)
- {
- byte[] bytes = new byte[buffer.ReadableBytes];
- buffer.ReadBytes(bytes);
- return bytes;
- }
-
- public static string ReadAllHex(this IByteBuffer buffer)
- {
- byte[] bytes = new byte[buffer.ReadableBytes];
- buffer.ReadBytes(bytes);
- return bytes.ToHexString();
- }
-
- public static void MakeSpace(this IByteBuffer output, int length, string reason = null)
- {
- if (output.WritableBytes < length)
- {
- if (output.ReaderIndex == output.WriterIndex)
- {
- output.Clear();
- }
- else
- {
- output.DiscardReadBytes();
- }
-
- if (output.WritableBytes < length)
- {
- output.EnsureWritable(length, true);
- }
- }
- }
- }
-}
diff --git a/src/Nethermind/Nethermind.Network/IMessagePad.cs b/src/Nethermind/Nethermind.Network/IMessagePad.cs
index 426a0455371..ec87d59cf61 100644
--- a/src/Nethermind/Nethermind.Network/IMessagePad.cs
+++ b/src/Nethermind/Nethermind.Network/IMessagePad.cs
@@ -1,23 +1,27 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using DotNetty.Buffers;
+
namespace Nethermind.Network
{
public interface IMessagePad
{
byte[] Pad(byte[] bytes);
+ void Pad(IByteBuffer bytes);
}
+
}
diff --git a/src/Nethermind/Nethermind.Network/IMessageSerializationService.cs b/src/Nethermind/Nethermind.Network/IMessageSerializationService.cs
index 5bd0055d488..e001c78ab9e 100644
--- a/src/Nethermind/Nethermind.Network/IMessageSerializationService.cs
+++ b/src/Nethermind/Nethermind.Network/IMessageSerializationService.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -21,12 +21,16 @@ namespace Nethermind.Network
{
public interface IMessageSerializationService
{
- IByteBuffer ZeroSerialize(T message) where T : MessageBase;
- byte[] Serialize(T messageBase) where T : MessageBase;
+ IByteBuffer ZeroSerialize(T message, ByteBufferAllocator allocator = ByteBufferAllocator.PooledByteBufferAllocator) where T : MessageBase;
T Deserialize(byte[] bytes) where T : MessageBase;
T Deserialize(IByteBuffer buffer) where T : MessageBase;
void Register(Assembly assembly);
- void Register(IMessageSerializer messageSerializer) where T : MessageBase;
void Register(IZeroMessageSerializer messageSerializer) where T : MessageBase;
}
+
+ public enum ByteBufferAllocator
+ {
+ UnpooledByteBufferAllocator,
+ PooledByteBufferAllocator
+ }
}
diff --git a/src/Nethermind/Nethermind.Network/IMessageSerializer.cs b/src/Nethermind/Nethermind.Network/IMessageSerializer.cs
deleted file mode 100644
index 41552454e20..00000000000
--- a/src/Nethermind/Nethermind.Network/IMessageSerializer.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2021 Demerzel Solutions Limited
-// This file is part of the Nethermind library.
-//
-// The Nethermind library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The Nethermind library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the Nethermind. If not, see .
-
-namespace Nethermind.Network
-{
- public interface IMessageSerializer where T : MessageBase
- {
- byte[] Serialize(T msg);
- T Deserialize(byte[] msgBytes);
- }
-}
diff --git a/src/Nethermind/Nethermind.Network/MessageSerializationService.cs b/src/Nethermind/Nethermind.Network/MessageSerializationService.cs
index 385aea38c47..11640961fc3 100644
--- a/src/Nethermind/Nethermind.Network/MessageSerializationService.cs
+++ b/src/Nethermind/Nethermind.Network/MessageSerializationService.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -31,12 +31,15 @@ public class MessageSerializationService : IMessageSerializationService
public T Deserialize(byte[] bytes) where T : MessageBase
{
- if (!TryGetSerializer(out IMessageSerializer messageSerializer))
+ if (TryGetZeroSerializer(out IZeroMessageSerializer zeroMessageSerializer))
{
- throw new InvalidOperationException($"No {nameof(IMessageSerializer)} registered for {typeof(T).Name}.");
+ IByteBuffer byteBuffer = PooledByteBufferAllocator.Default.Buffer(bytes.Length);
+ byteBuffer.WriteBytes(bytes);
+ return zeroMessageSerializer.Deserialize(byteBuffer);
}
- return messageSerializer.Deserialize(bytes);
+ throw new InvalidOperationException($"No {nameof(IZeroMessageSerializer)} registered for {typeof(T).Name}.");
+
}
public T Deserialize(IByteBuffer buffer) where T : MessageBase
@@ -45,10 +48,8 @@ public T Deserialize(IByteBuffer buffer) where T : MessageBase
{
return zeroMessageSerializer.Deserialize(buffer);
}
-
- // 3% allocation of a sample run of Goerli 3 million blocks fast sync on buffer.ReadAllBytes
- // this can be improved by adding ZeroMessageSerializer for a new message type
- return Deserialize(buffer.ReadAllBytes());
+
+ throw new InvalidOperationException($"No {nameof(IZeroMessageSerializer)} registered for {typeof(T).Name}.");
}
@@ -70,16 +71,6 @@ public void Register(Assembly assembly)
}
Type interfaceGenericDefinition = implementedInterface.GetGenericTypeDefinition();
- if (interfaceGenericDefinition == typeof(IMessageSerializer<>).GetGenericTypeDefinition())
- {
- ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
- if (constructor == null)
- {
- continue;
- }
-
- _serializers[implementedInterface.GenericTypeArguments[0].TypeHandle] = Activator.CreateInstance(type);
- }
if (interfaceGenericDefinition == typeof(IZeroMessageSerializer<>).GetGenericTypeDefinition())
{
@@ -95,17 +86,12 @@ public void Register(Assembly assembly)
}
}
- public void Register(IMessageSerializer messageSerializer) where T : MessageBase
- {
- _serializers[typeof(T).TypeHandle] = messageSerializer;
- }
-
public void Register(IZeroMessageSerializer messageSerializer) where T : MessageBase
{
_zeroSerializers[typeof(T).TypeHandle] = messageSerializer;
}
- public IByteBuffer ZeroSerialize(T message) where T : MessageBase
+ public IByteBuffer ZeroSerialize(T message, ByteBufferAllocator allocator = ByteBufferAllocator.PooledByteBufferAllocator) where T : MessageBase
{
void WriteAdaptivePacketType(in IByteBuffer buffer)
{
@@ -116,30 +102,34 @@ void WriteAdaptivePacketType(in IByteBuffer buffer)
}
int p2pMessageLength = (message is P2PMessage ? sizeof(int) : 0);
+ IByteBuffer byteBuffer;
if (TryGetZeroSerializer(out IZeroMessageSerializer zeroMessageSerializer))
{
- IByteBuffer byteBuffer = PooledByteBufferAllocator.Default.Buffer(
- zeroMessageSerializer is IZeroInnerMessageSerializer zeroInnerMessageSerializer
- ? zeroInnerMessageSerializer.GetLength(message, out _) + p2pMessageLength
- : 64);
+
+ switch (allocator)
+ {
+ case ByteBufferAllocator.UnpooledByteBufferAllocator:
+ byteBuffer = UnpooledByteBufferAllocator.Default.Buffer(
+ zeroMessageSerializer is IZeroInnerMessageSerializer zeroInnerMessageSerializerU
+ ? zeroInnerMessageSerializerU.GetLength(message, out _) + p2pMessageLength
+ : 64);
+ break;
+ case ByteBufferAllocator.PooledByteBufferAllocator:
+ byteBuffer = PooledByteBufferAllocator.Default.Buffer(
+ zeroMessageSerializer is IZeroInnerMessageSerializer zeroInnerMessageSerializerP
+ ? zeroInnerMessageSerializerP.GetLength(message, out _) + p2pMessageLength
+ : 64);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(allocator), allocator, null);
+ }
+
+
WriteAdaptivePacketType(byteBuffer);
zeroMessageSerializer.Serialize(byteBuffer, message);
return byteBuffer;
}
- else
- {
- byte[] serialized = Serialize(message);
- IByteBuffer byteBuffer = PooledByteBufferAllocator.Default.Buffer(serialized.Length + p2pMessageLength);
- WriteAdaptivePacketType(byteBuffer);
- byteBuffer.WriteBytes(serialized);
- return byteBuffer;
- }
- }
- public byte[] Serialize(T messageBase) where T : MessageBase
- {
- return TryGetSerializer(out IMessageSerializer messageSerializer)
- ? messageSerializer.Serialize(messageBase)
- : throw new InvalidOperationException($"No {nameof(IMessageSerializer)} registered for {typeof(T).Name}.");
+ throw new InvalidOperationException($"No {nameof(IZeroMessageSerializer)} registered for {typeof(T).Name}.");
}
private bool TryGetZeroSerializer(out IZeroMessageSerializer serializer) where T : MessageBase
@@ -160,22 +150,5 @@ private bool TryGetZeroSerializer(out IZeroMessageSerializer serializer) w
throw new InvalidOperationException($"Zero serializer for {nameof(T)} (registered: {serializerObject?.GetType().Name}) does not implement required interfaces");
}
- private bool TryGetSerializer(out IMessageSerializer serializer) where T : MessageBase
- {
- RuntimeTypeHandle typeHandle = typeof(T).TypeHandle;
- if (!_serializers.TryGetValue(typeHandle, out object serializerObject))
- {
- serializer = null;
- return false;
- }
-
- if (!(serializerObject is IMessageSerializer messageSerializer))
- {
- throw new InvalidOperationException($"Serializer for {nameof(T)} (registered: {serializerObject?.GetType().Name}) does not implement required interfaces");
- }
-
- serializer = messageSerializer;
- return true;
- }
}
}
diff --git a/src/Nethermind/Nethermind.Network/NoPad.cs b/src/Nethermind/Nethermind.Network/NoPad.cs
index 74467b9decc..33defe29d7b 100644
--- a/src/Nethermind/Nethermind.Network/NoPad.cs
+++ b/src/Nethermind/Nethermind.Network/NoPad.cs
@@ -1,19 +1,21 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using DotNetty.Buffers;
+
namespace Nethermind.Network
{
public class NoPad : IMessagePad
@@ -22,5 +24,6 @@ public byte[] Pad(byte[] bytes)
{
return bytes;
}
+ public void Pad(IByteBuffer bytes) { }
}
}
diff --git a/src/Nethermind/Nethermind.Network/P2P/Messages/AddCapabilityMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Messages/AddCapabilityMessageSerializer.cs
index 545c835ec44..8be17413579 100644
--- a/src/Nethermind/Nethermind.Network/P2P/Messages/AddCapabilityMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/P2P/Messages/AddCapabilityMessageSerializer.cs
@@ -1,19 +1,20 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using DotNetty.Buffers;
using Nethermind.Serialization.Rlp;
using Nethermind.Stats.Model;
@@ -22,20 +23,34 @@ namespace Nethermind.Network.P2P.Messages
///
/// This is probably used in NDM
///
- public class AddCapabilityMessageSerializer : IMessageSerializer
+ public class AddCapabilityMessageSerializer : IZeroMessageSerializer
{
- public byte[] Serialize(AddCapabilityMessage msg)
- => Rlp.Encode(Rlp.Encode(msg.Capability.ProtocolCode.ToLowerInvariant()),
- Rlp.Encode(msg.Capability.Version)).Bytes;
+ public void Serialize(IByteBuffer byteBuffer, AddCapabilityMessage msg)
+ {
+ int totalLength = GetLength(msg, out int contentLength);
+ byteBuffer.EnsureWritable(totalLength, true);
+
+ NettyRlpStream stream = new(byteBuffer);
+ stream.StartSequence(contentLength);
+ stream.Encode(msg.Capability.ProtocolCode.ToLowerInvariant());
+ stream.Encode(msg.Capability.Version);
+ }
- public AddCapabilityMessage Deserialize(byte[] msgBytes)
+ public AddCapabilityMessage Deserialize(IByteBuffer byteBuffer)
{
- RlpStream context = msgBytes.AsRlpStream();
+ NettyRlpStream context = new(byteBuffer);
context.ReadSequenceLength();
string protocolCode = context.DecodeString();
byte version = context.DecodeByte();
return new AddCapabilityMessage(new Capability(protocolCode, version));
}
+ private int GetLength(AddCapabilityMessage msg, out int contentLength)
+ {
+ contentLength = Rlp.LengthOf(msg.Capability.ProtocolCode.ToLowerInvariant());
+ contentLength += Rlp.LengthOf(msg.Capability.Version);
+
+ return Rlp.LengthOfSequence(contentLength);
+ }
}
}
diff --git a/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessageSerializer.cs
index dcf97c3cc5a..7f7673b4915 100644
--- a/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/P2P/Messages/DisconnectMessageSerializer.cs
@@ -1,56 +1,69 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using System;
using System.Linq;
+using DotNetty.Buffers;
using Nethermind.Core.Extensions;
using Nethermind.Serialization.Rlp;
using Nethermind.Stats.Model;
namespace Nethermind.Network.P2P.Messages
{
- public class DisconnectMessageSerializer : IMessageSerializer
+ public class DisconnectMessageSerializer : IZeroMessageSerializer
{
- public byte[] Serialize(DisconnectMessage msg)
+ public void Serialize(IByteBuffer byteBuffer, DisconnectMessage msg)
{
- return Rlp.Encode(
- Rlp.Encode((byte)msg.Reason) // sic!, as a list of 1 element
- ).Bytes;
+ int length = GetLength(msg, out int contentLength);
+ byteBuffer.EnsureWritable(length);
+ NettyRlpStream rlpStream = new(byteBuffer);
+
+ rlpStream.StartSequence(contentLength);
+ rlpStream.Encode((byte)msg.Reason);
+ }
+
+ private int GetLength(DisconnectMessage message, out int contentLength)
+ {
+ contentLength = Rlp.LengthOf((byte)message.Reason);
+
+ return Rlp.LengthOfSequence(contentLength);
}
private byte[] breach1 = Bytes.FromHexString("0204c104");
private byte[] breach2 = Bytes.FromHexString("0204c180");
-
- public DisconnectMessage Deserialize(byte[] msgBytes)
+
+ public DisconnectMessage Deserialize(IByteBuffer msgBytes)
{
- if (msgBytes.Length == 1)
+ if (msgBytes.ReadableBytes == 1)
{
- return new DisconnectMessage((DisconnectReason)msgBytes[0]);
+ return new DisconnectMessage((DisconnectReason)msgBytes.GetByte(0));
}
- if (msgBytes.SequenceEqual(breach1))
+ Span msg = msgBytes.ReadAllBytesAsSpan();
+ if (msg.SequenceEqual(breach1))
{
return new DisconnectMessage(DisconnectReason.Breach1);
}
-
- if (msgBytes.SequenceEqual(breach2))
+
+ if (msg.SequenceEqual(breach2))
{
return new DisconnectMessage(DisconnectReason.Breach2);
}
-
- RlpStream rlpStream = msgBytes.AsRlpStream();
+
+ Rlp.ValueDecoderContext rlpStream = msg.AsRlpValueContext();
rlpStream.ReadSequenceLength();
int reason = rlpStream.DecodeInt();
DisconnectMessage disconnectMessage = new(reason);
diff --git a/src/Nethermind/Nethermind.Network/P2P/Messages/HelloMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Messages/HelloMessageSerializer.cs
index 15e82015c25..0776b542727 100644
--- a/src/Nethermind/Nethermind.Network/P2P/Messages/HelloMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/P2P/Messages/HelloMessageSerializer.cs
@@ -1,45 +1,74 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System;
using System.Linq;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Serialization.Rlp;
using Nethermind.Stats.Model;
namespace Nethermind.Network.P2P.Messages
{
- public class HelloMessageSerializer : IMessageSerializer
+ public class HelloMessageSerializer : IZeroMessageSerializer
{
- public byte[] Serialize(HelloMessage msg)
+ public void Serialize(IByteBuffer byteBuffer, HelloMessage msg)
{
- return Rlp.Encode(
- Rlp.Encode(msg.P2PVersion),
- Rlp.Encode(msg.ClientId),
- Rlp.Encode(msg.Capabilities.Select(c => Rlp.Encode(
- Rlp.Encode(c.ProtocolCode.ToLowerInvariant()),
- Rlp.Encode(c.Version))).ToArray()),
- Rlp.Encode(msg.ListenPort),
- Rlp.Encode(msg.NodeId.Bytes)
- ).Bytes;
+ (int totalLength, int innerLength) length = GetLength(msg);
+ byteBuffer.EnsureWritable(Rlp.LengthOfSequence(length.totalLength), true);
+ NettyRlpStream stream = new(byteBuffer);
+ stream.StartSequence(length.totalLength);
+ stream.Encode(msg.P2PVersion);
+ stream.Encode(msg.ClientId);
+ stream.StartSequence(length.innerLength);
+ foreach (Capability? capability in msg.Capabilities)
+ {
+ string protocolCode = capability.ProtocolCode.ToLowerInvariant();
+ int capabilityLength = Rlp.LengthOf(protocolCode);
+ capabilityLength += Rlp.LengthOf(capability.Version);
+ stream.StartSequence(capabilityLength);
+ stream.Encode(protocolCode);
+ stream.Encode(capability.Version);
+ }
+
+ stream.Encode(msg.ListenPort);
+ stream.Encode(msg.NodeId.Bytes);
}
- public HelloMessage Deserialize(byte[] msgBytes)
+ private (int, int) GetLength(HelloMessage msg)
{
- RlpStream rlpStream = msgBytes.AsRlpStream();
+ int contentLength = 0;
+ contentLength += Rlp.LengthOf(msg.P2PVersion);
+ contentLength += Rlp.LengthOf(msg.ClientId);
+ int innerContentLength = 0;
+ foreach (Capability? capability in msg.Capabilities)
+ {
+ int capabilityLength = Rlp.LengthOf(capability.ProtocolCode.ToLowerInvariant());
+ capabilityLength += Rlp.LengthOf(capability.Version);
+ innerContentLength += Rlp.LengthOfSequence(capabilityLength);
+ }
+ contentLength += Rlp.LengthOfSequence(innerContentLength);
+ contentLength += Rlp.LengthOf(msg.ListenPort);
+ contentLength += Rlp.LengthOf(msg.NodeId.Bytes);
+ return (contentLength, innerContentLength);
+ }
+
+ public HelloMessage Deserialize(IByteBuffer msgBytes)
+ {
+ NettyRlpStream rlpStream = new (msgBytes);
rlpStream.ReadSequenceLength();
HelloMessage helloMessage = new();
@@ -52,7 +81,7 @@ public HelloMessage Deserialize(byte[] msgBytes)
int version = ctx.DecodeByte();
return new Capability(protocolCode, version);
}).ToList();
-
+
helloMessage.ListenPort = rlpStream.DecodeInt();
ReadOnlySpan publicKeyBytes = rlpStream.DecodeByteArraySpan();
diff --git a/src/Nethermind/Nethermind.Network/P2P/NettyRlpStream.cs b/src/Nethermind/Nethermind.Network/P2P/NettyRlpStream.cs
index 8edac5b3a52..e8e83cf3795 100644
--- a/src/Nethermind/Nethermind.Network/P2P/NettyRlpStream.cs
+++ b/src/Nethermind/Nethermind.Network/P2P/NettyRlpStream.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -97,7 +97,7 @@ public override int Position
public override int Length => _buffer.ReadableBytes + (_buffer.ReaderIndex - _initialPosition);
- public override bool HasBeenRead => _buffer.ReadableBytes > 0;
+ public override bool HasBeenRead => _buffer.ReadableBytes <= 0;
protected override string Description => "|NettyRlpStream|description missing|";
}
diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs
index 884790f93fc..17b3950f793 100644
--- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V62/Messages/BlockBodiesMessageSerializer.cs
@@ -1,19 +1,21 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using System;
+using System.Configuration;
using System.Linq;
using DotNetty.Buffers;
using Nethermind.Core;
@@ -23,20 +25,43 @@ namespace Nethermind.Network.P2P.Subprotocols.Eth.V62.Messages
{
public class BlockBodiesMessageSerializer : IZeroInnerMessageSerializer
{
- public byte[] Serialize(BlockBodiesMessage message)
+ private readonly TxDecoder _txDecoder = new();
+ private readonly HeaderDecoder _headerDecoder = new();
+
+ public void Serialize(IByteBuffer byteBuffer, BlockBodiesMessage message)
{
- return Rlp.Encode(message.Bodies.Select(b => b == null
- ? Rlp.OfEmptySequence
- : Rlp.Encode(
- Rlp.Encode(b.Transactions),
- Rlp.Encode(b.Uncles))).ToArray()).Bytes;
+
+ int totalLength = GetLength(message, out int contentLength);
+ byteBuffer.EnsureWritable(totalLength, true);
+ NettyRlpStream stream = new(byteBuffer);
+ stream.StartSequence(contentLength);
+ foreach (BlockBody? body in message.Bodies)
+ {
+ if (body == null)
+ {
+ stream.Encode(Rlp.OfEmptySequence);
+ }
+ else
+ {
+ SerializeBody(stream, body);
+ }
+ }
}
- public void Serialize(IByteBuffer byteBuffer, BlockBodiesMessage message)
+ private void SerializeBody(NettyRlpStream stream, BlockBody body)
{
- byte[] oldWay = Serialize(message);
- byteBuffer.EnsureWritable(oldWay.Length, true);
- byteBuffer.WriteBytes(oldWay);
+ stream.StartSequence(GetBodyLength(body));
+ stream.StartSequence(GetTxLength(body.Transactions));
+ foreach (Transaction? txn in body.Transactions)
+ {
+ stream.Encode(txn);
+ }
+
+ stream.StartSequence(GetUnclesLength(body.Uncles));
+ foreach (var uncle in body.Uncles)
+ {
+ stream.Encode(uncle);
+ }
}
public BlockBodiesMessage Deserialize(IByteBuffer byteBuffer)
@@ -47,9 +72,41 @@ public BlockBodiesMessage Deserialize(IByteBuffer byteBuffer)
public int GetLength(BlockBodiesMessage message, out int contentLength)
{
- byte[] oldWay = Serialize(message);
- contentLength = oldWay.Length;
- return contentLength;
+ contentLength = message.Bodies.Select(b => b == null
+ ? Rlp.OfEmptySequence.Length
+ : Rlp.LengthOfSequence(
+ GetBodyLength(b)
+ )
+ ).Sum();
+ return Rlp.LengthOfSequence(contentLength);
+ }
+
+ private int GetBodyLength(BlockBody b)
+ {
+ return Rlp.LengthOfSequence(GetTxLength(b.Transactions)) +
+ Rlp.LengthOfSequence(GetUnclesLength(b.Uncles));
+ }
+
+ private int GetTxLength(Transaction[] transactions)
+ {
+ int txLength = 0;
+ for (int i = 0; i < transactions.Length; i++)
+ {
+ txLength += _txDecoder.GetLength(transactions[i], RlpBehaviors.None);
+ }
+
+ return txLength;
+ }
+
+ private int GetUnclesLength(BlockHeader[] headers)
+ {
+ int unclesLength = 0;
+ for (int i = 0; i < headers.Length; i++)
+ {
+ unclesLength += _headerDecoder.GetLength(headers[i], RlpBehaviors.None);
+ }
+
+ return unclesLength;
}
public static BlockBodiesMessage Deserialize(RlpStream rlpStream)
diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Messages/ReceiptsMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Messages/ReceiptsMessageSerializer.cs
index 61704d98f6f..cf2e12b6d96 100644
--- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Messages/ReceiptsMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Eth/V63/Messages/ReceiptsMessageSerializer.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -33,30 +33,52 @@ public ReceiptsMessageSerializer(ISpecProvider specProvider)
{
_specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider));
}
-
+
public void Serialize(IByteBuffer byteBuffer, ReceiptsMessage message)
{
- Rlp rlp = Rlp.Encode(message.TxReceipts.Select(
- b => b == null
- ? Rlp.OfEmptySequence
- : Rlp.Encode(
- b.Select(
- n => n == null
- ? Rlp.OfEmptySequence
- : _decoder.Encode(n, _specProvider.GetSpec(n.BlockNumber).IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None)).ToArray())).ToArray());
-
- RlpStream rlpStream = new NettyRlpStream(byteBuffer);
- rlpStream.Encode(rlp);
+
+ int totalLength = GetLength(message, out int contentLength);
+
+ byteBuffer.EnsureWritable(totalLength, true);
+ NettyRlpStream stream = new(byteBuffer);
+ stream.StartSequence(contentLength);
+
+ foreach (TxReceipt?[]? txReceipts in message.TxReceipts)
+ {
+ if (txReceipts is null)
+ {
+ stream.Encode(Rlp.OfEmptySequence);
+ continue;
+ }
+
+ int innerLength = GetInnerLength(txReceipts);
+ stream.StartSequence(innerLength);
+ foreach (TxReceipt? txReceipt in txReceipts)
+ {
+ if (txReceipt is null)
+ {
+ stream.Encode(Rlp.OfEmptySequence);
+ continue;
+ }
+
+ _decoder.Encode(stream, txReceipt,
+ _specProvider.GetSpec(txReceipt.BlockNumber).IsEip658Enabled
+ ? RlpBehaviors.Eip658Receipts
+ : RlpBehaviors.None);
+ }
+
+
+ }
}
public ReceiptsMessage Deserialize(IByteBuffer byteBuffer)
{
if (byteBuffer.Array.Length == 0 || byteBuffer.Array.First() == Rlp.OfEmptySequence[0]) return new ReceiptsMessage(null);
-
+
RlpStream rlpStream = new NettyRlpStream(byteBuffer);
return Deserialize(rlpStream);
}
-
+
public ReceiptsMessage Deserialize(RlpStream rlpStream)
{
TxReceipt[][] data = rlpStream.DecodeArray(itemContext =>
@@ -69,7 +91,7 @@ public ReceiptsMessage Deserialize(RlpStream rlpStream)
public int GetLength(ReceiptsMessage message, out int contentLength)
{
contentLength = 0;
-
+
for (int i = 0; i < message.TxReceipts.Length; i++)
{
TxReceipt?[]? txReceipts = message.TxReceipts[i];
@@ -79,23 +101,30 @@ public int GetLength(ReceiptsMessage message, out int contentLength)
}
else
{
- for (int j = 0; j < txReceipts.Length; j++)
- {
- TxReceipt? txReceipt = txReceipts[j];
- if (txReceipt is null)
- {
- contentLength += Rlp.OfEmptySequence.Length;
- }
- else
- {
- contentLength += Rlp.LengthOfSequence(_decoder.GetLength(txReceipt, _specProvider.GetSpec(txReceipt.BlockNumber).IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None));
- }
- }
+ contentLength += Rlp.LengthOfSequence(GetInnerLength(txReceipts));
}
-
}
-
+
return Rlp.LengthOfSequence(contentLength);
}
+
+ private int GetInnerLength(TxReceipt?[]? txReceipts)
+ {
+ int contentLength = 0;
+ for (int j = 0; j < txReceipts.Length; j++)
+ {
+ TxReceipt? txReceipt = txReceipts[j];
+ if (txReceipt is null)
+ {
+ contentLength += Rlp.OfEmptySequence.Length;
+ }
+ else
+ {
+ contentLength += _decoder.GetLength(txReceipt, _specProvider.GetSpec(txReceipt.BlockNumber).IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None);
+ }
+ }
+
+ return contentLength;
+ }
}
}
diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/Messages/BlockBodiesMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/Messages/BlockBodiesMessageSerializer.cs
index 16b11591519..983b7bf7a63 100644
--- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/Messages/BlockBodiesMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Les/Messages/BlockBodiesMessageSerializer.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -24,8 +24,8 @@ public class BlockBodiesMessageSerializer: IZeroMessageSerializer.
@@ -26,28 +26,25 @@ public class HelperTrieProofsMessageSerializer: IZeroMessageSerializer(T[]...) could recurse to handle arbitrary array nesting. Would clean this up a lot.")]
public void Serialize(IByteBuffer byteBuffer, HelperTrieProofsMessage message)
{
- Rlp[] proofNodesRlp = new Rlp[message.ProofNodes.Length];
+ Keccak[] proofNodesKeccak = new Keccak[message.ProofNodes.Length];
+ int proofNodesContentLength = 0;
for (int i = 0; i < message.ProofNodes.Length; i++)
{
- proofNodesRlp[i] = Rlp.Encode(new Keccak(message.ProofNodes[i]));
+ proofNodesKeccak[i] = new Keccak(message.ProofNodes[i]);
+ proofNodesContentLength += Rlp.LengthOf(proofNodesKeccak[i]);
}
-
- Rlp proofsRlp = Rlp.Encode(proofNodesRlp);
- Rlp[] tempAuxRlp = new Rlp[message.AuxiliaryData.Length];
+ int tempAuxContentLength = 0;
for (int i = 0; i < message.AuxiliaryData.Length; i++)
{
- tempAuxRlp[i] = Rlp.Encode(message.AuxiliaryData[i]);
+ tempAuxContentLength += Rlp.LengthOf(message.AuxiliaryData[i]);
}
- Rlp auxRlp = Rlp.Encode(tempAuxRlp);
-
- int innerContentLength = proofsRlp.Length + auxRlp.Length;
+ int innerContentLength = Rlp.LengthOfSequence(proofNodesContentLength) + Rlp.LengthOfSequence(tempAuxContentLength);
int contentLength =
Rlp.LengthOf(message.RequestId) +
Rlp.LengthOf(message.BufferValue) +
Rlp.LengthOfSequence(innerContentLength);
-
int totalLength = Rlp.LengthOfSequence(contentLength);
RlpStream rlpStream = new NettyRlpStream(byteBuffer);
@@ -57,8 +54,16 @@ public void Serialize(IByteBuffer byteBuffer, HelperTrieProofsMessage message)
rlpStream.Encode(message.RequestId);
rlpStream.Encode(message.BufferValue);
rlpStream.StartSequence(innerContentLength);
- rlpStream.Encode(proofsRlp);
- rlpStream.Encode(auxRlp);
+ rlpStream.StartSequence(proofNodesContentLength);
+ for (int i = 0; i < message.ProofNodes.Length; i++)
+ {
+ rlpStream.Encode(proofNodesKeccak[i]);
+ }
+ rlpStream.StartSequence(tempAuxContentLength);
+ for (int i = 0; i < message.AuxiliaryData.Length; i++)
+ {
+ rlpStream.Encode(message.AuxiliaryData[i]);
+ }
}
public HelperTrieProofsMessage Deserialize(IByteBuffer byteBuffer)
diff --git a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializer.cs b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializer.cs
index 11f93e5a072..2ffe5673f3b 100644
--- a/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/P2P/Subprotocols/Snap/Messages/AccountRangeMessageSerializer.cs
@@ -1,19 +1,19 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
-//
+//
using DotNetty.Buffers;
using Nethermind.Core;
@@ -84,7 +84,7 @@ public AccountRangeMessage Deserialize(IByteBuffer byteBuffer)
return message;
}
-
+
private PathWithAccount DecodePathWithRlpData(RlpStream stream)
{
stream.ReadSequenceLength();
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckEip8MessageSerializer.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckEip8MessageSerializer.cs
index e21c8c5f895..0762dae51da 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckEip8MessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckEip8MessageSerializer.cs
@@ -1,25 +1,27 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Rlpx.Handshake
{
- public class AckEip8MessageSerializer : IMessageSerializer
+ public class AckEip8MessageSerializer : IZeroMessageSerializer
{
private readonly IMessagePad _messagePad;
public const int EphemeralPublicKeyLength = 64;
@@ -33,21 +35,24 @@ public AckEip8MessageSerializer(IMessagePad messagePad)
{
_messagePad = messagePad;
}
-
- public byte[] Serialize(AckEip8Message msg)
+
+ public void Serialize(IByteBuffer byteBuffer, AckEip8Message msg)
{
- byte[] data = Rlp.Encode(
- Rlp.Encode(msg.EphemeralPublicKey.Bytes),
- Rlp.Encode(msg.Nonce),
- Rlp.Encode(msg.Version)
- ).Bytes;
+ int totalLength = Rlp.LengthOf(msg.EphemeralPublicKey.Bytes);
+ totalLength += Rlp.LengthOf(msg.Nonce);
+ totalLength += Rlp.LengthOf(msg.Version);
- return _messagePad?.Pad(data) ?? data;
+ byteBuffer.EnsureWritable(Rlp.LengthOfSequence(totalLength), true);
+ NettyRlpStream stream = new(byteBuffer);
+ stream.StartSequence(totalLength);
+ stream.Encode(msg.EphemeralPublicKey.Bytes);
+ stream.Encode(msg.Nonce);
+ stream.Encode(msg.Version);
}
- public AckEip8Message Deserialize(byte[] msgBytes)
+ public AckEip8Message Deserialize(IByteBuffer msgBytes)
{
- RlpStream rlpStream = msgBytes.AsRlpStream();
+ NettyRlpStream rlpStream = new(msgBytes);
AckEip8Message authEip8Message = new();
rlpStream.ReadSequenceLength();
authEip8Message.EphemeralPublicKey = new PublicKey(rlpStream.DecodeByteArraySpan());
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckMessageSerializer.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckMessageSerializer.cs
index 027ea0d6691..0ef5dcafa34 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AckMessageSerializer.cs
@@ -1,26 +1,27 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
namespace Nethermind.Network.Rlpx.Handshake
{
- public class AckMessageSerializer : IMessageSerializer
+ public class AckMessageSerializer : IZeroMessageSerializer
{
public const int EphemeralPublicKeyLength = 64;
public const int EphemeralPublicKeyOffset = 0;
@@ -29,27 +30,29 @@ public class AckMessageSerializer : IMessageSerializer
public const int IsTokenUsedLength = 1;
public const int IsTokenUsedOffset = NonceOffset + NonceLength;
public const int TotalLength = IsTokenUsedOffset + IsTokenUsedLength;
-
- public byte[] Serialize(AckMessage msg)
+
+ public void Serialize(IByteBuffer byteBuffer, AckMessage msg)
{
+ byteBuffer.EnsureWritable(TotalLength);
+ // TODO: find a way to now allocate this here
byte[] data = new byte[TotalLength];
Buffer.BlockCopy(msg.EphemeralPublicKey.Bytes, 0, data, EphemeralPublicKeyOffset, EphemeralPublicKeyLength);
Buffer.BlockCopy(msg.Nonce, 0, data, NonceOffset, NonceLength);
data[IsTokenUsedOffset] = msg.IsTokenUsed ? (byte)0x01 : (byte)0x00;
- return data;
+ byteBuffer.WriteBytes(data);
}
- public AckMessage Deserialize(byte[] msgBytes)
+ public AckMessage Deserialize(IByteBuffer msgBytes)
{
- if (msgBytes.Length != TotalLength)
+ if (msgBytes.ReadableBytes != TotalLength)
{
- throw new NetworkingException($"Incorrect incoming {nameof(AckMessage)} length. Expected {TotalLength} but was {msgBytes.Length}", NetworkExceptionType.Validation);
+ throw new NetworkingException($"Incorrect incoming {nameof(AckMessage)} length. Expected {TotalLength} but was {msgBytes.ReadableBytes}", NetworkExceptionType.Validation);
}
AckMessage authMessage = new();
- authMessage.EphemeralPublicKey = new PublicKey(msgBytes.AsSpan().Slice(EphemeralPublicKeyOffset, EphemeralPublicKeyLength));
- authMessage.Nonce = msgBytes.Slice(NonceOffset, NonceLength);
- authMessage.IsTokenUsed = msgBytes[IsTokenUsedOffset] == 0x01;
+ authMessage.EphemeralPublicKey = new PublicKey(msgBytes.Slice(EphemeralPublicKeyOffset, EphemeralPublicKeyLength).ReadAllBytesAsSpan());
+ authMessage.Nonce = msgBytes.Slice(NonceOffset, NonceLength).ReadAllBytesAsArray();
+ authMessage.IsTokenUsed = msgBytes.GetByte(IsTokenUsedOffset) == 0x01;
return authMessage;
}
}
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthEip8MessageSerializer.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthEip8MessageSerializer.cs
index 11a82e607e0..d541b51ac6c 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthEip8MessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthEip8MessageSerializer.cs
@@ -1,27 +1,29 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Rlpx.Handshake
{
- public class AuthEip8MessageSerializer : IMessageSerializer
+ public class AuthEip8MessageSerializer : IZeroMessageSerializer
{
private readonly IMessagePad _messagePad;
@@ -29,22 +31,33 @@ public AuthEip8MessageSerializer(IMessagePad messagePad)
{
_messagePad = messagePad;
}
-
- public byte[] Serialize(AuthEip8Message msg)
+
+ public void Serialize(IByteBuffer byteBuffer, AuthEip8Message msg)
{
- byte[] data = Rlp.Encode(
- Rlp.Encode(Bytes.Concat(msg.Signature.Bytes, msg.Signature.RecoveryId)),
- Rlp.Encode(msg.PublicKey.Bytes),
- Rlp.Encode(msg.Nonce),
- Rlp.Encode(msg.Version)
- ).Bytes;
+ int totalLength = GetLength(msg);
+ // TODO: Account for the padding
+ byteBuffer.EnsureWritable(Rlp.LengthOfSequence(totalLength), true);
+ NettyRlpStream stream = new(byteBuffer);
+ stream.StartSequence(totalLength);
+ stream.Encode(Bytes.Concat(msg.Signature.Bytes, msg.Signature.RecoveryId));
+ stream.Encode(msg.PublicKey.Bytes);
+ stream.Encode(msg.Nonce);
+ stream.Encode(msg.Version);
+ _messagePad?.Pad(byteBuffer);
+ }
- return _messagePad?.Pad(data) ?? data;
+ public int GetLength(AuthEip8Message msg)
+ {
+ int contentLength = Rlp.LengthOf(Bytes.Concat(msg.Signature.Bytes, msg.Signature.RecoveryId))
+ + Rlp.LengthOf(msg.PublicKey.Bytes)
+ + Rlp.LengthOf(msg.Nonce)
+ + Rlp.LengthOf(msg.Version);
+ return contentLength;
}
- public AuthEip8Message Deserialize(byte[] msgBytes)
+ public AuthEip8Message Deserialize(IByteBuffer msgBytes)
{
- RlpStream rlpStream = msgBytes.AsRlpStream();
+ NettyRlpStream rlpStream = new(msgBytes);
AuthEip8Message authMessage = new();
rlpStream.ReadSequenceLength();
ReadOnlySpan sigAllBytes = rlpStream.DecodeByteArraySpan();
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthMessageSerializer.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthMessageSerializer.cs
index 54773ca9549..2372ffded7f 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthMessageSerializer.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/AuthMessageSerializer.cs
@@ -1,26 +1,28 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System;
+using System.Buffers;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
namespace Nethermind.Network.Rlpx.Handshake
{
- public class AuthMessageSerializer : IMessageSerializer
+ public class AuthMessageSerializer : IZeroMessageSerializer
{
public const int SigOffset = 0;
public const int SigLength = 65;
@@ -33,7 +35,7 @@ public class AuthMessageSerializer : IMessageSerializer
public const int IsTokenUsedLength = 1;
public const int IsTokenUsedOffset = NonceOffset + NonceLength;
public const int Length = IsTokenUsedOffset + IsTokenUsedLength;
-
+
// 65 (sig)
// 32 (ephem hash)
// 64 (pub)
@@ -47,31 +49,31 @@ public class AuthMessageSerializer : IMessageSerializer
// =============
// 307 (total)
- public byte[] Serialize(AuthMessage msg)
+ public void Serialize(IByteBuffer byteBuffer, AuthMessage msg)
{
- byte[] data = new byte[Length];
- Buffer.BlockCopy(msg.Signature.Bytes, 0, data, SigOffset, SigLength - 1);
- data[SigLength - 1] = msg.Signature.RecoveryId;
- Buffer.BlockCopy(msg.EphemeralPublicHash.Bytes, 0, data, EphemeralHashOffset, EphemeralHashLength);
- Buffer.BlockCopy(msg.PublicKey.Bytes, 0, data, PublicKeyOffset, PublicKeyLength);
- Buffer.BlockCopy(msg.Nonce, 0, data, NonceOffset, NonceLength);
- data[IsTokenUsedOffset] = msg.IsTokenUsed ? (byte)0x01 : (byte)0x00;
- return data;
+ byteBuffer.EnsureWritable(Length, true);
+ byteBuffer.WriteBytes(msg.Signature.Bytes);
+ byteBuffer.WriteByte(msg.Signature.RecoveryId);
+ byteBuffer.WriteBytes(msg.EphemeralPublicHash.Bytes);
+ byteBuffer.WriteBytes(msg.PublicKey.Bytes);
+ byteBuffer.WriteBytes(msg.Nonce);
+ byteBuffer.WriteByte(msg.IsTokenUsed ? 0x01 : 0x00);
}
- public AuthMessage Deserialize(byte[] msgBytes)
+ public AuthMessage Deserialize(IByteBuffer msgBytes)
{
- if (msgBytes.Length != Length)
+ if (msgBytes.ReadableBytes != Length)
{
- throw new NetworkingException($"Incorrect incoming {nameof(AuthMessage)} length. Expected {Length} but was {msgBytes.Length}", NetworkExceptionType.Validation);
+ throw new NetworkingException($"Incorrect incoming {nameof(AuthMessage)} length. Expected {Length} but was {msgBytes.ReadableBytes}", NetworkExceptionType.Validation);
}
AuthMessage authMessage = new();
- authMessage.Signature = new Signature(msgBytes.AsSpan().Slice(SigOffset, SigLength - 1), msgBytes[64]);
- authMessage.EphemeralPublicHash = new Keccak(msgBytes.Slice(EphemeralHashOffset, EphemeralHashLength));
- authMessage.PublicKey = new PublicKey(msgBytes.AsSpan().Slice(PublicKeyOffset, PublicKeyLength));
- authMessage.Nonce = msgBytes.Slice(NonceOffset, NonceLength);
- authMessage.IsTokenUsed = msgBytes[IsTokenUsedOffset] == 0x01;
+ Span msg = msgBytes.ReadAllBytesAsSpan();
+ authMessage.Signature = new Signature(msg.Slice(SigOffset, SigLength - 1), msg[64]);
+ authMessage.EphemeralPublicHash = new Keccak(msg.Slice(EphemeralHashOffset, EphemeralHashLength).ToArray());
+ authMessage.PublicKey = new PublicKey(msg.Slice(PublicKeyOffset, PublicKeyLength));
+ authMessage.Nonce = msg.Slice(NonceOffset, NonceLength).ToArray();
+ authMessage.IsTokenUsed = msg[IsTokenUsedOffset] == 0x01;
return authMessage;
}
}
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/Eip8MessagePad.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/Eip8MessagePad.cs
index d9c896d4be5..51d632e5ea7 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/Eip8MessagePad.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/Eip8MessagePad.cs
@@ -1,19 +1,20 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
+using DotNetty.Buffers;
using Nethermind.Core.Extensions;
using Nethermind.Crypto;
@@ -33,5 +34,11 @@ public byte[] Pad(byte[] message)
byte[] padding = _cryptoRandom.GenerateRandomBytes(100 + _cryptoRandom.NextInt(201));
return Bytes.Concat(message, padding);
}
+
+ public void Pad(IByteBuffer message)
+ {
+ byte[] padding = _cryptoRandom.GenerateRandomBytes(100 + _cryptoRandom.NextInt(201));
+ message.WriteBytes(padding);
+ }
}
}
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/HandshakeService.cs b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/HandshakeService.cs
index 5c182368314..cb826c312bd 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/Handshake/HandshakeService.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/Handshake/HandshakeService.cs
@@ -1,20 +1,22 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
using System;
+using System.Buffers;
+using DotNetty.Buffers;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
using Nethermind.Crypto;
@@ -67,31 +69,33 @@ public Packet Auth(PublicKey remoteNodeId, EncryptionHandshake handshake, bool p
if (preEip8Format)
{
- AuthMessage authMessage = new();
- authMessage.Nonce = handshake.InitiatorNonce;
- authMessage.PublicKey = _privateKey.PublicKey;
- authMessage.Signature = _ecdsa.Sign(handshake.EphemeralPrivateKey, new Keccak(forSigning));
- authMessage.IsTokenUsed = false;
- authMessage.EphemeralPublicHash = Keccak.Compute(handshake.EphemeralPrivateKey.PublicKey.Bytes);
-
- byte[] authData = _messageSerializationService.Serialize(authMessage);
- byte[] packetData = _eciesCipher.Encrypt(remoteNodeId, authData, Array.Empty());
+ AuthMessage authMessage = new()
+ {
+ Nonce = handshake.InitiatorNonce,
+ PublicKey = _privateKey.PublicKey,
+ Signature = _ecdsa.Sign(handshake.EphemeralPrivateKey, new Keccak(forSigning)),
+ IsTokenUsed = false,
+ EphemeralPublicHash = Keccak.Compute(handshake.EphemeralPrivateKey.PublicKey.Bytes)
+ };
+ IByteBuffer authData = _messageSerializationService.ZeroSerialize(authMessage);
+ byte[] packetData = _eciesCipher.Encrypt(remoteNodeId, authData.ReadAllBytesAsArray(), Array.Empty());
handshake.AuthPacket = new Packet(packetData);
return handshake.AuthPacket;
}
else
{
- AuthEip8Message authMessage = new();
- authMessage.Nonce = handshake.InitiatorNonce;
- authMessage.PublicKey = _privateKey.PublicKey;
- authMessage.Signature = _ecdsa.Sign(handshake.EphemeralPrivateKey, new Keccak(forSigning));
+ AuthEip8Message authMessage = new()
+ {
+ Nonce = handshake.InitiatorNonce,
+ PublicKey = _privateKey.PublicKey,
+ Signature = _ecdsa.Sign(handshake.EphemeralPrivateKey, new Keccak(forSigning))
+ };
- byte[] authData = _messageSerializationService.Serialize(authMessage);
- int size = authData.Length + 32 + 16 + 65; // data + MAC + IV + pub
+ IByteBuffer authData = _messageSerializationService.ZeroSerialize(authMessage);
+ int size = authData.ReadableBytes + 32 + 16 + 65; // data + MAC + IV + pub
byte[] sizeBytes = size.ToBigEndianByteArray().Slice(2, 2);
- byte[] packetData = _eciesCipher.Encrypt(remoteNodeId, authData,sizeBytes);
-
+ byte[] packetData = _eciesCipher.Encrypt(remoteNodeId, authData.ReadAllBytesAsArray(), sizeBytes);
handshake.AuthPacket = new Packet(Bytes.Concat(sizeBytes, packetData));
return handshake.AuthPacket;
}
@@ -143,26 +147,30 @@ public Packet Ack(EncryptionHandshake handshake, Packet auth)
if (preEip8Format)
{
if (_logger.IsTrace) _logger.Trace($"Building an {nameof(AckMessage)}");
- AckMessage ackMessage = new();
- ackMessage.EphemeralPublicKey = handshake.EphemeralPrivateKey.PublicKey;
- ackMessage.Nonce = handshake.RecipientNonce;
- byte[] ackData = _messageSerializationService.Serialize(ackMessage);
-
- data = _eciesCipher.Encrypt(handshake.RemoteNodeId, ackData, Array.Empty());
+ AckMessage ackMessage = new()
+ {
+ EphemeralPublicKey = handshake.EphemeralPrivateKey.PublicKey,
+ Nonce = handshake.RecipientNonce
+ };
+
+ IByteBuffer ackData = _messageSerializationService.ZeroSerialize(ackMessage);
+ data = _eciesCipher.Encrypt(handshake.RemoteNodeId, ackData.ReadAllBytesAsArray(), Array.Empty());
}
else
{
if (_logger.IsTrace) _logger.Trace($"Building an {nameof(AckEip8Message)}");
- AckEip8Message ackMessage = new();
- ackMessage.EphemeralPublicKey = handshake.EphemeralPrivateKey.PublicKey;
- ackMessage.Nonce = handshake.RecipientNonce;
- byte[] ackData = _messageSerializationService.Serialize(ackMessage);
-
- int size = ackData.Length + 32 + 16 + 65; // data + MAC + IV + pub
+ AckEip8Message ackMessage = new()
+ {
+ EphemeralPublicKey = handshake.EphemeralPrivateKey.PublicKey,
+ Nonce = handshake.RecipientNonce
+ };
+ IByteBuffer ackData = _messageSerializationService.ZeroSerialize(ackMessage);
+
+ int size = ackData.ReadableBytes + 32 + 16 + 65; // data + MAC + IV + pub
byte[] sizeBytes = size.ToBigEndianByteArray().Slice(2, 2);
- data = Bytes.Concat(sizeBytes, _eciesCipher.Encrypt(handshake.RemoteNodeId, ackData, sizeBytes));
+ data = Bytes.Concat(sizeBytes, _eciesCipher.Encrypt(handshake.RemoteNodeId, ackData.ReadAllBytesAsArray(), sizeBytes));
}
-
+
handshake.AckPacket = new Packet(data);
SetSecrets(handshake, HandshakeRole.Recipient);
return handshake.AckPacket;
@@ -231,11 +239,11 @@ public static void SetSecrets(EncryptionHandshake handshake, HandshakeRole hands
// byte[] token = Keccak.Compute(sharedSecret).Bytes;
sharedSecret.CopyTo(tempConcat.Slice(32, 32));
byte[] aesSecret = Keccak.Compute(tempConcat).Bytes;
-
+
sharedSecret.Clear();
aesSecret.CopyTo(tempConcat.Slice(32, 32));
byte[] macSecret = Keccak.Compute(tempConcat).Bytes;
-
+
ephemeralSharedSecret.Clear();
handshake.Secrets = new EncryptionSecrets();
// handshake.Secrets.Token = token;
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/Packet.cs b/src/Nethermind/Nethermind.Network/Rlpx/Packet.cs
index 35e0c9f1ed1..462437af4d9 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/Packet.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/Packet.cs
@@ -25,7 +25,7 @@ public class Packet
public Packet(ZeroPacket zeroPacket)
{
- Data = zeroPacket.Content.ReadAllBytes();
+ Data = zeroPacket.Content.ReadAllBytesAsArray();
PacketType = zeroPacket.PacketType;
Protocol = zeroPacket.Protocol;
}
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacketSplitter.cs b/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacketSplitter.cs
index 26529cf271b..524a15ceb11 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacketSplitter.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/ZeroPacketSplitter.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -21,6 +21,7 @@
using DotNetty.Transport.Channels;
using Nethermind.Core.Attributes;
using Nethermind.Logging;
+using Nethermind.Network.P2P;
using Nethermind.Serialization.Rlp;
namespace Nethermind.Network.Rlpx
@@ -38,7 +39,7 @@ public void DisableFraming()
{
MaxFrameSize = int.MaxValue;
}
-
+
public int MaxFrameSize { get; private set; } = Frame.DefaultMaxFrameSize;
private int _contextId;
@@ -77,7 +78,7 @@ protected override void Encode(IChannelHandlerContext context, IByteBuffer input
if (framesCount == 1)
{
// // commented out after Trinity reported #2052
- // // not 100% sure they are right but they may be
+ // // not 100% sure they are right but they may be
// // 193|128 is an RLP encoded array with one element that is zero
// /*3*/
// output.WriteByte(193);
@@ -85,7 +86,7 @@ protected override void Encode(IChannelHandlerContext context, IByteBuffer input
// output.WriteByte(128);
// /*5-16*/
// output.WriteZero(11);
-
+
// 194|128 is an RLP encoded array with two elements that are zero
/*3*/
output.WriteByte(194);
@@ -98,22 +99,21 @@ protected override void Encode(IChannelHandlerContext context, IByteBuffer input
}
else
{
- Rlp[] headerDataItems;
+ NettyRlpStream stream = new (output);
+ int contentLength = Rlp.LengthOf(_contextId) + Rlp.LengthOf(0);
if (i == 0)
{
- headerDataItems = new Rlp[3];
- headerDataItems[2] = Rlp.Encode(totalPayloadSize);
+ contentLength += Rlp.LengthOf(totalPayloadSize);
}
- else
+ output.EnsureWritable(Rlp.LengthOfSequence(contentLength));
+ stream.StartSequence(contentLength);
+ stream.Encode(0);
+ stream.Encode(_contextId);
+ if (i == 0)
{
- headerDataItems = new Rlp[2];
+ stream.Encode(totalPayloadSize);
}
-
- headerDataItems[1] = Rlp.Encode(_contextId);
- headerDataItems[0] = Rlp.Encode(0);
- byte[] headerDataBytes = Rlp.Encode(headerDataItems).Bytes;
- output.WriteBytes(headerDataBytes);
- output.WriteZero(Frame.HeaderSize - headerDataBytes.Length - 3);
+ output.WriteZero(Frame.HeaderSize - Rlp.LengthOfSequence(contentLength) - 3);
}
int framePacketTypeSize = 0;
diff --git a/src/Nethermind/Nethermind.Network/ZeroMessageSerializerExtensions.cs b/src/Nethermind/Nethermind.Network/ZeroMessageSerializerExtensions.cs
index f09773d190b..5c17c9f87c3 100644
--- a/src/Nethermind/Nethermind.Network/ZeroMessageSerializerExtensions.cs
+++ b/src/Nethermind/Nethermind.Network/ZeroMessageSerializerExtensions.cs
@@ -31,7 +31,7 @@ serializer is IZeroInnerMessageSerializer zeroInnerMessageSerializer
try
{
serializer.Serialize(byteBuffer, message);
- return byteBuffer.ReadAllBytes();
+ return byteBuffer.ReadAllBytesAsArray();
}
finally
diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/BlockInfoDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/BlockInfoDecoder.cs
index 85317352cfb..42430c64d13 100644
--- a/src/Nethermind/Nethermind.Serialization.Rlp/BlockInfoDecoder.cs
+++ b/src/Nethermind/Nethermind.Serialization.Rlp/BlockInfoDecoder.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -30,7 +30,7 @@ public class BlockInfoDecoder : IRlpStreamDecoder, IRlpValueDecoder, IRlpValueDecoder, IRlpValueDecoder.
using System;
using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
using Nethermind.Core;
namespace Nethermind.Serialization.Rlp
@@ -28,12 +30,12 @@ public class ChainLevelDecoder : IRlpStreamDecoder, IRlpValueDec
{
throw new RlpException($"Received a 0 length stream when decoding a {nameof(ChainLevelInfo)}");
}
-
+
if (rlpStream.IsNextItemNull())
{
return null;
}
-
+
int lastCheck = rlpStream.ReadSequenceLength() + rlpStream.Position;
bool hasMainChainBlock = rlpStream.DecodeBool();
@@ -59,9 +61,28 @@ public class ChainLevelDecoder : IRlpStreamDecoder, IRlpValueDec
return info;
}
- public void Encode(RlpStream stream, ChainLevelInfo item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
+ public void Encode(RlpStream stream, ChainLevelInfo? item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
- throw new NotImplementedException();
+ if (item == null)
+ {
+ stream.Encode(Rlp.OfEmptySequence);
+ return;
+ }
+
+ if (item.BlockInfos.Any(t => t == null))
+ {
+ throw new InvalidOperationException($"{nameof(BlockInfo)} is null when encoding {nameof(ChainLevelInfo)}");
+ }
+
+ int contentLength = GetLength(item, rlpBehaviors);
+ stream.StartSequence(contentLength);
+ stream.Encode(item.HasBlockOnMainChain);
+ int infoLength = GetBlockInfoLength(item.BlockInfos);
+ stream.StartSequence(infoLength);
+ foreach (BlockInfo? blockInfo in item.BlockInfos)
+ {
+ stream.Encode(blockInfo);
+ }
}
public ChainLevelInfo? Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
@@ -70,7 +91,7 @@ public void Encode(RlpStream stream, ChainLevelInfo item, RlpBehaviors rlpBehavi
{
return null;
}
-
+
int lastCheck = decoderContext.ReadSequenceLength() + decoderContext.Position;
bool hasMainChainBlock = decoderContext.DecodeBool();
@@ -110,7 +131,7 @@ public Rlp Encode(ChainLevelInfo? item, RlpBehaviors rlpBehaviors = RlpBehaviors
throw new InvalidOperationException($"{nameof(BlockInfo)} is null when encoding {nameof(ChainLevelInfo)}");
}
}
-
+
Rlp[] elements = new Rlp[2];
elements[0] = Rlp.Encode(item.HasBlockOnMainChain);
elements[1] = Rlp.Encode(item.BlockInfos);
@@ -121,7 +142,21 @@ public Rlp Encode(ChainLevelInfo? item, RlpBehaviors rlpBehaviors = RlpBehaviors
public int GetLength(ChainLevelInfo item, RlpBehaviors rlpBehaviors)
{
- throw new NotImplementedException();
+ int contentLength = 0;
+ contentLength += Rlp.LengthOf(item.HasBlockOnMainChain);
+ contentLength += Rlp.LengthOfSequence(GetBlockInfoLength(item.BlockInfos));
+ return contentLength;
+ }
+
+ private int GetBlockInfoLength(BlockInfo[] item)
+ {
+ int contentLength = 0;
+ foreach (BlockInfo? blockInfo in item)
+ {
+ contentLength += Rlp.LengthOf(blockInfo);
+ }
+
+ return contentLength;
}
}
}
diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs
index f57c3d4596f..b18d459a8fc 100644
--- a/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs
+++ b/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -26,7 +26,7 @@ static ReceiptMessageDecoder()
{
Rlp.Decoders[typeof(TxReceipt)] = new ReceiptMessageDecoder();
}
-
+
public TxReceipt Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
if (rlpStream.IsNextItemNull())
@@ -34,14 +34,14 @@ public TxReceipt Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBeha
rlpStream.ReadByte();
return null;
}
-
+
TxReceipt txReceipt = new();
if (!rlpStream.IsSequenceNext())
{
rlpStream.SkipLength();
txReceipt.TxType = (TxType)rlpStream.ReadByte();
}
-
+
_ = rlpStream.ReadSequenceLength();
byte[] firstItem = rlpStream.DecodeByteArray();
if (firstItem.Length == 1 && (firstItem[0] == 0 || firstItem[0] == 1))
@@ -59,7 +59,7 @@ public TxReceipt Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBeha
txReceipt.PostTransactionState = firstItem.Length == 0 ? null : new Keccak(firstItem);
txReceipt.GasUsedTotal = (long) rlpStream.DecodeUBigInt();
}
-
+
txReceipt.Bloom = rlpStream.DecodeBloom();
int lastCheck = rlpStream.ReadSequenceLength() + rlpStream.Position;
@@ -75,29 +75,13 @@ public TxReceipt Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBeha
return txReceipt;
}
- public Rlp Encode(TxReceipt item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
- {
- if (item.TxType == TxType.Legacy)
- {
- return Rlp.Encode(
- (rlpBehaviors & RlpBehaviors.Eip658Receipts) == RlpBehaviors.Eip658Receipts
- ? Rlp.Encode(item.StatusCode)
- : Rlp.Encode(item.PostTransactionState),
- Rlp.Encode(item.GasUsedTotal),
- Rlp.Encode(item.Bloom),
- Rlp.Encode(item.Logs));
- }
-
- return new Rlp(EncodeNew(item, rlpBehaviors));
- }
-
private (int Total, int Logs) GetContentLength(TxReceipt item, RlpBehaviors rlpBehaviors)
{
if (item == null)
{
return (0, 0);
}
-
+
int contentLength = 0;
contentLength += Rlp.LengthOf(item.GasUsedTotal);
contentLength += Rlp.LengthOf(item.Bloom);
@@ -109,14 +93,14 @@ public Rlp Encode(TxReceipt item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
if (!item.SkipStateAndStatusInRlp)
{
- contentLength += isEip658Receipts
- ? Rlp.LengthOf(item.StatusCode)
+ contentLength += isEip658Receipts
+ ? Rlp.LengthOf(item.StatusCode)
: Rlp.LengthOf(item.PostTransactionState);
}
return (contentLength, logsLength);
}
-
+
private int GetLogsLength(TxReceipt item)
{
int logsLength = 0;
@@ -124,7 +108,7 @@ private int GetLogsLength(TxReceipt item)
{
logsLength += Rlp.LengthOf(item.Logs[i]);
}
-
+
return logsLength;
}
@@ -144,20 +128,20 @@ public int GetLength(TxReceipt item, RlpBehaviors rlpBehaviors)
: receiptPayloadLength;
return result;
}
-
+
public byte[] EncodeNew(TxReceipt? item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
if (item is null)
{
return Rlp.OfEmptySequence.Bytes;
}
-
+
int length = GetLength(item, rlpBehaviors);
RlpStream stream = new(length);
Encode(stream, item, rlpBehaviors);
return stream.Data;
}
-
+
public void Encode(RlpStream rlpStream, TxReceipt item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
{
if (item == null)
@@ -168,16 +152,16 @@ public void Encode(RlpStream rlpStream, TxReceipt item, RlpBehaviors rlpBehavior
(int totalContentLength, int logsLength) = GetContentLength(item, rlpBehaviors);
int sequenceLength = Rlp.LengthOfSequence(totalContentLength);
-
+
bool isEip658Receipts = (rlpBehaviors & RlpBehaviors.Eip658Receipts) == RlpBehaviors.Eip658Receipts;
-
+
if (item.TxType != TxType.Legacy)
{
if ((rlpBehaviors & RlpBehaviors.SkipTypedWrapping) == RlpBehaviors.None)
{
rlpStream.StartByteArray(sequenceLength + 1, false);
}
-
+
rlpStream.WriteByte((byte)item.TxType);
}
@@ -196,7 +180,7 @@ public void Encode(RlpStream rlpStream, TxReceipt item, RlpBehaviors rlpBehavior
rlpStream.Encode(item.GasUsedTotal);
rlpStream.Encode(item.Bloom);
-
+
rlpStream.StartSequence(logsLength);
for (var i = 0; i < item.Logs.Length; i++)
{
diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs b/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs
index 505d3235a82..77bbe8997c7 100644
--- a/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs
+++ b/src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -35,11 +35,11 @@ namespace Nethermind.Serialization.Rlp
public class Rlp
{
public const int LengthOfKeccakRlp = 33;
-
+
public const int LengthOfAddressRlp = 21;
internal const int DebugMessageContentLength = 2048;
-
+
public const byte EmptyArrayByte = 128;
public const byte NullObjectByte = 192;
@@ -272,16 +272,16 @@ public static Rlp Encode(
{
sequence[position++] = Encode(transaction.GasPrice);
}
-
+
sequence[position++] = Encode(transaction.GasLimit);
sequence[position++] = Encode(transaction.To);
sequence[position++] = Encode(transaction.Value);
sequence[position++] = Encode(transaction.Data);
if (transaction.Type != TxType.Legacy)
{
- sequence[position++] = Encode(transaction.AccessList);
+ sequence[position++] = Encode(transaction.AccessList);
}
-
+
if (forSigning)
{
if (includeSigChainIdHack)
@@ -304,10 +304,10 @@ public static Rlp Encode(
{
sequence[position++] = Encode(transaction.Type == TxType.Legacy ? signature.V : signature.RecoveryId);
sequence[position++] = Encode(signature.RAsSpan.WithoutLeadingZeros());
- sequence[position++] = Encode(signature.SAsSpan.WithoutLeadingZeros());
+ sequence[position++] = Encode(signature.SAsSpan.WithoutLeadingZeros());
}
}
-
+
Debug.Assert(position == 6 + extraItems);
Rlp result = Encode(sequence);
@@ -399,7 +399,7 @@ public static Rlp EncodeNonce(ulong value)
BinaryPrimitives.WriteUInt64BigEndian(bytes, value);
return Encode(bytes);
}
-
+
public static Rlp Encode(ulong value)
{
return Encode((long)value);
@@ -812,14 +812,14 @@ public int PeekNextRlpLength()
(int a, int b) = PeekPrefixAndContentLength();
return a + b;
}
-
+
public Span Peek(int length)
{
Span item = Read(length);
Position -= item.Length;
return item;
}
-
+
public (int PrefixLength, int ContentLength) ReadPrefixAndContentLength()
{
(int prefixLength, int contentLengt) result;
@@ -865,16 +865,16 @@ public Span Peek(int length)
result = (lengthOfContentLength + 1, contentLength);
}
-
+
return result;
}
-
+
public (int PrefixLength, int ContentLength) PeekPrefixAndContentLength()
{
int memorizedPosition = Position;
(int PrefixLength, int ContentLength) result = ReadPrefixAndContentLength();
-
+
Position = memorizedPosition;
return result;
}
@@ -958,7 +958,7 @@ public void Check(int nextCheck)
}
// This class was introduce to reduce allocations when deserializing receipts. In order to deserialize receipts we first try to deserialize it in new format and then in old format.
- // If someone didn't do migration this will result in excessive allocations and GC of the not needed strings.
+ // If someone didn't do migration this will result in excessive allocations and GC of the not needed strings.
private class DecodeKeccakRlpException : RlpException
{
private readonly int _prefix;
@@ -1100,7 +1100,7 @@ public BigInteger DecodeUBigInt()
// https://github.com/NethermindEth/nethermind/issues/113
if (Data[Position] == 249)
{
- Position += 5; // tks: skip 249 1 2 129 127 and read 256 bytes
+ Position += 5; // tks: skip 249 1 2 129 127 and read 256 bytes
bloomBytes = Read(256);
}
else
@@ -1128,7 +1128,7 @@ public void DecodeBloomStructRef(out BloomStructRef bloom)
// https://github.com/NethermindEth/nethermind/issues/113
if (Data[Position] == 249)
{
- Position += 5; // tks: skip 249 1 2 129 127 and read 256 bytes
+ Position += 5; // tks: skip 249 1 2 129 127 and read 256 bytes
bloomBytes = Read(256);
}
else
@@ -1302,9 +1302,9 @@ public bool DecodeBool()
throw new RlpException($"Unexpected prefix of {prefix} when decoding a byte array at position {Position} in the message of length {Length} starting with {Description}");
}
-
+
private string Description => Data.Slice(0, Math.Min(DebugMessageContentLength, Length)).ToHexString();
-
+
public byte PeekByte()
{
return Data[Position];
@@ -1359,7 +1359,7 @@ public long DecodeLong()
return result;
}
-
+
public ulong DecodeULong()
{
int prefix = ReadByte();
@@ -1523,7 +1523,7 @@ public static int LengthOf(Keccak? item)
public static int LengthOf(Keccak[] keccaks, bool includeLengthOfSequenceStart = false)
{
int value = keccaks?.Length * LengthOfKeccakRlp ?? 0;
-
+
if (includeLengthOfSequenceStart)
{
value = LengthOfSequence(value);
@@ -1531,7 +1531,7 @@ public static int LengthOf(Keccak[] keccaks, bool includeLengthOfSequenceStart =
return value;
}
-
+
public static int LengthOf(Address? item)
{
return item is null ? 1 : 21;
@@ -1614,5 +1614,12 @@ public static int LengthOf(LogEntry item)
IRlpDecoder? rlpDecoder = GetDecoder();
return rlpDecoder?.GetLength(item, RlpBehaviors.None) ?? throw new RlpException($"{nameof(Rlp)} does not support length of {nameof(LogEntry)}");
}
+
+ public static int LengthOf(BlockInfo item)
+ {
+ IRlpDecoder? rlpDecoder = GetDecoder();
+ return rlpDecoder?.GetLength(item, RlpBehaviors.None) ?? throw new RlpException($"{nameof(Rlp)} does not support length of {nameof(BlockInfo)}");
+ }
+
}
}
diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs
index 917c0285f3a..4e92c226398 100644
--- a/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs
+++ b/src/Nethermind/Nethermind.Serialization.Rlp/RlpStream.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -29,6 +29,7 @@ public class RlpStream
{
private static readonly HeaderDecoder _headerDecoder = new();
private static readonly BlockDecoder _blockDecoder = new();
+ private static readonly BlockInfoDecoder _blockInfoDecoder = new();
private static readonly TxDecoder _txDecoder = new();
private static readonly ReceiptMessageDecoder _receiptDecoder = new();
private static readonly LogEntryDecoder _logEntryDecoder = LogEntryDecoder.Instance;
@@ -76,6 +77,11 @@ public void Encode(LogEntry value)
_logEntryDecoder.Encode(this, value);
}
+ public void Encode(BlockInfo value)
+ {
+ _blockInfoDecoder.Encode(this, value);
+ }
+
public void StartByteArray(int contentLength, bool firstByteLessThan128)
{
switch (contentLength)
@@ -208,7 +214,7 @@ public void Encode(Keccak[] keccaks)
}
}
}
-
+
public void Encode(Address? address)
{
if (address == null)
@@ -529,7 +535,7 @@ public int PeekNextRlpLength()
(int a, int b) = PeekPrefixAndContentLength();
return a + b;
}
-
+
public (int PrefixLength, int ContentLength) ReadPrefixAndContentLength()
{
(int prefixLength, int contentLength) result;
@@ -575,7 +581,7 @@ public int PeekNextRlpLength()
result = (lengthOfContentLength + 1, contentLength);
}
-
+
return result;
}
@@ -583,11 +589,11 @@ public int PeekNextRlpLength()
{
int memorizedPosition = Position;
(int PrefixLength, int ContentLength) result = ReadPrefixAndContentLength();
-
+
Position = memorizedPosition;
return result;
}
-
+
public int ReadSequenceLength()
{
int prefix = ReadByte();
@@ -771,7 +777,7 @@ public BigInteger DecodeUBigInt()
// https://github.com/NethermindEth/nethermind/issues/113
if (PeekByte() == 249)
{
- SkipBytes(5); // tks: skip 249 1 2 129 127 and read 256 bytes
+ SkipBytes(5); // tks: skip 249 1 2 129 127 and read 256 bytes
bloomBytes = Read(256);
}
else
@@ -796,7 +802,7 @@ public Span PeekNextItem()
int length = PeekNextRlpLength();
return Peek(length);
}
-
+
public Span Peek(int length)
{
Span item = Read(length);
diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs
index 4bae26a41a1..ee03297ab68 100644
--- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs
+++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -150,7 +150,7 @@ protected override async Task Dispatch(PeerInfo allocation, TestBatch request, C
}
await Task.CompletedTask;
- Console.WriteLine("Setting result");
+ // Console.WriteLine("Setting result");
int[] result = new int[request.Length];
for (int i = 0; i < request.Length; i++)
{
@@ -158,7 +158,7 @@ protected override async Task Dispatch(PeerInfo allocation, TestBatch request, C
}
request.Result = result;
- Console.WriteLine("Finished Execution");
+ // Console.WriteLine("Finished Execution");
}
}
@@ -181,12 +181,12 @@ public override SyncResponseHandlingResult HandleResponse(TestBatch response, Pe
{
if (response.Result == null)
{
- Console.WriteLine("Handling failed response");
+ // Console.WriteLine("Handling failed response");
_returned.Enqueue(response);
}
else
{
- Console.WriteLine("Handling OK response");
+ // Console.WriteLine("Handling OK response");
for (int i = 0; i < response.Length; i++)
{
lock (_results)
@@ -196,7 +196,7 @@ public override SyncResponseHandlingResult HandleResponse(TestBatch response, Pe
}
}
- Console.WriteLine($"Decrementing Pending Requests {Interlocked.Decrement(ref _pendingRequests)}");
+ // Console.WriteLine($"Decrementing Pending Requests {Interlocked.Decrement(ref _pendingRequests)}");
return SyncResponseHandlingResult.OK;
}
@@ -210,7 +210,7 @@ public override async Task PrepareRequest()
TestBatch testBatch;
if (_returned.TryDequeue(out TestBatch returned))
{
- Console.WriteLine("Sending previously failed batch");
+ // Console.WriteLine("Sending previously failed batch");
testBatch = returned;
}
else
@@ -221,10 +221,10 @@ public override async Task PrepareRequest()
if (_highestRequested >= Max)
{
- Console.WriteLine("Pending: " + _pendingRequests);
+ // Console.WriteLine("Pending: " + _pendingRequests);
if (_pendingRequests == 0)
{
- Console.WriteLine("Changing to finished");
+ // Console.WriteLine("Changing to finished");
Finish();
}
@@ -240,7 +240,7 @@ public override async Task PrepareRequest()
testBatch = new TestBatch(start, 8);
}
- Console.WriteLine($"Incrementing Pending Requests {Interlocked.Increment(ref _pendingRequests)}");
+ // Console.WriteLine($"Incrementing Pending Requests {Interlocked.Increment(ref _pendingRequests)}");
return testBatch;
}
}
diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs
index e7e26d4d6bc..b4db2c122ef 100644
--- a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs
+++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs
@@ -725,13 +725,13 @@ private async Task DoWork(string desc, SyncPeerAllocation allocation)
if (allocation.HasPeer)
{
int workTime = _workRandomDelay.Next(1000);
- Console.WriteLine($"{desc} will work for {workTime} ms");
+ // Console.WriteLine($"{desc} will work for {workTime} ms");
await Task.Delay(workTime);
- Console.WriteLine($"{desc} finished work after {workTime} ms");
+ // Console.WriteLine($"{desc} finished work after {workTime} ms");
}
ctx.Pool.Free(allocation);
- Console.WriteLine($"{desc} freed allocation");
+ // Console.WriteLine($"{desc} freed allocation");
}
[Test, Retry(3)]
@@ -761,12 +761,12 @@ public async Task Try_to_break_multithreaded()
task.ContinueWith(t =>
#pragma warning restore 4014
{
- Console.WriteLine($"{iterationsLocal} Decrement on {t.IsCompleted}");
+ // Console.WriteLine($"{iterationsLocal} Decrement on {t.IsCompleted}");
Interlocked.Decrement(ref _pendingRequests);
});
}
- Console.WriteLine(iterations + " " + failures + " " + ctx.Pool.ReplaceableAllocations.Count() + " " + _pendingRequests);
+ // Console.WriteLine(iterations + " " + failures + " " + ctx.Pool.ReplaceableAllocations.Count() + " " + _pendingRequests);
await Task.Delay(10);
} while (iterations-- > 0 || _pendingRequests > 0);
diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs
index 3008a2380f6..a643e0a5565 100644
--- a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs
+++ b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs
@@ -182,7 +182,7 @@ public Task GetBlockHeaders(Keccak startHash, int maxBlocks, int
{
if (_causeTimeoutOnInit)
{
- Console.WriteLine("RESPONDING TO GET HEAD BLOCK HEADER WITH EXCEPTION");
+ // Console.WriteLine("RESPONDING TO GET HEAD BLOCK HEADER WITH EXCEPTION");
await Task.FromException(new TimeoutException());
}
@@ -193,11 +193,11 @@ public Task GetBlockHeaders(Keccak startHash, int maxBlocks, int
}
catch (Exception)
{
- Console.WriteLine("RESPONDING TO GET HEAD BLOCK HEADER EXCEPTION");
+ // Console.WriteLine("RESPONDING TO GET HEAD BLOCK HEADER EXCEPTION");
throw;
}
- Console.WriteLine($"RESPONDING TO GET HEAD BLOCK HEADER WITH RESULT {header.Number}");
+ // Console.WriteLine($"RESPONDING TO GET HEAD BLOCK HEADER WITH RESULT {header.Number}");
return header;
}
@@ -744,7 +744,7 @@ public void Can_extend_chain_by_more_than_one_on_new_block_message()
.AfterNewBlockMessage(peerA.HeadBlock, peerA)
.BestSuggestedHeaderIs(peerA.HeadHeader).Wait().Stop();
- Console.WriteLine("why?");
+ // Console.WriteLine("why?");
}
[Test, Retry(3)]