Skip to content

Commit

Permalink
Simplify and improve consensus payload serialization and deserializat…
Browse files Browse the repository at this point in the history
…ion (#1149)

* Simplify and improve consensus payload serialiation

* Simplyfing read

* Function return instead of out parameter

* Reorganize

* Update UT_IOHelper.cs
  • Loading branch information
vncoelho committed Oct 15, 2019
1 parent 982e690 commit 29378af
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 45 deletions.
42 changes: 41 additions & 1 deletion neo.UnitTests/IO/UT_IOHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,46 @@ public void TestAsSerializableGeneric()
Assert.AreEqual(UInt160.Zero, result);
}

[TestMethod]
public void TestNullableArray()
{
var caseArray = new UInt160[]
{
null, UInt160.Zero, new UInt160(
new byte[] {
0xAA,0x00,0x00,0x00,0x00,
0xBB,0x00,0x00,0x00,0x00,
0xCC,0x00,0x00,0x00,0x00,
0xDD,0x00,0x00,0x00,0x00
})
};

byte[] data;
using (var stream = new MemoryStream())
using (var writter = new BinaryWriter(stream))
{
Neo.IO.Helper.WriteNullableArray(writter, caseArray);
data = stream.ToArray();
}

// Read Error

using (var stream = new MemoryStream(data))
using (var reader = new BinaryReader(stream))
{
Assert.ThrowsException<FormatException>(() => Neo.IO.Helper.ReadNullableArray<UInt160>(reader, 2));
}

// Read 100%

using (var stream = new MemoryStream(data))
using (var reader = new BinaryReader(stream))
{
var read = Neo.IO.Helper.ReadNullableArray<UInt160>(reader);
CollectionAssert.AreEqual(caseArray, read);
}
}

[TestMethod]
public void TestAsSerializable()
{
Expand All @@ -48,7 +88,7 @@ public void TestAsSerializable()
[TestMethod]
public void TestAsSerializableArray()
{
byte[] byteArray = Neo.IO.Helper.ToByteArray<UInt160>(new UInt160[] { UInt160.Zero });
byte[] byteArray = Neo.IO.Helper.ToByteArray(new UInt160[] { UInt160.Zero });
UInt160[] result = Neo.IO.Helper.AsSerializableArray<UInt160>(byteArray);
Assert.AreEqual(1, result.Length);
Assert.AreEqual(UInt160.Zero, result[0]);
Expand Down
52 changes: 8 additions & 44 deletions neo/Consensus/ConsensusContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,10 @@ public void Deserialize(BinaryReader reader)
ViewNumber = reader.ReadByte();
TransactionHashes = reader.ReadSerializableArray<UInt256>();
Transaction[] transactions = reader.ReadSerializableArray<Transaction>(Block.MaxTransactionsPerBlock);
PreparationPayloads = new ConsensusPayload[reader.ReadVarInt(Blockchain.MaxValidators)];
for (int i = 0; i < PreparationPayloads.Length; i++)
PreparationPayloads[i] = reader.ReadBoolean() ? reader.ReadSerializable<ConsensusPayload>() : null;
CommitPayloads = new ConsensusPayload[reader.ReadVarInt(Blockchain.MaxValidators)];
for (int i = 0; i < CommitPayloads.Length; i++)
CommitPayloads[i] = reader.ReadBoolean() ? reader.ReadSerializable<ConsensusPayload>() : null;
ChangeViewPayloads = new ConsensusPayload[reader.ReadVarInt(Blockchain.MaxValidators)];
for (int i = 0; i < ChangeViewPayloads.Length; i++)
ChangeViewPayloads[i] = reader.ReadBoolean() ? reader.ReadSerializable<ConsensusPayload>() : null;
LastChangeViewPayloads = new ConsensusPayload[reader.ReadVarInt(Blockchain.MaxValidators)];
for (int i = 0; i < LastChangeViewPayloads.Length; i++)
LastChangeViewPayloads[i] = reader.ReadBoolean() ? reader.ReadSerializable<ConsensusPayload>() : null;
PreparationPayloads = reader.ReadNullableArray<ConsensusPayload>(Blockchain.MaxValidators);
CommitPayloads = reader.ReadNullableArray<ConsensusPayload>(Blockchain.MaxValidators);
ChangeViewPayloads = reader.ReadNullableArray<ConsensusPayload>(Blockchain.MaxValidators);
LastChangeViewPayloads = reader.ReadNullableArray<ConsensusPayload>(Blockchain.MaxValidators);
if (TransactionHashes.Length == 0 && !RequestSentOrReceived)
TransactionHashes = null;
Transactions = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash);
Expand Down Expand Up @@ -416,38 +408,10 @@ public void Serialize(BinaryWriter writer)
writer.Write(ViewNumber);
writer.Write(TransactionHashes ?? new UInt256[0]);
writer.Write(Transactions?.Values.ToArray() ?? new Transaction[0]);
writer.WriteVarInt(PreparationPayloads.Length);
foreach (var payload in PreparationPayloads)
{
bool hasPayload = !(payload is null);
writer.Write(hasPayload);
if (!hasPayload) continue;
writer.Write(payload);
}
writer.WriteVarInt(CommitPayloads.Length);
foreach (var payload in CommitPayloads)
{
bool hasPayload = !(payload is null);
writer.Write(hasPayload);
if (!hasPayload) continue;
writer.Write(payload);
}
writer.WriteVarInt(ChangeViewPayloads.Length);
foreach (var payload in ChangeViewPayloads)
{
bool hasPayload = !(payload is null);
writer.Write(hasPayload);
if (!hasPayload) continue;
writer.Write(payload);
}
writer.WriteVarInt(LastChangeViewPayloads.Length);
foreach (var payload in LastChangeViewPayloads)
{
bool hasPayload = !(payload is null);
writer.Write(hasPayload);
if (!hasPayload) continue;
writer.Write(payload);
}
writer.WriteNullableArray(PreparationPayloads);
writer.WriteNullableArray(CommitPayloads);
writer.WriteNullableArray(ChangeViewPayloads);
writer.WriteNullableArray(LastChangeViewPayloads);
}
}
}
20 changes: 20 additions & 0 deletions neo/IO/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ public static string ReadFixedString(this BinaryReader reader, int length)
return Encoding.UTF8.GetString(data.TakeWhile(p => p != 0).ToArray());
}

public static T[] ReadNullableArray<T>(this BinaryReader reader, int max = 0x1000000) where T : class, ISerializable, new()
{
T[] array = new T[reader.ReadVarInt((ulong)max)];
for (int i = 0; i < array.Length; i++)
array[i] = reader.ReadBoolean() ? reader.ReadSerializable<T>() : null;
return array;
}

public static T ReadSerializable<T>(this BinaryReader reader) where T : ISerializable, new()
{
T obj = new T();
Expand Down Expand Up @@ -225,6 +233,18 @@ public static void WriteFixedString(this BinaryWriter writer, string value, int
writer.Write(new byte[length - bytes.Length]);
}

public static void WriteNullableArray<T>(this BinaryWriter writer, T[] value) where T : class, ISerializable
{
writer.WriteVarInt(value.Length);
foreach (var item in value)
{
bool isNull = item is null;
writer.Write(!isNull);
if (isNull) continue;
item.Serialize(writer);
}
}

public static void WriteVarBytes(this BinaryWriter writer, byte[] value)
{
writer.WriteVarInt(value.Length);
Expand Down

0 comments on commit 29378af

Please sign in to comment.