Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify and improve consensus payload serialization and deserialization #1149

Merged
merged 5 commits into from
Oct 15, 2019
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
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