From 00f9c270de46c605b49990bc6d399e8f2419d65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?= Date: Mon, 22 Jul 2019 14:21:38 -0300 Subject: [PATCH] Seconds to milliseconds (#918) * Seconds to milliseconds * Sending unsaved files * fixing formula of consensus bonification * Refactoring milliseconds * Refactoring milliseconds from capeslock * Refactoring milliseconds from capeslock II * Adjusting UT * Adjusting UT II * Super fast protocol to 2s * Fixing timestamps to long and tests * Minor adjusts * Change view deserialization fix * Timestamp to ulong * Update neo/Helper.cs Co-Authored-By: Shargon * Update JNumber.cs * Optimize and remove TODO * Update ApplicationEngine.cs * Fixing ExtendTimerByFactor This was already from milliseconds, thus, just removing the multiplier --- neo.UnitTests/TestUtils.cs | 9 +++--- neo.UnitTests/UT_Block.cs | 31 ++++++++++--------- neo.UnitTests/UT_Consensus.cs | 18 +++++------ neo.UnitTests/UT_Header.cs | 16 +++++----- neo.UnitTests/protocol.json | 2 +- neo/Consensus/ChangeView.cs | 6 ++-- neo/Consensus/ConsensusContext.cs | 8 ++--- neo/Consensus/ConsensusService.cs | 18 +++++------ neo/Consensus/PrepareRequest.cs | 6 ++-- ...ecoveryMessage.ChangeViewPayloadCompact.cs | 6 ++-- neo/Consensus/RecoveryRequest.cs | 6 ++-- neo/Helper.cs | 14 +++------ neo/IO/Json/JNumber.cs | 7 ----- neo/Ledger/Blockchain.cs | 11 ++++--- neo/Ledger/MemoryPool.cs | 16 +++++----- neo/Network/P2P/Payloads/BlockBase.cs | 16 +++++++--- neo/ProtocolSettings.cs | 4 +-- neo/SmartContract/ApplicationEngine.cs | 18 +++++++---- 18 files changed, 111 insertions(+), 101 deletions(-) diff --git a/neo.UnitTests/TestUtils.cs b/neo.UnitTests/TestUtils.cs index 9bf06acbf7..fd06f0ba1b 100644 --- a/neo.UnitTests/TestUtils.cs +++ b/neo.UnitTests/TestUtils.cs @@ -36,12 +36,12 @@ public static Transaction GetTransaction() }; } - public static void SetupHeaderWithValues(Header header, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal) + public static void SetupHeaderWithValues(Header header, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal) { setupBlockBaseWithValues(header, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out scriptVal); } - public static void SetupBlockWithValues(Block block, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, int numberOfTransactions) + public static void SetupBlockWithValues(Block block, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, int numberOfTransactions) { setupBlockBaseWithValues(block, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out scriptVal); @@ -58,13 +58,12 @@ public static void SetupBlockWithValues(Block block, UInt256 val256, out UInt256 block.Transactions = transactionsVal; } - private static void setupBlockBaseWithValues(BlockBase bb, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal) + private static void setupBlockBaseWithValues(BlockBase bb, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal) { bb.PrevHash = val256; merkRootVal = UInt256.Parse("0xd841af3d6bd7adb4bca24306725f9aec363edb10de3cafc5f8cca948d7b0290f"); - bb.MerkleRoot = merkRootVal; - timestampVal = new DateTime(1968, 06, 01, 0, 0, 0, DateTimeKind.Utc).ToTimestamp(); + timestampVal = new DateTime(1980, 06, 01, 0, 0, 1, 001, DateTimeKind.Utc).ToTimestampMS(); // GMT: Sunday, June 1, 1980 12:00:01.001 AM bb.Timestamp = timestampVal; indexVal = 0; bb.Index = indexVal; diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/UT_Block.cs index 886f5099f0..c91776f0c0 100644 --- a/neo.UnitTests/UT_Block.cs +++ b/neo.UnitTests/UT_Block.cs @@ -43,9 +43,9 @@ public void Size_Get() { UInt256 val256 = UInt256.Zero; TestUtils.SetupBlockWithValues(uut, val256, out var _, out var _, out var _, out var _, out var _, out var _, 0); - // blockbase 4 + 32 + 32 + 4 + 4 + 20 + 4 + // blockbase 4 + 64 + 32 + 4 + 4 + 20 + 4 // block 9 + 1 - uut.Size.Should().Be(110); + uut.Size.Should().Be(114); } [TestMethod] @@ -59,7 +59,7 @@ public void Size_Get_1_Transaction() TestUtils.GetTransaction() }; - uut.Size.Should().Be(161); + uut.Size.Should().Be(165); } [TestMethod] @@ -75,7 +75,7 @@ public void Size_Get_3_Transaction() TestUtils.GetTransaction() }; - uut.Size.Should().Be(263); + uut.Size.Should().Be(267); } [TestMethod] @@ -94,8 +94,7 @@ public void Serialize() } } - byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; - + byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 233, 19, 255, 133, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; data.Length.Should().Be(requiredData.Length); for (int i = 0; i < data.Length; i++) { @@ -111,7 +110,8 @@ public void Deserialize() uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid - byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; + byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 233, 19, 255, 133, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; + int index = 0; using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false)) { @@ -124,7 +124,7 @@ public void Deserialize() assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal, transactionsVal); } - private void assertStandardBlockTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, uint timestampVal, uint indexVal, Witness scriptVal, Transaction[] transactionsVal, bool testTransactions = true) + private void assertStandardBlockTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, ulong timestampVal, uint indexVal, Witness scriptVal, Transaction[] transactionsVal, bool testTransactions = true) { uut.PrevHash.Should().Be(val256); uut.MerkleRoot.Should().Be(merkRoot); @@ -155,7 +155,8 @@ public void Equals_DiffObj() UInt256 prevHash = new UInt256(TestUtils.GetByteArray(32, 0x42)); UInt256 merkRoot; UInt160 val160; - uint timestampVal, indexVal; + ulong timestampVal; + uint indexVal; Witness scriptVal; Transaction[] transactionsVal; TestUtils.SetupBlockWithValues(newBlock, val256, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1); @@ -178,7 +179,8 @@ public void Equals_SameHash() UInt256 prevHash = new UInt256(TestUtils.GetByteArray(32, 0x42)); UInt256 merkRoot; UInt160 val160; - uint timestampVal, indexVal; + ulong timestampVal; + uint indexVal; Witness scriptVal; Transaction[] transactionsVal; TestUtils.SetupBlockWithValues(newBlock, prevHash, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1); @@ -193,7 +195,8 @@ public void RebuildMerkleRoot_Updates() UInt256 val256 = UInt256.Zero; UInt256 merkRoot; UInt160 val160; - uint timestampVal, indexVal; + ulong timestampVal; + uint indexVal; Witness scriptVal; Transaction[] transactionsVal; TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1); @@ -214,12 +217,12 @@ public void ToJson() JObject jObj = uut.ToJson(); jObj.Should().NotBeNull(); - jObj["hash"].AsString().Should().Be("0x1d8642796276c8ce3c5c03b8984a1b593d99b49a63d830bb06f800b8c953be77"); - jObj["size"].AsNumber().Should().Be(161); + jObj["hash"].AsString().Should().Be("0x4e1d8392e7c44830e7e45c18e5e0e3ef3c36af883868846d3691a436a62494b2"); + jObj["size"].AsNumber().Should().Be(165); jObj["version"].AsNumber().Should().Be(0); jObj["previousblockhash"].AsString().Should().Be("0x0000000000000000000000000000000000000000000000000000000000000000"); jObj["merkleroot"].AsString().Should().Be("0xd841af3d6bd7adb4bca24306725f9aec363edb10de3cafc5f8cca948d7b0290f"); - jObj["time"].AsNumber().Should().Be(4244941696); + jObj["time"].AsNumber().Should().Be(328665601001); jObj["index"].AsNumber().Should().Be(0); jObj["nextconsensus"].AsString().Should().Be("AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM"); diff --git a/neo.UnitTests/UT_Consensus.cs b/neo.UnitTests/UT_Consensus.cs index d410bb5142..c5bf1828f8 100644 --- a/neo.UnitTests/UT_Consensus.cs +++ b/neo.UnitTests/UT_Consensus.cs @@ -47,10 +47,10 @@ public void ConsensusService_Primary_Sends_PrepareRequest_After_OnStart() int timeIndex = 0; var timeValues = new[] { //new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // For tests here - new DateTime(1968, 06, 01, 0, 0, 1, DateTimeKind.Utc), // For receiving block - new DateTime(1968, 06, 01, 0, 0, (int) Blockchain.SecondsPerBlock, DateTimeKind.Utc), // For Initialize - new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // unused - new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc) // unused + new DateTime(1980, 06, 01, 0, 0, 1, 001, DateTimeKind.Utc), // For receiving block + new DateTime(1980, 06, 01, 0, 0, (int) Blockchain.MillisecondsPerBlock / 1000, 100, DateTimeKind.Utc), // For Initialize + new DateTime(1980, 06, 01, 0, 0, 15, 001, DateTimeKind.Utc), // unused + new DateTime(1980, 06, 01, 0, 0, 15, 001, DateTimeKind.Utc) // unused }; //TimeProvider.Current.UtcNow.ToTimestamp().Should().Be(4244941711); //1968-06-01 00:00:15 @@ -74,12 +74,12 @@ public void ConsensusService_Primary_Sends_PrepareRequest_After_OnStart() // Creating proposed block Header header = new Header(); - TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal); - header.Size.Should().Be(101); + TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal); + header.Size.Should().Be(105); - Console.WriteLine($"header {header} hash {header.Hash} timstamp {timestampVal}"); + Console.WriteLine($"header {header} hash {header.Hash} timestamp {timestampVal}"); - timestampVal.Should().Be(4244941696); //1968-06-01 00:00:00 + timestampVal.Should().Be(328665601001); // GMT: Sunday, June 1, 1980 12:00:01.001 AM // check basic ConsensusContext //mockConsensusContext.Object.block_received_time.ToTimestamp().Should().Be(4244941697); //1968-06-01 00:00:01 @@ -197,7 +197,7 @@ public void TestSerializeAndDeserializeConsensusContext() consensusContext.CommitPayloads[6] = MakeSignedPayload(consensusContext, new Commit { Signature = sha256.ComputeHash(testTx2.Hash.ToArray()) }, 3, new[] { (byte)'6', (byte)'7' }); } - consensusContext.Block.Timestamp = TimeProvider.Current.UtcNow.ToTimestamp(); + consensusContext.Block.Timestamp = TimeProvider.Current.UtcNow.ToTimestampMS(); consensusContext.ChangeViewPayloads = new ConsensusPayload[consensusContext.Validators.Length]; consensusContext.ChangeViewPayloads[0] = MakeSignedPayload(consensusContext, new ChangeView { ViewNumber = 1, Timestamp = 6 }, 0, new[] { (byte)'A' }); diff --git a/neo.UnitTests/UT_Header.cs b/neo.UnitTests/UT_Header.cs index 82744a7f8b..f07be59051 100644 --- a/neo.UnitTests/UT_Header.cs +++ b/neo.UnitTests/UT_Header.cs @@ -22,22 +22,23 @@ public void Size_Get() { UInt256 val256 = UInt256.Zero; TestUtils.SetupHeaderWithValues(uut, val256, out _, out _, out _, out _, out _); - // blockbase 4 + 32 + 32 + 4 + 4 + 20 + 4 + // blockbase 4 + 64 + 32 + 4 + 4 + 20 + 4 // header 1 - uut.Size.Should().Be(101); + uut.Size.Should().Be(105); } [TestMethod] public void Deserialize() { UInt256 val256 = UInt256.Zero; - TestUtils.SetupHeaderWithValues(new Header(), val256, out UInt256 merkRoot, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal); + TestUtils.SetupHeaderWithValues(new Header(), val256, out UInt256 merkRoot, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal); uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid - byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 }; + byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 233, 19, 255, 133, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 }; + int index = 0; - using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false)) + using (MemoryStream ms = new MemoryStream(requiredData, index, requiredData.Length - index, false)) { using (BinaryReader reader = new BinaryReader(ms)) { @@ -48,7 +49,7 @@ public void Deserialize() assertStandardHeaderTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal); } - private void assertStandardHeaderTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, uint timestampVal, uint indexVal, Witness scriptVal) + private void assertStandardHeaderTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, ulong timestampVal, uint indexVal, Witness scriptVal) { uut.PrevHash.Should().Be(val256); uut.MerkleRoot.Should().Be(merkRoot); @@ -106,9 +107,10 @@ public void Serialize() } } - byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 }; + byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 233, 19, 255, 133, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 }; data.Length.Should().Be(requiredData.Length); + for (int i = 0; i < data.Length; i++) { data[i].Should().Be(requiredData[i]); diff --git a/neo.UnitTests/protocol.json b/neo.UnitTests/protocol.json index 476a25d4aa..06aec5ccce 100644 --- a/neo.UnitTests/protocol.json +++ b/neo.UnitTests/protocol.json @@ -1,5 +1,5 @@ { "ProtocolConfiguration": { - "SecondsPerBlock": 2 + "MillisecondsPerBlock": 2000 } } diff --git a/neo/Consensus/ChangeView.cs b/neo/Consensus/ChangeView.cs index 7d5b3e96eb..4c18b3fb3f 100644 --- a/neo/Consensus/ChangeView.cs +++ b/neo/Consensus/ChangeView.cs @@ -14,7 +14,7 @@ public class ChangeView : ConsensusMessage /// they only respond once to a specific ChangeView request (it thus prevents replay of the ChangeView /// message from repeatedly broadcasting RecoveryMessages). /// - public uint Timestamp; + public ulong Timestamp; /// /// Reason @@ -22,7 +22,7 @@ public class ChangeView : ConsensusMessage public ChangeViewReason Reason; public override int Size => base.Size + - sizeof(uint) + // Timestamp + sizeof(ulong) + // Timestamp sizeof(ChangeViewReason); // Reason public ChangeView() : base(ConsensusMessageType.ChangeView) { } @@ -30,7 +30,7 @@ public ChangeView() : base(ConsensusMessageType.ChangeView) { } public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); - Timestamp = reader.ReadUInt32(); + Timestamp = reader.ReadUInt64(); Reason = (ChangeViewReason)reader.ReadByte(); } diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs index 0d6855a623..270536fc89 100644 --- a/neo/Consensus/ConsensusContext.cs +++ b/neo/Consensus/ConsensusContext.cs @@ -95,7 +95,7 @@ public void Deserialize(BinaryReader reader) Reset(0); if (reader.ReadUInt32() != Block.Version) throw new FormatException(); if (reader.ReadUInt32() != Block.Index) throw new InvalidOperationException(); - Block.Timestamp = reader.ReadUInt32(); + Block.Timestamp = reader.ReadUInt64(); Block.NextConsensus = reader.ReadSerializable(); if (Block.NextConsensus.Equals(UInt160.Zero)) Block.NextConsensus = null; @@ -164,7 +164,7 @@ public ConsensusPayload MakeChangeView(ChangeViewReason reason) return ChangeViewPayloads[MyIndex] = MakeSignedPayload(new ChangeView { Reason = reason, - Timestamp = TimeProvider.Current.UtcNow.ToTimestamp() + Timestamp = TimeProvider.Current.UtcNow.ToTimestampMS() }); } @@ -216,7 +216,7 @@ public ConsensusPayload MakePrepareRequest() List transactions = memoryPoolTransactions.ToList(); TransactionHashes = transactions.Select(p => p.Hash).ToArray(); Transactions = transactions.ToDictionary(p => p.Hash); - Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestamp(), PrevHeader.Timestamp + 1); + Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); Block.ConsensusData.Nonce = BitConverter.ToUInt64(buffer, 0); return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareRequest { @@ -230,7 +230,7 @@ public ConsensusPayload MakeRecoveryRequest() { return MakeSignedPayload(new RecoveryRequest { - Timestamp = TimeProvider.Current.UtcNow.ToTimestamp() + Timestamp = TimeProvider.Current.UtcNow.ToTimestampMS() }); } diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index b8e594d642..2e850807e4 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -139,7 +139,7 @@ private void CheckPreparations() context.Save(); localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); // Set timer, so we will resend the commit in case of a networking issue - ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock)); + ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock)); CheckCommits(); } } @@ -155,7 +155,7 @@ private void InitializeConsensus(byte viewNumber) { if (isRecovering) { - ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (viewNumber + 1))); + ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock << (viewNumber + 1))); } else { @@ -168,7 +168,7 @@ private void InitializeConsensus(byte viewNumber) } else { - ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (viewNumber + 1))); + ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock << (viewNumber + 1))); } } @@ -229,10 +229,10 @@ private void OnCommitReceived(ConsensusPayload payload, Commit commit) existingCommitPayload = payload; } - // this function increases existing timer (never decreases) with a value proportional to `maxDelayInBlockTimes`*`Blockchain.SecondsPerBlock` + // this function increases existing timer (never decreases) with a value proportional to `maxDelayInBlockTimes`*`Blockchain.MillisecondsPerBlock` private void ExtendTimerByFactor(int maxDelayInBlockTimes) { - TimeSpan nextDelay = expected_delay - (TimeProvider.Current.UtcNow - clock_started) + TimeSpan.FromMilliseconds(maxDelayInBlockTimes * Blockchain.SecondsPerBlock * 1000.0 / context.M); + TimeSpan nextDelay = expected_delay - (TimeProvider.Current.UtcNow - clock_started) + TimeSpan.FromMilliseconds(maxDelayInBlockTimes * Blockchain.MillisecondsPerBlock / context.M); if (!context.WatchOnly && !context.ViewChanging && !context.CommitSent && (nextDelay > TimeSpan.Zero)) ChangeTimer(nextDelay); } @@ -390,7 +390,7 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m if (context.RequestSentOrReceived || context.NotAcceptingPayloadsDueToViewChanging) return; if (payload.ValidatorIndex != context.Block.ConsensusData.PrimaryIndex || message.ViewNumber != context.ViewNumber) return; Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}"); - if (message.Timestamp <= context.PrevHeader.Timestamp || message.Timestamp > TimeProvider.Current.UtcNow.AddMinutes(10).ToTimestamp()) + if (message.Timestamp <= context.PrevHeader.Timestamp || message.Timestamp > TimeProvider.Current.UtcNow.AddMinutes(10).ToTimestampMS()) { Log($"Timestamp incorrect: {message.Timestamp}", LogLevel.Warning); return; @@ -543,7 +543,7 @@ private void OnTimer(Timer timer) // Re-send commit periodically by sending recover message in case of a network issue. Log($"send recovery to resend commit"); localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeRecoveryMessage() }); - ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << 1)); + ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock << 1)); } else { @@ -590,7 +590,7 @@ private void RequestChangeView(ChangeViewReason reason) // The latter may happen by nodes in higher views with, at least, `M` proofs byte expectedView = context.ViewNumber; expectedView++; - ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (expectedView + 1))); + ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock << (expectedView + 1))); if ((context.CountCommitted + context.CountFailed) > context.F) { Log($"Skip requesting change view to nv={expectedView} because nc={context.CountCommitted} nf={context.CountFailed}"); @@ -622,7 +622,7 @@ private void SendPrepareRequest() foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes)) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } - ChangeTimer(TimeSpan.FromSeconds((Blockchain.SecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? Blockchain.SecondsPerBlock : 0))); + ChangeTimer(TimeSpan.FromMilliseconds((Blockchain.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? Blockchain.MillisecondsPerBlock : 0))); } } diff --git a/neo/Consensus/PrepareRequest.cs b/neo/Consensus/PrepareRequest.cs index 299b0f6a72..85823fe957 100644 --- a/neo/Consensus/PrepareRequest.cs +++ b/neo/Consensus/PrepareRequest.cs @@ -8,12 +8,12 @@ namespace Neo.Consensus { public class PrepareRequest : ConsensusMessage { - public uint Timestamp; + public ulong Timestamp; public ulong Nonce; public UInt256[] TransactionHashes; public override int Size => base.Size - + sizeof(uint) //Timestamp + + sizeof(ulong) //Timestamp + sizeof(ulong) //Nonce + TransactionHashes.GetVarSize(); //TransactionHashes @@ -25,7 +25,7 @@ public PrepareRequest() public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); - Timestamp = reader.ReadUInt32(); + Timestamp = reader.ReadUInt64(); Nonce = reader.ReadUInt64(); TransactionHashes = reader.ReadSerializableArray(Block.MaxTransactionsPerBlock); if (TransactionHashes.Distinct().Count() != TransactionHashes.Length) diff --git a/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs b/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs index 373e7e75a3..6d4d6a7ae2 100644 --- a/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs +++ b/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs @@ -10,20 +10,20 @@ public class ChangeViewPayloadCompact : ISerializable { public ushort ValidatorIndex; public byte OriginalViewNumber; - public uint Timestamp; + public ulong Timestamp; public byte[] InvocationScript; int ISerializable.Size => sizeof(ushort) + //ValidatorIndex sizeof(byte) + //OriginalViewNumber - sizeof(uint) + //Timestamp + sizeof(ulong) + //Timestamp InvocationScript.GetVarSize(); //InvocationScript void ISerializable.Deserialize(BinaryReader reader) { ValidatorIndex = reader.ReadUInt16(); OriginalViewNumber = reader.ReadByte(); - Timestamp = reader.ReadUInt32(); + Timestamp = reader.ReadUInt64(); InvocationScript = reader.ReadVarBytes(1024); } diff --git a/neo/Consensus/RecoveryRequest.cs b/neo/Consensus/RecoveryRequest.cs index 971b49a324..c02ceb176c 100644 --- a/neo/Consensus/RecoveryRequest.cs +++ b/neo/Consensus/RecoveryRequest.cs @@ -9,17 +9,17 @@ public class RecoveryRequest : ConsensusMessage /// they only respond once to a specific RecoveryRequest request. /// In this sense, it prevents replay of the RecoveryRequest message from the repeatedly broadcast of Recovery's messages. /// - public uint Timestamp; + public ulong Timestamp; public override int Size => base.Size - + sizeof(uint); //Timestamp + + sizeof(ulong); //Timestamp public RecoveryRequest() : base(ConsensusMessageType.RecoveryRequest) { } public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); - Timestamp = reader.ReadUInt32(); + Timestamp = reader.ReadUInt64(); } public override void Serialize(BinaryWriter writer) diff --git a/neo/Helper.cs b/neo/Helper.cs index 8c562740bd..d8409b64bd 100644 --- a/neo/Helper.cs +++ b/neo/Helper.cs @@ -140,15 +140,6 @@ internal static bool TestBit(this BigInteger i, int index) return (i & (BigInteger.One << index)) > BigInteger.Zero; } - public static DateTime ToDateTime(this uint timestamp) - { - return unixEpoch.AddSeconds(timestamp).ToLocalTime(); - } - - public static DateTime ToDateTime(this ulong timestamp) - { - return unixEpoch.AddSeconds(timestamp).ToLocalTime(); - } public static string ToHexString(this IEnumerable value) { @@ -181,6 +172,11 @@ public static uint ToTimestamp(this DateTime time) return (uint)(time.ToUniversalTime() - unixEpoch).TotalSeconds; } + public static ulong ToTimestampMS(this DateTime time) + { + return (ulong)(time.ToUniversalTime() - unixEpoch).TotalMilliseconds; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] unsafe internal static ushort ToUInt16(this byte[] value, int startIndex) { diff --git a/neo/IO/Json/JNumber.cs b/neo/IO/Json/JNumber.cs index f9fa5e05e5..2a23dc3157 100644 --- a/neo/IO/Json/JNumber.cs +++ b/neo/IO/Json/JNumber.cs @@ -101,13 +101,6 @@ public override string ToString() return AsString(); } - public DateTime ToTimestamp() - { - if (Value < 0 || Value > ulong.MaxValue) - throw new InvalidCastException(); - return ((ulong)Value).ToDateTime(); - } - public override T TryGetEnum(T defaultValue = default, bool ignoreCase = false) { Type enumType = typeof(T); diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index 5d9ad00ee9..854583423d 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -27,17 +27,17 @@ public class ImportCompleted { } public class FillMemoryPool { public IEnumerable Transactions; } public class FillCompleted { } - public static readonly uint SecondsPerBlock = ProtocolSettings.Default.SecondsPerBlock; + public static readonly uint MillisecondsPerBlock = ProtocolSettings.Default.MillisecondsPerBlock; public const uint DecrementInterval = 2000000; public const int MaxValidators = 1024; public static readonly uint[] GenerationAmount = { 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - public static readonly TimeSpan TimePerBlock = TimeSpan.FromSeconds(SecondsPerBlock); + public static readonly TimeSpan TimePerBlock = TimeSpan.FromMilliseconds(MillisecondsPerBlock); public static readonly ECPoint[] StandbyValidators = ProtocolSettings.Default.StandbyValidators.OfType().Select(p => ECPoint.DecodePoint(p.HexToBytes(), ECCurve.Secp256r1)).ToArray(); public static readonly Block GenesisBlock = new Block { PrevHash = UInt256.Zero, - Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestamp(), + Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestampMS(), Index = 0, NextConsensus = GetConsensusAddress(StandbyValidators), Witness = new Witness @@ -283,7 +283,10 @@ private RelayResultReason OnNewBlock(Block block) block_cache_unverified.Remove(blockToPersist.Index); Persist(blockToPersist); - if (blocksPersisted++ < blocksToPersistList.Count - (2 + Math.Max(0, (15 - SecondsPerBlock)))) continue; + // 15000 is the default among of seconds per block, while MilliSecondsPerBlock is the current + uint extraBlocks = (15000 - MillisecondsPerBlock) / 1000; + + if (blocksPersisted++ < blocksToPersistList.Count - (2 + Math.Max(0, extraBlocks))) continue; // Empirically calibrated for relaying the most recent 2 blocks persisted with 15s network // Increase in the rate of 1 block per second in configurations with faster blocks diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs index 96e17dc34f..912ea69c73 100644 --- a/neo/Ledger/MemoryPool.cs +++ b/neo/Ledger/MemoryPool.cs @@ -21,10 +21,10 @@ public class MemoryPool : IReadOnlyCollection private const int BlocksTillRebroadcastHighPriorityPoolTx = 10; private int RebroadcastMultiplierThreshold => Capacity / 10; - private static readonly double MaxSecondsToReverifyTx = (double)Blockchain.SecondsPerBlock / 3; + private static readonly double MaxMillisecondsToReverifyTx = (double)Blockchain.MillisecondsPerBlock / 3; // These two are not expected to be hit, they are just safegaurds. - private static readonly double MaxSecondsToReverifyTxPerIdle = (double)Blockchain.SecondsPerBlock / 15; + private static readonly double MaxMillisecondsToReverifyTxPerIdle = (double)Blockchain.MillisecondsPerBlock / 15; private readonly NeoSystem _system; @@ -378,7 +378,7 @@ internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot) return; ReverifyTransactions(_sortedTransactions, _unverifiedSortedTransactions, - _maxTxPerBlock, MaxSecondsToReverifyTx, snapshot); + _maxTxPerBlock, MaxMillisecondsToReverifyTx, snapshot); } internal void InvalidateAllTransactions() @@ -395,9 +395,9 @@ internal void InvalidateAllTransactions() } private int ReverifyTransactions(SortedSet verifiedSortedTxPool, - SortedSet unverifiedSortedTxPool, int count, double secondsTimeout, Snapshot snapshot) + SortedSet unverifiedSortedTxPool, int count, double millisecondsTimeout, Snapshot snapshot) { - DateTime reverifyCutOffTimeStamp = DateTime.UtcNow.AddSeconds(secondsTimeout); + DateTime reverifyCutOffTimeStamp = DateTime.UtcNow.AddMilliseconds(millisecondsTimeout); List reverifiedItems = new List(count); List invalidItems = new List(); @@ -421,8 +421,8 @@ private int ReverifyTransactions(SortedSet verifiedSortedTxPool, if (Count > RebroadcastMultiplierThreshold) blocksTillRebroadcast = blocksTillRebroadcast * Count / RebroadcastMultiplierThreshold; - var rebroadcastCutOffTime = DateTime.UtcNow.AddSeconds( - -Blockchain.SecondsPerBlock * blocksTillRebroadcast); + var rebroadcastCutOffTime = DateTime.UtcNow.AddMilliseconds( + -Blockchain.MillisecondsPerBlock * blocksTillRebroadcast); foreach (PoolItem item in reverifiedItems) { if (_unsortedTransactions.TryAdd(item.Tx.Hash, item)) @@ -477,7 +477,7 @@ internal bool ReVerifyTopUnverifiedTransactionsIfNeeded(int maxToVerify, Snapsho { int verifyCount = _sortedTransactions.Count > _maxTxPerBlock ? 1 : maxToVerify; ReverifyTransactions(_sortedTransactions, _unverifiedSortedTransactions, - verifyCount, MaxSecondsToReverifyTxPerIdle, snapshot); + verifyCount, MaxMillisecondsToReverifyTxPerIdle, snapshot); } return _unverifiedTransactions.Count > 0; diff --git a/neo/Network/P2P/Payloads/BlockBase.cs b/neo/Network/P2P/Payloads/BlockBase.cs index 9f56ca0d97..22ef72d021 100644 --- a/neo/Network/P2P/Payloads/BlockBase.cs +++ b/neo/Network/P2P/Payloads/BlockBase.cs @@ -14,7 +14,7 @@ public abstract class BlockBase : IVerifiable public uint Version; public UInt256 PrevHash; public UInt256 MerkleRoot; - public uint Timestamp; + public ulong Timestamp; public uint Index; public UInt160 NextConsensus; public Witness Witness; @@ -32,8 +32,16 @@ public UInt256 Hash } } - public virtual int Size => sizeof(uint) + PrevHash.Size + MerkleRoot.Size + sizeof(uint) + sizeof(uint) + NextConsensus.Size + 1 + Witness.Size; - + public virtual int Size => + sizeof(uint) + //Version + PrevHash.Size + //PrevHash + MerkleRoot.Size + //MerkleRoot + sizeof(ulong) + //Timestamp + sizeof(uint) + //Index + NextConsensus.Size + //NextConsensus + 1 + // + Witness.Size; //Witness + Witness[] IVerifiable.Witnesses { get @@ -59,7 +67,7 @@ void IVerifiable.DeserializeUnsigned(BinaryReader reader) Version = reader.ReadUInt32(); PrevHash = reader.ReadSerializable(); MerkleRoot = reader.ReadSerializable(); - Timestamp = reader.ReadUInt32(); + Timestamp = reader.ReadUInt64(); Index = reader.ReadUInt32(); NextConsensus = reader.ReadSerializable(); } diff --git a/neo/ProtocolSettings.cs b/neo/ProtocolSettings.cs index ba4c192e8b..b690cd7602 100644 --- a/neo/ProtocolSettings.cs +++ b/neo/ProtocolSettings.cs @@ -10,7 +10,7 @@ public class ProtocolSettings public byte AddressVersion { get; } public string[] StandbyValidators { get; } public string[] SeedList { get; } - public uint SecondsPerBlock { get; } + public uint MillisecondsPerBlock { get; } static ProtocolSettings _default; @@ -69,7 +69,7 @@ private ProtocolSettings(IConfigurationSection section) "seed4.neo.org:10333", "seed5.neo.org:10333" }; - this.SecondsPerBlock = section.GetValue("SecondsPerBlock", 15u); + this.MillisecondsPerBlock = section.GetValue("SecondsPerBlock", 15000u); } } } diff --git a/neo/SmartContract/ApplicationEngine.cs b/neo/SmartContract/ApplicationEngine.cs index ced43d379e..03a098530a 100644 --- a/neo/SmartContract/ApplicationEngine.cs +++ b/neo/SmartContract/ApplicationEngine.cs @@ -83,18 +83,18 @@ protected override bool PreExecuteInstruction() return true; return AddGas(OpCodePrices[CurrentContext.CurrentInstruction.OpCode]); } - - public static ApplicationEngine Run(byte[] script, Snapshot snapshot, - IVerifiable container = null, Block persistingBlock = null, bool testMode = false, long extraGAS = default) + + private static Block CreateDummyBlock(Snapshot snapshot) { - snapshot.PersistingBlock = persistingBlock ?? snapshot.PersistingBlock ?? new Block + var currentBlock = snapshot.Blocks[snapshot.CurrentBlockHash]; + return new Block { Version = 0, PrevHash = snapshot.CurrentBlockHash, MerkleRoot = new UInt256(), - Timestamp = snapshot.Blocks[snapshot.CurrentBlockHash].Timestamp + Blockchain.SecondsPerBlock, + Timestamp = currentBlock.Timestamp + Blockchain.MillisecondsPerBlock, Index = snapshot.Height + 1, - NextConsensus = snapshot.Blocks[snapshot.CurrentBlockHash].NextConsensus, + NextConsensus = currentBlock.NextConsensus, Witness = new Witness { InvocationScript = new byte[0], @@ -103,6 +103,12 @@ public static ApplicationEngine Run(byte[] script, Snapshot snapshot, ConsensusData = new ConsensusData(), Transactions = new Transaction[0] }; + } + + public static ApplicationEngine Run(byte[] script, Snapshot snapshot, + IVerifiable container = null, Block persistingBlock = null, bool testMode = false, long extraGAS = default) + { + snapshot.PersistingBlock = persistingBlock ?? snapshot.PersistingBlock ?? CreateDummyBlock(snapshot); ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, container, snapshot, extraGAS, testMode); engine.LoadScript(script); engine.Execute();