Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/Nethermind/Nethermind.Core.Test/RlpTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,5 @@ private static byte[] BuildLongFormRlp(int prefix, int contentLength)
}
return data;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ public BlockBodiesMessage(BlockBody?[] bodies)
Bodies = new OwnedBlockBodies(bodies);
}

public override void Dispose()
{
base.Dispose();
Bodies?.Dispose();
}

public override string ToString() => $"{nameof(BlockBodiesMessage)}({Bodies?.Bodies?.Length ?? 0})";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,24 @@ public int GetLength(BlockBodiesMessage message, out int contentLength)

public BlockBodiesMessage Deserialize(IByteBuffer byteBuffer)
{
NettyBufferMemoryOwner memoryOwner = new(byteBuffer);
NettyBufferMemoryOwner? memoryOwner = new(byteBuffer);

Rlp.ValueDecoderContext ctx = new(memoryOwner.Memory, true);
int startingPosition = ctx.Position;
BlockBody[]? bodies = ctx.DecodeArray(_blockBodyDecoder, false, limit: RlpLimit);
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startingPosition));
try
{
BlockBody[]? bodies = ctx.DecodeArray(_blockBodyDecoder, false, limit: RlpLimit);
OwnedBlockBodies ownedBodies = new(bodies, memoryOwner);
memoryOwner = null;
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startingPosition));

return new() { Bodies = new(bodies, memoryOwner) };
return new() { Bodies = ownedBodies };
}
catch
{
memoryOwner?.Dispose();
throw;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public class AccountRangeMessage : SnapMessageBase
public override void Dispose()
{
base.Dispose();
PathsWithAccounts.Dispose();
Proofs.Dispose();
PathsWithAccounts?.Dispose();
Proofs?.Dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,31 +50,43 @@ public void Serialize(IByteBuffer byteBuffer, AccountRangeMessage message)

public AccountRangeMessage Deserialize(IByteBuffer byteBuffer)
{
NettyBufferMemoryOwner memoryOwner = new(byteBuffer);
NettyBufferMemoryOwner? memoryOwner = new(byteBuffer);
Rlp.ValueDecoderContext ctx = new(memoryOwner.Memory, true);
int startPos = ctx.Position;

ctx.ReadSequenceLength();

AccountRangeMessage message = new();
message.RequestId = ctx.DecodeLong();
ArrayPoolList<PathWithAccount>? pathsWithAccounts = null;

int pwasCheck = ctx.ReadSequenceLength() + ctx.Position;
int count = ctx.PeekNumberOfItemsRemaining(pwasCheck);
ctx.GuardLimit(count, SnapMessageLimits.AccountRangeEntriesRlpLimit);
ArrayPoolList<PathWithAccount> pathsWithAccounts = new(count);
for (int i = 0; i < count; i++)
try
{
ctx.ReadSequenceLength();
pathsWithAccounts.Add(new PathWithAccount(ctx.DecodeKeccak(), _decoder.Decode(ref ctx)));
}
message.RequestId = ctx.DecodeLong();

message.PathsWithAccounts = pathsWithAccounts;
message.Proofs = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
int pwasCheck = ctx.ReadSequenceLength() + ctx.Position;
int count = ctx.PeekNumberOfItemsRemaining(pwasCheck);
ctx.GuardLimit(count, SnapMessageLimits.AccountRangeEntriesRlpLimit);
pathsWithAccounts = new ArrayPoolList<PathWithAccount>(count);
for (int i = 0; i < count; i++)
{
ctx.ReadSequenceLength();
pathsWithAccounts.Add(new PathWithAccount(ctx.DecodeKeccak(), _decoder.Decode(ref ctx)));
}

byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));
message.PathsWithAccounts = pathsWithAccounts;
pathsWithAccounts = null;
message.Proofs = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
memoryOwner = null;

return message;
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));

return message;
}
catch
{
pathsWithAccounts?.Dispose();
message.Dispose();
memoryOwner?.Dispose();
throw;
}
}

private (int contentLength, int pwasLength) GetLength(AccountRangeMessage message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,28 @@ public void Serialize(IByteBuffer byteBuffer, ByteCodesMessage message)

public ByteCodesMessage Deserialize(IByteBuffer byteBuffer)
{
NettyBufferMemoryOwner memoryOwner = new(byteBuffer);
NettyBufferMemoryOwner? memoryOwner = new(byteBuffer);
Rlp.ValueDecoderContext ctx = new(memoryOwner.Memory, true);
int startPos = ctx.Position;
RlpByteArrayList? list = null;

ctx.ReadSequenceLength();
long requestId = ctx.DecodeLong();
try
{
ctx.ReadSequenceLength();
long requestId = ctx.DecodeLong();

RlpByteArrayList list = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));
list = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
memoryOwner = null;
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));

return new ByteCodesMessage(list) { RequestId = requestId };
return new ByteCodesMessage(list) { RequestId = requestId };
}
catch
{
list?.Dispose();
memoryOwner?.Dispose();
throw;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,37 @@ private static void EncodePaths(RlpStream stream, IReadOnlyList<PathGroup> paths

public GetTrieNodesMessage Deserialize(IByteBuffer byteBuffer)
{
NettyBufferMemoryOwner memoryOwner = new(byteBuffer);
NettyBufferMemoryOwner? memoryOwner = new(byteBuffer);
Rlp.ValueDecoderContext ctx = new(memoryOwner.Memory, true);
int startingPosition = ctx.Position;
GetTrieNodesMessage message = new();
IRlpItemList? rawPaths = null;

ctx.ReadSequenceLength();
long requestId = ctx.DecodeLong();
Hash256? rootHash = ctx.DecodeKeccak();
try
{
ctx.ReadSequenceLength();
message.RequestId = ctx.DecodeLong();
Hash256? rootHash = ctx.DecodeKeccak();
message.RootHash = rootHash;

IRlpItemList rawPaths = RlpItemList.DecodeList(ref ctx, memoryOwner);
ValidatePathGroups(rawPaths);
RlpPathGroupList paths = new(rawPaths);
rawPaths = RlpItemList.DecodeList(ref ctx, memoryOwner);
memoryOwner = null;
ValidatePathGroups(rawPaths);
message.Paths = new RlpPathGroupList(rawPaths);
rawPaths = null;

long bytes = ctx.DecodeLong();
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startingPosition));
message.Bytes = ctx.DecodeLong();
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startingPosition));

return new GetTrieNodesMessage { RequestId = requestId, RootHash = rootHash, Paths = paths, Bytes = bytes };
return message;
}
catch
{
rawPaths?.Dispose();
message.Dispose();
memoryOwner?.Dispose();
throw;
}
}

private static void ValidatePathGroups(IRlpItemList paths)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,38 @@ public void Serialize(IByteBuffer byteBuffer, StorageRangeMessage message)

public StorageRangeMessage Deserialize(IByteBuffer byteBuffer)
{
NettyBufferMemoryOwner memoryOwner = new(byteBuffer);
NettyBufferMemoryOwner? memoryOwner = new(byteBuffer);
Rlp.ValueDecoderContext ctx = new(memoryOwner.Memory, true);
int startPos = ctx.Position;

ctx.ReadSequenceLength();

StorageRangeMessage message = new();
message.RequestId = ctx.DecodeLong();

message.Slots = ctx.DecodeArrayPoolList<IOwnedReadOnlyList<PathWithStorageSlot>>(static (ref Rlp.ValueDecoderContext outerCtx) =>
outerCtx.DecodeArrayPoolList(static (ref Rlp.ValueDecoderContext innerCtx) =>
{
innerCtx.ReadSequenceLength();
Hash256 path = innerCtx.DecodeKeccak();
byte[] value = innerCtx.DecodeByteArray(StorageSlotValueRlpLimit);
return new PathWithStorageSlot(in path.ValueHash256, value);
}, limit: SnapMessageLimits.StorageRangeSlotsPerAccountRlpLimit), limit: SnapMessageLimits.StorageRangeAccountsRlpLimit);
message.Proofs = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
try
{
ctx.ReadSequenceLength();
message.RequestId = ctx.DecodeLong();

message.Slots = ctx.DecodeArrayPoolList<IOwnedReadOnlyList<PathWithStorageSlot>>(static (ref Rlp.ValueDecoderContext outerCtx) =>
outerCtx.DecodeArrayPoolList(static (ref Rlp.ValueDecoderContext innerCtx) =>
{
innerCtx.ReadSequenceLength();
Hash256 path = innerCtx.DecodeKeccak();
byte[] value = innerCtx.DecodeByteArray(StorageSlotValueRlpLimit);
return new PathWithStorageSlot(in path.ValueHash256, value);
}, limit: SnapMessageLimits.StorageRangeSlotsPerAccountRlpLimit), limit: SnapMessageLimits.StorageRangeAccountsRlpLimit);
message.Proofs = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
memoryOwner = null;

byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));

return message;
return message;
}
catch
{
message.Dispose();
memoryOwner?.Dispose();
throw;
}
}

private static (int contentLength, int allSlotsLength, int[] accountSlotsLengths) CalculateLengths(StorageRangeMessage message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,28 @@ public void Serialize(IByteBuffer byteBuffer, TrieNodesMessage message)

public TrieNodesMessage Deserialize(IByteBuffer byteBuffer)
{
NettyBufferMemoryOwner memoryOwner = new(byteBuffer);
NettyBufferMemoryOwner? memoryOwner = new(byteBuffer);
Rlp.ValueDecoderContext ctx = new(memoryOwner.Memory, true);
int startPos = ctx.Position;
RlpByteArrayList? list = null;

ctx.ReadSequenceLength();
long requestId = ctx.DecodeLong();
try
{
ctx.ReadSequenceLength();
long requestId = ctx.DecodeLong();

RlpByteArrayList list = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));
list = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
memoryOwner = null;
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));

return new TrieNodesMessage(list) { RequestId = requestId };
return new TrieNodesMessage(list) { RequestId = requestId };
}
catch
{
list?.Dispose();
memoryOwner?.Dispose();
throw;
}
}
}
}
20 changes: 16 additions & 4 deletions src/Nethermind/Nethermind.Serialization.Rlp/NettyRlpStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,24 @@ public static void WriteByteArrayList(IByteBuffer byteBuffer, IByteArrayList lis

public static RlpByteArrayList DecodeByteArrayList(IByteBuffer byteBuffer)
{
NettyBufferMemoryOwner memoryOwner = new(byteBuffer);
NettyBufferMemoryOwner? memoryOwner = new(byteBuffer);
Rlp.ValueDecoderContext ctx = new(memoryOwner.Memory, true);
int startPos = ctx.Position;
RlpByteArrayList list = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));
return list;
RlpByteArrayList? list = null;

try
{
list = RlpByteArrayList.DecodeList(ref ctx, memoryOwner);
memoryOwner = null;
byteBuffer.SetReaderIndex(byteBuffer.ReaderIndex + (ctx.Position - startPos));
return list;
}
catch
{
list?.Dispose();
memoryOwner?.Dispose();
throw;
}
}
}
}
48 changes: 38 additions & 10 deletions src/Nethermind/Nethermind.Serialization.Rlp/Rlp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1463,25 +1463,53 @@ public ArrayPoolList<T> DecodeArrayPoolList<T>(DecodeRlpValue<T> decodeItem, boo
int count = PeekNumberOfItemsRemaining(checkPositions ? positionCheck : null);
GuardLimit(count, limit);
ArrayPoolList<T> result = new(count, count);
for (int i = 0; i < result.Count; i++)
int i = 0;
try
{
if (PeekByte() == OfEmptyList[0])
for (; i < result.Count; i++)
{
result[i] = defaultElement;
Position++;
if (PeekByte() == OfEmptyList[0])
{
result[i] = defaultElement;
Position++;
}
else
{
result[i] = decodeItem(ref this);
}
}
else

if (checkPositions)
{
result[i] = decodeItem(ref this);
Check(positionCheck);
}
}

if (checkPositions)
return result;
}
catch
{
Check(positionCheck);
try
{
DisposeDecodedItems(result, i);
}
finally
{
result.Dispose();
}

throw;
}

return result;
static void DisposeDecodedItems(ArrayPoolList<T> list, int count)
{
for (int j = 0; j < count; j++)
{
if (list[j] is IDisposable disposable)
{
disposable.Dispose();
}
}
}
}

public readonly bool IsNextItemEmptyByteArray() => PeekByte() is EmptyByteArrayByte;
Expand Down
Loading