From acef71985098558651b375006d8791bca9a04bc6 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Mar 2020 10:30:08 +0100 Subject: [PATCH] Read Fixed (#1454) * Read Fixed * format * Rename * Fix Consensus UT * Add ut, and allow buffered streams * Add ut, and allow buffered streams * Change name * Update Helper.cs Co-authored-by: erikzhang --- src/neo/Consensus/Commit.cs | 3 +- .../RecoveryMessage.CommitPayloadCompact.cs | 2 +- src/neo/Consensus/RecoveryMessage.cs | 2 +- src/neo/IO/Helper.cs | 27 +++++++++++++-- .../P2P/Payloads/NetworkAddressWithTime.cs | 3 +- tests/neo.UnitTests/Consensus/UT_Consensus.cs | 4 +-- tests/neo.UnitTests/IO/UT_IOHelper.cs | 34 +++++++++++++++++++ 7 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/neo/Consensus/Commit.cs b/src/neo/Consensus/Commit.cs index 84585e1ee4..fce9b8caaf 100644 --- a/src/neo/Consensus/Commit.cs +++ b/src/neo/Consensus/Commit.cs @@ -1,3 +1,4 @@ +using Neo.IO; using System.IO; namespace Neo.Consensus @@ -13,7 +14,7 @@ public class Commit : ConsensusMessage public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); - Signature = reader.ReadBytes(64); + Signature = reader.ReadFixedBytes(64); } public override void Serialize(BinaryWriter writer) diff --git a/src/neo/Consensus/RecoveryMessage.CommitPayloadCompact.cs b/src/neo/Consensus/RecoveryMessage.CommitPayloadCompact.cs index 72962f92b3..5d783c6796 100644 --- a/src/neo/Consensus/RecoveryMessage.CommitPayloadCompact.cs +++ b/src/neo/Consensus/RecoveryMessage.CommitPayloadCompact.cs @@ -23,7 +23,7 @@ void ISerializable.Deserialize(BinaryReader reader) { ViewNumber = reader.ReadByte(); ValidatorIndex = reader.ReadUInt16(); - Signature = reader.ReadBytes(64); + Signature = reader.ReadFixedBytes(64); InvocationScript = reader.ReadVarBytes(1024); } diff --git a/src/neo/Consensus/RecoveryMessage.cs b/src/neo/Consensus/RecoveryMessage.cs index a5e1c09ac6..c25816ee7f 100644 --- a/src/neo/Consensus/RecoveryMessage.cs +++ b/src/neo/Consensus/RecoveryMessage.cs @@ -39,7 +39,7 @@ public override void Deserialize(BinaryReader reader) { int preparationHashSize = UInt256.Zero.Size; if (preparationHashSize == (int)reader.ReadVarInt((ulong)preparationHashSize)) - PreparationHash = new UInt256(reader.ReadBytes(preparationHashSize)); + PreparationHash = new UInt256(reader.ReadFixedBytes(preparationHashSize)); } PreparationMessages = reader.ReadSerializableArray(Blockchain.MaxValidators).ToDictionary(p => (int)p.ValidatorIndex); diff --git a/src/neo/IO/Helper.cs b/src/neo/IO/Helper.cs index 3acc4b2c2f..e44e5bbe0a 100644 --- a/src/neo/IO/Helper.cs +++ b/src/neo/IO/Helper.cs @@ -151,7 +151,7 @@ public static byte[] ReadBytesWithGrouping(this BinaryReader reader) int count; do { - byte[] group = reader.ReadBytes(GroupingSizeInBytes); + byte[] group = reader.ReadFixedBytes(GroupingSizeInBytes); count = reader.ReadByte(); if (count > GroupingSizeInBytes) throw new FormatException(); @@ -162,9 +162,30 @@ public static byte[] ReadBytesWithGrouping(this BinaryReader reader) } } + public static byte[] ReadFixedBytes(this BinaryReader reader, int size) + { + var index = 0; + var data = new byte[size]; + + while (size > 0) + { + var bytesRead = reader.Read(data, index, size); + + if (bytesRead <= 0) + { + throw new FormatException(); + } + + size -= bytesRead; + index += bytesRead; + } + + return data; + } + public static string ReadFixedString(this BinaryReader reader, int length) { - byte[] data = reader.ReadBytes(length); + byte[] data = reader.ReadFixedBytes(length); return Encoding.UTF8.GetString(data.TakeWhile(p => p != 0).ToArray()); } @@ -196,7 +217,7 @@ public static T[] ReadSerializableArray(this BinaryReader reader, int max = 0 public static byte[] ReadVarBytes(this BinaryReader reader, int max = 0x1000000) { - return reader.ReadBytes((int)reader.ReadVarInt((ulong)max)); + return reader.ReadFixedBytes((int)reader.ReadVarInt((ulong)max)); } public static ulong ReadVarInt(this BinaryReader reader, ulong max = ulong.MaxValue) diff --git a/src/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/src/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index 6fcda2f809..a65e28c846 100644 --- a/src/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/src/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -31,8 +31,7 @@ void ISerializable.Deserialize(BinaryReader reader) Timestamp = reader.ReadUInt32(); // Address - byte[] data = reader.ReadBytes(16); - if (data.Length != 16) throw new FormatException(); + byte[] data = reader.ReadFixedBytes(16); Address = new IPAddress(data).Unmap(); // Capabilities diff --git a/tests/neo.UnitTests/Consensus/UT_Consensus.cs b/tests/neo.UnitTests/Consensus/UT_Consensus.cs index c7a0687729..4bdb0da2c5 100644 --- a/tests/neo.UnitTests/Consensus/UT_Consensus.cs +++ b/tests/neo.UnitTests/Consensus/UT_Consensus.cs @@ -531,8 +531,8 @@ public void TestSerializeAndDeserializeConsensusContext() consensusContext.CommitPayloads = new ConsensusPayload[consensusContext.Validators.Length]; using (SHA256 sha256 = SHA256.Create()) { - consensusContext.CommitPayloads[3] = MakeSignedPayload(consensusContext, new Commit { Signature = sha256.ComputeHash(testTx1.Hash.ToArray()) }, 3, new[] { (byte)'3', (byte)'4' }); - consensusContext.CommitPayloads[6] = MakeSignedPayload(consensusContext, new Commit { Signature = sha256.ComputeHash(testTx2.Hash.ToArray()) }, 3, new[] { (byte)'6', (byte)'7' }); + consensusContext.CommitPayloads[3] = MakeSignedPayload(consensusContext, new Commit { Signature = sha256.ComputeHash(testTx1.Hash.ToArray()).Concat(sha256.ComputeHash(testTx1.Hash.ToArray())).ToArray() }, 3, new[] { (byte)'3', (byte)'4' }); + consensusContext.CommitPayloads[6] = MakeSignedPayload(consensusContext, new Commit { Signature = sha256.ComputeHash(testTx2.Hash.ToArray()).Concat(sha256.ComputeHash(testTx2.Hash.ToArray())).ToArray() }, 3, new[] { (byte)'6', (byte)'7' }); } consensusContext.Block.Timestamp = TimeProvider.Current.UtcNow.ToTimestampMS(); diff --git a/tests/neo.UnitTests/IO/UT_IOHelper.cs b/tests/neo.UnitTests/IO/UT_IOHelper.cs index d0f63e5c1c..3b36695b2d 100644 --- a/tests/neo.UnitTests/IO/UT_IOHelper.cs +++ b/tests/neo.UnitTests/IO/UT_IOHelper.cs @@ -23,6 +23,40 @@ public void TestAsSerializableGeneric() Assert.AreEqual(UInt160.Zero, result); } + [TestMethod] + public void TestReadFixedBytes() + { + byte[] data = new byte[] { 0x01, 0x02, 0x03, 0x04 }; + + // Less data + + using (var reader = new BinaryReader(new MemoryStream(data), Encoding.UTF8, false)) + { + byte[] result = Neo.IO.Helper.ReadFixedBytes(reader, 3); + + Assert.AreEqual("010203", result.ToHexString()); + Assert.AreEqual(3, reader.BaseStream.Position); + } + + // Same data + + using (var reader = new BinaryReader(new MemoryStream(data), Encoding.UTF8, false)) + { + byte[] result = Neo.IO.Helper.ReadFixedBytes(reader, 4); + + Assert.AreEqual("01020304", result.ToHexString()); + Assert.AreEqual(4, reader.BaseStream.Position); + } + + // More data + + using (var reader = new BinaryReader(new MemoryStream(data), Encoding.UTF8, false)) + { + Assert.ThrowsException(() => Neo.IO.Helper.ReadFixedBytes(reader, 5)); + Assert.AreEqual(4, reader.BaseStream.Position); + } + } + [TestMethod] public void TestNullableArray() {