From 98e6d1c127a5b09b4dcfa6a809d49ad98eabad65 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 22 Jul 2019 12:03:41 +0200 Subject: [PATCH 01/54] Revert "Remove minner tx hole (#934)" (#944) This reverts commit 5b321fbcf97f9fff43980d9e0108c1cbf374968c. --- neo.UnitTests/UT_Block.cs | 27 +++++++++++++++++++-------- neo/Network/P2P/Payloads/Block.cs | 13 ++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/UT_Block.cs index f6b9218070..886f5099f0 100644 --- a/neo.UnitTests/UT_Block.cs +++ b/neo.UnitTests/UT_Block.cs @@ -1,6 +1,5 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO; using Neo.IO.Json; using Neo.Network.P2P.Payloads; using System.IO; @@ -87,13 +86,21 @@ public void Serialize() byte[] data; using (MemoryStream stream = new MemoryStream()) - using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true)) { - uut.Serialize(writer); - data = stream.ToArray(); + using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true)) + { + uut.Serialize(writer); + data = stream.ToArray(); + } } - Assert.AreEqual(data.ToHexString(), "0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d880ab04fd0000000000000000000000000000000000000000000000000100015101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000"); + 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 }; + + data.Length.Should().Be(requiredData.Length); + for (int i = 0; i < data.Length; i++) + { + data[i].Should().Be(requiredData[i]); + } } [TestMethod] @@ -104,10 +111,14 @@ public void Deserialize() uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid - using (MemoryStream ms = new MemoryStream("0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d880ab04fd0000000000000000000000000000000000000000000000000100015101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000".HexToBytes(), false)) - using (BinaryReader reader = new BinaryReader(ms)) + 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 }; + int index = 0; + using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false)) { - uut.Deserialize(reader); + using (BinaryReader reader = new BinaryReader(ms)) + { + uut.Deserialize(reader); + } } assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal, transactionsVal); diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index b63035e0ed..58faf54cb1 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -12,7 +12,7 @@ namespace Neo.Network.P2P.Payloads public class Block : BlockBase, IInventory, IEquatable { public const int MaxContentsPerBlock = ushort.MaxValue; - public const int MaxTransactionsPerBlock = MaxContentsPerBlock; + public const int MaxTransactionsPerBlock = MaxContentsPerBlock - 1; public ConsensusData ConsensusData; public Transaction[] Transactions; @@ -41,13 +41,13 @@ public Header Header InventoryType IInventory.InventoryType => InventoryType.Block; public override int Size => base.Size - + IO.Helper.GetVarSize(Transactions.Length) //Count + + IO.Helper.GetVarSize(Transactions.Length + 1) //Count + ConsensusData.Size //ConsensusData + Transactions.Sum(p => p.Size); //Transactions public static UInt256 CalculateMerkleRoot(UInt256 consensusDataHash, params UInt256[] transactionHashes) { - List hashes = new List(transactionHashes.Length) { consensusDataHash }; + List hashes = new List(transactionHashes.Length + 1) { consensusDataHash }; hashes.AddRange(transactionHashes); return MerkleTree.ComputeRoot(hashes); } @@ -58,7 +58,7 @@ public override void Deserialize(BinaryReader reader) int count = (int)reader.ReadVarInt(MaxContentsPerBlock); if (count == 0) throw new FormatException(); ConsensusData = reader.ReadSerializable(); - Transactions = new Transaction[count]; + Transactions = new Transaction[count - 1]; for (int i = 0; i < Transactions.Length; i++) Transactions[i] = reader.ReadSerializable(); if (Transactions.Distinct().Count() != Transactions.Length) @@ -76,8 +76,7 @@ public bool Equals(Block other) public override bool Equals(object obj) { - if (!(obj is Block b)) return false; - return Equals(b); + return Equals(obj as Block); } public override int GetHashCode() @@ -93,7 +92,7 @@ public void RebuildMerkleRoot() public override void Serialize(BinaryWriter writer) { base.Serialize(writer); - writer.WriteVarInt(Transactions.Length); + writer.WriteVarInt(Transactions.Length + 1); writer.Write(ConsensusData); foreach (Transaction tx in Transactions) writer.Write(tx); 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 02/54] 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 class ChangeView : ConsensusMessage 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 @@ internal void InvalidateAllTransactions() 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 @@ protected override bool PreExecuteInstruction() 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(); From d048805a30f1f323718f89b13db0a53dead615df Mon Sep 17 00:00:00 2001 From: Nikolai Perevozchikov Date: Tue, 23 Jul 2019 15:39:05 +0900 Subject: [PATCH 03/54] allow CheckWitness to work when using invokescript (#335) * allow CheckWitness to work when using invokescript * Fix * Update RpcServer.cs * Allow more than one signature * Reorder properties --- neo/Network/RPC/RpcServer.cs | 49 +++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/neo/Network/RPC/RpcServer.cs b/neo/Network/RPC/RpcServer.cs index 6bfdd15618..c47e6644e7 100644 --- a/neo/Network/RPC/RpcServer.cs +++ b/neo/Network/RPC/RpcServer.cs @@ -31,6 +31,43 @@ namespace Neo.Network.RPC { public sealed class RpcServer : IDisposable { + private class CheckWitnessHashes : IVerifiable + { + private readonly UInt160[] _scriptHashesForVerifying; + public Witness[] Witnesses { get; set; } + public int Size { get; } + + public CheckWitnessHashes(UInt160[] scriptHashesForVerifying) + { + _scriptHashesForVerifying = scriptHashesForVerifying; + } + + public void Serialize(BinaryWriter writer) + { + throw new NotImplementedException(); + } + + public void Deserialize(BinaryReader reader) + { + throw new NotImplementedException(); + } + + public void DeserializeUnsigned(BinaryReader reader) + { + throw new NotImplementedException(); + } + + public UInt160[] GetScriptHashesForVerifying(Snapshot snapshot) + { + return _scriptHashesForVerifying; + } + + public void SerializeUnsigned(BinaryWriter writer) + { + throw new NotImplementedException(); + } + } + public Wallet Wallet { get; set; } public long MaxGasInvoke { get; } @@ -72,9 +109,9 @@ public void Dispose() } } - private JObject GetInvokeResult(byte[] script) + private JObject GetInvokeResult(byte[] script, IVerifiable checkWitnessHashes = null) { - ApplicationEngine engine = ApplicationEngine.Run(script, extraGAS: MaxGasInvoke); + ApplicationEngine engine = ApplicationEngine.Run(script, checkWitnessHashes, extraGAS: MaxGasInvoke); JObject json = new JObject(); json["script"] = script.ToHexString(); json["state"] = engine.State; @@ -202,7 +239,13 @@ private JObject Process(string method, JArray _params) case "invokescript": { byte[] script = _params[0].AsString().HexToBytes(); - return InvokeScript(script); + CheckWitnessHashes checkWitnessHashes = null; + if (_params.Count > 1) + { + UInt160[] scriptHashesForVerifying = _params.Skip(1).Select(u => UInt160.Parse(u.AsString())).ToArray(); + checkWitnessHashes = new CheckWitnessHashes(scriptHashesForVerifying); + } + return GetInvokeResult(script, checkWitnessHashes); } case "listplugins": { From abda789f2de624acaf1f92d28be26bd6ebb9747b Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 23 Jul 2019 20:50:38 +0200 Subject: [PATCH 04/54] Allow to configure the memory pool capacity (#948) Making memory pool capacity configurable --- neo/Ledger/Blockchain.cs | 3 +-- neo/ProtocolSettings.cs | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index 854583423d..ee8e114701 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -53,7 +53,6 @@ public class FillCompleted { } Transactions = new[] { DeployNativeContracts() } }; - private const int MemoryPoolMaxTransactions = 50_000; private const int MaxTxToReverifyPerIdle = 10; private static readonly object lockObj = new object(); private readonly NeoSystem system; @@ -89,7 +88,7 @@ static Blockchain() public Blockchain(NeoSystem system, Store store) { this.system = system; - this.MemPool = new MemoryPool(system, MemoryPoolMaxTransactions); + this.MemPool = new MemoryPool(system, ProtocolSettings.Default.MemoryPoolMaxTransactions); this.Store = store; lock (lockObj) { diff --git a/neo/ProtocolSettings.cs b/neo/ProtocolSettings.cs index b690cd7602..478d5b71b3 100644 --- a/neo/ProtocolSettings.cs +++ b/neo/ProtocolSettings.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Configuration; +using System; using System.Linq; using System.Threading; @@ -11,6 +12,7 @@ public class ProtocolSettings public string[] StandbyValidators { get; } public string[] SeedList { get; } public uint MillisecondsPerBlock { get; } + public int MemoryPoolMaxTransactions { get; } static ProtocolSettings _default; @@ -70,6 +72,7 @@ private ProtocolSettings(IConfigurationSection section) "seed5.neo.org:10333" }; this.MillisecondsPerBlock = section.GetValue("SecondsPerBlock", 15000u); + this.MemoryPoolMaxTransactions = Math.Max(1, section.GetValue("MemoryPoolMaxTransactions", 50_000)); } } } From 34f37b9f93ee97df95a7d9583955dc6837826463 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Thu, 25 Jul 2019 20:16:33 +0800 Subject: [PATCH 05/54] Update dependency: Neo.VM v3.0.0-CI00030 (#956) --- neo/SmartContract/ApplicationEngine.OpCodePrices.cs | 2 -- neo/neo.csproj | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/neo/SmartContract/ApplicationEngine.OpCodePrices.cs index 05105e2261..9da0f6c75d 100644 --- a/neo/SmartContract/ApplicationEngine.OpCodePrices.cs +++ b/neo/SmartContract/ApplicationEngine.OpCodePrices.cs @@ -162,8 +162,6 @@ partial class ApplicationEngine [OpCode.MIN] = 200, [OpCode.MAX] = 200, [OpCode.WITHIN] = 200, - [OpCode.SHA1] = 300000, - [OpCode.SHA256] = 1000000, [OpCode.ARRAYSIZE] = 150, [OpCode.PACK] = 7000, [OpCode.UNPACK] = 7000, diff --git a/neo/neo.csproj b/neo/neo.csproj index e811c280dd..df29d088f2 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -29,7 +29,7 @@ - + From a9f46bc7d351933e7d8666665c49f850ed5d8e24 Mon Sep 17 00:00:00 2001 From: Charis Zhao Date: Fri, 26 Jul 2019 18:46:28 +0800 Subject: [PATCH 06/54] Unit tests for IO, Cryptography, Wallets and VM modules (#943) * testDemo * add dll lib * add dbsnapshot dispose * test get blocks in levelDBStore * add levelDBStore test funcs * fix levelDBStore funcs * add DbCache addInternal * differ db path * space * fix delete internal test * add test getInternal tryGetInternal move libleveldb.dll * add dbCache method test * add store test * add cache unit tests * add cache unit tests * up readonly max_capacity * fix leveldbexception * fix comment on UT_Cache * format * fix multithread test problem * up cache * update travis config * update travis.yml * test DbMetaDataCache * fix db directory * format and update travis for maxos * fix mac env travis * 2019/7/12 10:34 * 2019/7/12 11:01 * remove commented line * test BigDecimal * fix format and csproj * rm coverage.opencover.xml * update method name * add UT_P_Helper * modify UT_P_Helper * modify UT_P_helper * Clean ut * test Base58 & BloomFilter * Update UT_Cache.cs * Correct Typo * test JsonArray * update namespace * update namespace * update format * update format * organise folder structure * add UT_JString * test JBoolean JNumber & JObject * 2019/7/16 10:30 add some test case for UInt32Wrapper and SerializableWrapper * fix timestamp * test ECDsa and Crypto * test OrderedDictionary & complete IO.Json tests * 2019/7/16 17:33 add some test case of SQLiteWallet * test FIFOSet * add CloneCache and DataCache unit tests * fix namespace * add UT_Cryptography_Helper * format UT_CloneCache and UT_DataCache * add UT_DataCache.GetAndChange unit test * update namespace * remove comment code * delete Persistence part * 2019/7/19 11:07 add some test case for Helper in VM * Fix Base58 Test * 2019/7/19 11:33 change some format * update IOHelper exception assert * 2019/7/19 14:22 change format * format IOHelper * review IO.Wrapper * review Wallets.SQLite UT * Test ECFieldElement ECPoint * refactor package * format ECDsa * update namespace * Code fix * review cache * modify UT_JString * fomat * using Actin replace with try-catch * add UT_CloneMetaCache and UT_MetaDataCache * update namespace * format UT_DataCache.cs * Code Fix * format * update csproj * Code fix for UT_ECFieldElement and UT_ECPoint * Code fix * format * update travis * delete deleteFiles * fix path and comment * update travis * delete test ToTimeStamp * format UT_*Cache * update format * fomat * use hex extensions in Cryptography_Helper * remove reflection * optimization of UT_DataCache * update namespace * modify TestSha256 --- neo.UnitTests/{ => Consensus}/UT_Consensus.cs | 16 +- .../UT_ConsensusServiceMailbox.cs | 2 +- neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs | 55 ++ .../Cryptography/ECC/UT_ECFieldElement.cs | 69 +++ neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs | 310 ++++++++++ neo.UnitTests/Cryptography/UT_Base58.cs | 31 + neo.UnitTests/Cryptography/UT_BloomFilter.cs | 69 +++ neo.UnitTests/Cryptography/UT_Crypto.cs | 64 ++ .../Cryptography/UT_Cryptography_Helper.cs | 225 +++++++ neo.UnitTests/{ => Cryptography}/UT_Scrypt.cs | 4 +- .../Extensions/NativeContractExtensions.cs | 4 +- .../Nep5NativeContractExtensions.cs | 8 +- neo.UnitTests/IO/Caching/UT_Cache.cs | 214 +++++++ neo.UnitTests/IO/Caching/UT_CloneCache.cs | 126 ++++ neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs | 48 ++ neo.UnitTests/IO/Caching/UT_DataCache.cs | 347 +++++++++++ neo.UnitTests/IO/Caching/UT_FifoSet.cs | 120 ++++ neo.UnitTests/IO/Caching/UT_MetaDataCache.cs | 76 +++ .../IO/Caching/UT_OrderedDictionary.cs | 87 +++ neo.UnitTests/IO/Json/UT_JArray.cs | 249 ++++++++ neo.UnitTests/IO/Json/UT_JBoolean.cs | 77 +++ neo.UnitTests/IO/Json/UT_JNumber.cs | 67 +++ neo.UnitTests/IO/Json/UT_JObject.cs | 119 ++++ neo.UnitTests/IO/Json/UT_JString.cs | 73 +++ neo.UnitTests/IO/UT_IOHelper.cs | 549 ++++++++++++++++++ .../IO/Wrappers/UT_SerializableWrapper.cs | 50 ++ neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs | 97 ++++ neo.UnitTests/{ => Ledger}/UT_MemoryPool.cs | 2 +- neo.UnitTests/{ => Ledger}/UT_PoolItem.cs | 2 +- neo.UnitTests/{ => Ledger}/UT_StorageItem.cs | 2 +- neo.UnitTests/{ => Ledger}/UT_StorageKey.cs | 2 +- .../{ => Network/P2P/Payloads}/UT_Block.cs | 2 +- .../{ => Network/P2P/Payloads}/UT_Header.cs | 2 +- .../P2P/Payloads}/UT_Transaction.cs | 2 +- .../{ => Network/P2P/Payloads}/UT_Witness.cs | 2 +- .../P2P/UT_Message.cs} | 4 +- .../{ => Network/P2P}/UT_ProtocolHandler.cs | 2 +- .../P2P}/UT_ProtocolHandlerMailbox.cs | 15 +- .../{ => Network/P2P}/UT_RemoteNode.cs | 2 +- .../{ => Network/P2P}/UT_RemoteNodeMailbox.cs | 6 +- .../P2P}/UT_TaskManagerMailbox.cs | 12 +- .../Iterators}/UT_ConcatenatedIterator.cs | 2 +- .../Manifest}/UT_ContractManifest.cs | 2 +- .../Native/Tokens}/UT_GasToken.cs | 2 +- .../Native/Tokens}/UT_NeoToken.cs | 2 +- .../Native/UT_PolicyContract.cs} | 10 +- .../{ => SmartContract}/UT_InteropPrices.cs | 2 +- .../{ => SmartContract}/UT_InteropService.cs | 5 +- .../{ => SmartContract}/UT_JsonSerializer.cs | 2 +- .../{ => SmartContract}/UT_OpCodePrices.cs | 2 +- .../{ => SmartContract}/UT_Syscalls.cs | 2 +- neo.UnitTests/UT_BigDecimal.cs | 191 ++++++ neo.UnitTests/UT_FifoSet.cs | 54 -- neo.UnitTests/UT_ProtocolSettings.cs | 2 +- neo.UnitTests/VM/UT_Helper.cs | 82 +++ .../{ => Wallets/NEP6}/UT_NEP6Wallet.cs | 2 +- .../{ => Wallets/NEP6}/UT_ScryptParameters.cs | 2 +- neo.UnitTests/Wallets/SQLite/UT_Account.cs | 37 ++ neo.UnitTests/Wallets/SQLite/UT_Address.cs | 27 + neo.UnitTests/Wallets/SQLite/UT_Contract.cs | 65 +++ neo.UnitTests/Wallets/SQLite/UT_Key.cs | 37 ++ .../UT_AssetDescriptor.cs} | 8 +- neo.UnitTests/neo.UnitTests.csproj | 1 - neo/Ledger/MemoryPool.cs | 2 +- 64 files changed, 3625 insertions(+), 129 deletions(-) rename neo.UnitTests/{ => Consensus}/UT_Consensus.cs (97%) rename neo.UnitTests/{ => Consensus}/UT_ConsensusServiceMailbox.cs (97%) create mode 100644 neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs create mode 100644 neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs create mode 100644 neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs create mode 100644 neo.UnitTests/Cryptography/UT_Base58.cs create mode 100644 neo.UnitTests/Cryptography/UT_BloomFilter.cs create mode 100644 neo.UnitTests/Cryptography/UT_Crypto.cs create mode 100644 neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs rename neo.UnitTests/{ => Cryptography}/UT_Scrypt.cs (93%) create mode 100644 neo.UnitTests/IO/Caching/UT_Cache.cs create mode 100644 neo.UnitTests/IO/Caching/UT_CloneCache.cs create mode 100644 neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs create mode 100644 neo.UnitTests/IO/Caching/UT_DataCache.cs create mode 100644 neo.UnitTests/IO/Caching/UT_FifoSet.cs create mode 100644 neo.UnitTests/IO/Caching/UT_MetaDataCache.cs create mode 100644 neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs create mode 100644 neo.UnitTests/IO/Json/UT_JArray.cs create mode 100644 neo.UnitTests/IO/Json/UT_JBoolean.cs create mode 100644 neo.UnitTests/IO/Json/UT_JNumber.cs create mode 100644 neo.UnitTests/IO/Json/UT_JObject.cs create mode 100644 neo.UnitTests/IO/Json/UT_JString.cs create mode 100644 neo.UnitTests/IO/UT_IOHelper.cs create mode 100644 neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs create mode 100644 neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs rename neo.UnitTests/{ => Ledger}/UT_MemoryPool.cs (99%) rename neo.UnitTests/{ => Ledger}/UT_PoolItem.cs (99%) rename neo.UnitTests/{ => Ledger}/UT_StorageItem.cs (98%) rename neo.UnitTests/{ => Ledger}/UT_StorageKey.cs (99%) rename neo.UnitTests/{ => Network/P2P/Payloads}/UT_Block.cs (99%) rename neo.UnitTests/{ => Network/P2P/Payloads}/UT_Header.cs (99%) rename neo.UnitTests/{ => Network/P2P/Payloads}/UT_Transaction.cs (99%) rename neo.UnitTests/{ => Network/P2P/Payloads}/UT_Witness.cs (98%) rename neo.UnitTests/{UT_P2PMessage.cs => Network/P2P/UT_Message.cs} (98%) rename neo.UnitTests/{ => Network/P2P}/UT_ProtocolHandler.cs (97%) rename neo.UnitTests/{ => Network/P2P}/UT_ProtocolHandlerMailbox.cs (98%) rename neo.UnitTests/{ => Network/P2P}/UT_RemoteNode.cs (98%) rename neo.UnitTests/{ => Network/P2P}/UT_RemoteNodeMailbox.cs (94%) rename neo.UnitTests/{ => Network/P2P}/UT_TaskManagerMailbox.cs (93%) rename neo.UnitTests/{ => SmartContract/Iterators}/UT_ConcatenatedIterator.cs (97%) rename neo.UnitTests/{ => SmartContract/Manifest}/UT_ContractManifest.cs (99%) rename neo.UnitTests/{ => SmartContract/Native/Tokens}/UT_GasToken.cs (99%) rename neo.UnitTests/{ => SmartContract/Native/Tokens}/UT_NeoToken.cs (99%) rename neo.UnitTests/{UT_Policy.cs => SmartContract/Native/UT_PolicyContract.cs} (94%) rename neo.UnitTests/{ => SmartContract}/UT_InteropPrices.cs (99%) rename neo.UnitTests/{ => SmartContract}/UT_InteropService.cs (98%) rename neo.UnitTests/{ => SmartContract}/UT_JsonSerializer.cs (99%) rename neo.UnitTests/{ => SmartContract}/UT_OpCodePrices.cs (91%) rename neo.UnitTests/{ => SmartContract}/UT_Syscalls.cs (98%) create mode 100644 neo.UnitTests/UT_BigDecimal.cs delete mode 100644 neo.UnitTests/UT_FifoSet.cs create mode 100644 neo.UnitTests/VM/UT_Helper.cs rename neo.UnitTests/{ => Wallets/NEP6}/UT_NEP6Wallet.cs (97%) rename neo.UnitTests/{ => Wallets/NEP6}/UT_ScryptParameters.cs (97%) create mode 100644 neo.UnitTests/Wallets/SQLite/UT_Account.cs create mode 100644 neo.UnitTests/Wallets/SQLite/UT_Address.cs create mode 100644 neo.UnitTests/Wallets/SQLite/UT_Contract.cs create mode 100644 neo.UnitTests/Wallets/SQLite/UT_Key.cs rename neo.UnitTests/{UT_AssetDescription.cs => Wallets/UT_AssetDescriptor.cs} (77%) diff --git a/neo.UnitTests/UT_Consensus.cs b/neo.UnitTests/Consensus/UT_Consensus.cs similarity index 97% rename from neo.UnitTests/UT_Consensus.cs rename to neo.UnitTests/Consensus/UT_Consensus.cs index c5bf1828f8..34e8322615 100644 --- a/neo.UnitTests/UT_Consensus.cs +++ b/neo.UnitTests/Consensus/UT_Consensus.cs @@ -18,7 +18,7 @@ using System.Security.Cryptography; using ECPoint = Neo.Cryptography.ECC.ECPoint; -namespace Neo.UnitTests +namespace Neo.UnitTests.Consensus { [TestClass] @@ -151,13 +151,13 @@ public void TestSerializeAndDeserializeConsensusContext() ViewNumber = 2, Validators = new ECPoint[7] { - ECPoint.Parse("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", Cryptography.ECC.ECCurve.Secp256r1), - ECPoint.Parse("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", Cryptography.ECC.ECCurve.Secp256r1), - ECPoint.Parse("02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", Cryptography.ECC.ECCurve.Secp256r1), - ECPoint.Parse("02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", Cryptography.ECC.ECCurve.Secp256r1), - ECPoint.Parse("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", Cryptography.ECC.ECCurve.Secp256r1), - ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", Cryptography.ECC.ECCurve.Secp256r1), - ECPoint.Parse("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", Cryptography.ECC.ECCurve.Secp256r1) + ECPoint.Parse("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", Neo.Cryptography.ECC.ECCurve.Secp256r1), + ECPoint.Parse("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", Neo.Cryptography.ECC.ECCurve.Secp256r1), + ECPoint.Parse("02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", Neo.Cryptography.ECC.ECCurve.Secp256r1), + ECPoint.Parse("02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", Neo.Cryptography.ECC.ECCurve.Secp256r1), + ECPoint.Parse("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", Neo.Cryptography.ECC.ECCurve.Secp256r1), + ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", Neo.Cryptography.ECC.ECCurve.Secp256r1), + ECPoint.Parse("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", Neo.Cryptography.ECC.ECCurve.Secp256r1) }, MyIndex = -1 }; diff --git a/neo.UnitTests/UT_ConsensusServiceMailbox.cs b/neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs similarity index 97% rename from neo.UnitTests/UT_ConsensusServiceMailbox.cs rename to neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs index fded2ab54e..fec1ee6bc9 100644 --- a/neo.UnitTests/UT_ConsensusServiceMailbox.cs +++ b/neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs @@ -10,7 +10,7 @@ using Akka.Configuration; using Neo.Consensus; -namespace Neo.UnitTests +namespace Neo.UnitTests.Consensus { [TestClass] public class UT_ConsensusServiceMailbox : TestKit diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs b/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs new file mode 100644 index 0000000000..dcd394fa4f --- /dev/null +++ b/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs @@ -0,0 +1,55 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Wallets; +using System; +using System.Numerics; +using ECDsa = Neo.Cryptography.ECC.ECDsa; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_ECDsa + { + private KeyPair key = null; + + [TestInitialize] + public void TestSetup() + { + key = UT_Crypto.generateCertainKey(32); + } + + [TestMethod] + public void TestECDsaConstructor() + { + Action action = () => new ECDsa(key.PublicKey); + action.ShouldNotThrow(); + action = () => new ECDsa(key.PrivateKey, key.PublicKey.Curve); + action.ShouldNotThrow(); + } + + [TestMethod] + public void TestGenerateSignature() + { + ECDsa sa = new ECDsa(key.PrivateKey, key.PublicKey.Curve); + byte[] message = System.Text.Encoding.Default.GetBytes("HelloWorld"); + for (int i = 0; i < 30; i++) + { + BigInteger[] result = sa.GenerateSignature(message); + result.Length.Should().Be(2); + } + sa = new ECDsa(key.PublicKey); + Action action = () => sa.GenerateSignature(message); + action.ShouldThrow(); + } + + [TestMethod] + public void TestVerifySignature() + { + ECDsa sa = new ECDsa(key.PrivateKey, key.PublicKey.Curve); + byte[] message = System.Text.Encoding.Default.GetBytes("HelloWorld"); + BigInteger[] result = sa.GenerateSignature(message); + sa.VerifySignature(message, result[0], result[1]).Should().BeTrue(); + sa.VerifySignature(message, new BigInteger(-100), result[1]).Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs b/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs new file mode 100644 index 0000000000..035e4dc469 --- /dev/null +++ b/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs @@ -0,0 +1,69 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.ECC; +using System; +using System.Globalization; +using System.Numerics; +using System.Reflection; + +namespace Neo.UnitTests.Cryptography.ECC +{ + [TestClass] + public class UT_ECFieldElement + { + [TestMethod] + public void TestECFieldElementConstructor() + { + BigInteger input = new BigInteger(100); + Action action = () => new ECFieldElement(input, ECCurve.Secp256k1); + action.ShouldNotThrow(); + + input = ECCurve.Secp256k1.Q; + action = () => new ECFieldElement(input, ECCurve.Secp256k1); + action.ShouldThrow(); + } + + [TestMethod] + public void TestEquals() + { + BigInteger input = new BigInteger(100); + object element = new ECFieldElement(input, ECCurve.Secp256k1); + element.Equals(element).Should().BeTrue(); + element.Equals(1).Should().BeFalse(); + + input = new BigInteger(200); + element.Equals(new ECFieldElement(input, ECCurve.Secp256k1)).Should().BeFalse(); + } + + [TestMethod] + public void TestSqrt() + { + ECFieldElement element = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1); + element.Sqrt().Should().Be(new ECFieldElement(BigInteger.Parse("115792089237316195423570985008687907853269984665640564039457584007908834671653"), ECCurve.Secp256k1)); + + ConstructorInfo constructor = typeof(ECCurve).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(BigInteger), typeof(BigInteger), typeof(BigInteger), typeof(BigInteger), typeof(byte[]) }, null); + ECCurve testCruve = constructor.Invoke(new object[] { + BigInteger.Parse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFF0", NumberStyles.AllowHexSpecifier), + BigInteger.Parse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFF00", NumberStyles.AllowHexSpecifier), + BigInteger.Parse("005AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", NumberStyles.AllowHexSpecifier), + BigInteger.Parse("00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", NumberStyles.AllowHexSpecifier), + ("04" + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5").HexToBytes() }) as ECCurve; + element = new ECFieldElement(new BigInteger(200), testCruve); + element.Sqrt().Should().Be(null); + } + + [TestMethod] + public void TestToByteArray() + { + byte[] result = new byte[32]; + result[31] = 100; + new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1).ToByteArray().Should().BeEquivalentTo(result); + + byte[] result2 = { 2, 53, 250, 221, 129, 194, 130, 43, 179, 240, 120, 119, 151, 61, 80, 242, 139, 242, 42, 49, 190, 142, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + new ECFieldElement(BigInteger.Pow(new BigInteger(10), 75), ECCurve.Secp256k1).ToByteArray().Should().BeEquivalentTo(result2); + + byte[] result3 = { 221, 21, 254, 134, 175, 250, 217, 18, 73, 239, 14, 183, 19, 243, 158, 190, 170, 152, 123, 110, 111, 210, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + new ECFieldElement(BigInteger.Pow(new BigInteger(10), 77), ECCurve.Secp256k1).ToByteArray().Should().BeEquivalentTo(result3); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs new file mode 100644 index 0000000000..9de751e851 --- /dev/null +++ b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs @@ -0,0 +1,310 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.ECC; +using Neo.IO; +using System; +using System.IO; +using System.Linq; +using System.Numerics; +using ECCurve = Neo.Cryptography.ECC.ECCurve; +using ECPoint = Neo.Cryptography.ECC.ECPoint; + +namespace Neo.UnitTests.Cryptography.ECC +{ + [TestClass] + public class UT_ECPoint + { + public static byte[] generatePrivateKey(int privateKeyLength) + { + byte[] privateKey = new byte[privateKeyLength]; + for (int i = 0; i < privateKeyLength; i++) + { + privateKey[i] = (byte)((byte)i % byte.MaxValue); + } + return privateKey; + } + + [TestMethod] + public void TestCompareTo() + { + ECFieldElement X1 = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1); + ECFieldElement Y1 = new ECFieldElement(new BigInteger(200), ECCurve.Secp256k1); + ECFieldElement X2 = new ECFieldElement(new BigInteger(300), ECCurve.Secp256k1); + ECFieldElement Y2 = new ECFieldElement(new BigInteger(400), ECCurve.Secp256k1); + ECPoint point1 = new ECPoint(X1, Y1, ECCurve.Secp256k1); + ECPoint point2 = new ECPoint(X2, Y1, ECCurve.Secp256k1); + ECPoint point3 = new ECPoint(X1, Y2, ECCurve.Secp256k1); + + point1.CompareTo(point1).Should().Be(0); + point1.CompareTo(point2).Should().Be(-1); + point2.CompareTo(point1).Should().Be(1); + point1.CompareTo(point3).Should().Be(-1); + point3.CompareTo(point1).Should().Be(1); + } + + [TestMethod] + public void TestECPointConstructor() + { + ECPoint point = new ECPoint(); + point.X.Should().BeNull(); + point.Y.Should().BeNull(); + point.Curve.Should().Be(ECCurve.Secp256r1); + + ECFieldElement X = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1); + ECFieldElement Y = new ECFieldElement(new BigInteger(200), ECCurve.Secp256k1); + point = new ECPoint(X, Y, ECCurve.Secp256k1); + point.X.Should().Be(X); + point.Y.Should().Be(Y); + point.Curve.Should().Be(ECCurve.Secp256k1); + } + + [TestMethod] + public void TestDecodePoint() + { + byte[] input1 = { 0 }; + Action action = () => ECPoint.DecodePoint(input1, ECCurve.Secp256k1); + action.ShouldThrow(); + + byte[] input2 = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72, + 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 }; + ECPoint.DecodePoint(input2, ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + action = () => ECPoint.DecodePoint(input2.Take(32).ToArray(), ECCurve.Secp256k1); + action.ShouldThrow(); + + byte[] input3 = { 2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152 }; + byte[] input4 = { 3, 107, 23, 209, 242, 225, 44, 66, 71, 248, 188, 230, 229, 99, 164, 64, 242, 119, 3, 125, 129, 45, 235, 51, 160, 244, 161, 57, 69, 216, 152, 194, 150 }; + ECPoint.DecodePoint(input3, ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + ECPoint.DecodePoint(input4, ECCurve.Secp256r1).Should().Be(ECCurve.Secp256r1.G); + + action = () => ECPoint.DecodePoint(input3.Take(input3.Length - 1).ToArray(), ECCurve.Secp256k1); + action.ShouldThrow(); + } + + [TestMethod] + public void TestDeserializeFrom() + { + byte[] input1 = { 0 }; + Action action = () => ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input1)), ECCurve.Secp256k1); + action.ShouldThrow(); + + byte[] input2 = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72, + 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 }; + ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input2)), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + action = () => ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input2.Take(32).ToArray())), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + action.ShouldThrow(); + + byte[] input3 = { 2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152 }; + ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input3)), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + byte[] input4 = { 3, 107, 23, 209, 242, 225, 44, 66, 71, 248, 188, 230, 229, 99, 164, 64, 242, 119, 3, 125, 129, 45, 235, 51, 160, 244, 161, 57, 69, 216, 152, 194, 150 }; + ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input4)), ECCurve.Secp256r1).Should().Be(ECCurve.Secp256r1.G); + + action = () => ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input3.Take(input3.Length - 1).ToArray())), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + action.ShouldThrow(); + } + + [TestMethod] + public void TestEncodePoint() + { + ECPoint point = new ECPoint(null, null, ECCurve.Secp256k1); + byte[] result1 = { 0 }; + point.EncodePoint(true).Should().BeEquivalentTo(result1); + + point = ECCurve.Secp256k1.G; + byte[] result2 = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72, + 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 }; + point.EncodePoint(false).Should().BeEquivalentTo(result2); + + byte[] result3 = { 2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152 }; + point.EncodePoint(true).Should().BeEquivalentTo(result3); + + point = ECCurve.Secp256r1.G; + byte[] result4 = { 3, 107, 23, 209, 242, 225, 44, 66, 71, 248, 188, 230, 229, 99, 164, 64, 242, 119, 3, 125, 129, 45, 235, 51, 160, 244, 161, 57, 69, 216, 152, 194, 150 }; + point.EncodePoint(true).Should().BeEquivalentTo(result4); + } + + [TestMethod] + public void TestEquals() + { + ECPoint point = ECCurve.Secp256k1.G; + point.Equals(point).Should().BeTrue(); + point.Equals(null).Should().BeFalse(); + + point = new ECPoint(null, null, ECCurve.Secp256k1); + point.Equals(new ECPoint(null, null, ECCurve.Secp256r1)).Should().BeTrue(); + point.Equals(ECCurve.Secp256r1.G).Should().BeFalse(); + ECCurve.Secp256r1.G.Equals(point).Should().BeFalse(); + + ECFieldElement X1 = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1); + ECFieldElement Y1 = new ECFieldElement(new BigInteger(200), ECCurve.Secp256k1); + ECFieldElement X2 = new ECFieldElement(new BigInteger(300), ECCurve.Secp256k1); + ECFieldElement Y2 = new ECFieldElement(new BigInteger(400), ECCurve.Secp256k1); + ECPoint point1 = new ECPoint(X1, Y1, ECCurve.Secp256k1); + ECPoint point2 = new ECPoint(X2, Y1, ECCurve.Secp256k1); + ECPoint point3 = new ECPoint(X1, Y2, ECCurve.Secp256k1); + point1.Equals(point2).Should().BeFalse(); + point1.Equals(point3).Should().BeFalse(); + } + + [TestMethod] + public void TestFromBytes() + { + byte[] input1 = { 0 }; + Action action = () => ECPoint.FromBytes(input1, ECCurve.Secp256k1); + action.ShouldThrow(); + + byte[] input2 = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72, + 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 }; + ECPoint.FromBytes(input2, ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + + byte[] input3 = { 2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152 }; + ECPoint.FromBytes(input3, ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + ECPoint.FromBytes(input2.Skip(1).ToArray(), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G); + + byte[] input4 = generatePrivateKey(72); + ECPoint.FromBytes(input4, ECCurve.Secp256k1).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("3634473727541135791764834762056624681715094789735830699031648" + + "273128038409767"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("18165245710263168158644330920009617039772504630129940696140050972160274286151"), + ECCurve.Secp256k1), ECCurve.Secp256k1)); + + byte[] input5 = generatePrivateKey(96); + ECPoint.FromBytes(input5, ECCurve.Secp256k1).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("1780731860627700044960722568376592200742329637303199754547598" + + "369979440671"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("14532552714582660066924456880521368950258152170031413196862950297402215317055"), + ECCurve.Secp256k1), ECCurve.Secp256k1)); + + byte[] input6 = generatePrivateKey(104); + ECPoint.FromBytes(input6, ECCurve.Secp256k1).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("3634473727541135791764834762056624681715094789735830699031648" + + "273128038409767"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("18165245710263168158644330920009617039772504630129940696140050972160274286151"), + ECCurve.Secp256k1), ECCurve.Secp256k1)); + } + + [TestMethod] + public void TestMultiply() + { + ECPoint p = ECCurve.Secp256k1.G; + BigInteger k = BigInteger.Parse("100"); + ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("107303582290733097924842193972465022053148211775194373671539518313500194639752"), + ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("103795966108782717446806684023742168462365449272639790795591544606836007446638"), ECCurve.Secp256k1), + ECCurve.Secp256k1)); + + k = BigInteger.Parse("10000"); + ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("55279067612272658004429375184716238028207484982037227804583126224321918234542"), + ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("93139664895507357192565643142424306097487832058389223752321585898830257071353"), ECCurve.Secp256k1), + ECCurve.Secp256k1)); + + k = BigInteger.Parse("10000000000000"); + ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("115045167963494515061513744671884131783397561769819471159495798754884242293003"), + ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("93759167105263077270762304290738437383691912799231615884447658154878797241853"), ECCurve.Secp256k1), + ECCurve.Secp256k1)); + + k = BigInteger.Parse("1000000000000000000000000000000000000000"); + ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("114831276968810911840931876895388845736099852671055832194631099067239418074350"), + ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("16721517996619732311261078486295444964227498319433363271180755596201863690708"), ECCurve.Secp256k1), + ECCurve.Secp256k1)); + + k = new BigInteger(generatePrivateKey(100)); + ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("19222995016448259376216431079553428738726180595337971417371897285865264889977"), + ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("6637081904924493791520919212064582313497884724460823966446023080706723904419"), ECCurve.Secp256k1), + ECCurve.Secp256k1)); + + k = new BigInteger(generatePrivateKey(120)); + ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("79652345192111851576650978679091010173409410384772942769927955775006682639778"), + ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("6460429961979335115790346961011058418773289452368186110818621539624566803831"), ECCurve.Secp256k1), + ECCurve.Secp256k1)); + + k = new BigInteger(generatePrivateKey(300)); + ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("105331914562708556186724786757483927866790351460145374033180496740107603569412"), + ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("60523670886755698512704385951571322569877668383890769288780681319304421873758"), ECCurve.Secp256k1), + ECCurve.Secp256k1)); + } + + [TestMethod] + public void TestDeserialize() + { + ECPoint point = new ECPoint(null, null, ECCurve.Secp256k1); + ISerializable serializable = point; + byte[] input = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, + 72, 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 }; + serializable.Deserialize(new BinaryReader(new MemoryStream(input))); + point.X.Should().Be(ECCurve.Secp256k1.G.X); + point.Y.Should().Be(ECCurve.Secp256k1.G.Y); + } + + [TestMethod] + public void TestSerialize() + { + MemoryStream stream = new MemoryStream(); + ECPoint point = new ECPoint(null, null, ECCurve.Secp256k1); + ISerializable serializable = point; + serializable.Serialize(new BinaryWriter(stream)); + stream.ToArray().Should().BeEquivalentTo(new byte[] { 0 }); + } + + [TestMethod] + public void TestOpAddition() + { + (ECCurve.Secp256k1.Infinity + ECCurve.Secp256k1.G).Should().Be(ECCurve.Secp256k1.G); + (ECCurve.Secp256k1.G + ECCurve.Secp256k1.Infinity).Should().Be(ECCurve.Secp256k1.G); + (ECCurve.Secp256k1.G + ECCurve.Secp256k1.G).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("8956589192654700423125292042593569236064414582962220983368432" + + "9913297188986597"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("12158399299693830322967808612713398636155367887041628176798871954788371653930"), + ECCurve.Secp256k1), ECCurve.Secp256k1)); + (ECCurve.Secp256k1.G + new ECPoint(ECCurve.Secp256k1.G.X, new ECFieldElement(BigInteger.One, ECCurve.Secp256k1), ECCurve.Secp256k1)).Should().Be(ECCurve.Secp256k1.Infinity); + (ECCurve.Secp256k1.G + ECCurve.Secp256k1.G + ECCurve.Secp256k1.G).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("112711660439710606056748659173929673102" + + "114977341539408544630613555209775888121"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("2558302798057088369165690587740197640644886825481629506991988" + + "8960541586679410"), ECCurve.Secp256k1), ECCurve.Secp256k1)); + } + + [TestMethod] + public void TestOpMultiply() + { + ECPoint p = null; + byte[] n = new byte[] { 1 }; + Action action = () => p = p * n; + action.ShouldThrow(); + + p = ECCurve.Secp256k1.G; + n = null; + action.ShouldThrow(); + + n = new byte[] { 1 }; + action.ShouldThrow(); + + p = ECCurve.Secp256k1.Infinity; + n = new byte[32]; + (p * n).Should().Be(p); + + p = ECCurve.Secp256k1.G; + (p * n).Should().Be(ECCurve.Secp256k1.Infinity); + + n[0] = 1; + (p * n).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("63395642421589016740518975608504846303065672135176650115036476193363423546538"), ECCurve.Secp256k1), + new ECFieldElement(BigInteger.Parse("29236048674093813394523910922582374630829081423043497254162533033164154049666"), ECCurve.Secp256k1), ECCurve.Secp256k1)); + } + + [TestMethod] + public void TestOpUnaryNegation() + { + (-ECCurve.Secp256k1.G).Should().Be(new ECPoint(ECCurve.Secp256k1.G.X, -ECCurve.Secp256k1.G.Y, ECCurve.Secp256k1)); + } + + [TestMethod] + public void TestTryParse() + { + ECPoint.TryParse("00", ECCurve.Secp256k1, out ECPoint result).Should().BeFalse(); + result.Should().BeNull(); + + ECPoint.TryParse("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", ECCurve.Secp256k1, + out result).Should().BeTrue(); + result.Should().Be(ECCurve.Secp256k1.G); + } + + [TestMethod] + public void TestTwice() + { + ECCurve.Secp256k1.Infinity.Twice().Should().Be(ECCurve.Secp256k1.Infinity); + new ECPoint(new ECFieldElement(BigInteger.Zero, ECCurve.Secp256k1), new ECFieldElement(BigInteger.Zero, ECCurve.Secp256k1), + ECCurve.Secp256k1).Twice().Should().Be(ECCurve.Secp256k1.Infinity); + ECCurve.Secp256k1.G.Twice().Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("89565891926547004231252920425935692360644145829622209833684329913297188986597"), + ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("12158399299693830322967808612713398636155367887041628176798871954788371653930"), ECCurve.Secp256k1), + ECCurve.Secp256k1)); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/UT_Base58.cs b/neo.UnitTests/Cryptography/UT_Base58.cs new file mode 100644 index 0000000000..2d18975445 --- /dev/null +++ b/neo.UnitTests/Cryptography/UT_Base58.cs @@ -0,0 +1,31 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using System; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_Base58 + { + byte[] decoded1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + string encoded1 = "1kA3B2yGe2z4"; + byte[] decoded2 = { 0, 0, 0, 0, 0}; + string encoded2 = "1111"; + + [TestMethod] + public void TestEncode() + { + Base58.Encode(decoded1).Should().Be(encoded1); + } + + [TestMethod] + public void TestDecode() + { + Base58.Decode(encoded1).Should().BeEquivalentTo(decoded1); + Base58.Decode(encoded2).Should().BeEquivalentTo(decoded2); + Action action = () => Base58.Decode(encoded1 + "l").Should().BeEquivalentTo(decoded1); + action.ShouldThrow(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/UT_BloomFilter.cs b/neo.UnitTests/Cryptography/UT_BloomFilter.cs new file mode 100644 index 0000000000..d611e0965d --- /dev/null +++ b/neo.UnitTests/Cryptography/UT_BloomFilter.cs @@ -0,0 +1,69 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using System; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_BloomFilter + { + [TestMethod] + public void TestAddCheck() + { + int m = 7, n = 10; + uint nTweak = 123456; + byte[] elements = { 0, 1, 2, 3, 4 }; + BloomFilter filter = new BloomFilter(m, n, nTweak); + filter.Add(elements); + filter.Check(elements).Should().BeTrue(); + byte[] anotherElements = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + filter.Check(anotherElements).Should().BeFalse(); + } + + [TestMethod] + public void TestBloomFIlterConstructorGetKMTweak() + { + int m = -7, n = 10; + uint nTweak = 123456; + Action action = () => new BloomFilter(m, n, nTweak); + action.ShouldThrow(); + + m = 7; + n = -10; + action = () => new BloomFilter(m, n, nTweak); + action.ShouldThrow(); + + n = 10; + BloomFilter filter = new BloomFilter(m, n, nTweak); + filter.M.Should().Be(m); + filter.K.Should().Be(n); + filter.Tweak.Should().Be(nTweak); + + byte[] shorterElements = { 0, 1, 2, 3, 4 }; + filter = new BloomFilter(m, n, nTweak, shorterElements); + filter.M.Should().Be(m); + filter.K.Should().Be(n); + filter.Tweak.Should().Be(nTweak); + + byte[] longerElements = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + filter = new BloomFilter(m, n, nTweak, longerElements); + filter.M.Should().Be(m); + filter.K.Should().Be(n); + filter.Tweak.Should().Be(nTweak); + } + + [TestMethod] + public void TestGetBits() + { + int m = 7, n = 10; + uint nTweak = 123456; + byte[] elements = { 0, 1, 2, 3, 4 }; + BloomFilter filter = new BloomFilter(m, n, nTweak); + byte[] result = new byte[m]; + filter.GetBits(result); + foreach (byte value in result) + value.Should().Be(0); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/UT_Crypto.cs b/neo.UnitTests/Cryptography/UT_Crypto.cs new file mode 100644 index 0000000000..ec0d95add6 --- /dev/null +++ b/neo.UnitTests/Cryptography/UT_Crypto.cs @@ -0,0 +1,64 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.Wallets; +using System; +using System.Linq; +using System.Security.Cryptography; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_Crypto + { + private KeyPair key = null; + + public static KeyPair generateKey(int privateKeyLength) + { + byte[] privateKey = new byte[privateKeyLength]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + return new KeyPair(privateKey); + } + + public static KeyPair generateCertainKey(int privateKeyLength) + { + byte[] privateKey = new byte[privateKeyLength]; + for (int i = 0; i < privateKeyLength; i++) + { + privateKey[i] = (byte)((byte)i % byte.MaxValue); + } + return new KeyPair(privateKey); + } + + [TestInitialize] + public void TestSetup() + { + key = generateKey(32); + } + + [TestMethod] + public void TestVerifySignature() + { + byte[] message = System.Text.Encoding.Default.GetBytes("HelloWorld"); + byte[] signature = Crypto.Default.Sign(message, key.PrivateKey, key.PublicKey.EncodePoint(false).Skip(1).ToArray()); + Crypto.Default.VerifySignature(message, signature, key.PublicKey.EncodePoint(false)).Should().BeTrue(); + Crypto.Default.VerifySignature(message, signature, key.PublicKey.EncodePoint(false).Skip(1).ToArray()).Should().BeTrue(); + Crypto.Default.VerifySignature(message, signature, key.PublicKey.EncodePoint(false).Skip(1).ToArray()).Should().BeTrue(); + + byte[] wrongKey = new byte[33]; + wrongKey[0] = 0x02; + Crypto.Default.VerifySignature(message, signature, wrongKey).Should().BeFalse(); + + wrongKey[0] = 0x03; + for (int i = 1; i < 33; i++) wrongKey[i] = byte.MaxValue; + Crypto.Default.VerifySignature(message, signature, wrongKey).Should().BeFalse(); + + wrongKey = new byte[36]; + Action action = () => Crypto.Default.VerifySignature(message, signature, wrongKey).Should().BeFalse(); + action.ShouldThrow(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs new file mode 100644 index 0000000000..af909e3d71 --- /dev/null +++ b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -0,0 +1,225 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.Network.P2P.Payloads; +using System; +using System.Security; +using System.Text; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_Cryptography_Helper + { + [TestMethod] + public void TestAES256Encrypt() + { + byte[] block = Encoding.ASCII.GetBytes("00000000000000000000000000000000"); + byte[] key = Encoding.ASCII.GetBytes("1234567812345678"); + byte[] result = block.AES256Encrypt(key); + string encryptString = result.ToHexString(); + encryptString.Should().Be("f69e0923d8247eef417d6a78944a4b39f69e0923d8247eef417d6a78944a4b39"); + } + + [TestMethod] + public void TestAES256Decrypt() + { + byte[] block = new byte[32]; + byte[] key = Encoding.ASCII.GetBytes("1234567812345678"); + string decryptString = "f69e0923d8247eef417d6a78944a4b39f69e0923d8247eef417d6a78944a4b399ae8fd02b340288a0e7bbff0f0ba54d6"; + for (int i = 0; i < 32; i++) + block[i] = Convert.ToByte(decryptString.Substring(i * 2, 2), 16); + string str = System.Text.Encoding.Default.GetString(block.AES256Decrypt(key)); + str.Should().Be("00000000000000000000000000000000"); + } + + [TestMethod] + public void TestAesEncrypt() + { + byte[] data = Encoding.ASCII.GetBytes("00000000000000000000000000000000"); + byte[] key = Encoding.ASCII.GetBytes("12345678123456781234567812345678"); + byte[] iv = Encoding.ASCII.GetBytes("1234567812345678"); + byte[] result = data.AesEncrypt(key, iv); + + string encryptString = result.ToHexString(); + encryptString.Should().Be("07c748cf7d326782f82e60ebe60e2fac289e84e9ce91c1bc41565d14ecb53640"); + + byte[] nullData = null; + Action action = () => nullData.AesEncrypt(key, iv); + action.ShouldThrow(); + + byte[] nullKey = null; + action = () => data.AesEncrypt(nullKey, iv); + action.ShouldThrow(); + + byte[] nullIv = null; + action = () => data.AesEncrypt(key, nullIv); + action.ShouldThrow(); + + byte[] wrongData = Encoding.ASCII.GetBytes("000000000000000000000000000000001"); ; + action = () => wrongData.AesEncrypt(key, iv); + action.ShouldThrow(); + + byte[] wrongKey = Encoding.ASCII.GetBytes("123456781234567812345678123456780"); ; + action = () => data.AesEncrypt(wrongKey, iv); + action.ShouldThrow(); + + byte[] wrongIv = Encoding.ASCII.GetBytes("12345678123456780"); ; + action = () => data.AesEncrypt(key, wrongIv); + action.ShouldThrow(); + } + + [TestMethod] + public void TestAesDecrypt() + { + byte[] data = new byte[32]; + byte[] key = Encoding.ASCII.GetBytes("12345678123456781234567812345678"); + byte[] iv = Encoding.ASCII.GetBytes("1234567812345678"); + string decryptString = "07c748cf7d326782f82e60ebe60e2fac289e84e9ce91c1bc41565d14ecb5364073f28c9aa7bd6b069e44d8a97beb2b58"; + for (int i = 0; i < 32; i++) + data[i] = Convert.ToByte(decryptString.Substring(i * 2, 2), 16); + string str = System.Text.Encoding.Default.GetString(data.AesDecrypt(key, iv)); + str.Should().Be("00000000000000000000000000000000"); + + byte[] nullData = null; + Action action = () => nullData.AesDecrypt(key, iv); + action.ShouldThrow(); + + byte[] nullKey = null; + action = () => data.AesDecrypt(nullKey, iv); + action.ShouldThrow(); + + byte[] nullIv = null; + action = () => data.AesDecrypt(key, nullIv); + action.ShouldThrow(); + + byte[] wrongData = Encoding.ASCII.GetBytes("00000000000000001"); ; + action = () => wrongData.AesDecrypt(key, iv); + action.ShouldThrow(); + + byte[] wrongKey = Encoding.ASCII.GetBytes("123456781234567812345678123456780"); ; + action = () => data.AesDecrypt(wrongKey, iv); + action.ShouldThrow(); + + byte[] wrongIv = Encoding.ASCII.GetBytes("12345678123456780"); ; + action = () => data.AesDecrypt(key, wrongIv); + action.ShouldThrow(); + } + + [TestMethod] + public void TestBase58CheckDecode() + { + string input = "3vQB7B6MrGQZaxCuFg4oh"; + byte[] result = input.Base58CheckDecode(); + byte[] helloWorld = { 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 }; + result.Should().Equal(helloWorld); + + input = "3v"; + Action action = () => input.Base58CheckDecode(); + action.ShouldThrow(); + + input = "3vQB7B6MrGQZaxCuFg4og"; + action = () => input.Base58CheckDecode(); + action.ShouldThrow(); + } + + [TestMethod] + public void TestSha256() + { + byte[] value = Encoding.ASCII.GetBytes("hello world"); + byte[] result = value.Sha256(0, value.Length); + string resultStr = result.ToHexString(); + resultStr.Should().Be("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"); + } + + [TestMethod] + public void TestTest() + { + int m = 7, n = 10; + uint nTweak = 123456; + BloomFilter filter = new BloomFilter(m, n, nTweak); + + Transaction tx = new Transaction + { + Script = TestUtils.GetByteArray(32, 0x42), + Sender = UInt160.Zero, + SystemFee = 4200000000, + Attributes = new TransactionAttribute[0], + Witnesses = new[] + { + new Witness + { + InvocationScript = new byte[0], + VerificationScript = new byte[0] + } + } + }; + filter.Test(tx).Should().BeFalse(); + + filter.Add(tx.Witnesses[0].ScriptHash.ToArray()); + filter.Test(tx).Should().BeTrue(); + + filter.Add(tx.Hash.ToArray()); + filter.Test(tx).Should().BeTrue(); + } + + [TestMethod] + public void TestStringToAesKey() + { + string password = "hello world"; + string string1 = "bc62d4b80d9e36da29c16c5d4d9f11731f36052c72401a76c23c0fb5a9b74423"; + byte[] byteArray = new byte[string1.Length / 2]; + byteArray = string1.HexToBytes(); + password.ToAesKey().Should().Equal(byteArray); + } + + [TestMethod] + public void TestSecureStringToAesKey() + { + var password = new SecureString(); + password.AppendChar('h'); + password.AppendChar('e'); + password.AppendChar('l'); + password.AppendChar('l'); + password.AppendChar('o'); + password.AppendChar(' '); + password.AppendChar('w'); + password.AppendChar('o'); + password.AppendChar('r'); + password.AppendChar('l'); + password.AppendChar('d'); + string string1 = "bc62d4b80d9e36da29c16c5d4d9f11731f36052c72401a76c23c0fb5a9b74423"; + byte[] byteArray = new byte[string1.Length / 2]; + byteArray = string1.HexToBytes(); + password.ToAesKey().Should().Equal(byteArray); + } + + [TestMethod] + public void TestToArray() + { + var password = new SecureString(); + password.AppendChar('h'); + password.AppendChar('e'); + password.AppendChar('l'); + password.AppendChar('l'); + password.AppendChar('o'); + password.AppendChar(' '); + password.AppendChar('w'); + password.AppendChar('o'); + password.AppendChar('r'); + password.AppendChar('l'); + password.AppendChar('d'); + byte[] byteArray = { 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64 }; + password.ToArray().Should().Equal(byteArray); + + SecureString nullString = null; + Action action = () => nullString.ToArray(); + action.ShouldThrow(); + + var zeroString = new SecureString(); + var result = zeroString.ToArray(); + byteArray = new byte[0]; + result.Should().Equal(byteArray); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/UT_Scrypt.cs b/neo.UnitTests/Cryptography/UT_Scrypt.cs similarity index 93% rename from neo.UnitTests/UT_Scrypt.cs rename to neo.UnitTests/Cryptography/UT_Scrypt.cs index 8e2bf1e30a..8ec603da48 100644 --- a/neo.UnitTests/UT_Scrypt.cs +++ b/neo.UnitTests/Cryptography/UT_Scrypt.cs @@ -2,7 +2,7 @@ using Neo.Cryptography; using System; -namespace Neo.UnitTests +namespace Neo.UnitTests.Cryptography { [TestClass] public class UT_Scrypt @@ -16,4 +16,4 @@ public void DeriveKeyTest() Assert.AreEqual("b6274d3a81892c24335ab46a08ec16d040ac00c5943b212099a44b76a9b8102631ab988fa07fb35357cee7b0e3910098c0774c0e97399997676d890b2bf2bb25", derivedkey); } } -} +} \ No newline at end of file diff --git a/neo.UnitTests/Extensions/NativeContractExtensions.cs b/neo.UnitTests/Extensions/NativeContractExtensions.cs index 7d33841ef8..6a641c2387 100644 --- a/neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -8,12 +8,12 @@ namespace Neo.UnitTests.Extensions { public static class NativeContractExtensions { - public static StackItem Call(this NativeContract contract, Persistence.Snapshot snapshot, string method, params ContractParameter[] args) + public static StackItem Call(this NativeContract contract, Neo.Persistence.Snapshot snapshot, string method, params ContractParameter[] args) { return Call(contract, snapshot, null, method, args); } - public static StackItem Call(this NativeContract contract, Persistence.Snapshot snapshot, IVerifiable container, string method, params ContractParameter[] args) + public static StackItem Call(this NativeContract contract, Neo.Persistence.Snapshot snapshot, IVerifiable container, string method, params ContractParameter[] args) { var engine = new ApplicationEngine(TriggerType.Application, container, snapshot, 0, true); diff --git a/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs b/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs index a87fd7c3e1..42c5c87543 100644 --- a/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs +++ b/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs @@ -34,14 +34,14 @@ public ManualWitness(params UInt160[] hashForVerify) public void DeserializeUnsigned(BinaryReader reader) { } - public UInt160[] GetScriptHashesForVerifying(Persistence.Snapshot snapshot) => _hashForVerify; + public UInt160[] GetScriptHashesForVerifying(Neo.Persistence.Snapshot snapshot) => _hashForVerify; public void Serialize(BinaryWriter writer) { } public void SerializeUnsigned(BinaryWriter writer) { } } - public static bool Transfer(this NativeContract contract, Persistence.Snapshot snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom) + public static bool Transfer(this NativeContract contract, Neo.Persistence.Snapshot snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom) { var engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(signFrom ? new UInt160(from) : null), snapshot, 0, true); @@ -90,7 +90,7 @@ public static string[] SupportedStandards(this NativeContract contract) .ToArray(); } - public static BigInteger TotalSupply(this NativeContract contract, Persistence.Snapshot snapshot) + public static BigInteger TotalSupply(this NativeContract contract, Neo.Persistence.Snapshot snapshot) { var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); @@ -110,7 +110,7 @@ public static BigInteger TotalSupply(this NativeContract contract, Persistence.S return (result as VM.Types.Integer).GetBigInteger(); } - public static BigInteger BalanceOf(this NativeContract contract, Persistence.Snapshot snapshot, byte[] account) + public static BigInteger BalanceOf(this NativeContract contract, Neo.Persistence.Snapshot snapshot, byte[] account) { var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); diff --git a/neo.UnitTests/IO/Caching/UT_Cache.cs b/neo.UnitTests/IO/Caching/UT_Cache.cs new file mode 100644 index 0000000000..01484ae65e --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_Cache.cs @@ -0,0 +1,214 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Caching; +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Neo.UnitTests.IO.Caching +{ + class MyCache : Cache + { + public MyCache(int max_capacity) : base(max_capacity) { } + + protected override int GetKeyForItem(string item) + { + return item.GetHashCode(); + } + + protected override void OnAccess(CacheItem item) { } + + public IEnumerator MyGetEnumerator() + { + IEnumerable enumerable = this; + return enumerable.GetEnumerator(); + } + } + + [TestClass] + public class UT_Cache + { + MyCache cache; + readonly int max_capacity = 4; + + [TestInitialize] + public void init() + { + cache = new MyCache(max_capacity); + } + + [TestMethod] + public void TestCount() + { + cache.Count.Should().Be(0); + + cache.Add("hello"); + cache.Add("world"); + cache.Count.Should().Be(2); + + cache.Remove("hello"); + cache.Count.Should().Be(1); + } + + [TestMethod] + public void TestIsReadOnly() + { + cache.IsReadOnly.Should().BeFalse(); + } + + [TestMethod] + public void TestAddAndAddInternal() + { + cache.Add("hello"); + cache.Contains("hello").Should().BeTrue(); + cache.Contains("world").Should().BeFalse(); + cache.Add("hello"); + cache.Count.Should().Be(1); + } + + [TestMethod] + public void TestAddRange() + { + string[] range = { "hello", "world" }; + cache.AddRange(range); + cache.Count.Should().Be(2); + cache.Contains("hello").Should().BeTrue(); + cache.Contains("world").Should().BeTrue(); + cache.Contains("non exist string").Should().BeFalse(); + } + + [TestMethod] + public void TestClear() + { + cache.Add("hello"); + cache.Add("world"); + cache.Count.Should().Be(2); + cache.Clear(); + cache.Count.Should().Be(0); + } + + [TestMethod] + public void TestContainsKey() + { + cache.Add("hello"); + cache.Contains("hello").Should().BeTrue(); + cache.Contains("world").Should().BeFalse(); + } + + [TestMethod] + public void TestContainsValue() + { + cache.Add("hello"); + cache.Contains("hello".GetHashCode()).Should().BeTrue(); + cache.Contains("world".GetHashCode()).Should().BeFalse(); + } + + [TestMethod] + public void TestCopyTo() + { + cache.Add("hello"); + cache.Add("world"); + string[] temp = new string[2]; + + Action action = () => cache.CopyTo(null, 1); + action.ShouldThrow(); + + action = () => cache.CopyTo(temp, -1); + action.ShouldThrow(); + + action = () => cache.CopyTo(temp, 1); + action.ShouldThrow(); + + cache.CopyTo(temp, 0); + temp[0].Should().Be("hello"); + temp[1].Should().Be("world"); + } + + [TestMethod] + public void TestRemoveKey() + { + cache.Add("hello"); + cache.Remove("hello".GetHashCode()).Should().BeTrue(); + cache.Remove("world".GetHashCode()).Should().BeFalse(); + cache.Contains("hello").Should().BeFalse(); + } + + [TestMethod] + public void TestRemoveValue() + { + cache.Add("hello"); + cache.Remove("hello").Should().BeTrue(); + cache.Remove("world").Should().BeFalse(); + cache.Contains("hello").Should().BeFalse(); + } + + [TestMethod] + public void TestTryGet() + { + cache.Add("hello"); + cache.TryGet("hello".GetHashCode(), out string output).Should().BeTrue(); + output.Should().Be("hello"); + cache.TryGet("world".GetHashCode(), out string output2).Should().BeFalse(); + output2.Should().NotBe("world"); + output2.Should().BeNull(); + } + + [TestMethod] + public void TestArrayIndexAccess() + { + cache.Add("hello"); + cache.Add("world"); + cache["hello".GetHashCode()].Should().Be("hello"); + cache["world".GetHashCode()].Should().Be("world"); + + Action action = () => + { + string temp = cache["non exist string".GetHashCode()]; + }; + action.ShouldThrow(); + } + + [TestMethod] + public void TestGetEnumerator() + { + cache.Add("hello"); + cache.Add("world"); + int i = 0; + foreach (string item in cache) + { + if (i == 0) item.Should().Be("hello"); + if (i == 1) item.Should().Be("world"); + i++; + } + i.Should().Be(2); + cache.MyGetEnumerator().Should().NotBeNull(); + } + + [TestMethod] + public void TestOverMaxCapacity() + { + int i = 1; + for (; i <= max_capacity; i++) + { + cache.Add(i.ToString()); + } + cache.Add(i.ToString()); // The first one will be deleted + cache.Count.Should().Be(max_capacity); + cache.Contains((max_capacity + 1).ToString()).Should().BeTrue(); + } + + [TestMethod] + public void TestDispose() + { + cache.Add("hello"); + cache.Add("world"); + cache.Dispose(); + + Action action = () => + { + int count = cache.Count; + }; + action.ShouldThrow(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Caching/UT_CloneCache.cs b/neo.UnitTests/IO/Caching/UT_CloneCache.cs new file mode 100644 index 0000000000..1c9c2db74d --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_CloneCache.cs @@ -0,0 +1,126 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO; +using Neo.IO.Caching; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Neo.UnitTests.IO.Caching +{ + [TestClass] + public class UT_CloneCache + { + CloneCache cloneCache; + MyDataCache myDataCache; + + [TestInitialize] + public void Init() + { + myDataCache = new MyDataCache(); + cloneCache = new CloneCache(myDataCache); + } + + [TestMethod] + public void TestCloneCache() + { + cloneCache.Should().NotBeNull(); + } + + [TestMethod] + public void TestAddInternal() + { + cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + cloneCache[new MyKey("key1")].Should().Be(new MyValue("value1")); + + cloneCache.Commit(); + myDataCache[new MyKey("key1")].Should().Be(new MyValue("value1")); + } + + [TestMethod] + public void TestDeleteInternal() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); + cloneCache.Delete(new MyKey("key1")); // trackable.State = TrackState.Deleted + cloneCache.Commit(); + + cloneCache.TryGet(new MyKey("key1")).Should().BeNull(); + myDataCache.TryGet(new MyKey("key1")).Should().BeNull(); + } + + [TestMethod] + public void TestFindInternal() + { + cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + + var items = cloneCache.Find(new MyKey("key1").ToArray()); + items.ElementAt(0).Key.Should().Be(new MyKey("key1")); + items.ElementAt(0).Value.Should().Be(new MyValue("value1")); + items.Count().Should().Be(1); + + items = cloneCache.Find(new MyKey("key2").ToArray()); + items.ElementAt(0).Key.Should().Be(new MyKey("key2")); + items.ElementAt(0).Value.Should().Be(new MyValue("value2")); + items.Count().Should().Be(1); + + items = cloneCache.Find(new MyKey("key3").ToArray()); + items.ElementAt(0).Key.Should().Be(new MyKey("key3")); + items.ElementAt(0).Value.Should().Be(new MyValue("value3")); + items.Count().Should().Be(1); + + items = cloneCache.Find(new MyKey("key4").ToArray()); + items.Count().Should().Be(0); + } + + [TestMethod] + public void TestGetInternal() + { + cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + + cloneCache[new MyKey("key1")].Should().Be(new MyValue("value1")); + cloneCache[new MyKey("key2")].Should().Be(new MyValue("value2")); + cloneCache[new MyKey("key3")].Should().Be(new MyValue("value3")); + + Action action = () => { + var item = cloneCache[new MyKey("key4")]; + }; + action.ShouldThrow(); + } + + [TestMethod] + public void TestTryGetInternal() + { + cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + + cloneCache.TryGet(new MyKey("key1")).Should().Be(new MyValue("value1")); + cloneCache.TryGet(new MyKey("key2")).Should().Be(new MyValue("value2")); + cloneCache.TryGet(new MyKey("key3")).Should().Be(new MyValue("value3")); + cloneCache.TryGet(new MyKey("key4")).Should().BeNull(); + } + + [TestMethod] + public void TestUpdateInternal() + { + cloneCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + + cloneCache.GetAndChange(new MyKey("key1")).Value = "value_new_1"; + cloneCache.GetAndChange(new MyKey("key2")).Value = "value_new_2"; + cloneCache.GetAndChange(new MyKey("key3")).Value = "value_new_3"; + + cloneCache.Commit(); + + cloneCache[new MyKey("key1")].Should().Be(new MyValue("value_new_1")); + cloneCache[new MyKey("key2")].Should().Be(new MyValue("value_new_2")); + cloneCache[new MyKey("key3")].Should().Be(new MyValue("value_new_3")); + myDataCache[new MyKey("key2")].Should().Be(new MyValue("value_new_2")); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs b/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs new file mode 100644 index 0000000000..812cbc26ba --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs @@ -0,0 +1,48 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Caching; + +namespace Neo.UnitTests.IO.Caching +{ + [TestClass] + public class UT_CloneMetaCache + { + MyMetaCache myMetaCache; + CloneMetaCache cloneMetaCache; + + [TestInitialize] + public void Init() + { + myMetaCache = new MyMetaCache(() => new MyValue()); + cloneMetaCache = new CloneMetaCache(myMetaCache); + } + + [TestMethod] + public void TestConstructor() + { + cloneMetaCache.Should().NotBeNull(); + } + + [TestMethod] + public void TestTryGetInternal() + { + MyValue value = myMetaCache.GetAndChange(); + value.Value = "value1"; + + cloneMetaCache.Get().Should().Be(value); + } + + [TestMethod] + public void TestUpdateInternal() + { + MyValue value = myMetaCache.GetAndChange(); + value.Value = "value1"; + + MyValue value2 = cloneMetaCache.GetAndChange(); + value2.Value = "value2"; + + cloneMetaCache.Commit(); + value.Value.Should().Be("value2"); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Caching/UT_DataCache.cs b/neo.UnitTests/IO/Caching/UT_DataCache.cs new file mode 100644 index 0000000000..d93316022d --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_DataCache.cs @@ -0,0 +1,347 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO; +using Neo.IO.Caching; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Neo.UnitTests.IO.Caching +{ + class MyKey : ISerializable, IEquatable + { + public string Key; + + public int Size => Key.Length; + + public MyKey() { } + + public MyKey(string val) + { + Key = val; + } + + public void Deserialize(BinaryReader reader) + { + Key = reader.ReadString(); + } + + public void Serialize(BinaryWriter writer) + { + writer.Write(Key); + } + + public bool Equals(MyKey other) + { + return Key.Equals(other.Key); + } + + public override bool Equals(object obj) + { + if (!(obj is MyKey key)) return false; + return Equals(key); + } + + public override int GetHashCode() + { + return Key.GetHashCode(); + } + } + + public class MyValue : ISerializable, ICloneable + { + public string Value; + + public int Size => Value.Length; + + public MyValue() { } + + public MyValue(string val) + { + Value = val; + } + + public void Deserialize(BinaryReader reader) + { + Value = reader.ReadString(); + } + + public void Serialize(BinaryWriter writer) + { + writer.Write(Value); + } + + MyValue ICloneable.Clone() + { + return new MyValue(Value); + } + + void ICloneable.FromReplica(MyValue replica) + { + Value = replica.Value; + } + + public bool Equals(MyValue other) + { + return (Value == null && other.Value == null) || Value.Equals(other.Value); + } + + public override bool Equals(object obj) + { + if (!(obj is MyValue key)) return false; + return Equals(key); + } + + public override int GetHashCode() + { + return Value.GetHashCode(); + } + } + + class MyDataCache : DataCache + where TKey : IEquatable, ISerializable, new() + where TValue : class, ICloneable, ISerializable, new() + { + public Dictionary InnerDict = new Dictionary(); + + public override void DeleteInternal(TKey key) + { + InnerDict.Remove(key); + } + + protected override void AddInternal(TKey key, TValue value) + { + InnerDict.Add(key, value); + } + + protected override IEnumerable> FindInternal(byte[] key_prefix) + { + return InnerDict.Where(kvp => kvp.Key.ToArray().Take(key_prefix.Length).SequenceEqual(key_prefix)); + } + + protected override TValue GetInternal(TKey key) + { + if (InnerDict.TryGetValue(key, out TValue value)) + { + return value.Clone(); + } + throw new KeyNotFoundException(); + } + + protected override TValue TryGetInternal(TKey key) + { + if (InnerDict.TryGetValue(key, out TValue value)) + { + return value.Clone(); + } + return null; + } + + protected override void UpdateInternal(TKey key, TValue value) + { + InnerDict[key] = value; + } + } + + [TestClass] + public class UT_DataCache + { + MyDataCache myDataCache; + + [TestInitialize] + public void Initialize() + { + myDataCache = new MyDataCache(); + } + + [TestMethod] + public void TestAccessByKey() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); + + myDataCache[new MyKey("key1")].Should().Be(new MyValue("value1")); + + // case 2 read from inner + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + myDataCache[new MyKey("key3")].Should().Be(new MyValue("value3")); + } + + [TestMethod] + public void TestAccessByNotFoundKey() + { + Action action = () => + { + var item = myDataCache[new MyKey("key1")]; + }; + action.ShouldThrow(); + } + + [TestMethod] + public void TestAccessByDeletedKey() + { + myDataCache.InnerDict.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Delete(new MyKey("key1")); + + Action action = () => + { + var item = myDataCache[new MyKey("key1")]; + }; + action.ShouldThrow(); + } + + [TestMethod] + public void TestAdd() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache[new MyKey("key1")].Should().Be(new MyValue("value1")); + + Action action = () => myDataCache.Add(new MyKey("key1"), new MyValue("value1")); + action.ShouldThrow(); + + myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.Delete(new MyKey("key2")); // trackable.State = TrackState.Deleted + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); // trackable.State = TrackState.Changed + + action = () => myDataCache.Add(new MyKey("key2"), new MyValue("value2")); + action.ShouldThrow(); + } + + [TestMethod] + public void TestCommit() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added + + myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.Delete(new MyKey("key2")); // trackable.State = TrackState.Deleted + + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted + myDataCache.Add(new MyKey("key3"), new MyValue("value4")); // trackable.State = TrackState.Changed + + myDataCache.Commit(); + + myDataCache.InnerDict[new MyKey("key1")].Should().Be(new MyValue("value1")); + myDataCache.InnerDict.ContainsKey(new MyKey("key2")).Should().BeFalse(); + myDataCache.InnerDict[new MyKey("key3")].Should().Be(new MyValue("value4")); + } + + [TestMethod] + public void TestCreateSnapshot() + { + myDataCache.CreateSnapshot().Should().NotBeNull(); + } + + [TestMethod] + public void TestDelete() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Delete(new MyKey("key1")); + myDataCache.InnerDict.ContainsKey(new MyKey("key1")).Should().BeFalse(); + + myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.Delete(new MyKey("key2")); + myDataCache.Commit(); + myDataCache.InnerDict.ContainsKey(new MyKey("key2")).Should().BeFalse(); + } + + [TestMethod] + public void TestDeleteWhere() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); + + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4")); + + myDataCache.DeleteWhere((k, v) => k.Key.StartsWith("key")); + myDataCache.Commit(); + myDataCache.TryGet(new MyKey("key1")).Should().BeNull(); + myDataCache.TryGet(new MyKey("key2")).Should().BeNull(); + myDataCache.InnerDict.ContainsKey(new MyKey("key1")).Should().BeFalse(); + myDataCache.InnerDict.ContainsKey(new MyKey("key2")).Should().BeFalse(); + } + + [TestMethod] + public void TestFind() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); + + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4")); + + var items = myDataCache.Find(new MyKey("key1").ToArray()); + items.ElementAt(0).Key.Should().Be(new MyKey("key1")); + items.ElementAt(0).Value.Should().Be(new MyValue("value1")); + items.Count().Should().Be(1); + + items = myDataCache.Find(new MyKey("key5").ToArray()); + items.Count().Should().Be(0); + } + + [TestMethod] + public void TestGetChangeSet() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added + myDataCache.Add(new MyKey("key2"), new MyValue("value2")); // trackable.State = TrackState.Added + + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4")); + myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted + myDataCache.Delete(new MyKey("key4")); // trackable.State = TrackState.Deleted + + var items = myDataCache.GetChangeSet(); + int i = 0; + foreach (var item in items) + { + i++; + item.Key.Should().Be(new MyKey("key" + i)); + item.Item.Should().Be(new MyValue("value" + i)); + } + i.Should().Be(4); + } + + [TestMethod] + public void TestGetAndChange() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added + myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted + + myDataCache.GetAndChange(new MyKey("key1"), () => new MyValue("value_bk_1")).Should().Be(new MyValue("value1")); + myDataCache.GetAndChange(new MyKey("key2"), () => new MyValue("value_bk_2")).Should().Be(new MyValue("value2")); + myDataCache.GetAndChange(new MyKey("key3"), () => new MyValue("value_bk_3")).Should().Be(new MyValue("value_bk_3")); + myDataCache.GetAndChange(new MyKey("key4"), () => new MyValue("value_bk_4")).Should().Be(new MyValue("value_bk_4")); + } + + [TestMethod] + public void TestGetOrAdd() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added + myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted + + myDataCache.GetOrAdd(new MyKey("key1"), () => new MyValue("value_bk_1")).Should().Be(new MyValue("value1")); + myDataCache.GetOrAdd(new MyKey("key2"), () => new MyValue("value_bk_2")).Should().Be(new MyValue("value2")); + myDataCache.GetOrAdd(new MyKey("key3"), () => new MyValue("value_bk_3")).Should().Be(new MyValue("value_bk_3")); + myDataCache.GetOrAdd(new MyKey("key4"), () => new MyValue("value_bk_4")).Should().Be(new MyValue("value_bk_4")); + } + + [TestMethod] + public void TestTryGet() + { + myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added + myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2")); + myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3")); + myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted + + myDataCache.TryGet(new MyKey("key1")).Should().Be(new MyValue("value1")); + myDataCache.TryGet(new MyKey("key2")).Should().Be(new MyValue("value2")); + myDataCache.TryGet(new MyKey("key3")).Should().BeNull(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Caching/UT_FifoSet.cs b/neo.UnitTests/IO/Caching/UT_FifoSet.cs new file mode 100644 index 0000000000..8242572e86 --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_FifoSet.cs @@ -0,0 +1,120 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Caching; +using System; +using System.Linq; + +namespace Neo.UnitTests.IO.Caching +{ + [TestClass] + public class UT_FIFOSet + { + [TestMethod] + public void FIFOSetTest() + { + var a = UInt256.Zero; + var b = new UInt256(); + var c = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01 + }); + + var set = new FIFOSet(3); + + Assert.IsTrue(set.Add(a)); + Assert.IsFalse(set.Add(a)); + Assert.IsFalse(set.Add(b)); + Assert.IsTrue(set.Add(c)); + + CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c }); + + var d = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02 + }); + + // Testing Fifo max size + Assert.IsTrue(set.Add(d)); + CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c, d }); + + var e = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x03 + }); + + Assert.IsTrue(set.Add(e)); + Assert.IsFalse(set.Add(e)); + CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { c, d, e }); + } + + [TestMethod] + public void TestConstructor() + { + Action action1 = () => new FIFOSet(-1); + action1.ShouldThrow(); + + Action action2 = () => new FIFOSet(1,-1); + action2.ShouldThrow(); + + Action action3 = () => new FIFOSet(1,2); + action3.ShouldThrow(); + } + + [TestMethod] + public void TestAdd() + { + var a = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01 + }); + var b = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02 + }); + var set = new FIFOSet(1, 1); + set.Add(a); + set.Add(b); + CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { b }); + } + + [TestMethod] + public void TestExceptWith() + { + var a = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01 + }); + var b = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02 + }); + var c = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x03 + }); + + var set = new FIFOSet(10); + set.Add(a); + set.Add(b); + set.Add(c); + set.ExceptWith(new UInt256[] { b, c }); + CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a }); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs b/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs new file mode 100644 index 0000000000..368e866f54 --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs @@ -0,0 +1,76 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO; +using Neo.IO.Caching; +using System; + +namespace Neo.UnitTests.IO.Caching +{ + public class MyMetaCache : MetaDataCache + where T : class, ICloneable, ISerializable, new() + { + public T Value; + + public MyMetaCache(Func factory) : base(factory) { } + + protected override void AddInternal(T item) + { + Value = item; + } + + protected override T TryGetInternal() + { + return Value; + } + + protected override void UpdateInternal(T item) + { + Value = item; + } + } + + [TestClass] + public class UT_MetaDataCache + { + MyMetaCache myMetaCache; + + [TestInitialize] + public void SetUp() + { + myMetaCache = new MyMetaCache(() => new MyValue()); + } + + [TestMethod] + public void TestContructor() + { + myMetaCache.Should().NotBeNull(); + } + + [TestMethod] + public void TestCommitAndAddInternal() + { + MyValue value = myMetaCache.Get(); + value.Should().NotBeNull(); + value.Value.Should().BeNull(); + + myMetaCache.Commit(); + myMetaCache.Value.Should().Be(value); + } + + public void TestCommitAndUpdateInternal() + { + MyValue value = myMetaCache.GetAndChange(); + value.Value = "value1"; + + myMetaCache.Commit(); + myMetaCache.Value.Should().Be(value); + myMetaCache.Value.Value.Should().Be("value1"); + } + + [TestMethod] + public void TestCreateSnapshot() + { + myMetaCache.CreateSnapshot().Should().NotBeNull(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs b/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs new file mode 100644 index 0000000000..94d7b70ce1 --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs @@ -0,0 +1,87 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Caching; + +namespace Neo.UnitTests.IO.Caching +{ + [TestClass] + public class UT_OrderedDictionary + { + private OrderedDictionary od; + + [TestInitialize] + public void SetUp() + { + od = new OrderedDictionary(); + od.Add("a", 1); + od.Add("b", 2); + od.Add("c", 3); + } + + [TestMethod] + public void TestClear() + { + od.Clear(); + od.Count.Should().Be(0); + od.TryGetValue("a", out uint i).Should().BeFalse(); + } + + [TestMethod] + public void TestCount() + { + od.Count.Should().Be(3); + od.Add("d", 4); + od.Count.Should().Be(4); + } + + [TestMethod] + public void TestIsReadOnly() + { + od.IsReadOnly.Should().BeFalse(); + } + + [TestMethod] + public void TestSetAndGetItem() + { + var val = od["a"]; + val.Should().Be(1); + od["d"] = 10; + od["d"].Should().Be(10); + od["d"] = 15; + od["d"].Should().Be(15); + } + + [TestMethod] + public void TestGetKeys() + { + var keys = od.Keys; + keys.Contains("a").Should().BeTrue(); + keys.Count.Should().Be(3); + } + + [TestMethod] + public void TestGetValues() + { + var values = od.Values; + values.Contains(1).Should().BeTrue(); + values.Count.Should().Be(3); + } + + [TestMethod] + public void TestRemove() + { + od.Remove("a"); + od.Count.Should().Be(2); + od.ContainsKey("a").Should().BeFalse(); + } + + [TestMethod] + public void TestTryGetValue() + { + od.TryGetValue("a", out uint i).Should().BeTrue(); + i.Should().Be(1); + od.TryGetValue("d", out uint j).Should().BeFalse(); + j.Should().Be(0); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Json/UT_JArray.cs b/neo.UnitTests/IO/Json/UT_JArray.cs new file mode 100644 index 0000000000..7e6e81c8d3 --- /dev/null +++ b/neo.UnitTests/IO/Json/UT_JArray.cs @@ -0,0 +1,249 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Json; +using FluentAssertions; +using System; +using System.Linq; +using System.Collections; + +namespace Neo.UnitTests.IO.Json +{ + enum Foo + { + male, + female + } + + [TestClass] + public class UT_JArray + { + private JObject alice; + private JObject bob; + + [TestInitialize] + public void SetUp() + { + alice = new JObject(); + alice["name"] = "alice"; + alice["age"] = 30; + alice["score"] = 100.001; + alice["gender"] = Foo.female; + alice["isMarried"] = true; + var pet1 = new JObject(); + pet1["name"] = "Tom"; + pet1["type"] = "cat"; + alice["pet"] = pet1; + + bob = new JObject(); + bob["name"] = "bob"; + bob["age"] = 100000; + bob["score"] = 0.001; + bob["gender"] = Foo.male; + bob["isMarried"] = false; + var pet2 = new JObject(); + pet2["name"] = "Paul"; + pet2["type"] = "dog"; + bob["pet"] = pet2; + } + + [TestMethod] + public void TestAdd() + { + var jArray = new JArray(); + jArray.Add(alice); + jArray.Add(bob); + var jAlice = jArray[0]; + var jBob = jArray[1]; + jAlice["name"].ToString().Should().Be(alice["name"].ToString()); + jAlice["age"].ToString().Should().Be(alice["age"].ToString()); + jAlice["score"].ToString().Should().Be(alice["score"].ToString()); + jAlice["gender"].ToString().Should().Be(alice["gender"].ToString()); + jAlice["isMarried"].ToString().Should().Be(alice["isMarried"].ToString()); + jAlice["pet"].ToString().Should().Be(alice["pet"].ToString()); + jBob["name"].ToString().Should().Be(bob["name"].ToString()); + jBob["age"].ToString().Should().Be(bob["age"].ToString()); + jBob["score"].ToString().Should().Be(bob["score"].ToString()); + jBob["gender"].ToString().Should().Be(bob["gender"].ToString()); + jBob["isMarried"].ToString().Should().Be(bob["isMarried"].ToString()); + jBob["pet"].ToString().Should().Be(bob["pet"].ToString()); + } + + [TestMethod] + public void TestSetItem() + { + var jArray = new JArray + { + alice + }; + jArray[0] = bob; + Assert.AreEqual(jArray[0], bob); + + Action action = () => jArray[1] = alice; + action.ShouldThrow(); + } + + [TestMethod] + public void TestClear() + { + var jArray = new JArray + { + alice + }; + var jAlice = jArray[0]; + jAlice["name"].ToString().Should().Be(alice["name"].ToString()); + jAlice["age"].ToString().Should().Be(alice["age"].ToString()); + jAlice["score"].ToString().Should().Be(alice["score"].ToString()); + jAlice["gender"].ToString().Should().Be(alice["gender"].ToString()); + jAlice["isMarried"].ToString().Should().Be(alice["isMarried"].ToString()); + jAlice["pet"].ToString().Should().Be(alice["pet"].ToString()); + + jArray.Clear(); + Action action = () => jArray[0].ToString(); + action.ShouldThrow(); + } + + [TestMethod] + public void TestContains() + { + var jArray = new JArray(); + jArray.Add(alice); + + jArray.Contains(alice).Should().BeTrue(); + jArray.Contains(bob).Should().BeFalse(); + } + + [TestMethod] + public void TestCopyTo() + { + var jArray = new JArray + { + alice, + bob + }; + + JObject[] jObjects1 = new JObject[2]; + jArray.CopyTo(jObjects1, 0); + var jAlice1 = jObjects1[0]; + var jBob1 = jObjects1[1]; + Assert.AreEqual(alice, jAlice1); + Assert.AreEqual(bob, jBob1); + + JObject[] jObjects2 = new JObject[4]; + jArray.CopyTo(jObjects2, 2); + var jAlice2 = jObjects2[2]; + var jBob2 = jObjects2[3]; + jObjects2[0].Should().BeNull(); + jObjects2[1].Should().BeNull(); + Assert.AreEqual(alice, jAlice2); + Assert.AreEqual(bob, jBob2); + } + + [TestMethod] + public void TestInsert() + { + var jArray = new JArray + { + alice, + alice, + alice, + alice + }; + + jArray.Insert(1, bob); + jArray.Count().Should().Be(5); + jArray[0].Should().Be(alice); + jArray[1].Should().Be(bob); + jArray[2].Should().Be(alice); + + jArray.Insert(5, bob); + jArray.Count().Should().Be(6); + jArray[5].Should().Be(bob); + } + + [TestMethod] + public void TestIndexOf() + { + var jArray = new JArray(); + jArray.IndexOf(alice).Should().Be(-1); + + jArray.Add(alice); + jArray.Add(alice); + jArray.Add(alice); + jArray.Add(alice); + jArray.IndexOf(alice).Should().Be(0); + + jArray.Insert(1, bob); + jArray.IndexOf(bob).Should().Be(1); + } + + [TestMethod] + public void TestIsReadOnly() + { + var jArray = new JArray(); + jArray.IsReadOnly.Should().BeFalse(); + } + + [TestMethod] + public void TestRemove() + { + var jArray = new JArray + { + alice + }; + jArray.Count().Should().Be(1); + jArray.Remove(alice); + jArray.Count().Should().Be(0); + + jArray.Add(alice); + jArray.Add(alice); + jArray.Count().Should().Be(2); + jArray.Remove(alice); + jArray.Count().Should().Be(1); + } + + [TestMethod] + public void TestRemoveAt() + { + var jArray = new JArray + { + alice, + bob, + alice + }; + jArray.RemoveAt(1); + jArray.Count().Should().Be(2); + jArray.Contains(bob).Should().BeFalse(); + } + + [TestMethod] + public void TestGetEnumerator() + { + var jArray = new JArray + { + alice, + bob, + alice, + bob + }; + int i = 0; + foreach (var item in jArray) + { + if (i % 2 == 0) item.Should().Be(alice); + if (i % 2 != 0) item.Should().Be(bob); + i++; + } + Assert.IsNotNull(((IEnumerable)jArray).GetEnumerator()); + } + + [TestMethod] + public void TestAsString() + { + var jArray = new JArray + { + alice, + bob, + }; + var s = jArray.AsString(); + Assert.AreEqual(s, "{\"name\":\"alice\",\"age\":30,\"score\":100.001,\"gender\":\"female\",\"isMarried\":true,\"pet\":{\"name\":\"Tom\",\"type\":\"cat\"}},{\"name\":\"bob\",\"age\":100000,\"score\":0.001,\"gender\":\"male\",\"isMarried\":false,\"pet\":{\"name\":\"Paul\",\"type\":\"dog\"}}"); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Json/UT_JBoolean.cs b/neo.UnitTests/IO/Json/UT_JBoolean.cs new file mode 100644 index 0000000000..cb44570e45 --- /dev/null +++ b/neo.UnitTests/IO/Json/UT_JBoolean.cs @@ -0,0 +1,77 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Json; +using System; +using System.IO; + +namespace Neo.UnitTests.IO.Json +{ + [TestClass] + public class UT_JBoolean + { + private JBoolean jFalse; + private JBoolean jTrue; + + [TestInitialize] + public void SetUp() + { + jFalse = new JBoolean(); + jTrue = new JBoolean(true); + } + + [TestMethod] + public void TestAsNumber() + { + jFalse.AsNumber().Should().Be(0); + jTrue.AsNumber().Should().Be(1); + } + + [TestMethod] + public void TestParse() + { + TextReader tr1 = new StringReader("true"); + JBoolean ret1 = JBoolean.Parse(tr1); + ret1.AsBoolean().Should().BeTrue(); + + TextReader tr2 = new StringReader("false"); + JBoolean ret2 = JBoolean.Parse(tr2); + ret2.AsBoolean().Should().BeFalse(); + + TextReader tr3 = new StringReader("aaa"); + Action action = () => JBoolean.Parse(tr3); + action.ShouldThrow(); + } + + [TestMethod] + public void TestParseFalse() + { + TextReader tr1 = new StringReader("false"); + JBoolean ret1 = JBoolean.ParseFalse(tr1); + ret1.AsBoolean().Should().BeFalse(); + + TextReader tr2 = new StringReader("aaa"); + Action action = () => JBoolean.ParseFalse(tr2); + action.ShouldThrow(); + + TextReader tr3 = new StringReader("\t\rfalse"); + JBoolean ret3 = JBoolean.ParseFalse(tr3); + ret3.AsBoolean().Should().BeFalse(); + } + + [TestMethod] + public void TestParseTrue() + { + TextReader tr1 = new StringReader("true"); + JBoolean ret1 = JBoolean.ParseTrue(tr1); + ret1.AsBoolean().Should().BeTrue(); + + TextReader tr2 = new StringReader("aaa"); + Action action = () => JBoolean.ParseTrue(tr2); + action.ShouldThrow(); + + TextReader tr3 = new StringReader(" true"); + JBoolean ret3 = JBoolean.ParseTrue(tr3); + ret3.AsBoolean().Should().BeTrue(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Json/UT_JNumber.cs b/neo.UnitTests/IO/Json/UT_JNumber.cs new file mode 100644 index 0000000000..7232e8b969 --- /dev/null +++ b/neo.UnitTests/IO/Json/UT_JNumber.cs @@ -0,0 +1,67 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Json; +using System; +using System.IO; + +namespace Neo.UnitTests.IO.Json +{ + enum Woo + { + Tom, + Jerry, + James + } + + [TestClass] + public class UT_JNumber + { + private JNumber maxInt; + private JNumber minInt; + private JNumber zero; + + [TestInitialize] + public void SetUp() + { + maxInt = new JNumber(JNumber.MAX_SAFE_INTEGER); + minInt = new JNumber(JNumber.MIN_SAFE_INTEGER); + zero = new JNumber(); + } + + [TestMethod] + public void TestAsBoolean() + { + maxInt.AsBoolean().Should().BeTrue(); + zero.AsBoolean().Should().BeFalse(); + } + + [TestMethod] + public void TestAsString() + { + Action action1 = () => new JNumber(double.PositiveInfinity).AsString(); + action1.ShouldThrow(); + + Action action2 = () => new JNumber(double.NegativeInfinity).AsString(); + action2.ShouldThrow(); + } + + [TestMethod] + public void TestTryGetEnum() + { + zero.TryGetEnum().Should().Be(Woo.Tom); + new JNumber(1).TryGetEnum().Should().Be(Woo.Jerry); + new JNumber(2).TryGetEnum().Should().Be(Woo.James); + new JNumber(3).TryGetEnum().Should().Be(Woo.Tom); + } + + [TestMethod] + public void TestParse() + { + Action action1 = () => JNumber.Parse(new StringReader("100.a")); + action1.ShouldThrow(); + + Action action2 = () => JNumber.Parse(new StringReader("100.+")); + action2.ShouldThrow(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Json/UT_JObject.cs b/neo.UnitTests/IO/Json/UT_JObject.cs new file mode 100644 index 0000000000..38781ed96a --- /dev/null +++ b/neo.UnitTests/IO/Json/UT_JObject.cs @@ -0,0 +1,119 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Json; +using System; +using System.IO; +using System.Reflection; + +namespace Neo.UnitTests.IO.Json +{ + [TestClass] + public class UT_JObject + { + private JObject alice; + private JObject bob; + + [TestInitialize] + public void SetUp() + { + alice = new JObject(); + alice["name"] = "alice"; + alice["age"] = 30; + alice["score"] = 100.001; + alice["gender"] = Foo.female; + alice["isMarried"] = true; + var pet1 = new JObject(); + pet1["name"] = "Tom"; + pet1["type"] = "cat"; + alice["pet"] = pet1; + + bob = new JObject(); + bob["name"] = "bob"; + bob["age"] = 100000; + bob["score"] = 0.001; + bob["gender"] = Foo.male; + bob["isMarried"] = false; + var pet2 = new JObject(); + pet2["name"] = "Paul"; + pet2["type"] = "dog"; + bob["pet"] = pet2; + } + + [TestMethod] + public void TestAsBoolean() + { + alice.AsBoolean().Should().BeTrue(); + } + + [TestMethod] + public void TestAsNumber() + { + alice.AsNumber().Should().Be(double.NaN); + } + + [TestMethod] + public void TestParse() + { + Action action = () => JObject.Parse(new StringReader(""), -1); + action.ShouldThrow(); + } + + [TestMethod] + public void TestParseNull() + { + Action action = () => JObject.Parse(new StringReader("naaa")); + action.ShouldThrow(); + + JObject.Parse(new StringReader("null")).Should().BeNull(); + } + + [TestMethod] + public void TestParseObject() + { + Action action1 = () => JObject.Parse(new StringReader("{\"k1\":\"v1\",\"k1\":\"v2\"}"), 100); + action1.ShouldThrow(); + + Action action2 = () => JObject.Parse(new StringReader("{\"k1\",\"k1\"}"), 100); + action2.ShouldThrow(); + + Action action3 = () => JObject.Parse(new StringReader("{\"k1\":\"v1\""), 100); + action3.ShouldThrow(); + + Action action4 = () => JObject.Parse(new StringReader("aaa"), 100); + action4.ShouldThrow(); + + JObject.Parse(new StringReader("{\"k1\":\"v1\"}"), 100).ToString().Should().Be("{\"k1\":\"v1\"}"); + } + + [TestMethod] + public void TestTryGetEnum() + { + alice.TryGetEnum().Should().Be(Woo.Tom); + } + + [TestMethod] + public void TestOpImplicitEnum() + { + var obj = new JObject(); + obj = Woo.Tom; + obj.AsString().Should().Be("Tom"); + } + + [TestMethod] + public void TestOpImplicitString() + { + var obj = new JObject(); + obj = null; + obj.Should().BeNull(); + + obj = "{\"aaa\":\"111\"}"; + obj.AsString().Should().Be("{\"aaa\":\"111\"}"); + } + + [TestMethod] + public void TestGetNull() + { + JObject.Null.Should().BeNull(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Json/UT_JString.cs b/neo.UnitTests/IO/Json/UT_JString.cs new file mode 100644 index 0000000000..07f231674f --- /dev/null +++ b/neo.UnitTests/IO/Json/UT_JString.cs @@ -0,0 +1,73 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Json; +using Neo.SmartContract; +using System; +using System.IO; + +namespace Neo.UnitTests.IO +{ + [TestClass] + public class UT_JString + { + [TestMethod] + public void TestConstructor() + { + String s = "hello world"; + JString jstring = new JString(s); + Assert.AreEqual(s, jstring.Value); + Assert.ThrowsException(() => new JString(null)); + } + + [TestMethod] + public void TestAsBoolean() + { + String s1 = "hello world"; + String s2 = ""; + JString jstring1 = new JString(s1); + JString jstring2 = new JString(s2); + Assert.AreEqual(true, jstring1.AsBoolean()); + Assert.AreEqual(false, jstring2.AsBoolean()); + } + + [TestMethod] + public void TestParse() + { + TextReader tr = new StringReader("\"hello world\""); + String s = JString.Parse(tr).Value; + Assert.AreEqual("hello world", s); + + tr = new StringReader("hello world"); + Assert.ThrowsException(() => JString.Parse(tr)); + + tr = new StringReader("\"\\s\""); + Assert.ThrowsException(() => JString.Parse(tr)); + + tr = new StringReader("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\""); + s = JString.Parse(tr).Value; + Assert.AreEqual("\"\\/\b\f\n\r\t", s); + + tr = new StringReader("\"\\u0030\""); + s = JString.Parse(tr).Value; + Assert.AreEqual("0", s); + + tr = new StringReader("\"a"); + Assert.ThrowsException(() => JString.Parse(tr)); + + byte[] byteArray = new byte[] { 0x22, 0x01, 0x22 }; + tr = new StringReader(System.Text.Encoding.ASCII.GetString(byteArray)); + Assert.ThrowsException(() => JString.Parse(tr)); + } + + [TestMethod] + public void TestTryGetEnum() + { + JString s = new JString("Signature"); + ContractParameterType cp = s.TryGetEnum(ContractParameterType.Void, false); + Assert.AreEqual(ContractParameterType.Signature, cp); + + s = new JString(""); + cp = s.TryGetEnum(ContractParameterType.Void, false); + Assert.AreEqual(ContractParameterType.Void, cp); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/UT_IOHelper.cs b/neo.UnitTests/IO/UT_IOHelper.cs new file mode 100644 index 0000000000..e113ce8cd4 --- /dev/null +++ b/neo.UnitTests/IO/UT_IOHelper.cs @@ -0,0 +1,549 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Neo.UnitTests.IO +{ + [TestClass] + public class UT_IOHelper + { + [TestMethod] + public void TestAsSerializableGeneric() + { + byte[] caseArray = new byte[] { 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00 }; + UInt160 result = Neo.IO.Helper.AsSerializable(caseArray); + Assert.AreEqual(UInt160.Zero, result); + } + + [TestMethod] + public void TestAsSerializable() + { + for (int i = 0; i < 2; i++) + { + if (i == 0) + { + byte[] caseArray = new byte[] { 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00 }; + ISerializable result = Neo.IO.Helper.AsSerializable(caseArray, typeof(UInt160)); + Assert.AreEqual(UInt160.Zero, result); + } + else + { + Action action = () => Neo.IO.Helper.AsSerializable(new byte[0], typeof(Double)); + action.ShouldThrow(); + } + } + } + + [TestMethod] + public void TestAsSerializableArray() + { + byte[] byteArray = Neo.IO.Helper.ToByteArray(new UInt160[] { UInt160.Zero }); + UInt160[] result = Neo.IO.Helper.AsSerializableArray(byteArray); + Assert.AreEqual(1, result.Length); + Assert.AreEqual(UInt160.Zero, result[0]); + } + + [TestMethod] + public void TestGetVarSizeInt() + { + for (int i = 0; i < 3; i++) + { + if (i == 0) + { + int result = Neo.IO.Helper.GetVarSize(1); + Assert.AreEqual(1, result); + } + else if (i == 1) + { + int result = Neo.IO.Helper.GetVarSize(0xFFFF); + Assert.AreEqual(3, result); + } + else + { + int result = Neo.IO.Helper.GetVarSize(0xFFFFFF); + Assert.AreEqual(5, result); + } + } + } + enum TestEnum0 : sbyte + { + case1 = 1, case2 = 2 + } + + enum TestEnum1 : byte + { + case1 = 1, case2 = 2 + } + + enum TestEnum2 : short + { + case1 = 1, case2 = 2 + } + + enum TestEnum3 : ushort + { + case1 = 1, case2 = 2 + } + + enum TestEnum4 : int + { + case1 = 1, case2 = 2 + } + + enum TestEnum5 : uint + { + case1 = 1, case2 = 2 + } + + enum TestEnum6 : long + { + case1 = 1, case2 = 2 + } + + [TestMethod] + public void TestGetVarSizeGeneric() + { + for (int i = 0; i < 9; i++) + { + if (i == 0) + { + int result = Neo.IO.Helper.GetVarSize(new UInt160[] { UInt160.Zero }); + Assert.AreEqual(21, result); + } + else if (i == 1)//sbyte + { + List initList = new List + { + TestEnum0.case1 + }; + IReadOnlyCollection testList = initList.AsReadOnly(); + int result = Neo.IO.Helper.GetVarSize(testList); + Assert.AreEqual(2, result); + } + else if (i == 2)//byte + { + List initList = new List + { + TestEnum1.case1 + }; + IReadOnlyCollection testList = initList.AsReadOnly(); + int result = Neo.IO.Helper.GetVarSize(testList); + Assert.AreEqual(2, result); + } + else if (i == 3)//short + { + List initList = new List + { + TestEnum2.case1 + }; + IReadOnlyCollection testList = initList.AsReadOnly(); + int result = Neo.IO.Helper.GetVarSize(testList); + Assert.AreEqual(3, result); + } + else if (i == 4)//ushort + { + List initList = new List + { + TestEnum3.case1 + }; + IReadOnlyCollection testList = initList.AsReadOnly(); + int result = Neo.IO.Helper.GetVarSize(testList); + Assert.AreEqual(3, result); + } + else if (i == 5)//int + { + List initList = new List + { + TestEnum4.case1 + }; + IReadOnlyCollection testList = initList.AsReadOnly(); + int result = Neo.IO.Helper.GetVarSize(testList); + Assert.AreEqual(5, result); + } + else if (i == 6)//uint + { + List initList = new List + { + TestEnum5.case1 + }; + IReadOnlyCollection testList = initList.AsReadOnly(); + int result = Neo.IO.Helper.GetVarSize(testList); + Assert.AreEqual(5, result); + } + else if (i == 7)//long + { + List initList = new List + { + TestEnum6.case1 + }; + IReadOnlyCollection testList = initList.AsReadOnly(); + int result = Neo.IO.Helper.GetVarSize(testList); + Assert.AreEqual(9, result); + } + else if (i == 8) + { + List initList = new List + { + 1 + }; + IReadOnlyCollection testList = initList.AsReadOnly(); + int result = Neo.IO.Helper.GetVarSize(testList); + Assert.AreEqual(5, result); + } + } + } + + [TestMethod] + public void TestGetVarSizeString() + { + int result = Neo.IO.Helper.GetVarSize("AA"); + Assert.AreEqual(3, result); + } + + [TestMethod] + public void TestReadBytesWithGrouping() + { + for (int i = 0; i < 2; i++) + { + if (i == 0) + { + byte[] caseArray = new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA}; + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteBytesWithGrouping(writer, caseArray); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + byte[] result = Neo.IO.Helper.ReadBytesWithGrouping(reader); + Assert.AreEqual(Encoding.Default.GetString(caseArray), Encoding.Default.GetString(result)); + } + else + { + byte[] caseArray = new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x11}; + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + writer.Write(caseArray); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + Action action = () => Neo.IO.Helper.ReadBytesWithGrouping(reader); + action.ShouldThrow(); + } + } + } + + [TestMethod] + public void TestReadFixedString() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteFixedString(writer, "AA", Encoding.UTF8.GetBytes("AA").Length + 1); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + string result = Neo.IO.Helper.ReadFixedString(reader, Encoding.UTF8.GetBytes("AA").Length + 1); + Assert.AreEqual("AA", result); + } + + [TestMethod] + public void TestReadSerializable() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.Write(writer, UInt160.Zero); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + UInt160 result = Neo.IO.Helper.ReadSerializable(reader); + Assert.AreEqual(UInt160.Zero, result); + } + + [TestMethod] + public void TestReadSerializableArray() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.Write(writer, new UInt160[] { UInt160.Zero }); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + UInt160[] resultArray = Neo.IO.Helper.ReadSerializableArray(reader); + Assert.AreEqual(1, resultArray.Length); + Assert.AreEqual(UInt160.Zero, resultArray[0]); + } + + [TestMethod] + public void TestReadVarBytes() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarBytes(writer, new byte[] { 0xAA, 0xAA }); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + byte[] byteArray = Neo.IO.Helper.ReadVarBytes(reader, 10); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xAA, 0xAA }), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestReadVarInt() + { + for (int i = 0; i < 4; i++) + { + if (i == 0) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarInt(writer, 0xFFFF); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + ulong result = Neo.IO.Helper.ReadVarInt(reader, 0xFFFF); + Assert.AreEqual((ulong)0xFFFF, result); + } + else if (i == 1) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarInt(writer, 0xFFFFFFFF); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + ulong result = Neo.IO.Helper.ReadVarInt(reader, 0xFFFFFFFF); + Assert.AreEqual(0xFFFFFFFF, result); + } + else + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarInt(writer, 0xFFFFFFFFFF); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + Action action = () => Neo.IO.Helper.ReadVarInt(reader, 0xFFFFFFFF); + action.ShouldThrow(); + } + } + } + + [TestMethod] + public void TestReadVarString() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarString(writer, "AAAAAAA"); + stream.Seek(0, SeekOrigin.Begin); + BinaryReader reader = new BinaryReader(stream); + string result = Neo.IO.Helper.ReadVarString(reader, 10); + stream.Seek(0, SeekOrigin.Begin); + Assert.AreEqual("AAAAAAA", result); + } + + [TestMethod] + public void TestToArray() + { + byte[] byteArray = Neo.IO.Helper.ToArray(UInt160.Zero); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00}), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestToByteArrayGeneric() + { + byte[] byteArray = Neo.IO.Helper.ToByteArray(new UInt160[] { UInt160.Zero }); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00}), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestWrite() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.Write(writer, UInt160.Zero); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00}), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestWriteGeneric() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.Write(writer, new UInt160[] { UInt160.Zero }); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00}), Encoding.Default.GetString(byteArray)); + } + + + [TestMethod] + public void TestWriteBytesWithGrouping() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteBytesWithGrouping(writer, new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA}); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x0C}), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestWriteFixedString() + { + for (int i = 0; i < 5; i++) + { + if (i == 0) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Action action = () => Neo.IO.Helper.WriteFixedString(writer, null, 0); + action.ShouldThrow(); + } + else if (i == 1) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Action action = () => Neo.IO.Helper.WriteFixedString(writer, "AA", Encoding.UTF8.GetBytes("AA").Length - 1); + action.ShouldThrow(); + } + else if (i == 2) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Action action = () => Neo.IO.Helper.WriteFixedString(writer, "拉拉", Encoding.UTF8.GetBytes("拉拉").Length - 1); + action.ShouldThrow(); + } + else if (i == 3) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteFixedString(writer, "AA", Encoding.UTF8.GetBytes("AA").Length + 1); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + byte[] newArray = new byte[Encoding.UTF8.GetBytes("AA").Length + 1]; + Encoding.UTF8.GetBytes("AA").CopyTo(newArray, 0); + Assert.AreEqual(Encoding.Default.GetString(newArray), Encoding.Default.GetString(byteArray)); + } + } + } + + [TestMethod] + public void TestWriteVarBytes() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarBytes(writer, new byte[] { 0xAA }); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01, 0xAA }), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestWriteVarInt() + { + for (int i = 0; i < 5; i++) + { + if (i == 0) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Action action = () => Neo.IO.Helper.WriteVarInt(writer, -1); + action.ShouldThrow(); + } + else if (i == 1) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarInt(writer, 0xFC); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(0xFC, byteArray[0]); + } + else if (i == 2) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarInt(writer, 0xFFFF); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(0xFD, byteArray[0]); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xFF, 0xFF }), Encoding.Default.GetString(byteArray.Skip(1).Take(byteArray.Length - 1).ToArray())); + } + else if (i == 3) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarInt(writer, 0xFFFFFFFF); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(0xFE, byteArray[0]); + Assert.AreEqual(0xFFFFFFFF, BitConverter.ToUInt32(byteArray, 1)); + } + else + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarInt(writer, 0xAEFFFFFFFF); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(0xFF, byteArray[0]); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 }), Encoding.Default.GetString(byteArray.Skip(1).Take(byteArray.Length - 1).ToArray())); + } + } + } + + [TestMethod] + public void TestWriteVarString() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + Neo.IO.Helper.WriteVarString(writer, "a"); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + Assert.AreEqual(0x01, byteArray[0]); + Assert.AreEqual(0x61, byteArray[1]); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs b/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs new file mode 100644 index 0000000000..3f4f0c6d06 --- /dev/null +++ b/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs @@ -0,0 +1,50 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Wrappers; +using System.IO; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_SerializableWrapper + { + [TestMethod] + public void TestGetSize() + { + SerializableWrapper temp = new UInt32Wrapper(); + Assert.AreEqual(4, temp.Size); + } + + [TestMethod] + public void TestEqualsOtherObject() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + BinaryReader reader = new BinaryReader(stream); + writer.Write((uint)1); + stream.Seek(0, SeekOrigin.Begin); + SerializableWrapper temp = new UInt32Wrapper(); + temp.Deserialize(reader); + Assert.AreEqual(true, temp.Equals(1)); + } + + [TestMethod] + public void TestEqualsOtherSerializableWrapper() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + BinaryReader reader = new BinaryReader(stream); + writer.Write((uint)1); + stream.Seek(0, SeekOrigin.Begin); + SerializableWrapper temp = new UInt32Wrapper(); + temp.Deserialize(reader); + MemoryStream stream2 = new MemoryStream(); + BinaryWriter writer2 = new BinaryWriter(stream2); + BinaryReader reader2 = new BinaryReader(stream2); + writer2.Write((uint)1); + stream2.Seek(0, SeekOrigin.Begin); + SerializableWrapper temp2 = new UInt32Wrapper(); + temp2.Deserialize(reader2); + Assert.AreEqual(true, temp.Equals(temp2)); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs b/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs new file mode 100644 index 0000000000..7762c56b7c --- /dev/null +++ b/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs @@ -0,0 +1,97 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Wrappers; +using System.IO; +using System.Text; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_UInt32Wrapper + { + [TestMethod] + public void TestGetSize() + { + UInt32Wrapper temp = new UInt32Wrapper(); + Assert.AreEqual(4, temp.Size); + } + + [TestMethod] + public void TestDeserialize() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + BinaryReader reader = new BinaryReader(stream); + writer.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }); + stream.Seek(0, SeekOrigin.Begin); + UInt32Wrapper temp = new UInt32Wrapper(); + temp.Deserialize(reader); + MemoryStream stream2 = new MemoryStream(); + BinaryWriter writer2 = new BinaryWriter(stream2); + temp.Serialize(writer2); + stream2.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream2.Length]; + stream2.Read(byteArray, 0, (int)stream2.Length); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00, 0x00, 0x00, 0x01 }), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestSerialize() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + BinaryReader reader = new BinaryReader(stream); + writer.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }); + stream.Seek(0, SeekOrigin.Begin); + UInt32Wrapper temp = new UInt32Wrapper(); + temp.Deserialize(reader); + MemoryStream stream2 = new MemoryStream(); + BinaryWriter writer2 = new BinaryWriter(stream2); + temp.Serialize(writer2); + stream2.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream2.Length]; + stream2.Read(byteArray, 0, (int)stream2.Length); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00, 0x00, 0x00, 0x01 }), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestEqualsUInt32Wrapper() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + BinaryReader reader = new BinaryReader(stream); + writer.Write((uint)1); + stream.Seek(0, SeekOrigin.Begin); + UInt32Wrapper temp = new UInt32Wrapper(); + temp.Deserialize(reader); + MemoryStream stream2 = new MemoryStream(); + BinaryWriter writer2 = new BinaryWriter(stream2); + BinaryReader reader2 = new BinaryReader(stream2); + writer2.Write((uint)1); + stream2.Seek(0, SeekOrigin.Begin); + UInt32Wrapper temp2 = new UInt32Wrapper(); + temp2.Deserialize(reader2); + Assert.AreEqual(true, temp.Equals(temp2)); + } + + [TestMethod] + public void TestOperatorUint() + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + BinaryReader reader = new BinaryReader(stream); + writer.Write((uint)1); + stream.Seek(0, SeekOrigin.Begin); + UInt32Wrapper temp = new UInt32Wrapper(); + temp.Deserialize(reader); + uint result = temp; + Assert.AreEqual((uint)1, result); + } + + [TestMethod] + public void TestOperatorUInt32Wrapper() + { + UInt32Wrapper temp = 1; + Assert.AreEqual(true, temp.Equals(1)); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/UT_MemoryPool.cs b/neo.UnitTests/Ledger/UT_MemoryPool.cs similarity index 99% rename from neo.UnitTests/UT_MemoryPool.cs rename to neo.UnitTests/Ledger/UT_MemoryPool.cs index ee79d96842..1b5af16240 100644 --- a/neo.UnitTests/UT_MemoryPool.cs +++ b/neo.UnitTests/Ledger/UT_MemoryPool.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; using System.Linq; -namespace Neo.UnitTests +namespace Neo.UnitTests.Ledger { [TestClass] public class UT_MemoryPool diff --git a/neo.UnitTests/UT_PoolItem.cs b/neo.UnitTests/Ledger/UT_PoolItem.cs similarity index 99% rename from neo.UnitTests/UT_PoolItem.cs rename to neo.UnitTests/Ledger/UT_PoolItem.cs index cedf7f3fa9..d8f4e4f696 100644 --- a/neo.UnitTests/UT_PoolItem.cs +++ b/neo.UnitTests/Ledger/UT_PoolItem.cs @@ -5,7 +5,7 @@ using Neo.Network.P2P.Payloads; using System; -namespace Neo.UnitTests +namespace Neo.UnitTests.Ledger { [TestClass] public class UT_PoolItem diff --git a/neo.UnitTests/UT_StorageItem.cs b/neo.UnitTests/Ledger/UT_StorageItem.cs similarity index 98% rename from neo.UnitTests/UT_StorageItem.cs rename to neo.UnitTests/Ledger/UT_StorageItem.cs index c7372eb455..9afab26372 100644 --- a/neo.UnitTests/UT_StorageItem.cs +++ b/neo.UnitTests/Ledger/UT_StorageItem.cs @@ -5,7 +5,7 @@ using System.IO; using System.Text; -namespace Neo.UnitTests +namespace Neo.UnitTests.Ledger { [TestClass] public class UT_StorageItem diff --git a/neo.UnitTests/UT_StorageKey.cs b/neo.UnitTests/Ledger/UT_StorageKey.cs similarity index 99% rename from neo.UnitTests/UT_StorageKey.cs rename to neo.UnitTests/Ledger/UT_StorageKey.cs index ab718f0f89..7e2ec9bdb2 100644 --- a/neo.UnitTests/UT_StorageKey.cs +++ b/neo.UnitTests/Ledger/UT_StorageKey.cs @@ -3,7 +3,7 @@ using Neo.IO; using Neo.Ledger; -namespace Neo.UnitTests +namespace Neo.UnitTests.Ledger { [TestClass] public class UT_StorageKey diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs similarity index 99% rename from neo.UnitTests/UT_Block.cs rename to neo.UnitTests/Network/P2P/Payloads/UT_Block.cs index c91776f0c0..6736d8f936 100644 --- a/neo.UnitTests/UT_Block.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs @@ -5,7 +5,7 @@ using System.IO; using System.Text; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P.Payloads { [TestClass] public class UT_Block diff --git a/neo.UnitTests/UT_Header.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs similarity index 99% rename from neo.UnitTests/UT_Header.cs rename to neo.UnitTests/Network/P2P/Payloads/UT_Header.cs index f07be59051..f9dfd30d1e 100644 --- a/neo.UnitTests/UT_Header.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs @@ -4,7 +4,7 @@ using System.IO; using System.Text; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P.Payloads { [TestClass] public class UT_Header diff --git a/neo.UnitTests/UT_Transaction.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs similarity index 99% rename from neo.UnitTests/UT_Transaction.cs rename to neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index dc41d3a0d8..2dfa8b4c35 100644 --- a/neo.UnitTests/UT_Transaction.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -13,7 +13,7 @@ using Neo.Wallets; using Neo.Wallets.NEP6; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P.Payloads { [TestClass] public class UT_Transaction diff --git a/neo.UnitTests/UT_Witness.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs similarity index 98% rename from neo.UnitTests/UT_Witness.cs rename to neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs index 4ca00b6643..ec3525931e 100644 --- a/neo.UnitTests/UT_Witness.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs @@ -3,7 +3,7 @@ using Neo.IO.Json; using Neo.Network.P2P.Payloads; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P.Payloads { [TestClass] public class UT_Witness diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/Network/P2P/UT_Message.cs similarity index 98% rename from neo.UnitTests/UT_P2PMessage.cs rename to neo.UnitTests/Network/P2P/UT_Message.cs index 99af976992..4bb37a8166 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/Network/P2P/UT_Message.cs @@ -6,10 +6,10 @@ using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P { [TestClass] - public class UT_P2PMessage + public class UT_Message { [TestMethod] public void Serialize_Deserialize() diff --git a/neo.UnitTests/UT_ProtocolHandler.cs b/neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs similarity index 97% rename from neo.UnitTests/UT_ProtocolHandler.cs rename to neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs index 63bfe90e44..4ea998ef40 100644 --- a/neo.UnitTests/UT_ProtocolHandler.cs +++ b/neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs @@ -4,7 +4,7 @@ using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P { [TestClass] public class UT_ProtocolHandler : TestKit diff --git a/neo.UnitTests/UT_ProtocolHandlerMailbox.cs b/neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs similarity index 98% rename from neo.UnitTests/UT_ProtocolHandlerMailbox.cs rename to neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs index edd5a4191f..91caf65297 100644 --- a/neo.UnitTests/UT_ProtocolHandlerMailbox.cs +++ b/neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs @@ -1,18 +1,13 @@ -using Akka.TestKit; -using Akka.TestKit.Xunit2; +using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using Moq; -using Neo.Ledger; -using Neo.Network.P2P.Payloads; -using Neo.Network.P2P; -using Akka.Configuration; using Neo.IO; -using System.Linq; +using Neo.Network.P2P; +using System; using System.Collections.Generic; +using System.Linq; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P { [TestClass] public class UT_ProtocolHandlerMailbox : TestKit diff --git a/neo.UnitTests/UT_RemoteNode.cs b/neo.UnitTests/Network/P2P/UT_RemoteNode.cs similarity index 98% rename from neo.UnitTests/UT_RemoteNode.cs rename to neo.UnitTests/Network/P2P/UT_RemoteNode.cs index 60d587ed13..03da2a3db8 100644 --- a/neo.UnitTests/UT_RemoteNode.cs +++ b/neo.UnitTests/Network/P2P/UT_RemoteNode.cs @@ -6,7 +6,7 @@ using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P { [TestClass] [NotReRunnable] diff --git a/neo.UnitTests/UT_RemoteNodeMailbox.cs b/neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs similarity index 94% rename from neo.UnitTests/UT_RemoteNodeMailbox.cs rename to neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs index ff3e6e17d9..860012a31e 100644 --- a/neo.UnitTests/UT_RemoteNodeMailbox.cs +++ b/neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs @@ -1,11 +1,11 @@ -using System; -using Akka.IO; +using Akka.IO; using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Network.P2P; +using System; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P { [TestClass] [NotReRunnable] diff --git a/neo.UnitTests/UT_TaskManagerMailbox.cs b/neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs similarity index 93% rename from neo.UnitTests/UT_TaskManagerMailbox.cs rename to neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs index 2ba4ff2d85..6d014cd9c7 100644 --- a/neo.UnitTests/UT_TaskManagerMailbox.cs +++ b/neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs @@ -1,15 +1,11 @@ -using Akka.TestKit; -using Akka.TestKit.Xunit2; +using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using Moq; -using Neo.Ledger; -using Neo.Network.P2P.Payloads; using Neo.Network.P2P; -using Akka.Configuration; +using Neo.Network.P2P.Payloads; +using System; -namespace Neo.UnitTests +namespace Neo.UnitTests.Network.P2P { [TestClass] public class UT_TaskManagerMailbox : TestKit diff --git a/neo.UnitTests/UT_ConcatenatedIterator.cs b/neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs similarity index 97% rename from neo.UnitTests/UT_ConcatenatedIterator.cs rename to neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs index 7051f5f4f8..51db50ea31 100644 --- a/neo.UnitTests/UT_ConcatenatedIterator.cs +++ b/neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs @@ -4,7 +4,7 @@ using Neo.VM.Types; using System.Numerics; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract.Iterators { [TestClass] diff --git a/neo.UnitTests/UT_ContractManifest.cs b/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs similarity index 99% rename from neo.UnitTests/UT_ContractManifest.cs rename to neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs index 451791e9bd..bbb613c2be 100644 --- a/neo.UnitTests/UT_ContractManifest.cs +++ b/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs @@ -2,7 +2,7 @@ using Neo.Cryptography.ECC; using Neo.SmartContract.Manifest; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract.Manifest { [TestClass] public class UT_ContractManifest diff --git a/neo.UnitTests/UT_GasToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs similarity index 99% rename from neo.UnitTests/UT_GasToken.cs rename to neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index 72a0c4d7ae..0ad69a7198 100644 --- a/neo.UnitTests/UT_GasToken.cs +++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -11,7 +11,7 @@ using System.Linq; using System.Numerics; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract.Native.Tokens { [TestClass] public class UT_GasToken diff --git a/neo.UnitTests/UT_NeoToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs similarity index 99% rename from neo.UnitTests/UT_NeoToken.cs rename to neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 3997573c0f..9a22bab3c4 100644 --- a/neo.UnitTests/UT_NeoToken.cs +++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -15,7 +15,7 @@ using System.Linq; using System.Numerics; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract.Native.Tokens { [TestClass] public class UT_NeoToken diff --git a/neo.UnitTests/UT_Policy.cs b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs similarity index 94% rename from neo.UnitTests/UT_Policy.cs rename to neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index 09a09b20ba..0f353e37da 100644 --- a/neo.UnitTests/UT_Policy.cs +++ b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -7,10 +7,10 @@ using Neo.UnitTests.Extensions; using System.Linq; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract.Native { [TestClass] - public class UT_Policy + public class UT_PolicyContract { Store Store; @@ -55,7 +55,7 @@ public void Check_SetMaxTransactionsPerBlock() // Fake blockchain snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); + snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); @@ -90,7 +90,7 @@ public void Check_SetFeePerByte() // Fake blockchain snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); + snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); @@ -125,7 +125,7 @@ public void Check_Block_UnblockAccount() // Fake blockchain snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero }; - snapshot.Blocks.Add(UInt256.Zero, new Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); + snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); diff --git a/neo.UnitTests/UT_InteropPrices.cs b/neo.UnitTests/SmartContract/UT_InteropPrices.cs similarity index 99% rename from neo.UnitTests/UT_InteropPrices.cs rename to neo.UnitTests/SmartContract/UT_InteropPrices.cs index 27c0a4cdc0..d6b9b8254b 100644 --- a/neo.UnitTests/UT_InteropPrices.cs +++ b/neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -3,7 +3,7 @@ using Neo.SmartContract; using Neo.VM; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract { [TestClass] public class UT_InteropPrices diff --git a/neo.UnitTests/UT_InteropService.cs b/neo.UnitTests/SmartContract/UT_InteropService.cs similarity index 98% rename from neo.UnitTests/UT_InteropService.cs rename to neo.UnitTests/SmartContract/UT_InteropService.cs index b5e3626109..023ba4c8e5 100644 --- a/neo.UnitTests/UT_InteropService.cs +++ b/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -1,10 +1,9 @@ -using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; using Neo.SmartContract.Manifest; using Neo.VM; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract { [TestClass] public class UT_InteropService @@ -42,7 +41,7 @@ public void Runtime_GetNotifications_Test() scriptHash2 = script.ToArray().ToScriptHash(); snapshot.Contracts.Delete(scriptHash2); - snapshot.Contracts.Add(scriptHash2, new Ledger.ContractState() + snapshot.Contracts.Add(scriptHash2, new Neo.Ledger.ContractState() { Script = script.ToArray(), Manifest = ContractManifest.CreateDefault(scriptHash2), diff --git a/neo.UnitTests/UT_JsonSerializer.cs b/neo.UnitTests/SmartContract/UT_JsonSerializer.cs similarity index 99% rename from neo.UnitTests/UT_JsonSerializer.cs rename to neo.UnitTests/SmartContract/UT_JsonSerializer.cs index ed20b15392..adfbea8760 100644 --- a/neo.UnitTests/UT_JsonSerializer.cs +++ b/neo.UnitTests/SmartContract/UT_JsonSerializer.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Numerics; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract { [TestClass] public class UT_JsonSerializer diff --git a/neo.UnitTests/UT_OpCodePrices.cs b/neo.UnitTests/SmartContract/UT_OpCodePrices.cs similarity index 91% rename from neo.UnitTests/UT_OpCodePrices.cs rename to neo.UnitTests/SmartContract/UT_OpCodePrices.cs index b53d745d6a..3174d8494b 100644 --- a/neo.UnitTests/UT_OpCodePrices.cs +++ b/neo.UnitTests/SmartContract/UT_OpCodePrices.cs @@ -3,7 +3,7 @@ using Neo.VM; using System; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract { [TestClass] public class UT_OpCodePrices diff --git a/neo.UnitTests/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs similarity index 98% rename from neo.UnitTests/UT_Syscalls.cs rename to neo.UnitTests/SmartContract/UT_Syscalls.cs index c6642c4e88..c80899b8f8 100644 --- a/neo.UnitTests/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -4,7 +4,7 @@ using Neo.VM; using System.Linq; -namespace Neo.UnitTests +namespace Neo.UnitTests.SmartContract { [TestClass] public class UT_Syscalls diff --git a/neo.UnitTests/UT_BigDecimal.cs b/neo.UnitTests/UT_BigDecimal.cs new file mode 100644 index 0000000000..3975d5503e --- /dev/null +++ b/neo.UnitTests/UT_BigDecimal.cs @@ -0,0 +1,191 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Numerics; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_BigDecimal + { + [TestMethod] + public void TestChangeDecimals() + { + BigDecimal originalValue = new BigDecimal(new BigInteger(12300), 5); + BigDecimal result1 = originalValue.ChangeDecimals(7); + result1.Value.Should().Be(new BigInteger(1230000)); + result1.Decimals.Should().Be(7); + BigDecimal result2 = originalValue.ChangeDecimals(3); + result2.Value.Should().Be(new BigInteger(123)); + result2.Decimals.Should().Be(3); + BigDecimal result3 = originalValue.ChangeDecimals(5); + result3.Value.Should().Be(originalValue.Value); + Action action = () => originalValue.ChangeDecimals(2); + action.ShouldThrow(); + } + + [TestMethod] + public void TestBigDecimalConstructor() + { + BigDecimal value = new BigDecimal(new BigInteger(45600), 7); + value.Value.Should().Be(new BigInteger(45600)); + value.Decimals.Should().Be(7); + value = new BigDecimal(new BigInteger(0), 5); + value.Value.Should().Be(new BigInteger(0)); + value.Decimals.Should().Be(5); + value = new BigDecimal(new BigInteger(-10), 0); + value.Value.Should().Be(new BigInteger(-10)); + value.Decimals.Should().Be(0); + } + + [TestMethod] + public void TestGetDecimals() + { + BigDecimal value = new BigDecimal(new BigInteger(45600), 7); + value.Sign.Should().Be(1); + value = new BigDecimal(new BigInteger(0), 5); + value.Sign.Should().Be(0); + value = new BigDecimal(new BigInteger(-10), 0); + value.Sign.Should().Be(-1); + } + + [TestMethod] + public void TestGetSign() + { + BigDecimal value = new BigDecimal(new BigInteger(45600), 7); + value.Sign.Should().Be(1); + value = new BigDecimal(new BigInteger(0), 5); + value.Sign.Should().Be(0); + value = new BigDecimal(new BigInteger(-10), 0); + value.Sign.Should().Be(-1); + } + + [TestMethod] + public void TestParse() + { + string s = "12345"; + byte decimals = 0; + BigDecimal.Parse(s, decimals).Should().Be(new BigDecimal(new BigInteger(12345), 0)); + + s = "abcdEfg"; + Action action = () => BigDecimal.Parse(s, decimals); + action.ShouldThrow(); + } + + [TestMethod] + public void TestToString() + { + BigDecimal value = new BigDecimal(new BigInteger(100000), 5); + value.ToString().Should().Be("1"); + value = new BigDecimal(new BigInteger(123456), 5); + value.ToString().Should().Be("1.23456"); + } + + [TestMethod] + public void TestTryParse() + { + string s = ""; + byte decimals = 0; + BigDecimal result; + + s = "12345"; + decimals = 0; + BigDecimal.TryParse(s, decimals, out result).Should().BeTrue(); + result.Should().Be(new BigDecimal(new BigInteger(12345), 0)); + + s = "12345E-5"; + decimals = 5; + BigDecimal.TryParse(s, decimals, out result).Should().BeTrue(); + result.Should().Be(new BigDecimal(new BigInteger(12345), 5)); + + s = "abcdEfg"; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "123.45"; + decimals = 2; + BigDecimal.TryParse(s, decimals, out result).Should().BeTrue(); + result.Should().Be(new BigDecimal(new BigInteger(12345), 2)); + + s = "123.45E-5"; + decimals = 7; + BigDecimal.TryParse(s, decimals, out result).Should().BeTrue(); + result.Should().Be(new BigDecimal(new BigInteger(12345), 7)); + + s = "12345E-5"; + decimals = 3; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "1.2345"; + decimals = 3; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "1.2345E-5"; + decimals = 3; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "12345"; + decimals = 3; + BigDecimal.TryParse(s, decimals, out result).Should().BeTrue(); + result.Should().Be(new BigDecimal(new BigInteger(12345000), 3)); + + s = "12345E-2"; + decimals = 3; + BigDecimal.TryParse(s, decimals, out result).Should().BeTrue(); + result.Should().Be(new BigDecimal(new BigInteger(123450), 3)); + + s = "123.45"; + decimals = 3; + BigDecimal.TryParse(s, decimals, out result).Should().BeTrue(); + result.Should().Be(new BigDecimal(new BigInteger(123450), 3)); + + s = "123.45E3"; + decimals = 3; + BigDecimal.TryParse(s, decimals, out result).Should().BeTrue(); + result.Should().Be(new BigDecimal(new BigInteger(123450000), 3)); + + s = "a456bcdfg"; + decimals = 0; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "a456bce-5"; + decimals = 5; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "a4.56bcd"; + decimals = 5; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "a4.56bce3"; + decimals = 2; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "a456bcd"; + decimals = 2; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "a456bcdE3"; + decimals = 2; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "a456b.cd"; + decimals = 5; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + + s = "a456b.cdE3"; + decimals = 5; + BigDecimal.TryParse(s, decimals, out result).Should().BeFalse(); + result.Should().Be(default(BigDecimal)); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/UT_FifoSet.cs b/neo.UnitTests/UT_FifoSet.cs deleted file mode 100644 index ff5ccf9c27..0000000000 --- a/neo.UnitTests/UT_FifoSet.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.IO.Caching; -using System.Linq; - -namespace Neo.UnitTests -{ - [TestClass] - public class UT_FifoSet - { - [TestMethod] - public void FifoSetTest() - { - var a = UInt256.Zero; - var b = new UInt256(); - var c = new UInt256(new byte[32] { - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01 - }); - - var set = new FIFOSet(3); - - Assert.IsTrue(set.Add(a)); - Assert.IsFalse(set.Add(a)); - Assert.IsFalse(set.Add(b)); - Assert.IsTrue(set.Add(c)); - - CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c }); - - var d = new UInt256(new byte[32] { - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x02 - }); - - // Testing Fifo max size - Assert.IsTrue(set.Add(d)); - CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c, d }); - - var e = new UInt256(new byte[32] { - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x03 - }); - - Assert.IsTrue(set.Add(e)); - Assert.IsFalse(set.Add(e)); - CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { c, d, e }); - } - } -} diff --git a/neo.UnitTests/UT_ProtocolSettings.cs b/neo.UnitTests/UT_ProtocolSettings.cs index 92cabae19b..053c5d7e37 100644 --- a/neo.UnitTests/UT_ProtocolSettings.cs +++ b/neo.UnitTests/UT_ProtocolSettings.cs @@ -93,4 +93,4 @@ public void Cant_initialize_ProtocolSettings_twice() ProtocolSettings.Default.Magic.Should().Be(expectedMagic); } } -} +} \ No newline at end of file diff --git a/neo.UnitTests/VM/UT_Helper.cs b/neo.UnitTests/VM/UT_Helper.cs new file mode 100644 index 0000000000..7fc0088632 --- /dev/null +++ b/neo.UnitTests/VM/UT_Helper.cs @@ -0,0 +1,82 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.SmartContract; +using Neo.VM; +using System; +using System.Text; + +namespace Neo.UnitTests.IO +{ + [TestClass] + public class UT_Helper + { + [TestMethod] + public void TestEmit() + { + ScriptBuilder sb = new ScriptBuilder(); + sb.Emit(new OpCode[] { OpCode.PUSH0 }); + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00 }), Encoding.Default.GetString(sb.ToArray())); + } + + [TestMethod] + public void TestEmitAppCall1() + { + //format:(byte)0x00+(byte)OpCode.NEWARRAY+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call + ScriptBuilder sb = new ScriptBuilder(); + sb.EmitAppCall(UInt160.Zero, "AAAAA"); + byte[] tempArray = new byte[34]; + tempArray[0] = 0x00;//0 + tempArray[1] = 0xC5;//OpCode.NEWARRAY + tempArray[2] = 5;//operation.Length + Array.Copy(Encoding.UTF8.GetBytes("AAAAA"),0, tempArray,3, 5);//operation.data + tempArray[8] = 0x14;//scriptHash.Length + Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 9, 20);//operation.data + uint api = InteropService.System_Contract_Call; + tempArray[29] = 0x68;//OpCode.SYSCALL + Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 30, 4);//api.data + byte[] resultArray = sb.ToArray(); + Assert.AreEqual(Encoding.Default.GetString(tempArray), Encoding.Default.GetString(resultArray)); + } + + [TestMethod] + public void TestEmitAppCall2() + { + //format:(ContractParameter[])ContractParameter+(byte)OpCode.PACK+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call + ScriptBuilder sb = new ScriptBuilder(); + sb.EmitAppCall(UInt160.Zero, "AAAAA",new ContractParameter[] {new ContractParameter(ContractParameterType.Integer)}); + byte[] tempArray = new byte[35]; + tempArray[0] = 0x00;//0 + tempArray[1] = 0x51;//ContractParameter.Length + tempArray[2] = 0xC1;//OpCode.PACK + tempArray[3] = 0x05;//operation.Length + Array.Copy(Encoding.UTF8.GetBytes("AAAAA"), 0, tempArray, 4, 5);//operation.data + tempArray[9] = 0x14;//scriptHash.Length + Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 10, 20);//operation.data + uint api = InteropService.System_Contract_Call; + tempArray[30] = 0x68;//OpCode.SYSCALL + Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 31, 4);//api.data + byte[] resultArray = sb.ToArray(); + Assert.AreEqual(Encoding.Default.GetString(tempArray), Encoding.Default.GetString(resultArray)); + } + + [TestMethod] + public void TestEmitAppCall3() + { + //format:(object[])args+(byte)OpCode.PACK+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call + ScriptBuilder sb = new ScriptBuilder(); + sb.EmitAppCall(UInt160.Zero, "AAAAA", true); + byte[] tempArray = new byte[35]; + tempArray[0] = 0x51;//arg + tempArray[1] = 0x51;//args.Length + tempArray[2] = 0xC1;//OpCode.PACK + tempArray[3] = 0x05;//operation.Length + Array.Copy(Encoding.UTF8.GetBytes("AAAAA"), 0, tempArray, 4, 5);//operation.data + tempArray[9] = 0x14;//scriptHash.Length + Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 10, 20);//operation.data + uint api = InteropService.System_Contract_Call; + tempArray[30] = 0x68;//OpCode.SYSCALL + Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 31, 4);//api.data + byte[] resultArray = sb.ToArray(); + Assert.AreEqual(Encoding.Default.GetString(tempArray), Encoding.Default.GetString(resultArray)); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/UT_NEP6Wallet.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs similarity index 97% rename from neo.UnitTests/UT_NEP6Wallet.cs rename to neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs index 187e487030..9bac3de4ac 100644 --- a/neo.UnitTests/UT_NEP6Wallet.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs @@ -4,7 +4,7 @@ using Neo.Wallets.NEP6; using System; -namespace Neo.UnitTests +namespace Neo.UnitTests.Wallets.NEP6 { [TestClass] public class UT_NEP6Wallet diff --git a/neo.UnitTests/UT_ScryptParameters.cs b/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs similarity index 97% rename from neo.UnitTests/UT_ScryptParameters.cs rename to neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs index e0021f0eb0..3d4550a48d 100644 --- a/neo.UnitTests/UT_ScryptParameters.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs @@ -3,7 +3,7 @@ using Neo.IO.Json; using Neo.Wallets.NEP6; -namespace Neo.UnitTests +namespace Neo.UnitTests.Wallets.NEP6 { [TestClass] public class UT_ScryptParameters diff --git a/neo.UnitTests/Wallets/SQLite/UT_Account.cs b/neo.UnitTests/Wallets/SQLite/UT_Account.cs new file mode 100644 index 0000000000..c60e90fd10 --- /dev/null +++ b/neo.UnitTests/Wallets/SQLite/UT_Account.cs @@ -0,0 +1,37 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Wallets.SQLite; +using System.Text; + +namespace Neo.UnitTests.Wallets.SQLite +{ + [TestClass] + public class UT_Account + { + [TestMethod] + public void TestGenerator() + { + Account account = new Account(); + Assert.IsNotNull(account); + } + + [TestMethod] + public void TestSetAndGetPrivateKeyEncrypted() + { + Account account = new Account + { + PrivateKeyEncrypted = new byte[] { 0x01 } + }; + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(account.PrivateKeyEncrypted)); + } + + [TestMethod] + public void TestSetAndGetPublicKeyHash() + { + Account account = new Account + { + PublicKeyHash = new byte[] { 0x01 } + }; + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(account.PublicKeyHash)); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Wallets/SQLite/UT_Address.cs b/neo.UnitTests/Wallets/SQLite/UT_Address.cs new file mode 100644 index 0000000000..4d3e2d6717 --- /dev/null +++ b/neo.UnitTests/Wallets/SQLite/UT_Address.cs @@ -0,0 +1,27 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Wallets.SQLite; +using System.Text; + +namespace Neo.UnitTests.Wallets.SQLite +{ + [TestClass] + public class UT_Address + { + [TestMethod] + public void TestGenerator() + { + Address address = new Address(); + Assert.IsNotNull(address); + } + + [TestMethod] + public void TestSetAndGetScriptHash() + { + Address address = new Address + { + ScriptHash = new byte[] { 0x01 } + }; + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(address.ScriptHash)); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Wallets/SQLite/UT_Contract.cs b/neo.UnitTests/Wallets/SQLite/UT_Contract.cs new file mode 100644 index 0000000000..52c197a778 --- /dev/null +++ b/neo.UnitTests/Wallets/SQLite/UT_Contract.cs @@ -0,0 +1,65 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Wallets.SQLite; +using System.Text; + +namespace Neo.UnitTests.Wallets.SQLite +{ + [TestClass] + public class UT_Contract + { + [TestMethod] + public void TestGenerator() + { + Contract contract = new Contract(); + Assert.IsNotNull(contract); + } + + [TestMethod] + public void TestSetAndGetRawData() + { + Contract contract = new Contract + { + RawData = new byte[] { 0x01 } + }; + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(contract.RawData)); + } + + [TestMethod] + public void TestSetAndGetScriptHash() + { + Contract contract = new Contract + { + ScriptHash = new byte[] { 0x01 } + }; + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(contract.ScriptHash)); + } + + [TestMethod] + public void TestSetAndGetPublicKeyHash() + { + Contract contract = new Contract + { + PublicKeyHash = new byte[] { 0x01 } + }; + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(contract.PublicKeyHash)); + } + + [TestMethod] + public void TestSetAndGetAccount() + { + Contract contract = new Contract(); + Account account = new Account(); + contract.Account = account; + Assert.AreEqual(account, contract.Account); + } + + [TestMethod] + public void TestSetAndGetAddress() + { + Contract contract = new Contract(); + Address address = new Address(); + contract.Address = address; + Assert.AreEqual(address, contract.Address); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Wallets/SQLite/UT_Key.cs b/neo.UnitTests/Wallets/SQLite/UT_Key.cs new file mode 100644 index 0000000000..e09896b72c --- /dev/null +++ b/neo.UnitTests/Wallets/SQLite/UT_Key.cs @@ -0,0 +1,37 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Wallets.SQLite; +using System.Text; + +namespace Neo.UnitTests.Wallets.SQLite +{ + [TestClass] + public class UT_Key + { + [TestMethod] + public void TestGenerator() + { + Key key = new Key(); + Assert.IsNotNull(key); + } + + [TestMethod] + public void TestSetAndGetName() + { + Key key = new Key + { + Name = "AAA" + }; + Assert.AreEqual("AAA", key.Name); + } + + [TestMethod] + public void TestSetAndGetValue() + { + Key key = new Key + { + Value = new byte[] { 0x01 } + }; + Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(key.Value)); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/UT_AssetDescription.cs b/neo.UnitTests/Wallets/UT_AssetDescriptor.cs similarity index 77% rename from neo.UnitTests/UT_AssetDescription.cs rename to neo.UnitTests/Wallets/UT_AssetDescriptor.cs index 175814b91f..6630a8450b 100644 --- a/neo.UnitTests/UT_AssetDescription.cs +++ b/neo.UnitTests/Wallets/UT_AssetDescriptor.cs @@ -3,10 +3,10 @@ using Neo.Persistence; using Neo.SmartContract.Native; -namespace Neo.UnitTests +namespace Neo.UnitTests.Wallets { [TestClass] - public class UT_AssetDescription + public class UT_AssetDescriptor { private Store Store; @@ -20,7 +20,7 @@ public void TestSetup() [TestMethod] public void Check_GAS() { - var descriptor = new Wallets.AssetDescriptor(NativeContract.GAS.Hash); + var descriptor = new Neo.Wallets.AssetDescriptor(NativeContract.GAS.Hash); descriptor.AssetId.Should().Be(NativeContract.GAS.Hash); descriptor.AssetName.Should().Be("GAS"); descriptor.Decimals.Should().Be(8); @@ -29,7 +29,7 @@ public void Check_GAS() [TestMethod] public void Check_NEO() { - var descriptor = new Wallets.AssetDescriptor(NativeContract.NEO.Hash); + var descriptor = new Neo.Wallets.AssetDescriptor(NativeContract.NEO.Hash); descriptor.AssetId.Should().Be(NativeContract.NEO.Hash); descriptor.AssetName.Should().Be("NEO"); descriptor.Decimals.Should().Be(0); diff --git a/neo.UnitTests/neo.UnitTests.csproj b/neo.UnitTests/neo.UnitTests.csproj index 9f57166c69..5d967c0845 100644 --- a/neo.UnitTests/neo.UnitTests.csproj +++ b/neo.UnitTests/neo.UnitTests.csproj @@ -31,5 +31,4 @@ - diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs index 912ea69c73..739085f5b6 100644 --- a/neo/Ledger/MemoryPool.cs +++ b/neo/Ledger/MemoryPool.cs @@ -361,7 +361,7 @@ internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot) if (policyChanged) { foreach (PoolItem item in _unverifiedSortedTransactions.Reverse()) - if(item.Tx.FeePerByte >= _feePerByte) + if (item.Tx.FeePerByte >= _feePerByte) _system.Blockchain.Tell(item.Tx, ActorRefs.NoSender); _unverifiedTransactions.Clear(); _unverifiedSortedTransactions.Clear(); From f4adfac864e7844079120f50f2bee224aa3a406a Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 29 Jul 2019 07:24:58 +0200 Subject: [PATCH 07/54] Script header (#903) * Script header * Script header draft * Clean files * Typo * Rename class and magic header * Clean hash * UT * Erik's suggestions * Change name * Typo * Check magic * 64 to 32 * Nef file only for neo-cli * Real Checksum * Clean * Clean again * Remove code * Update neo/SmartContract/NefFile.cs Co-Authored-By: Igor Machado Coelho * Enum to const * Remove unnecessary change * Apply Erik's suggestions --- neo.UnitTests/UT_NefFile.cs | 75 ++++++++++++++++++++ neo/SmartContract/NefFile.cs | 129 +++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 neo.UnitTests/UT_NefFile.cs create mode 100644 neo/SmartContract/NefFile.cs diff --git a/neo.UnitTests/UT_NefFile.cs b/neo.UnitTests/UT_NefFile.cs new file mode 100644 index 0000000000..ba14496a27 --- /dev/null +++ b/neo.UnitTests/UT_NefFile.cs @@ -0,0 +1,75 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.IO; +using Neo.SmartContract; +using System; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_NefFile + { + [TestMethod] + public void ParseTest() + { + var file = new NefFile() + { + Compiler = "".PadLeft(32, ' '), + Version = new Version(1, 2, 3, 4), + Script = new byte[] { 0x01, 0x02, 0x03 } + }; + + file.ScriptHash = file.Script.ToScriptHash(); + file.CheckSum = NefFile.ComputeChecksum(file); + + var data = file.ToArray(); + file = data.AsSerializable(); + + Assert.AreEqual("".PadLeft(32, ' '), file.Compiler); + Assert.AreEqual(new Version(1, 2, 3, 4), file.Version); + Assert.AreEqual(file.Script.ToScriptHash(), file.ScriptHash); + CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }, file.Script); + } + + [TestMethod] + public void LimitTest() + { + var file = new NefFile() + { + Compiler = "".PadLeft(byte.MaxValue, ' '), + Version = new Version(1, 2, 3, 4), + Script = new byte[1024 * 1024], + ScriptHash = new byte[1024 * 1024].ToScriptHash(), + CheckSum = 0 + }; + + // Wrong compiler + + Assert.ThrowsException(() => file.ToArray()); + + // Wrong script + + file.Compiler = ""; + file.Script = new byte[(1024 * 1024) + 1]; + file.ScriptHash = file.Script.ToScriptHash(); + var data = file.ToArray(); + + Assert.ThrowsException(() => data.AsSerializable()); + + // Wrong script hash + + file.Script = new byte[1024 * 1024]; + data = file.ToArray(); + + Assert.ThrowsException(() => data.AsSerializable()); + + // Wrong checksum + + file.Script = new byte[1024]; + data = file.ToArray(); + file.CheckSum = NefFile.ComputeChecksum(file) + 1; + + Assert.ThrowsException(() => data.AsSerializable()); + } + } +} \ No newline at end of file diff --git a/neo/SmartContract/NefFile.cs b/neo/SmartContract/NefFile.cs new file mode 100644 index 0000000000..52507eda08 --- /dev/null +++ b/neo/SmartContract/NefFile.cs @@ -0,0 +1,129 @@ +using Neo.Cryptography; +using Neo.IO; +using System; +using System.IO; + +namespace Neo.SmartContract +{ + /// + /// +------------+-----------+------------------------------------------------------------+ + /// | Field | Length | Comment | + /// +------------+-----------+------------------------------------------------------------+ + /// | Magic | 4 bytes | Magic header | + /// | Compiler | 32 bytes | Compiler used | + /// | Version | 16 bytes | Compiler version (Mayor, Minor, Build, Version) | + /// | ScriptHash | 20 bytes | ScriptHash for the script | + /// +------------+-----------+------------------------------------------------------------+ + /// | Checksum | 4 bytes | Sha256 of the header (CRC) | + /// +------------+-----------+------------------------------------------------------------+ + /// | Script | Var bytes | Var bytes for the payload | + /// +------------+-----------+------------------------------------------------------------+ + /// + public class NefFile : ISerializable + { + /// + /// NEO Executable Format 3 (NEF3) + /// + private const uint Magic = 0x3346454E; + + /// + /// Compiler + /// + public string Compiler { get; set; } + + /// + /// Version + /// + public Version Version { get; set; } + + /// + /// Script Hash + /// + public UInt160 ScriptHash { get; set; } + + /// + /// Checksum + /// + public uint CheckSum { get; set; } + + /// + /// Script + /// + public byte[] Script { get; set; } + + private const int HeaderSize = + sizeof(uint) + // Magic + 32 + // Compiler + (sizeof(int) * 4) + // Version + UInt160.Length + // ScriptHash + sizeof(uint); // Checksum + + public int Size => + HeaderSize + // Header + Script.GetVarSize(); // Script + + public void Serialize(BinaryWriter writer) + { + writer.Write(Magic); + writer.WriteFixedString(Compiler, 32); + + // Version + writer.Write(Version.Major); + writer.Write(Version.Minor); + writer.Write(Version.Build); + writer.Write(Version.Revision); + + writer.Write(ScriptHash); + writer.Write(CheckSum); + writer.WriteVarBytes(Script ?? new byte[0]); + } + + public void Deserialize(BinaryReader reader) + { + if (reader.ReadUInt32() != Magic) + { + throw new FormatException("Wrong magic"); + } + + Compiler = reader.ReadFixedString(32); + Version = new Version(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32()); + ScriptHash = reader.ReadSerializable(); + CheckSum = reader.ReadUInt32(); + + if (CheckSum != ComputeChecksum(this)) + { + throw new FormatException("CRC verification fail"); + } + + Script = reader.ReadVarBytes(1024 * 1024); + + if (Script.ToScriptHash() != ScriptHash) + { + throw new FormatException("ScriptHash is different"); + } + } + + /// + /// Compute checksum for a file + /// + /// File + /// Return checksum + public static uint ComputeChecksum(NefFile file) + { + using (var ms = new MemoryStream()) + using (var wr = new BinaryWriter(ms)) + { + file.Serialize(wr); + wr.Flush(); + + // Read header without CRC + + var buffer = new byte[HeaderSize - sizeof(uint)]; + ms.Seek(0, SeekOrigin.Begin); + ms.Read(buffer, 0, buffer.Length); + + return BitConverter.ToUInt32(buffer.Sha256(), 0); + } + } + } +} From 5c9484242858195b1c68b8b2405dd3968e0c7acd Mon Sep 17 00:00:00 2001 From: Charis Zhao Date: Mon, 29 Jul 2019 23:41:14 +0800 Subject: [PATCH 08/54] Unit Tests of Crypto Module (#962) * testDemo * add dll lib * add dbsnapshot dispose * test get blocks in levelDBStore * add levelDBStore test funcs * fix levelDBStore funcs * add DbCache addInternal * differ db path * space * fix delete internal test * add test getInternal tryGetInternal move libleveldb.dll * add dbCache method test * add store test * add cache unit tests * add cache unit tests * up readonly max_capacity * fix leveldbexception * fix comment on UT_Cache * format * fix multithread test problem * up cache * update travis config * update travis.yml * test DbMetaDataCache * fix db directory * format and update travis for maxos * fix mac env travis * 2019/7/12 10:34 * 2019/7/12 11:01 * remove commented line * test BigDecimal * fix format and csproj * rm coverage.opencover.xml * update method name * add UT_P_Helper * modify UT_P_Helper * modify UT_P_helper * Clean ut * test Base58 & BloomFilter * Update UT_Cache.cs * Correct Typo * test JsonArray * update namespace * update namespace * update format * update format * organise folder structure * add UT_JString * test JBoolean JNumber & JObject * 2019/7/16 10:30 add some test case for UInt32Wrapper and SerializableWrapper * fix timestamp * test ECDsa and Crypto * test OrderedDictionary & complete IO.Json tests * 2019/7/16 17:33 add some test case of SQLiteWallet * test FIFOSet * add CloneCache and DataCache unit tests * fix namespace * add UT_Cryptography_Helper * format UT_CloneCache and UT_DataCache * add UT_DataCache.GetAndChange unit test * update namespace * remove comment code * delete Persistence part * 2019/7/19 11:07 add some test case for Helper in VM * Fix Base58 Test * 2019/7/19 11:33 change some format * update IOHelper exception assert * 2019/7/19 14:22 change format * format IOHelper * review IO.Wrapper * review Wallets.SQLite UT * Test ECFieldElement ECPoint * refactor package * format ECDsa * update namespace * Code fix * review cache * modify UT_JString * fomat * using Actin replace with try-catch * add UT_CloneMetaCache and UT_MetaDataCache * update namespace * format UT_DataCache.cs * Code Fix * format * update csproj * Code fix for UT_ECFieldElement and UT_ECPoint * Code fix * format * update travis * delete deleteFiles * fix path and comment * update travis * delete test ToTimeStamp * format UT_*Cache * update format * fomat * use hex extensions in Cryptography_Helper * remove reflection * optimization of UT_DataCache * update namespace * modify TestSha256 * update UT in crypto module * Rename UT_Scrypt.cs to UT_SCrypt.cs * format * update UT_Murmur3 --- neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs | 42 ++++++++++ neo.UnitTests/Cryptography/UT_MerkleTree.cs | 80 +++++++++++++++++++ .../Cryptography/UT_MerkleTreeNode.cs | 51 ++++++++++++ neo.UnitTests/Cryptography/UT_Murmur3.cs | 24 ++++++ .../{UT_Scrypt.cs => UT_SCrypt.cs} | 3 +- 5 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 neo.UnitTests/Cryptography/UT_MerkleTree.cs create mode 100644 neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs create mode 100644 neo.UnitTests/Cryptography/UT_Murmur3.cs rename neo.UnitTests/Cryptography/{UT_Scrypt.cs => UT_SCrypt.cs} (93%) diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs index 9de751e851..cc6fa87d5a 100644 --- a/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs +++ b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs @@ -56,6 +56,10 @@ public void TestECPointConstructor() point.X.Should().Be(X); point.Y.Should().Be(Y); point.Curve.Should().Be(ECCurve.Secp256k1); + Action action = () => new ECPoint(X, null, ECCurve.Secp256k1); + action.ShouldThrow(); + action = () => new ECPoint(null, Y, ECCurve.Secp256k1); + action.ShouldThrow(); } [TestMethod] @@ -145,6 +149,30 @@ public void TestEquals() point1.Equals(point3).Should().BeFalse(); } + [TestMethod] + public void TestEqualsObject() + { + object point = ECCurve.Secp256k1.G; + point.Equals(point).Should().BeTrue(); + point.Equals(null).Should().BeFalse(); + point.Equals(1u).Should().BeFalse(); + + point = new ECPoint(null, null, ECCurve.Secp256k1); + point.Equals(new ECPoint(null, null, ECCurve.Secp256r1)).Should().BeTrue(); + point.Equals(ECCurve.Secp256r1.G).Should().BeFalse(); + ECCurve.Secp256r1.G.Equals(point).Should().BeFalse(); + + ECFieldElement X1 = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1); + ECFieldElement Y1 = new ECFieldElement(new BigInteger(200), ECCurve.Secp256k1); + ECFieldElement X2 = new ECFieldElement(new BigInteger(300), ECCurve.Secp256k1); + ECFieldElement Y2 = new ECFieldElement(new BigInteger(400), ECCurve.Secp256k1); + object point1 = new ECPoint(X1, Y1, ECCurve.Secp256k1); + object point2 = new ECPoint(X2, Y1, ECCurve.Secp256k1); + object point3 = new ECPoint(X1, Y2, ECCurve.Secp256k1); + point1.Equals(point2).Should().BeFalse(); + point1.Equals(point3).Should().BeFalse(); + } + [TestMethod] public void TestFromBytes() { @@ -176,6 +204,13 @@ public void TestFromBytes() ECCurve.Secp256k1), ECCurve.Secp256k1)); } + [TestMethod] + public void TestGetSize() + { + ECCurve.Secp256k1.G.Size.Should().Be(33); + ECCurve.Secp256k1.Infinity.Size.Should().Be(1); + } + [TestMethod] public void TestMultiply() { @@ -279,6 +314,13 @@ public void TestOpMultiply() new ECFieldElement(BigInteger.Parse("29236048674093813394523910922582374630829081423043497254162533033164154049666"), ECCurve.Secp256k1), ECCurve.Secp256k1)); } + [TestMethod] + public void TestOpSubtraction() + { + (ECCurve.Secp256k1.G - ECCurve.Secp256k1.Infinity).Should().Be(ECCurve.Secp256k1.G); + (ECCurve.Secp256k1.G - ECCurve.Secp256k1.G).Should().Be(ECCurve.Secp256k1.Infinity); + } + [TestMethod] public void TestOpUnaryNegation() { diff --git a/neo.UnitTests/Cryptography/UT_MerkleTree.cs b/neo.UnitTests/Cryptography/UT_MerkleTree.cs new file mode 100644 index 0000000000..3edf6b4a8b --- /dev/null +++ b/neo.UnitTests/Cryptography/UT_MerkleTree.cs @@ -0,0 +1,80 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_MerkleTree + { + public UInt256 GetByteArrayHash(byte[] byteArray) + { + if(byteArray == null || byteArray.Length == 0) throw new ArgumentNullException(); + var hash = new UInt256(Crypto.Default.Hash256(byteArray)); + return hash; + } + + [TestMethod] + public void TestBuildAndDepthFirstSearch() + { + IReadOnlyList hashNull = new UInt256[] { }; + Action action = () => new MerkleTree(hashNull); + action.ShouldThrow(); + + byte[] array1 = { 0x01 }; + var hash1 = GetByteArrayHash(array1); + + byte[] array2 = { 0x02 }; + var hash2 = GetByteArrayHash(array2); + + byte[] array3 = { 0x03 }; + var hash3 = GetByteArrayHash(array3); + + IReadOnlyList hashes = new UInt256[] { hash1, hash2, hash3 }; + MerkleTree tree = new MerkleTree(hashes); + var hashArray = tree.ToHashArray(); + hashArray[0].Should().Be(hash1); + hashArray[1].Should().Be(hash2); + hashArray[2].Should().Be(hash3); + hashArray[3].Should().Be(hash3); + + var rootHash = MerkleTree.ComputeRoot(hashes); + var hash4 = Crypto.Default.Hash256(hash1.ToArray().Concat(hash2.ToArray()).ToArray()); + var hash5 = Crypto.Default.Hash256(hash3.ToArray().Concat(hash3.ToArray()).ToArray()); + var result = new UInt256(Crypto.Default.Hash256(hash4.ToArray().Concat(hash5.ToArray()).ToArray())); + rootHash.Should().Be(result); + } + + [TestMethod] + public void TestTrim() + { + byte[] array1 = { 0x01 }; + var hash1 = GetByteArrayHash(array1); + + byte[] array2 = { 0x02 }; + var hash2 = GetByteArrayHash(array2); + + byte[] array3 = { 0x03 }; + var hash3 = GetByteArrayHash(array3); + + IReadOnlyList hashes = new UInt256[] { hash1, hash2, hash3 }; + MerkleTree tree = new MerkleTree(hashes); + + bool[] boolArray = { false, false, false }; + BitArray bitArray = new BitArray(boolArray); + tree.Trim(bitArray); + var hashArray = tree.ToHashArray(); + + hashArray.Length.Should().Be(1); + var rootHash = MerkleTree.ComputeRoot(hashes); + var hash4 = Crypto.Default.Hash256(hash1.ToArray().Concat(hash2.ToArray()).ToArray()); + var hash5 = Crypto.Default.Hash256(hash3.ToArray().Concat(hash3.ToArray()).ToArray()); + var result = new UInt256(Crypto.Default.Hash256(hash4.ToArray().Concat(hash5.ToArray()).ToArray())); + hashArray[0].Should().Be(result); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs b/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs new file mode 100644 index 0000000000..48fd05745d --- /dev/null +++ b/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs @@ -0,0 +1,51 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using System.Text; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_MerkleTreeNode + { + private MerkleTreeNode node = new MerkleTreeNode(); + + [TestInitialize] + public void TestSetup() + { + node.Hash = null; + node.Parent = null; + node.LeftChild = null; + node.RightChild = null; + } + + [TestMethod] + public void TestConstructor() + { + byte[] byteArray = Encoding.ASCII.GetBytes("hello world"); + var hash = new UInt256(Crypto.Default.Hash256(byteArray)); + node.Hash = hash; + + node.Hash.Should().Be(hash); + node.Parent.Should().BeNull(); + node.LeftChild.Should().BeNull(); + node.RightChild.Should().BeNull(); + } + + [TestMethod] + public void TestGetIsLeaf() + { + node.IsLeaf.Should().BeTrue(); + + MerkleTreeNode child = new MerkleTreeNode(); + node.LeftChild = child; + node.IsLeaf.Should().BeFalse(); + } + + [TestMethod] + public void TestGetIsRoot() + { + node.IsRoot.Should().BeTrue(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/UT_Murmur3.cs b/neo.UnitTests/Cryptography/UT_Murmur3.cs new file mode 100644 index 0000000000..c59a53645a --- /dev/null +++ b/neo.UnitTests/Cryptography/UT_Murmur3.cs @@ -0,0 +1,24 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_Murmur3 + { + [TestMethod] + public void TestGetHashSize() + { + Murmur3 murmur3 = new Murmur3(1); + murmur3.HashSize.Should().Be(32); + } + + [TestMethod] + public void TestHashCore() + { + byte[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1 }; + array.Murmur32(10u).Should().Be(378574820u); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Cryptography/UT_Scrypt.cs b/neo.UnitTests/Cryptography/UT_SCrypt.cs similarity index 93% rename from neo.UnitTests/Cryptography/UT_Scrypt.cs rename to neo.UnitTests/Cryptography/UT_SCrypt.cs index 8ec603da48..afe41bf475 100644 --- a/neo.UnitTests/Cryptography/UT_Scrypt.cs +++ b/neo.UnitTests/Cryptography/UT_SCrypt.cs @@ -1,11 +1,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; -using System; namespace Neo.UnitTests.Cryptography { [TestClass] - public class UT_Scrypt + public class UT_SCrypt { [TestMethod] public void DeriveKeyTest() From 2cf115988b1e6336833114bcd19afef739625fea Mon Sep 17 00:00:00 2001 From: erikzhang Date: Mon, 29 Jul 2019 23:44:55 +0800 Subject: [PATCH 09/54] Fix `System.Contract.Call` --- neo/SmartContract/InteropService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index fbb3a8655d..c4daa8a89b 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -54,7 +54,7 @@ public static partial class InteropService public static readonly uint System_Block_GetTransactions = Register("System.Block.GetTransactions", Block_GetTransactions, 0_00010000, TriggerType.Application); public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, TriggerType.Application); public static readonly uint System_Transaction_GetHash = Register("System.Transaction.GetHash", Transaction_GetHash, 0_00000400, TriggerType.All); - public static readonly uint System_Contract_Call = Register("System.Contract.Call", Contract_Call, 0_01000000, TriggerType.Application); + public static readonly uint System_Contract_Call = Register("System.Contract.Call", Contract_Call, 0_01000000, TriggerType.System | TriggerType.Application); public static readonly uint System_Contract_Destroy = Register("System.Contract.Destroy", Contract_Destroy, 0_01000000, TriggerType.Application); public static readonly uint System_Storage_GetContext = Register("System.Storage.GetContext", Storage_GetContext, 0_00000400, TriggerType.Application); public static readonly uint System_Storage_GetReadOnlyContext = Register("System.Storage.GetReadOnlyContext", Storage_GetReadOnlyContext, 0_00000400, TriggerType.Application); From 9e2faf5267a81182f276d27d7b680643ef06ff57 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Mon, 29 Jul 2019 23:57:24 +0800 Subject: [PATCH 10/54] Fix ProtocolSettings.cs --- neo/ProtocolSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/ProtocolSettings.cs b/neo/ProtocolSettings.cs index 478d5b71b3..381e56c8a7 100644 --- a/neo/ProtocolSettings.cs +++ b/neo/ProtocolSettings.cs @@ -71,7 +71,7 @@ private ProtocolSettings(IConfigurationSection section) "seed4.neo.org:10333", "seed5.neo.org:10333" }; - this.MillisecondsPerBlock = section.GetValue("SecondsPerBlock", 15000u); + this.MillisecondsPerBlock = section.GetValue("MillisecondsPerBlock", 15000u); this.MemoryPoolMaxTransactions = Math.Max(1, section.GetValue("MemoryPoolMaxTransactions", 50_000)); } } From 547234a14ad7d380ff7ef548ee23a19b6557aadd Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Tue, 30 Jul 2019 13:00:52 +0800 Subject: [PATCH 11/54] Fixes #946 (#950) --- neo.UnitTests/IO/UT_IOHelper.cs | 12 +-- neo.UnitTests/UT_DataCache.cs | 126 ++++++++++++++++++++++++ neo/IO/ByteArrayComparer.cs | 21 ++++ neo/IO/Caching/DataCache.cs | 54 ++++++++-- neo/IO/Helper.cs | 13 ++- neo/SmartContract/InteropService.NEO.cs | 2 +- 6 files changed, 208 insertions(+), 20 deletions(-) create mode 100644 neo.UnitTests/UT_DataCache.cs create mode 100644 neo/IO/ByteArrayComparer.cs diff --git a/neo.UnitTests/IO/UT_IOHelper.cs b/neo.UnitTests/IO/UT_IOHelper.cs index e113ce8cd4..b0593c02ec 100644 --- a/neo.UnitTests/IO/UT_IOHelper.cs +++ b/neo.UnitTests/IO/UT_IOHelper.cs @@ -234,9 +234,9 @@ public void TestReadBytesWithGrouping() else { byte[] caseArray = new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x10, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x10, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x11}; MemoryStream stream = new MemoryStream(); @@ -415,11 +415,11 @@ public void TestWriteBytesWithGrouping() byte[] byteArray = new byte[stream.Length]; stream.Read(byteArray, 0, (int)stream.Length); Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x10, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, - 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x10, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x0C}), Encoding.Default.GetString(byteArray)); + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x04}), Encoding.Default.GetString(byteArray)); } [TestMethod] @@ -546,4 +546,4 @@ public void TestWriteVarString() Assert.AreEqual(0x61, byteArray[1]); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/UT_DataCache.cs b/neo.UnitTests/UT_DataCache.cs new file mode 100644 index 0000000000..85df272db5 --- /dev/null +++ b/neo.UnitTests/UT_DataCache.cs @@ -0,0 +1,126 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Caching; +using Neo.Ledger; +using System.Linq; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_DataCache + { + [TestInitialize] + public void TestSetup() + { + TestBlockchain.InitializeMockNeoSystem(); + } + + [TestMethod] + public void TestCachedFind_Between() + { + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + var storages = snapshot.Storages; + var cache = new CloneCache(storages); + + storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero); + + storages.Add + ( + new StorageKey() { Key = new byte[] { 0x01, 0x01 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + storages.Add + ( + new StorageKey() { Key = new byte[] { 0x00, 0x01 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + storages.Add + ( + new StorageKey() { Key = new byte[] { 0x00, 0x03 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + cache.Add + ( + new StorageKey() { Key = new byte[] { 0x01, 0x02 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + cache.Add + ( + new StorageKey() { Key = new byte[] { 0x00, 0x02 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + + CollectionAssert.AreEqual( + cache.Find(new byte[21]).Select(u => u.Key.Key[1]).ToArray(), + new byte[] { 0x01, 0x02, 0x03 } + ); + + storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero); + } + + [TestMethod] + public void TestCachedFind_Last() + { + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + var storages = snapshot.Storages; + var cache = new CloneCache(storages); + + storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero); + + storages.Add + ( + new StorageKey() { Key = new byte[] { 0x00, 0x01 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + storages.Add + ( + new StorageKey() { Key = new byte[] { 0x01, 0x01 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + cache.Add + ( + new StorageKey() { Key = new byte[] { 0x00, 0x02 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + cache.Add + ( + new StorageKey() { Key = new byte[] { 0x01, 0x02 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + + CollectionAssert.AreEqual( + cache.Find(new byte[21]).Select(u => u.Key.Key[1]).ToArray(), + new byte[] { 0x01, 0x02 } + ); + + storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero); + } + + [TestMethod] + public void TestCachedFind_Empty() + { + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + var storages = snapshot.Storages; + var cache = new CloneCache(storages); + + storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero); + + cache.Add + ( + new StorageKey() { Key = new byte[] { 0x00, 0x02 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + cache.Add + ( + new StorageKey() { Key = new byte[] { 0x01, 0x02 }, ScriptHash = UInt160.Zero }, + new StorageItem() { IsConstant = false, Value = new byte[] { } } + ); + + CollectionAssert.AreEqual( + cache.Find(new byte[21]).Select(u => u.Key.Key[1]).ToArray(), + new byte[] { 0x02 } + ); + + storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero); + } + } +} diff --git a/neo/IO/ByteArrayComparer.cs b/neo/IO/ByteArrayComparer.cs new file mode 100644 index 0000000000..956ab758e6 --- /dev/null +++ b/neo/IO/ByteArrayComparer.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace Neo.IO +{ + internal class ByteArrayComparer : IComparer + { + public static readonly ByteArrayComparer Default = new ByteArrayComparer(); + + public int Compare(byte[] x, byte[] y) + { + int length = Math.Min(x.Length, y.Length); + for (int i = 0; i < length; i++) + { + int r = x[i].CompareTo(y[i]); + if (r != 0) return r; + } + return x.Length.CompareTo(y.Length); + } + } +} diff --git a/neo/IO/Caching/DataCache.cs b/neo/IO/Caching/DataCache.cs index 5e9886d10c..278c01d650 100644 --- a/neo/IO/Caching/DataCache.cs +++ b/neo/IO/Caching/DataCache.cs @@ -118,16 +118,58 @@ public void DeleteWhere(Func predicate) } } + /// + /// Find the entries that start with the `key_prefix` + /// + /// Must maintain the deserialized format of TKey + /// Entries found with the desired prefix public IEnumerable> Find(byte[] key_prefix = null) { + IEnumerable<(byte[], TKey, TValue)> cached; lock (dictionary) { - foreach (var pair in FindInternal(key_prefix ?? new byte[0])) - if (!dictionary.ContainsKey(pair.Key)) - yield return pair; - foreach (var pair in dictionary) - if (pair.Value.State != TrackState.Deleted && (key_prefix == null || pair.Key.ToArray().Take(key_prefix.Length).SequenceEqual(key_prefix))) - yield return new KeyValuePair(pair.Key, pair.Value.Item); + cached = dictionary + .Where(p => p.Value.State != TrackState.Deleted && (key_prefix == null || p.Key.ToArray().Take(key_prefix.Length).SequenceEqual(key_prefix))) + .Select(p => + ( + KeyBytes: p.Key.ToArray(), + p.Key, + p.Value.Item + )) + .OrderBy(p => p.KeyBytes, ByteArrayComparer.Default) + .ToArray(); + } + var uncached = FindInternal(key_prefix ?? new byte[0]) + .Where(p => !dictionary.ContainsKey(p.Key)) + .Select(p => + ( + KeyBytes: p.Key.ToArray(), + p.Key, + p.Value + )); + using (var e1 = cached.GetEnumerator()) + using (var e2 = uncached.GetEnumerator()) + { + (byte[] KeyBytes, TKey Key, TValue Item) i1, i2; + bool c1 = e1.MoveNext(); + bool c2 = e2.MoveNext(); + i1 = c1 ? e1.Current : default; + i2 = c2 ? e2.Current : default; + while (c1 || c2) + { + if (!c2 || (c1 && ByteArrayComparer.Default.Compare(i1.KeyBytes, i2.KeyBytes) < 0)) + { + yield return new KeyValuePair(i1.Key, i1.Item); + c1 = e1.MoveNext(); + i1 = c1 ? e1.Current : default; + } + else + { + yield return new KeyValuePair(i2.Key, i2.Item); + c2 = e2.MoveNext(); + i2 = c2 ? e2.Current : default; + } + } } } diff --git a/neo/IO/Helper.cs b/neo/IO/Helper.cs index 647ae2cfb1..a306e297d5 100644 --- a/neo/IO/Helper.cs +++ b/neo/IO/Helper.cs @@ -92,17 +92,16 @@ public static byte[] ReadBytesWithGrouping(this BinaryReader reader) { using (MemoryStream ms = new MemoryStream()) { - int padding = 0; + int count; do { byte[] group = reader.ReadBytes(GroupingSizeInBytes); - padding = reader.ReadByte(); - if (padding > GroupingSizeInBytes) + count = reader.ReadByte(); + if (count > GroupingSizeInBytes) throw new FormatException(); - int count = GroupingSizeInBytes - padding; if (count > 0) ms.Write(group, 0, count); - } while (padding == 0); + } while (count == GroupingSizeInBytes); return ms.ToArray(); } } @@ -200,7 +199,7 @@ public static void WriteBytesWithGrouping(this BinaryWriter writer, byte[] value while (remain >= GroupingSizeInBytes) { writer.Write(value, index, GroupingSizeInBytes); - writer.Write((byte)0); + writer.Write((byte)GroupingSizeInBytes); index += GroupingSizeInBytes; remain -= GroupingSizeInBytes; } @@ -209,7 +208,7 @@ public static void WriteBytesWithGrouping(this BinaryWriter writer, byte[] value int padding = GroupingSizeInBytes - remain; for (int i = 0; i < padding; i++) writer.Write((byte)0); - writer.Write((byte)padding); + writer.Write((byte)remain); } public static void WriteFixedString(this BinaryWriter writer, string value, int length) diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index 5787cebdb4..669a9b7073 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -353,7 +353,7 @@ private static bool Storage_Find(ApplicationEngine engine) while (remain >= 16) { ms.Write(prefix, index, 16); - ms.WriteByte(0); + ms.WriteByte(16); index += 16; remain -= 16; } From cd994894acce73a871dccdf2ba6c2f0d598ec1b8 Mon Sep 17 00:00:00 2001 From: Krain Chen Date: Tue, 30 Jul 2019 22:20:55 +0800 Subject: [PATCH 12/54] Add NEO SDK RPC module (#850) * Add NEO SDK based on RPC client * add rpc interface methods for neo3 * update unit test * add unit test * Update TransactionHelper.cs Changed for neo 3.0, not final yet. * implement sdk rpc client methods * backup files * change class name * remove uncompleted modules for pull request * change json deserialize method with Neo JObject * modified JSON implementation, added FromJson() * more RPC change * PR correction * RPC module fix, remove newton.json * fix * fix getblock issue * PR correction * PR Correction * PR Correction: rename RPC models * PR Correction * resolve conflicts * Clean code * Clean code * Clean code * Clean code * Update RpcValidateAddressResult.cs * Clean code * PR correction * Move test file to the right place --- neo.UnitTests/Network/RPC/UT_RpcClient.cs | 540 ++++++++++++++++++ neo/Ledger/ContractState.cs | 8 + neo/Network/P2P/Payloads/Block.cs | 11 + neo/Network/P2P/Payloads/BlockBase.cs | 16 +- neo/Network/P2P/Payloads/ConsensusData.cs | 10 + neo/Network/P2P/Payloads/Header.cs | 14 +- neo/Network/P2P/Payloads/Transaction.cs | 15 + .../P2P/Payloads/TransactionAttribute.cs | 8 + neo/Network/P2P/Payloads/Witness.cs | 8 + neo/Network/RPC/Models/RpcBlock.cs | 37 ++ neo/Network/RPC/Models/RpcBlockHeader.cs | 37 ++ neo/Network/RPC/Models/RpcInvokeResult.cs | 69 +++ neo/Network/RPC/Models/RpcNep5Balances.cs | 57 ++ neo/Network/RPC/Models/RpcPeers.cs | 55 ++ neo/Network/RPC/Models/RpcPlugin.cs | 32 ++ neo/Network/RPC/Models/RpcRawMemPool.cs | 32 ++ neo/Network/RPC/Models/RpcRequest.cs | 37 ++ neo/Network/RPC/Models/RpcResponse.cs | 72 +++ neo/Network/RPC/Models/RpcTransaction.cs | 41 ++ .../RPC/Models/RpcValidateAddressResult.cs | 27 + neo/Network/RPC/Models/RpcValidator.cs | 32 ++ neo/Network/RPC/Models/RpcVersion.cs | 35 ++ neo/Network/RPC/RpcClient.cs | 292 ++++++++++ 23 files changed, 1482 insertions(+), 3 deletions(-) create mode 100644 neo.UnitTests/Network/RPC/UT_RpcClient.cs create mode 100644 neo/Network/RPC/Models/RpcBlock.cs create mode 100644 neo/Network/RPC/Models/RpcBlockHeader.cs create mode 100644 neo/Network/RPC/Models/RpcInvokeResult.cs create mode 100644 neo/Network/RPC/Models/RpcNep5Balances.cs create mode 100644 neo/Network/RPC/Models/RpcPeers.cs create mode 100644 neo/Network/RPC/Models/RpcPlugin.cs create mode 100644 neo/Network/RPC/Models/RpcRawMemPool.cs create mode 100644 neo/Network/RPC/Models/RpcRequest.cs create mode 100644 neo/Network/RPC/Models/RpcResponse.cs create mode 100644 neo/Network/RPC/Models/RpcTransaction.cs create mode 100644 neo/Network/RPC/Models/RpcValidateAddressResult.cs create mode 100644 neo/Network/RPC/Models/RpcValidator.cs create mode 100644 neo/Network/RPC/Models/RpcVersion.cs create mode 100644 neo/Network/RPC/RpcClient.cs diff --git a/neo.UnitTests/Network/RPC/UT_RpcClient.cs b/neo.UnitTests/Network/RPC/UT_RpcClient.cs new file mode 100644 index 0000000000..955c481248 --- /dev/null +++ b/neo.UnitTests/Network/RPC/UT_RpcClient.cs @@ -0,0 +1,540 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Moq.Protected; +using Neo.IO; +using Neo.IO.Json; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.Network.RPC; +using Neo.Network.RPC.Models; +using Neo.SmartContract; +using Neo.SmartContract.Manifest; +using Neo.VM; +using System; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Neo.UnitTests.Network.RPC +{ + [TestClass] + public class UT_RpcClient + { + RpcClient rpc; + Mock handlerMock; + + [TestInitialize] + public void TestSetup() + { + handlerMock = new Mock(MockBehavior.Strict); + + // use real http client with mocked handler here + var httpClient = new HttpClient(handlerMock.Object) + { + BaseAddress = new Uri("http://seed1.neo.org:10331"), + }; + + rpc = new RpcClient(httpClient); + } + + private void MockResponse(string content) + { + handlerMock.Protected() + // Setup the PROTECTED method to mock + .Setup>( + "SendAsync", + ItExpr.IsAny(), + ItExpr.IsAny() + ) + // prepare the expected response of the mocked http call + .ReturnsAsync(new HttpResponseMessage() + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(content), + }) + .Verifiable(); + } + + private JObject CreateErrorResponse(JObject id, int code, string message, JObject data = null) + { + JObject response = CreateResponse(id); + response["error"] = new JObject(); + response["error"]["code"] = code; + response["error"]["message"] = message; + if (data != null) + response["error"]["data"] = data; + return response; + } + + private JObject CreateResponse(JObject id) + { + JObject response = new JObject(); + response["jsonrpc"] = "2.0"; + response["id"] = id; + return response; + } + + [TestMethod] + public void TestErrorResponse() + { + JObject response = CreateErrorResponse(null, -32700, "Parse error"); + MockResponse(response.ToString()); + try + { + var result = rpc.GetBlockHex("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e"); + } + catch (RpcException ex) + { + Assert.AreEqual(-32700, ex.HResult); + Assert.AreEqual("Parse error", ex.Message); + } + } + + [TestMethod] + public void TestGetBestBlockHash() + { + JObject response = CreateResponse(1); + response["result"] = "000000002deadfa82cbc4682f5800"; + MockResponse(response.ToString()); + + var result = rpc.GetBestBlockHash(); + Assert.AreEqual("000000002deadfa82cbc4682f5800", result); + } + + [TestMethod] + public void TestGetBlockHex() + { + JObject response = CreateResponse(1); + response["result"] = "000000002deadfa82cbc4682f5800"; + MockResponse(response.ToString()); + + var result = rpc.GetBlockHex("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e"); + Assert.AreEqual("000000002deadfa82cbc4682f5800", result); + } + + [TestMethod] + public void TestGetBlock() + { + // create block + var block = new Block(); + TestUtils.SetupBlockWithValues(block, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, 0); + + block.Transactions = new[] + { + TestUtils.GetTransaction(), + TestUtils.GetTransaction(), + TestUtils.GetTransaction() + }; + + JObject json = block.ToJson(); + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.GetBlock("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e"); + Assert.AreEqual(block.Hash.ToString(), result.Block.Hash.ToString()); + Assert.IsNull(result.Confirmations); + Assert.AreEqual(block.Transactions.Length, result.Block.Transactions.Length); + Assert.AreEqual(block.Transactions[0].Hash.ToString(), result.Block.Transactions[0].Hash.ToString()); + + // verbose with confirmations + json["confirmations"] = 20; + json["nextblockhash"] = "773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e"; + MockResponse(response.ToString()); + result = rpc.GetBlock("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e"); + Assert.AreEqual(block.Hash.ToString(), result.Block.Hash.ToString()); + Assert.AreEqual(20, result.Confirmations); + Assert.AreEqual(block.Transactions.Length, result.Block.Transactions.Length); + Assert.AreEqual(block.Transactions[0].Hash.ToString(), result.Block.Transactions[0].Hash.ToString()); + } + + [TestMethod] + public void TestGetBlockCount() + { + JObject response = CreateResponse(1); + response["result"] = 100; + MockResponse(response.ToString()); + + var result = rpc.GetBlockCount(); + Assert.AreEqual(100, result); + } + + [TestMethod] + public void TestGetBlockHash() + { + JObject response = CreateResponse(1); + response["result"] = "0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2"; + MockResponse(response.ToString()); + + var result = rpc.GetBlockHash(100); + Assert.AreEqual("0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2", result); + } + + [TestMethod] + public void TestGetBlockHeaderHex() + { + JObject response = CreateResponse(1); + response["result"] = "0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2"; + MockResponse(response.ToString()); + + var result = rpc.GetBlockHeaderHex("100"); + Assert.AreEqual("0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2", result); + } + + [TestMethod] + public void TestGetBlockHeader() + { + Header header = new Header(); + TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal); + + JObject json = header.ToJson(); + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.GetBlockHeader("100"); + Assert.AreEqual(header.Hash.ToString(), result.Header.Hash.ToString()); + Assert.IsNull(result.Confirmations); + + json["confirmations"] = 20; + json["nextblockhash"] = "4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2"; + MockResponse(response.ToString()); + result = rpc.GetBlockHeader("100"); + Assert.AreEqual(header.Hash.ToString(), result.Header.Hash.ToString()); + Assert.AreEqual(20, result.Confirmations); + } + + [TestMethod] + public void TestGetBlockSysFee() + { + JObject response = CreateResponse(1); + response["result"] = "195500"; + MockResponse(response.ToString()); + + var result = rpc.GetBlockSysFee(100); + Assert.AreEqual("195500", result); + } + + [TestMethod] + public void TestGetConnectionCount() + { + JObject response = CreateResponse(1); + response["result"] = 9; + MockResponse(response.ToString()); + + var result = rpc.GetConnectionCount(); + Assert.AreEqual(9, result); + } + + [TestMethod] + public void TestGetContractState() + { + var sb = new ScriptBuilder(); + sb.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); + + ContractState state = new ContractState + { + Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(sb.ToArray()).ToArray(), + Manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")) + }; + + JObject response = CreateResponse(1); + response["result"] = state.ToJson(); + MockResponse(response.ToString()); + + var result = rpc.GetContractState("17694b31cc7ee215cea2ded146e0b2b28768fc46"); + + Assert.AreEqual(state.Script.ToHexString(), result.Script.ToHexString()); + Assert.AreEqual(state.Manifest.Abi.EntryPoint.Name, result.Manifest.Abi.EntryPoint.Name); + } + + [TestMethod] + public void TestGetPeers() + { + JObject response = CreateResponse(1); + response["result"] = JObject.Parse(@"{ + ""unconnected"": [ + { + ""address"": ""::ffff:70.73.16.236"", + ""port"": 10333 + }, + { + ""address"": ""::ffff:82.95.77.148"", + ""port"": 10333 + }, + { + ""address"": ""::ffff:49.50.215.166"", + ""port"": 10333 + } + ], + ""bad"": [], + ""connected"": [ + { + ""address"": ""::ffff:139.219.106.33"", + ""port"": 10333 + }, + { + ""address"": ""::ffff:47.88.53.224"", + ""port"": 10333 + } + ] + }"); + MockResponse(response.ToString()); + + var result = rpc.GetPeers(); + Assert.AreEqual("::ffff:139.219.106.33", result.Connected[0].Address); + Assert.AreEqual("::ffff:82.95.77.148", result.Unconnected[1].Address); + } + + [TestMethod] + public void TestGetRawMempool() + { + JObject response = CreateResponse(1); + response["result"] = JObject.Parse(@"[ + ""0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e"", + ""0xb488ad25eb474f89d5ca3f985cc047ca96bc7373a6d3da8c0f192722896c1cd7"", + ""0xf86f6f2c08fbf766ebe59dc84bc3b8829f1053f0a01deb26bf7960d99fa86cd6"" + ]"); + MockResponse(response.ToString()); + + var result = rpc.GetRawMempool(); + Assert.AreEqual("0xb488ad25eb474f89d5ca3f985cc047ca96bc7373a6d3da8c0f192722896c1cd7", result[1]); + } + + [TestMethod] + public void TestGetRawMempoolBoth() + { + JObject json = new JObject(); + json["height"] = 65535; + json["verified"] = new JArray(new[] { "0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e" }.Select(p => (JObject)p)); + json["unverified"] = new JArray(new[] { "0xb488ad25eb474f89d5ca3f985cc047ca96bc7373a6d3da8c0f192722896c1cd7", "0xf86f6f2c08fbf766ebe59dc84bc3b8829f1053f0a01deb26bf7960d99fa86cd6" }.Select(p => (JObject)p)); + + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.GetRawMempoolBoth(); + Assert.AreEqual((uint)65535, result.Height); + Assert.AreEqual("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e", result.Verified[0]); + Assert.AreEqual("0xf86f6f2c08fbf766ebe59dc84bc3b8829f1053f0a01deb26bf7960d99fa86cd6", result.UnVerified[1]); + } + + [TestMethod] + public void TestGetRawTransactionHex() + { + var json = TestUtils.GetTransaction().ToArray().ToHexString(); + + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + //var result = rpc.GetRawTransactionHex("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e"); + var result = rpc.GetRawTransactionHex(TestUtils.GetTransaction().Hash.ToString()); + Assert.AreEqual(json, result); + } + + [TestMethod] + public void TestGetRawTransaction() + { + var transaction = TestUtils.GetTransaction(); + JObject json = transaction.ToJson(); + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.GetRawTransaction("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e"); + Assert.AreEqual(transaction.Hash, result.Transaction.Hash); + Assert.AreEqual(json.ToString(), result.ToJson().ToString()); + + json["blockhash"] = UInt256.Zero.ToString(); + json["confirmations"] = 100; + json["blocktime"] = 10; + MockResponse(response.ToString()); + + result = rpc.GetRawTransaction("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e"); + Assert.AreEqual(transaction.Hash, result.Transaction.Hash); + Assert.AreEqual(100, result.Confirmations); + Assert.AreEqual(json.ToString(), result.ToJson().ToString()); + } + + [TestMethod] + public void TestGetStorage() + { + JObject json = "4c696e"; + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.GetStorage("03febccf81ac85e3d795bc5cbd4e84e907812aa3", "5065746572"); + Assert.AreEqual("4c696e", result); + } + + [TestMethod] + public void TestGetTransactionHeight() + { + JObject json = 10000; + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.GetTransactionHeight("9c909e1e3ba03290553a68d862e002c7a21ba302e043fc492fe069bf6a134d29"); + Assert.AreEqual(json.ToString(), result.ToString()); + } + + [TestMethod] + public void TestGetValidators() + { + JObject json = JObject.Parse(@"[ + { + ""publickey"": ""02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70"", + ""votes"": ""46632420"", + ""active"": true + }, + { + ""publickey"": ""024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d"", + ""votes"": ""46632420"", + ""active"": true + } + ]"); + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.GetValidators(); + Assert.AreEqual(((JArray)json)[0].ToString(), (result[0]).ToJson().ToString()); + } + + [TestMethod] + public void TestGetVersion() + { + JObject json = new JObject(); + json["tcpPort"] = 30001; + json["wsPort"] = 30002; + json["nonce"] = 1546258664; + json["useragent"] = "/NEO:2.7.5/"; + + var json1 = JObject.Parse(@"{ + ""tcpPort"": 30001, + ""wsPort"": 30002, + ""nonce"": 1546258664, + ""useragent"": ""/NEO:2.7.5/"" + }"); + Assert.AreEqual(json.ToString(), json1.ToString()); + + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.GetVersion(); + Assert.AreEqual(30001, result.TcpPort); + Assert.AreEqual("/NEO:2.7.5/", result.UserAgent); + } + + [TestMethod] + public void TestInvokeFunction() + { + JObject json = JObject.Parse(@" + { + ""script"": ""1426ae7c6c9861ec418468c1f0fdc4a7f2963eb89151c10962616c616e63654f6667be39e7b562f60cbfe2aebca375a2e5ee28737caf"", + ""state"": ""HALT"", + ""gas_consumed"": ""0.311"", + ""stack"": [ + { + ""type"": ""ByteArray"", + ""value"": ""262bec084432"" + } + ], + ""tx"":""d101361426ae7c6c9861ec418468c1f0fdc4a7f2963eb89151c10962616c616e63654f6667be39e7b562f60cbfe2aebca375a2e5ee28737caf000000000000000000000000"" + }"); + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.InvokeFunction("af7c7328eee5a275a3bcaee2bf0cf662b5e739be", "balanceOf", new[] { new RpcStack { Type = "Hash160", Value = "91b83e96f2a7c4fdf0c1688441ec61986c7cae26" } }); + Assert.AreEqual(json.ToString(), result.ToJson().ToString()); + } + + [TestMethod] + public void TestInvokeScript() + { + JObject json = JObject.Parse(@" + { + ""script"": ""1426ae7c6c9861ec418468c1f0fdc4a7f2963eb89151c10962616c616e63654f6667be39e7b562f60cbfe2aebca375a2e5ee28737caf"", + ""state"": ""HALT"", + ""gas_consumed"": ""0.311"", + ""stack"": [ + { + ""type"": ""ByteArray"", + ""value"": ""262bec084432"" + } + ], + ""tx"":""d101361426ae7c6c9861ec418468c1f0fdc4a7f2963eb89151c10962616c616e63654f6667be39e7b562f60cbfe2aebca375a2e5ee28737caf000000000000000000000000"" + }"); + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.InvokeScript("00046e616d656724058e5e1b6008847cd662728549088a9ee82191"); + Assert.AreEqual(json.ToString(), result.ToJson().ToString()); + } + + [TestMethod] + public void TestListPlugins() + { + JObject json = JObject.Parse(@"[{ + ""name"": ""SimplePolicyPlugin"", + ""version"": ""2.10.1.0"", + ""interfaces"": [ + ""ILogPlugin"", + ""IPolicyPlugin"" + ] + }]"); + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.ListPlugins(); + Assert.AreEqual(((JArray)json)[0].ToString(), result[0].ToJson().ToString()); + } + + [TestMethod] + public void TestSendRawTransaction() + { + JObject json = true; + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.SendRawTransaction("80000001195876cb34364dc38b730077156c6bc3a7fc570044a66fbfeeea56f71327e8ab0000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500c65eaf440000000f9a23e06f74cf86b8827a9108ec2e0f89ad956c9b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50092e14b5e00000030aab52ad93f6ce17ca07fa88fc191828c58cb71014140915467ecd359684b2dc358024ca750609591aa731a0b309c7fb3cab5cd0836ad3992aa0a24da431f43b68883ea5651d548feb6bd3c8e16376e6e426f91f84c58232103322f35c7819267e721335948d385fae5be66e7ba8c748ac15467dcca0693692dac"); + Assert.AreEqual(json.ToString(), ((JObject)result).ToString()); + } + + [TestMethod] + public void TestSubmitBlock() + { + JObject json = true; + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.SubmitBlock("03febccf81ac85e3d795bc5cbd4e84e907812aa3"); + Assert.AreEqual(json.ToString(), ((JObject)result).ToString()); + } + + [TestMethod] + public void TestValidateAddress() + { + JObject json = new JObject(); + json["address"] = "AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i"; + json["isvalid"] = false; + JObject response = CreateResponse(1); + response["result"] = json; + MockResponse(response.ToString()); + + var result = rpc.ValidateAddress("AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i"); + Assert.AreEqual(json.ToString(), result.ToJson().ToString()); + } + } +} diff --git a/neo/Ledger/ContractState.cs b/neo/Ledger/ContractState.cs index 8f97d4b363..da02db912f 100644 --- a/neo/Ledger/ContractState.cs +++ b/neo/Ledger/ContractState.cs @@ -64,5 +64,13 @@ public JObject ToJson() json["manifest"] = Manifest.ToJson(); return json; } + + public static ContractState FromJson(JObject json) + { + ContractState contractState = new ContractState(); + contractState.Script = json["script"].AsString().HexToBytes(); + contractState.Manifest = ContractManifest.FromJson(json["manifest"]); + return contractState; + } } } diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index 58faf54cb1..3f29bb9428 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -2,6 +2,7 @@ using Neo.IO; using Neo.IO.Json; using Neo.Ledger; +using Neo.Wallets; using System; using System.Collections.Generic; using System.IO; @@ -106,6 +107,16 @@ public override JObject ToJson() return json; } + public new static Block FromJson(JObject json) + { + Block block = new Block(); + BlockBase blockBase = block; + blockBase.FromJson(json); + block.ConsensusData = ConsensusData.FromJson(json["consensus_data"]); + block.Transactions = ((JArray)json["tx"]).Select(p => Transaction.FromJson(p)).ToArray(); + return block; + } + public TrimmedBlock Trim() { return new TrimmedBlock diff --git a/neo/Network/P2P/Payloads/BlockBase.cs b/neo/Network/P2P/Payloads/BlockBase.cs index 22ef72d021..8820c95538 100644 --- a/neo/Network/P2P/Payloads/BlockBase.cs +++ b/neo/Network/P2P/Payloads/BlockBase.cs @@ -6,6 +6,7 @@ using Neo.Wallets; using System; using System.IO; +using System.Linq; namespace Neo.Network.P2P.Payloads { @@ -32,7 +33,7 @@ public UInt256 Hash } } - public virtual int Size => + public virtual int Size => sizeof(uint) + //Version PrevHash.Size + //PrevHash MerkleRoot.Size + //MerkleRoot @@ -41,7 +42,7 @@ public UInt256 Hash NextConsensus.Size + //NextConsensus 1 + // Witness.Size; //Witness - + Witness[] IVerifiable.Witnesses { get @@ -111,6 +112,17 @@ public virtual JObject ToJson() return json; } + public void FromJson(JObject json) + { + Version = (uint)json["version"].AsNumber(); + PrevHash = UInt256.Parse(json["previousblockhash"].AsString()); + MerkleRoot = UInt256.Parse(json["merkleroot"].AsString()); + Timestamp = (ulong)json["time"].AsNumber(); + Index = (uint)json["index"].AsNumber(); + NextConsensus = json["nextconsensus"].AsString().ToScriptHash(); + Witness = ((JArray)json["witnesses"]).Select(p => Witness.FromJson(p)).FirstOrDefault(); + } + public virtual bool Verify(Snapshot snapshot) { Header prev_header = snapshot.GetHeader(PrevHash); diff --git a/neo/Network/P2P/Payloads/ConsensusData.cs b/neo/Network/P2P/Payloads/ConsensusData.cs index a48a8f1304..622c42e464 100644 --- a/neo/Network/P2P/Payloads/ConsensusData.cs +++ b/neo/Network/P2P/Payloads/ConsensusData.cs @@ -2,6 +2,7 @@ using Neo.IO; using Neo.IO.Json; using Neo.Ledger; +using System.Globalization; using System.IO; namespace Neo.Network.P2P.Payloads @@ -45,5 +46,14 @@ public JObject ToJson() json["nonce"] = Nonce.ToString("x16"); return json; } + + public static ConsensusData FromJson(JObject json) + { + ConsensusData block = new ConsensusData(); + block.PrimaryIndex = (uint)json["primary"].AsNumber(); + block.Nonce = ulong.Parse(json["nonce"].AsString(), NumberStyles.HexNumber); + return block; + } + } } diff --git a/neo/Network/P2P/Payloads/Header.cs b/neo/Network/P2P/Payloads/Header.cs index 149f4a020f..abd7fbd370 100644 --- a/neo/Network/P2P/Payloads/Header.cs +++ b/neo/Network/P2P/Payloads/Header.cs @@ -1,6 +1,9 @@ -using Neo.Ledger; +using Neo.IO.Json; +using Neo.Ledger; +using Neo.Wallets; using System; using System.IO; +using System.Linq; namespace Neo.Network.P2P.Payloads { @@ -51,5 +54,14 @@ public TrimmedBlock Trim() Hashes = new UInt256[0] }; } + + public new static Header FromJson(JObject json) + { + Header header = new Header(); + BlockBase blockBase = header; + blockBase.FromJson(json); + return header; + } + } } diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs index 923fe6447f..40efe0e9d3 100644 --- a/neo/Network/P2P/Payloads/Transaction.cs +++ b/neo/Network/P2P/Payloads/Transaction.cs @@ -177,6 +177,21 @@ public JObject ToJson() return json; } + public static Transaction FromJson(JObject json) + { + Transaction tx = new Transaction(); + tx.Version = byte.Parse(json["version"].AsString()); + tx.Nonce = uint.Parse(json["nonce"].AsString()); + tx.Sender = json["sender"].AsString().ToScriptHash(); + tx.SystemFee = long.Parse(json["sys_fee"].AsString()); + tx.NetworkFee = long.Parse(json["net_fee"].AsString()); + tx.ValidUntilBlock = uint.Parse(json["valid_until_block"].AsString()); + tx.Attributes = ((JArray)json["attributes"]).Select(p => TransactionAttribute.FromJson(p)).ToArray(); + tx.Script = json["script"].AsString().HexToBytes(); + tx.Witnesses = ((JArray)json["witnesses"]).Select(p => Witness.FromJson(p)).ToArray(); + return tx; + } + bool IInventory.Verify(Snapshot snapshot) { return Verify(snapshot, Enumerable.Empty()); diff --git a/neo/Network/P2P/Payloads/TransactionAttribute.cs b/neo/Network/P2P/Payloads/TransactionAttribute.cs index 2f384fa046..99d1671ebd 100644 --- a/neo/Network/P2P/Payloads/TransactionAttribute.cs +++ b/neo/Network/P2P/Payloads/TransactionAttribute.cs @@ -33,5 +33,13 @@ public JObject ToJson() json["data"] = Data.ToHexString(); return json; } + + public static TransactionAttribute FromJson(JObject json) + { + TransactionAttribute transactionAttribute = new TransactionAttribute(); + transactionAttribute.Usage = (TransactionAttributeUsage)(byte.Parse(json["usage"].AsString())); + transactionAttribute.Data = json["data"].AsString().HexToBytes(); + return transactionAttribute; + } } } diff --git a/neo/Network/P2P/Payloads/Witness.cs b/neo/Network/P2P/Payloads/Witness.cs index 237a954642..d352882e17 100644 --- a/neo/Network/P2P/Payloads/Witness.cs +++ b/neo/Network/P2P/Payloads/Witness.cs @@ -45,5 +45,13 @@ public JObject ToJson() json["verification"] = VerificationScript.ToHexString(); return json; } + + public static Witness FromJson(JObject json) + { + Witness witness = new Witness(); + witness.InvocationScript = json["invocation"].AsString().HexToBytes(); + witness.VerificationScript = json["verification"].AsString().HexToBytes(); + return witness; + } } } diff --git a/neo/Network/RPC/Models/RpcBlock.cs b/neo/Network/RPC/Models/RpcBlock.cs new file mode 100644 index 0000000000..0d49b3b53a --- /dev/null +++ b/neo/Network/RPC/Models/RpcBlock.cs @@ -0,0 +1,37 @@ +using Neo.IO.Json; +using Neo.Network.P2P.Payloads; + +namespace Neo.Network.RPC.Models +{ + public class RpcBlock + { + public Block Block { get; set; } + + public int? Confirmations { get; set; } + + public UInt256 NextBlockHash { get; set; } + + public JObject ToJson() + { + JObject json = Block.ToJson(); + if (Confirmations != null) + { + json["confirmations"] = Confirmations; + json["nextblockhash"] = NextBlockHash.ToString(); + } + return json; + } + + public static RpcBlock FromJson(JObject json) + { + RpcBlock block = new RpcBlock(); + block.Block = Block.FromJson(json); + if (json["confirmations"] != null) + { + block.Confirmations = (int)json["confirmations"].AsNumber(); + block.NextBlockHash = UInt256.Parse(json["nextblockhash"].AsString()); + } + return block; + } + } +} diff --git a/neo/Network/RPC/Models/RpcBlockHeader.cs b/neo/Network/RPC/Models/RpcBlockHeader.cs new file mode 100644 index 0000000000..250acfd818 --- /dev/null +++ b/neo/Network/RPC/Models/RpcBlockHeader.cs @@ -0,0 +1,37 @@ +using Neo.IO.Json; +using Neo.Network.P2P.Payloads; + +namespace Neo.Network.RPC.Models +{ + public class RpcBlockHeader + { + public Header Header { get; set; } + + public int? Confirmations { get; set; } + + public UInt256 NextBlockHash { get; set; } + + public JObject ToJson() + { + JObject json = Header.ToJson(); + if (Confirmations != null) + { + json["confirmations"] = Confirmations; + json["nextblockhash"] = NextBlockHash.ToString(); + } + return json; + } + + public static RpcBlockHeader FromJson(JObject json) + { + RpcBlockHeader block = new RpcBlockHeader(); + block.Header = Header.FromJson(json); + if (json["confirmations"] != null) + { + block.Confirmations = (int)json["confirmations"].AsNumber(); + block.NextBlockHash = UInt256.Parse(json["nextblockhash"].AsString()); + } + return block; + } + } +} diff --git a/neo/Network/RPC/Models/RpcInvokeResult.cs b/neo/Network/RPC/Models/RpcInvokeResult.cs new file mode 100644 index 0000000000..9a0f646588 --- /dev/null +++ b/neo/Network/RPC/Models/RpcInvokeResult.cs @@ -0,0 +1,69 @@ +using Neo.IO.Json; +using Newtonsoft.Json; +using System.Linq; + +namespace Neo.Network.RPC.Models +{ + public class RpcInvokeResult + { + [JsonProperty(PropertyName = "script")] + public string Script { get; set; } + + [JsonProperty(PropertyName = "state")] + public string State { get; set; } + + [JsonProperty(PropertyName = "gas_consumed")] + public string GasConsumed { get; set; } + + [JsonProperty(PropertyName = "stack")] + public RpcStack[] Stack { get; set; } + + [JsonProperty(PropertyName = "tx")] + public string Tx { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["script"] = Script; + json["state"] = State; + json["gas_consumed"] = GasConsumed; + json["stack"] = new JArray(Stack.Select(p => p.ToJson())); + json["tx"] = Tx; + return json; + } + + public static RpcInvokeResult FromJson(JObject json) + { + RpcInvokeResult invokeScriptResult = new RpcInvokeResult(); + invokeScriptResult.Script = json["script"].AsString(); + invokeScriptResult.State = json["state"].AsString(); + invokeScriptResult.GasConsumed = json["gas_consumed"].AsString(); + invokeScriptResult.Tx = json["tx"].AsString(); + invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => RpcStack.FromJson(p)).ToArray(); + return invokeScriptResult; + } + } + + public class RpcStack + { + public string Type { get; set; } + + public string Value { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["type"] = Type; + json["value"] = Value; + return json; + } + + public static RpcStack FromJson(JObject json) + { + RpcStack stackJson = new RpcStack(); + stackJson.Type = json["type"].AsString(); + stackJson.Value = json["value"].AsString(); + return stackJson; + } + } +} diff --git a/neo/Network/RPC/Models/RpcNep5Balances.cs b/neo/Network/RPC/Models/RpcNep5Balances.cs new file mode 100644 index 0000000000..edcf8d7f5e --- /dev/null +++ b/neo/Network/RPC/Models/RpcNep5Balances.cs @@ -0,0 +1,57 @@ +using Neo.IO.Json; +using System.Linq; +using System.Numerics; + +namespace Neo.Network.RPC.Models +{ + public class RpcNep5Balances + { + public string Address { get; set; } + + public RpcNep5Balance[] Balances { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["address"] = Address; + json["balance"] = Balances.Select(p => p.ToJson()).ToArray(); + return json; + } + + public static RpcNep5Balances FromJson(JObject json) + { + RpcNep5Balances nep5Balance = new RpcNep5Balances(); + nep5Balance.Address = json["address"].AsString(); + //List listBalance = new List(); + nep5Balance.Balances = ((JArray)json["balance"]).Select(p => RpcNep5Balance.FromJson(p)).ToArray(); + return nep5Balance; + } + } + + public class RpcNep5Balance + { + public UInt160 AssetHash { get; set; } + + public BigInteger Amount { get; set; } + + public uint LastUpdatedBlock { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["asset_hash"] = AssetHash.ToArray().ToHexString(); + json["amount"] = Amount.ToString(); + json["last_updated_block"] = LastUpdatedBlock.ToString(); + return json; + } + + public static RpcNep5Balance FromJson(JObject json) + { + RpcNep5Balance balance = new RpcNep5Balance(); + balance.AssetHash = UInt160.Parse(json["asset_hash"].AsString()); + balance.Amount = BigInteger.Parse(json["amount"].AsString()); + balance.LastUpdatedBlock = uint.Parse(json["last_updated_block"].AsString()); + return balance; + } + } +} diff --git a/neo/Network/RPC/Models/RpcPeers.cs b/neo/Network/RPC/Models/RpcPeers.cs new file mode 100644 index 0000000000..5caa99a66a --- /dev/null +++ b/neo/Network/RPC/Models/RpcPeers.cs @@ -0,0 +1,55 @@ +using Neo.IO.Json; +using System.Linq; + +namespace Neo.Network.RPC.Models +{ + public class RpcPeers + { + public RpcPeer[] Unconnected { get; set; } + + public RpcPeer[] Bad { get; set; } + + public RpcPeer[] Connected { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["unconnected"] = new JArray(Unconnected.Select(p => p.ToJson())); + json["bad"] = new JArray(Bad.Select(p => p.ToJson())); + json["connected"] = new JArray(Connected.Select(p => p.ToJson())); + return json; + } + + public static RpcPeers FromJson(JObject json) + { + RpcPeers result = new RpcPeers(); + result.Unconnected = ((JArray)json["unconnected"]).Select(p => RpcPeer.FromJson(p)).ToArray(); + result.Bad = ((JArray)json["bad"]).Select(p => RpcPeer.FromJson(p)).ToArray(); + result.Connected = ((JArray)json["connected"]).Select(p => RpcPeer.FromJson(p)).ToArray(); + return result; + } + } + + public class RpcPeer + { + public string Address { get; set; } + + public int Port { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["address"] = Address; + json["port"] = Port; + return json; + } + + public static RpcPeer FromJson(JObject json) + { + RpcPeer peer = new RpcPeer(); + peer.Address = json["address"].AsString(); + peer.Port = int.Parse(json["port"].AsString()); + return peer; + } + } +} diff --git a/neo/Network/RPC/Models/RpcPlugin.cs b/neo/Network/RPC/Models/RpcPlugin.cs new file mode 100644 index 0000000000..465b3f2d17 --- /dev/null +++ b/neo/Network/RPC/Models/RpcPlugin.cs @@ -0,0 +1,32 @@ +using Neo.IO.Json; +using System.Linq; + +namespace Neo.Network.RPC.Models +{ + public class RpcPlugin + { + public string Name { get; set; } + + public string Version { get; set; } + + public string[] Interfaces { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["name"] = Name; + json["version"] = Version; + json["interfaces"] = new JArray(Interfaces.Select(p => (JObject)p)); + return json; + } + + public static RpcPlugin FromJson(JObject json) + { + RpcPlugin plugin = new RpcPlugin(); + plugin.Name = json["name"].AsString(); + plugin.Version = json["version"].AsString(); + plugin.Interfaces = ((JArray)json["interfaces"]).Select(p => p.AsString()).ToArray(); + return plugin; + } + } +} diff --git a/neo/Network/RPC/Models/RpcRawMemPool.cs b/neo/Network/RPC/Models/RpcRawMemPool.cs new file mode 100644 index 0000000000..1841916ff2 --- /dev/null +++ b/neo/Network/RPC/Models/RpcRawMemPool.cs @@ -0,0 +1,32 @@ +using Neo.IO.Json; +using System.Linq; + +namespace Neo.Network.RPC.Models +{ + public class RpcRawMemPool + { + public uint Height { get; set; } + + public string[] Verified { get; set; } + + public string[] UnVerified { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["height"] = Height; + json["verified"] = new JArray(Verified.Select(p=>(JObject)p)); + json["unverified"] = new JArray(UnVerified.Select(p => (JObject)p)); + return json; + } + + public static RpcRawMemPool FromJson(JObject json) + { + RpcRawMemPool rawMemPool = new RpcRawMemPool(); + rawMemPool.Height = uint.Parse(json["height"].AsString()); + rawMemPool.Verified = ((JArray)json["verified"]).Select(p => p.AsString()).ToArray(); + rawMemPool.UnVerified = ((JArray)json["unverified"]).Select(p => p.AsString()).ToArray(); + return rawMemPool; + } + } +} diff --git a/neo/Network/RPC/Models/RpcRequest.cs b/neo/Network/RPC/Models/RpcRequest.cs new file mode 100644 index 0000000000..9c2d2f05ec --- /dev/null +++ b/neo/Network/RPC/Models/RpcRequest.cs @@ -0,0 +1,37 @@ +using Neo.IO.Json; +using System.Linq; + +namespace Neo.Network.RPC.Models +{ + public class RpcRequest + { + public int Id { get; set; } + + public string Jsonrpc { get; set; } + + public string Method { get; set; } + + public JObject[] Params { get; set; } + + public static RpcRequest FromJson(JObject json) + { + return new RpcRequest + { + Id = (int)json["id"].AsNumber(), + Jsonrpc = json["jsonrpc"].AsString(), + Method = json["method"].AsString(), + Params = ((JArray)json["params"]).ToArray() + }; + } + + public JObject ToJson() + { + var json = new JObject(); + json["id"] = Id; + json["jsonrpc"] = Jsonrpc; + json["method"] = Method; + json["params"] = new JArray(Params); + return json; + } + } +} diff --git a/neo/Network/RPC/Models/RpcResponse.cs b/neo/Network/RPC/Models/RpcResponse.cs new file mode 100644 index 0000000000..ff20200519 --- /dev/null +++ b/neo/Network/RPC/Models/RpcResponse.cs @@ -0,0 +1,72 @@ +using Neo.IO.Json; + +namespace Neo.Network.RPC.Models +{ + public class RpcResponse + { + public int? Id { get; set; } + + public string Jsonrpc { get; set; } + + public RpcResponseError Error { get; set; } + + public JObject Result { get; set; } + + public string RawResponse { get; set; } + + public static RpcResponse FromJson(JObject json) + { + var response = new RpcResponse + { + Id = (int?)json["id"]?.AsNumber(), + Jsonrpc = json["jsonrpc"].AsString(), + Result = json["result"] + }; + + if (json["error"] != null) + { + response.Error = RpcResponseError.FromJson(json["error"]); + } + + return response; + } + + public JObject ToJson() + { + var json = new JObject(); + json["id"] = Id; + json["jsonrpc"] = Jsonrpc; + json["error"] = Error.ToJson(); + json["result"] = Result; + return json; + } + } + + public class RpcResponseError + { + public int Code { get; set; } + + public string Message { get; set; } + + public JObject Data { get; set; } + + public static RpcResponseError FromJson(JObject json) + { + return new RpcResponseError + { + Code = (int)json["code"].AsNumber(), + Message = json["message"].AsString(), + Data = json["data"], + }; + } + + public JObject ToJson() + { + var json = new JObject(); + json["code"] = Code; + json["message"] = Message; + json["data"] = Data; + return json; + } + } +} diff --git a/neo/Network/RPC/Models/RpcTransaction.cs b/neo/Network/RPC/Models/RpcTransaction.cs new file mode 100644 index 0000000000..3e45830ae6 --- /dev/null +++ b/neo/Network/RPC/Models/RpcTransaction.cs @@ -0,0 +1,41 @@ +using Neo.IO.Json; +using Neo.Network.P2P.Payloads; + +namespace Neo.Network.RPC.Models +{ + public class RpcTransaction + { + public Transaction Transaction { get; set; } + + public UInt256 BlockHash { get; set; } + + public int? Confirmations { get; set; } + + public uint? BlockTime { get; set; } + + public JObject ToJson() + { + JObject json = Transaction.ToJson(); + if (Confirmations != null) + { + json["blockhash"] = BlockHash.ToString(); + json["confirmations"] = Confirmations; + json["blocktime"] = BlockTime; + } + return json; + } + + public static RpcTransaction FromJson(JObject json) + { + RpcTransaction transaction = new RpcTransaction(); + transaction.Transaction = Transaction.FromJson(json); + if (json["confirmations"] != null) + { + transaction.BlockHash = UInt256.Parse(json["blockhash"].AsString()); + transaction.Confirmations = (int)json["confirmations"].AsNumber(); + transaction.BlockTime = (uint)json["blocktime"].AsNumber(); + } + return transaction; + } + } +} diff --git a/neo/Network/RPC/Models/RpcValidateAddressResult.cs b/neo/Network/RPC/Models/RpcValidateAddressResult.cs new file mode 100644 index 0000000000..5e59bf8eaf --- /dev/null +++ b/neo/Network/RPC/Models/RpcValidateAddressResult.cs @@ -0,0 +1,27 @@ +using Neo.IO.Json; + +namespace Neo.Network.RPC.Models +{ + public class RpcValidateAddressResult + { + public string Address { get; set; } + + public bool IsValid { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["address"] = Address; + json["isvalid"] = IsValid; + return json; + } + + public static RpcValidateAddressResult FromJson(JObject json) + { + RpcValidateAddressResult validateAddress = new RpcValidateAddressResult(); + validateAddress.Address = json["address"].AsString(); + validateAddress.IsValid = json["isvalid"].AsBoolean(); + return validateAddress; + } + } +} diff --git a/neo/Network/RPC/Models/RpcValidator.cs b/neo/Network/RPC/Models/RpcValidator.cs new file mode 100644 index 0000000000..b694a6dfcd --- /dev/null +++ b/neo/Network/RPC/Models/RpcValidator.cs @@ -0,0 +1,32 @@ +using Neo.IO.Json; +using System.Numerics; + +namespace Neo.Network.RPC.Models +{ + public class RpcValidator + { + public string PublicKey { get; set; } + + public BigInteger Votes { get; set; } + + public bool Active { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["publickey"] = PublicKey; + json["votes"] = Votes.ToString(); + json["active"] = Active; + return json; + } + + public static RpcValidator FromJson(JObject json) + { + RpcValidator validator = new RpcValidator(); + validator.PublicKey = json["publickey"].AsString(); + validator.Votes = BigInteger.Parse(json["votes"].AsString()); + validator.Active = json["active"].AsBoolean(); + return validator; + } + } +} diff --git a/neo/Network/RPC/Models/RpcVersion.cs b/neo/Network/RPC/Models/RpcVersion.cs new file mode 100644 index 0000000000..02f4dc3407 --- /dev/null +++ b/neo/Network/RPC/Models/RpcVersion.cs @@ -0,0 +1,35 @@ +using Neo.IO.Json; + +namespace Neo.Network.RPC.Models +{ + public class RpcVersion + { + public int TcpPort { get; set; } + + public int WsPort { get; set; } + + public uint Nonce { get; set; } + + public string UserAgent { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + json["topPort"] = TcpPort.ToString(); + json["wsPort"] = WsPort.ToString(); + json["nonce"] = Nonce.ToString(); + json["useragent"] = UserAgent; + return json; + } + + public static RpcVersion FromJson(JObject json) + { + RpcVersion version = new RpcVersion(); + version.TcpPort = int.Parse(json["tcpPort"].AsString()); + version.WsPort = int.Parse(json["wsPort"].AsString()); + version.Nonce = uint.Parse(json["nonce"].AsString()); + version.UserAgent = json["useragent"].AsString(); + return version; + } + } +} diff --git a/neo/Network/RPC/RpcClient.cs b/neo/Network/RPC/RpcClient.cs new file mode 100644 index 0000000000..4b968163c7 --- /dev/null +++ b/neo/Network/RPC/RpcClient.cs @@ -0,0 +1,292 @@ +using Neo.IO.Json; +using Neo.Ledger; +using Neo.Network.RPC.Models; +using System; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace Neo.Network.RPC +{ + public class RpcClient : IDisposable + { + private readonly HttpClient httpClient; + + public RpcClient(string url) + { + httpClient = new HttpClient() { BaseAddress = new Uri(url) }; + } + + public RpcClient(HttpClient client) + { + httpClient = client; + } + + public void Dispose() + { + httpClient?.Dispose(); + } + + public async Task SendAsync(RpcRequest request) + { + var requestJson = request.ToJson().ToString(); + var result = await httpClient.PostAsync(httpClient.BaseAddress, new StringContent(requestJson, Encoding.UTF8)); + var content = await result.Content.ReadAsStringAsync(); + var response = RpcResponse.FromJson(JObject.Parse(content)); + response.RawResponse = content; + + if (response.Error != null) + { + throw new RpcException(response.Error.Code, response.Error.Message); + } + + return response; + } + + public RpcResponse Send(RpcRequest request) + { + try + { + return SendAsync(request).Result; + } + catch (AggregateException ex) + { + throw ex.GetBaseException(); + } + } + + private JObject RpcSend(string method, params JObject[] paraArgs) + { + var request = new RpcRequest + { + Id = 1, + Jsonrpc = "2.0", + Method = method, + Params = paraArgs.Select(p => p).ToArray() + }; + return Send(request).Result; + } + + /// + /// Returns the hash of the tallest block in the main chain. + /// + public string GetBestBlockHash() + { + return RpcSend("getbestblockhash").AsString(); + } + + /// + /// Returns the hash of the tallest block in the main chain. + /// The serialized information of the block is returned, represented by a hexadecimal string. + /// + public string GetBlockHex(string hashOrIndex) + { + if (int.TryParse(hashOrIndex, out int index)) + { + return RpcSend("getblock", index).AsString(); + } + return RpcSend("getblock", hashOrIndex).AsString(); + } + + /// + /// Returns the hash of the tallest block in the main chain. + /// + public RpcBlock GetBlock(string hashOrIndex) + { + if (int.TryParse(hashOrIndex, out int index)) + { + return RpcBlock.FromJson(RpcSend("getblock", index, true)); + } + return RpcBlock.FromJson(RpcSend("getblock", hashOrIndex, true)); + } + + /// + /// Gets the number of blocks in the main chain. + /// + public int GetBlockCount() + { + return (int)RpcSend("getblockcount").AsNumber(); + } + + /// + /// Returns the hash value of the corresponding block, based on the specified index. + /// + public string GetBlockHash(int index) + { + return RpcSend("getblockhash", index).AsString(); + } + + /// + /// Returns the corresponding block header information according to the specified script hash. + /// + public string GetBlockHeaderHex(string hashOrIndex) + { + if (int.TryParse(hashOrIndex, out int index)) + { + return RpcSend("getblockheader", index).AsString(); + } + return RpcSend("getblockheader", hashOrIndex).AsString(); + } + + /// + /// Returns the corresponding block header information according to the specified script hash. + /// + public RpcBlockHeader GetBlockHeader(string hashOrIndex) + { + if (int.TryParse(hashOrIndex, out int index)) + { + return RpcBlockHeader.FromJson(RpcSend("getblockheader", index, true)); + } + return RpcBlockHeader.FromJson(RpcSend("getblockheader", hashOrIndex, true)); + } + + /// + /// Returns the system fees of the block, based on the specified index. + /// + public string GetBlockSysFee(int height) + { + return RpcSend("getblocksysfee", height).AsString(); + } + + /// + /// Gets the current number of connections for the node. + /// + public int GetConnectionCount() + { + return (int)RpcSend("getconnectioncount").AsNumber(); + } + + /// + /// Queries contract information, according to the contract script hash. + /// + public ContractState GetContractState(string hash) + { + return ContractState.FromJson(RpcSend("getcontractstate", hash)); + } + + /// + /// Gets the list of nodes that the node is currently connected/disconnected from. + /// + public RpcPeers GetPeers() + { + return RpcPeers.FromJson(RpcSend("getpeers")); + } + + /// + /// Obtains the list of unconfirmed transactions in memory. + /// + public string[] GetRawMempool() + { + return ((JArray)RpcSend("getrawmempool")).Select(p => p.AsString()).ToArray(); + } + + /// + /// Obtains the list of unconfirmed transactions in memory. + /// shouldGetUnverified = true + /// + public RpcRawMemPool GetRawMempoolBoth() + { + return RpcRawMemPool.FromJson(RpcSend("getrawmempool")); + } + + /// + /// Returns the corresponding transaction information, based on the specified hash value. + /// + public string GetRawTransactionHex(string txid) + { + return RpcSend("getrawtransaction", txid).AsString(); + } + + /// + /// Returns the corresponding transaction information, based on the specified hash value. + /// verbose = true + /// + public RpcTransaction GetRawTransaction(string txid) + { + return RpcTransaction.FromJson(RpcSend("getrawtransaction", txid, true)); + } + + /// + /// Returns the stored value, according to the contract script hash and the stored key. + /// + public string GetStorage(string script_hash, string key) + { + return RpcSend("getstorage", script_hash, key).AsString(); + } + + /// + /// Returns the block index in which the transaction is found. + /// + public uint GetTransactionHeight(string txid) + { + return uint.Parse(RpcSend("gettransactionheight", txid).AsString()); + } + + /// + /// Returns the current NEO consensus nodes information and voting status. + /// + public RpcValidator[] GetValidators() + { + return ((JArray)RpcSend("getvalidators")).Select(p => RpcValidator.FromJson(p)).ToArray(); + } + + /// + /// Returns the version information about the queried node. + /// + public RpcVersion GetVersion() + { + return RpcVersion.FromJson(RpcSend("getversion")); + } + + /// + /// Returns the result after calling a smart contract at scripthash with the given operation and parameters. + /// This RPC call does not affect the blockchain in any way. + /// + public RpcInvokeResult InvokeFunction(string address, string function, RpcStack[] stacks) + { + return RpcInvokeResult.FromJson(RpcSend("invokefunction", address, function, stacks.Select(p => p.ToJson()).ToArray())); + } + + /// + /// Returns the result after passing a script through the VM. + /// This RPC call does not affect the blockchain in any way. + /// + public RpcInvokeResult InvokeScript(string script) + { + return RpcInvokeResult.FromJson(RpcSend("invokescript", script)); + } + + /// + /// Returns a list of plugins loaded by the node. + /// + public RpcPlugin[] ListPlugins() + { + return ((JArray)RpcSend("listplugins")).Select(p => RpcPlugin.FromJson(p)).ToArray(); + } + + /// + /// Broadcasts a transaction over the NEO network. + /// + public bool SendRawTransaction(string rawTransaction) + { + return RpcSend("sendrawtransaction", rawTransaction).AsBoolean(); + } + + /// + /// Broadcasts a raw block over the NEO network. + /// + public bool SubmitBlock(string block) + { + return RpcSend("submitblock", block).AsBoolean(); + } + + /// + /// Verifies that the address is a correct NEO address. + /// + public RpcValidateAddressResult ValidateAddress(string address) + { + return RpcValidateAddressResult.FromJson(RpcSend("validateaddress", address)); + } + } +} From 46ed67f6d4b551b2ef55c5daa0cfc8aefeea1981 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Wed, 31 Jul 2019 20:29:24 +0800 Subject: [PATCH 13/54] Remove `IPolicyPlugin` (#971) --- neo/Consensus/ConsensusContext.cs | 8 +++----- neo/Consensus/ConsensusService.cs | 3 ++- neo/Ledger/Blockchain.cs | 4 ++-- neo/Plugins/IPolicyPlugin.cs | 11 ----------- neo/Plugins/Plugin.cs | 11 ----------- neo/SmartContract/Native/PolicyContract.cs | 9 +++++++++ 6 files changed, 16 insertions(+), 30 deletions(-) delete mode 100644 neo/Plugins/IPolicyPlugin.cs diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs index 270536fc89..ba7edf66c5 100644 --- a/neo/Consensus/ConsensusContext.cs +++ b/neo/Consensus/ConsensusContext.cs @@ -4,7 +4,6 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; -using Neo.Plugins; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.Wallets; @@ -210,10 +209,9 @@ public ConsensusPayload MakePrepareRequest() { byte[] buffer = new byte[sizeof(ulong)]; random.NextBytes(buffer); - IEnumerable memoryPoolTransactions = Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions(); - foreach (IPolicyPlugin plugin in Plugin.Policies) - memoryPoolTransactions = plugin.FilterForBlock(memoryPoolTransactions); - List transactions = memoryPoolTransactions.ToList(); + List transactions = Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions() + .Take((int)NativeContract.Policy.GetMaxTransactionsPerBlock(Snapshot)) + .ToList(); TransactionHashes = transactions.Select(p => p.Hash).ToArray(); Transactions = transactions.ToDictionary(p => p.Hash); Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index 2e850807e4..08cf41e8b9 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -8,6 +8,7 @@ using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.Plugins; +using Neo.SmartContract.Native; using Neo.Wallets; using System; using System.Collections.Generic; @@ -66,7 +67,7 @@ private bool AddTransaction(Transaction tx, bool verify) RequestChangeView(ChangeViewReason.TxInvalid); return false; } - if (!Plugin.CheckPolicy(tx)) + if (!NativeContract.Policy.CheckPolicy(tx, context.Snapshot)) { Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning); RequestChangeView(ChangeViewReason.TxRejectedByPolicy); diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index ee8e114701..663d142d62 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -228,7 +228,7 @@ private void OnFillMemoryPool(IEnumerable transactions) { if (Store.ContainsTransaction(tx.Hash)) continue; - if (!Plugin.CheckPolicy(tx)) + if (!NativeContract.Policy.CheckPolicy(tx, currentSnapshot)) continue; // First remove the tx if it is unverified in the pool. MemPool.TryRemoveUnVerified(tx.Hash, out _); @@ -361,7 +361,7 @@ private RelayResultReason OnNewTransaction(Transaction transaction) return RelayResultReason.OutOfMemory; if (!transaction.Verify(currentSnapshot, MemPool.GetVerifiedTransactions())) return RelayResultReason.Invalid; - if (!Plugin.CheckPolicy(transaction)) + if (!NativeContract.Policy.CheckPolicy(transaction, currentSnapshot)) return RelayResultReason.PolicyFail; if (!MemPool.TryAdd(transaction.Hash, transaction)) diff --git a/neo/Plugins/IPolicyPlugin.cs b/neo/Plugins/IPolicyPlugin.cs deleted file mode 100644 index 812d418ee2..0000000000 --- a/neo/Plugins/IPolicyPlugin.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Neo.Network.P2P.Payloads; -using System.Collections.Generic; - -namespace Neo.Plugins -{ - public interface IPolicyPlugin - { - bool FilterForMemoryPool(Transaction tx); - IEnumerable FilterForBlock(IEnumerable transactions); - } -} diff --git a/neo/Plugins/Plugin.cs b/neo/Plugins/Plugin.cs index 862ff6ae9a..72c7ce3b14 100644 --- a/neo/Plugins/Plugin.cs +++ b/neo/Plugins/Plugin.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Configuration; -using Neo.Network.P2P.Payloads; using System; using System.Collections.Generic; using System.IO; @@ -13,7 +12,6 @@ public abstract class Plugin { public static readonly List Plugins = new List(); private static readonly List Loggers = new List(); - internal static readonly List Policies = new List(); internal static readonly List RpcPlugins = new List(); internal static readonly List PersistencePlugins = new List(); internal static readonly List P2PPlugins = new List(); @@ -51,7 +49,6 @@ protected Plugin() if (this is ILogPlugin logger) Loggers.Add(logger); if (this is IP2PPlugin p2p) P2PPlugins.Add(p2p); - if (this is IPolicyPlugin policy) Policies.Add(policy); if (this is IRpcPlugin rpc) RpcPlugins.Add(rpc); if (this is IPersistencePlugin persistence) PersistencePlugins.Add(persistence); if (this is IMemoryPoolTxObserverPlugin txObserver) TxObserverPlugins.Add(txObserver); @@ -59,14 +56,6 @@ protected Plugin() Configure(); } - public static bool CheckPolicy(Transaction tx) - { - foreach (IPolicyPlugin plugin in Policies) - if (!plugin.FilterForMemoryPool(tx)) - return false; - return true; - } - public abstract void Configure(); protected virtual void OnPluginsLoaded() diff --git a/neo/SmartContract/Native/PolicyContract.cs b/neo/SmartContract/Native/PolicyContract.cs index 2109e8b65d..239cd92200 100644 --- a/neo/SmartContract/Native/PolicyContract.cs +++ b/neo/SmartContract/Native/PolicyContract.cs @@ -3,6 +3,7 @@ using Neo.IO; using Neo.Ledger; +using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract.Manifest; using Neo.VM; @@ -26,6 +27,14 @@ public PolicyContract() Manifest.Features = ContractFeatures.HasStorage; } + internal bool CheckPolicy(Transaction tx, Snapshot snapshot) + { + UInt160[] blockedAccounts = GetBlockedAccounts(snapshot); + if (blockedAccounts.Intersect(tx.GetScriptHashesForVerifying(snapshot)).Any()) + return false; + return true; + } + private bool CheckValidators(ApplicationEngine engine) { UInt256 prev_hash = engine.Snapshot.PersistingBlock.PrevHash; From f927dec43409515e02f8156a6d22db9de3252601 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Wed, 31 Jul 2019 23:48:31 +0800 Subject: [PATCH 14/54] Add `Console.WriteLine()` in `ConsensusService.Log()` (#974) --- neo/Consensus/ConsensusService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index 08cf41e8b9..e4983830a4 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -175,6 +175,7 @@ private void InitializeConsensus(byte viewNumber) private void Log(string message, LogLevel level = LogLevel.Info) { + Console.WriteLine($"[{DateTime.Now.TimeOfDay:hh\\:mm\\:ss\\.fff}] {message}"); Plugin.Log(nameof(ConsensusService), level, message); } From 53f7d022afba7b1dfce5a437f8bc11557423a7fb Mon Sep 17 00:00:00 2001 From: Igor Machado Coelho Date: Fri, 2 Aug 2019 05:01:10 -0300 Subject: [PATCH 15/54] dotnet format (#983) --- neo.UnitTests/Consensus/UT_Consensus.cs | 4 ++-- neo.UnitTests/Cryptography/UT_Base58.cs | 2 +- neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs | 8 ++++---- neo.UnitTests/Cryptography/UT_MerkleTree.cs | 6 +++--- neo.UnitTests/IO/Caching/UT_CloneCache.cs | 3 ++- neo.UnitTests/IO/Caching/UT_FifoSet.cs | 4 ++-- neo.UnitTests/Network/P2P/Payloads/UT_Header.cs | 2 +- neo.UnitTests/VM/UT_Helper.cs | 4 ++-- neo/Network/RPC/Models/RpcInvokeResult.cs | 2 +- neo/Network/RPC/Models/RpcNep5Balances.cs | 6 +++--- neo/Network/RPC/Models/RpcPlugin.cs | 4 ++-- neo/Network/RPC/Models/RpcRawMemPool.cs | 6 +++--- neo/Network/RPC/Models/RpcRequest.cs | 6 +++--- neo/Network/RPC/Models/RpcValidateAddressResult.cs | 2 +- neo/SmartContract/ApplicationEngine.cs | 2 +- 15 files changed, 31 insertions(+), 30 deletions(-) diff --git a/neo.UnitTests/Consensus/UT_Consensus.cs b/neo.UnitTests/Consensus/UT_Consensus.cs index 34e8322615..14c287bcff 100644 --- a/neo.UnitTests/Consensus/UT_Consensus.cs +++ b/neo.UnitTests/Consensus/UT_Consensus.cs @@ -80,8 +80,8 @@ public void ConsensusService_Primary_Sends_PrepareRequest_After_OnStart() Console.WriteLine($"header {header} hash {header.Hash} timestamp {timestampVal}"); 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 + // check basic ConsensusContext + //mockConsensusContext.Object.block_received_time.ToTimestamp().Should().Be(4244941697); //1968-06-01 00:00:01 // ============================================================================ // creating ConsensusService actor diff --git a/neo.UnitTests/Cryptography/UT_Base58.cs b/neo.UnitTests/Cryptography/UT_Base58.cs index 2d18975445..21cc63dda2 100644 --- a/neo.UnitTests/Cryptography/UT_Base58.cs +++ b/neo.UnitTests/Cryptography/UT_Base58.cs @@ -10,7 +10,7 @@ public class UT_Base58 { byte[] decoded1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; string encoded1 = "1kA3B2yGe2z4"; - byte[] decoded2 = { 0, 0, 0, 0, 0}; + byte[] decoded2 = { 0, 0, 0, 0, 0 }; string encoded2 = "1111"; [TestMethod] diff --git a/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index af909e3d71..06f672ff77 100644 --- a/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -18,7 +18,7 @@ public void TestAES256Encrypt() byte[] key = Encoding.ASCII.GetBytes("1234567812345678"); byte[] result = block.AES256Encrypt(key); string encryptString = result.ToHexString(); - encryptString.Should().Be("f69e0923d8247eef417d6a78944a4b39f69e0923d8247eef417d6a78944a4b39"); + encryptString.Should().Be("f69e0923d8247eef417d6a78944a4b39f69e0923d8247eef417d6a78944a4b39"); } [TestMethod] @@ -104,7 +104,7 @@ public void TestAesDecrypt() byte[] wrongIv = Encoding.ASCII.GetBytes("12345678123456780"); ; action = () => data.AesDecrypt(key, wrongIv); action.ShouldThrow(); - } + } [TestMethod] public void TestBase58CheckDecode() @@ -126,7 +126,7 @@ public void TestBase58CheckDecode() [TestMethod] public void TestSha256() { - byte[] value = Encoding.ASCII.GetBytes("hello world"); + byte[] value = Encoding.ASCII.GetBytes("hello world"); byte[] result = value.Sha256(0, value.Length); string resultStr = result.ToHexString(); resultStr.Should().Be("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"); @@ -169,7 +169,7 @@ public void TestStringToAesKey() string password = "hello world"; string string1 = "bc62d4b80d9e36da29c16c5d4d9f11731f36052c72401a76c23c0fb5a9b74423"; byte[] byteArray = new byte[string1.Length / 2]; - byteArray = string1.HexToBytes(); + byteArray = string1.HexToBytes(); password.ToAesKey().Should().Equal(byteArray); } diff --git a/neo.UnitTests/Cryptography/UT_MerkleTree.cs b/neo.UnitTests/Cryptography/UT_MerkleTree.cs index 3edf6b4a8b..75ab2330b2 100644 --- a/neo.UnitTests/Cryptography/UT_MerkleTree.cs +++ b/neo.UnitTests/Cryptography/UT_MerkleTree.cs @@ -13,7 +13,7 @@ public class UT_MerkleTree { public UInt256 GetByteArrayHash(byte[] byteArray) { - if(byteArray == null || byteArray.Length == 0) throw new ArgumentNullException(); + if (byteArray == null || byteArray.Length == 0) throw new ArgumentNullException(); var hash = new UInt256(Crypto.Default.Hash256(byteArray)); return hash; } @@ -26,13 +26,13 @@ public void TestBuildAndDepthFirstSearch() action.ShouldThrow(); byte[] array1 = { 0x01 }; - var hash1 = GetByteArrayHash(array1); + var hash1 = GetByteArrayHash(array1); byte[] array2 = { 0x02 }; var hash2 = GetByteArrayHash(array2); byte[] array3 = { 0x03 }; - var hash3 = GetByteArrayHash(array3); + var hash3 = GetByteArrayHash(array3); IReadOnlyList hashes = new UInt256[] { hash1, hash2, hash3 }; MerkleTree tree = new MerkleTree(hashes); diff --git a/neo.UnitTests/IO/Caching/UT_CloneCache.cs b/neo.UnitTests/IO/Caching/UT_CloneCache.cs index 1c9c2db74d..52c665a95d 100644 --- a/neo.UnitTests/IO/Caching/UT_CloneCache.cs +++ b/neo.UnitTests/IO/Caching/UT_CloneCache.cs @@ -85,7 +85,8 @@ public void TestGetInternal() cloneCache[new MyKey("key2")].Should().Be(new MyValue("value2")); cloneCache[new MyKey("key3")].Should().Be(new MyValue("value3")); - Action action = () => { + Action action = () => + { var item = cloneCache[new MyKey("key4")]; }; action.ShouldThrow(); diff --git a/neo.UnitTests/IO/Caching/UT_FifoSet.cs b/neo.UnitTests/IO/Caching/UT_FifoSet.cs index 8242572e86..cbbafae402 100644 --- a/neo.UnitTests/IO/Caching/UT_FifoSet.cs +++ b/neo.UnitTests/IO/Caching/UT_FifoSet.cs @@ -59,10 +59,10 @@ public void TestConstructor() Action action1 = () => new FIFOSet(-1); action1.ShouldThrow(); - Action action2 = () => new FIFOSet(1,-1); + Action action2 = () => new FIFOSet(1, -1); action2.ShouldThrow(); - Action action3 = () => new FIFOSet(1,2); + Action action3 = () => new FIFOSet(1, 2); action3.ShouldThrow(); } diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs index f9dfd30d1e..8002f4b196 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs @@ -110,7 +110,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, 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/VM/UT_Helper.cs b/neo.UnitTests/VM/UT_Helper.cs index 7fc0088632..b57ca02a7c 100644 --- a/neo.UnitTests/VM/UT_Helper.cs +++ b/neo.UnitTests/VM/UT_Helper.cs @@ -27,7 +27,7 @@ public void TestEmitAppCall1() tempArray[0] = 0x00;//0 tempArray[1] = 0xC5;//OpCode.NEWARRAY tempArray[2] = 5;//operation.Length - Array.Copy(Encoding.UTF8.GetBytes("AAAAA"),0, tempArray,3, 5);//operation.data + Array.Copy(Encoding.UTF8.GetBytes("AAAAA"), 0, tempArray, 3, 5);//operation.data tempArray[8] = 0x14;//scriptHash.Length Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 9, 20);//operation.data uint api = InteropService.System_Contract_Call; @@ -42,7 +42,7 @@ public void TestEmitAppCall2() { //format:(ContractParameter[])ContractParameter+(byte)OpCode.PACK+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call ScriptBuilder sb = new ScriptBuilder(); - sb.EmitAppCall(UInt160.Zero, "AAAAA",new ContractParameter[] {new ContractParameter(ContractParameterType.Integer)}); + sb.EmitAppCall(UInt160.Zero, "AAAAA", new ContractParameter[] { new ContractParameter(ContractParameterType.Integer) }); byte[] tempArray = new byte[35]; tempArray[0] = 0x00;//0 tempArray[1] = 0x51;//ContractParameter.Length diff --git a/neo/Network/RPC/Models/RpcInvokeResult.cs b/neo/Network/RPC/Models/RpcInvokeResult.cs index 9a0f646588..9df9492e2b 100644 --- a/neo/Network/RPC/Models/RpcInvokeResult.cs +++ b/neo/Network/RPC/Models/RpcInvokeResult.cs @@ -47,7 +47,7 @@ public static RpcInvokeResult FromJson(JObject json) public class RpcStack { public string Type { get; set; } - + public string Value { get; set; } public JObject ToJson() diff --git a/neo/Network/RPC/Models/RpcNep5Balances.cs b/neo/Network/RPC/Models/RpcNep5Balances.cs index edcf8d7f5e..f29f0c5564 100644 --- a/neo/Network/RPC/Models/RpcNep5Balances.cs +++ b/neo/Network/RPC/Models/RpcNep5Balances.cs @@ -7,7 +7,7 @@ namespace Neo.Network.RPC.Models public class RpcNep5Balances { public string Address { get; set; } - + public RpcNep5Balance[] Balances { get; set; } public JObject ToJson() @@ -31,9 +31,9 @@ public static RpcNep5Balances FromJson(JObject json) public class RpcNep5Balance { public UInt160 AssetHash { get; set; } - + public BigInteger Amount { get; set; } - + public uint LastUpdatedBlock { get; set; } public JObject ToJson() diff --git a/neo/Network/RPC/Models/RpcPlugin.cs b/neo/Network/RPC/Models/RpcPlugin.cs index 465b3f2d17..ae778ee87a 100644 --- a/neo/Network/RPC/Models/RpcPlugin.cs +++ b/neo/Network/RPC/Models/RpcPlugin.cs @@ -6,9 +6,9 @@ namespace Neo.Network.RPC.Models public class RpcPlugin { public string Name { get; set; } - + public string Version { get; set; } - + public string[] Interfaces { get; set; } public JObject ToJson() diff --git a/neo/Network/RPC/Models/RpcRawMemPool.cs b/neo/Network/RPC/Models/RpcRawMemPool.cs index 1841916ff2..df439bf3a6 100644 --- a/neo/Network/RPC/Models/RpcRawMemPool.cs +++ b/neo/Network/RPC/Models/RpcRawMemPool.cs @@ -6,16 +6,16 @@ namespace Neo.Network.RPC.Models public class RpcRawMemPool { public uint Height { get; set; } - + public string[] Verified { get; set; } - + public string[] UnVerified { get; set; } public JObject ToJson() { JObject json = new JObject(); json["height"] = Height; - json["verified"] = new JArray(Verified.Select(p=>(JObject)p)); + json["verified"] = new JArray(Verified.Select(p => (JObject)p)); json["unverified"] = new JArray(UnVerified.Select(p => (JObject)p)); return json; } diff --git a/neo/Network/RPC/Models/RpcRequest.cs b/neo/Network/RPC/Models/RpcRequest.cs index 9c2d2f05ec..010e3037b8 100644 --- a/neo/Network/RPC/Models/RpcRequest.cs +++ b/neo/Network/RPC/Models/RpcRequest.cs @@ -6,11 +6,11 @@ namespace Neo.Network.RPC.Models public class RpcRequest { public int Id { get; set; } - + public string Jsonrpc { get; set; } - + public string Method { get; set; } - + public JObject[] Params { get; set; } public static RpcRequest FromJson(JObject json) diff --git a/neo/Network/RPC/Models/RpcValidateAddressResult.cs b/neo/Network/RPC/Models/RpcValidateAddressResult.cs index 5e59bf8eaf..f33467356e 100644 --- a/neo/Network/RPC/Models/RpcValidateAddressResult.cs +++ b/neo/Network/RPC/Models/RpcValidateAddressResult.cs @@ -5,7 +5,7 @@ namespace Neo.Network.RPC.Models public class RpcValidateAddressResult { public string Address { get; set; } - + public bool IsValid { get; set; } public JObject ToJson() diff --git a/neo/SmartContract/ApplicationEngine.cs b/neo/SmartContract/ApplicationEngine.cs index 03a098530a..d211d7aac8 100644 --- a/neo/SmartContract/ApplicationEngine.cs +++ b/neo/SmartContract/ApplicationEngine.cs @@ -83,7 +83,7 @@ protected override bool PreExecuteInstruction() return true; return AddGas(OpCodePrices[CurrentContext.CurrentInstruction.OpCode]); } - + private static Block CreateDummyBlock(Snapshot snapshot) { var currentBlock = snapshot.Blocks[snapshot.CurrentBlockHash]; From 30a89970f481782e9074df94107fa328d390a516 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 5 Aug 2019 00:47:11 +0800 Subject: [PATCH 16/54] Fixes `NeoToken.CalculateBonus()` (#992) --- neo/SmartContract/Native/Tokens/NeoToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/SmartContract/Native/Tokens/NeoToken.cs b/neo/SmartContract/Native/Tokens/NeoToken.cs index 6de1ac1970..d9e2dd2d4f 100644 --- a/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -93,7 +93,7 @@ private BigInteger CalculateBonus(Snapshot snapshot, BigInteger value, uint star } amount += (iend - istart) * Blockchain.GenerationAmount[ustart]; } - amount += GAS.GetSysFeeAmount(snapshot, end - 1) - (start == 0 ? 0 : GAS.GetSysFeeAmount(snapshot, start - 1)); + amount += (GAS.GetSysFeeAmount(snapshot, end - 1) - (start == 0 ? 0 : GAS.GetSysFeeAmount(snapshot, start - 1))) / GAS.Factor; return value * amount * GAS.Factor / TotalAmount; } From aa1172073a355fb6f67fe8f65022c10143a2e301 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 4 Aug 2019 20:34:42 +0200 Subject: [PATCH 17/54] Small cache changes (#994) * Cache changes * Update UT_Cache.cs --- neo.UnitTests/IO/Caching/UT_Cache.cs | 44 +++++++++++++++++++++++++++- neo/IO/Caching/Cache.cs | 18 ++++-------- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/neo.UnitTests/IO/Caching/UT_Cache.cs b/neo.UnitTests/IO/Caching/UT_Cache.cs index 01484ae65e..1376863e1a 100644 --- a/neo.UnitTests/IO/Caching/UT_Cache.cs +++ b/neo.UnitTests/IO/Caching/UT_Cache.cs @@ -25,6 +25,35 @@ public IEnumerator MyGetEnumerator() } } + class CacheDisposableEntry : IDisposable + { + public int Key { get; set; } + public bool IsDisposed { get; private set; } + + public void Dispose() + { + IsDisposed = true; + } + } + + class MyDisposableCache : Cache + { + public MyDisposableCache(int max_capacity) : base(max_capacity) { } + + protected override int GetKeyForItem(CacheDisposableEntry item) + { + return item.Key; + } + + protected override void OnAccess(CacheItem item) { } + + public IEnumerator MyGetEnumerator() + { + IEnumerable enumerable = this; + return enumerable.GetEnumerator(); + } + } + [TestClass] public class UT_Cache { @@ -133,6 +162,19 @@ public void TestRemoveKey() cache.Contains("hello").Should().BeFalse(); } + [TestMethod] + public void TestRemoveDisposableKey() + { + var entry = new CacheDisposableEntry() { Key = 1 }; + var dcache = new MyDisposableCache(100); + dcache.Add(entry); + + entry.IsDisposed.Should().BeFalse(); + dcache.Remove(entry.Key).Should().BeTrue(); + dcache.Remove(entry.Key).Should().BeFalse(); + entry.IsDisposed.Should().BeTrue(); + } + [TestMethod] public void TestRemoveValue() { @@ -211,4 +253,4 @@ public void TestDispose() action.ShouldThrow(); } } -} \ No newline at end of file +} diff --git a/neo/IO/Caching/Cache.cs b/neo/IO/Caching/Cache.cs index 45556b8ae3..5b97d3a223 100644 --- a/neo/IO/Caching/Cache.cs +++ b/neo/IO/Caching/Cache.cs @@ -10,15 +10,15 @@ internal abstract class Cache : ICollection, IDisposable { protected class CacheItem { - public TKey Key; - public TValue Value; - public DateTime Time; + public readonly TKey Key; + public readonly TValue Value; + public readonly DateTime Time; public CacheItem(TKey key, TValue value) { this.Key = key; this.Value = value; - this.Time = DateTime.Now; + this.Time = TimeProvider.Current.UtcNow; } } @@ -60,13 +60,7 @@ public int Count } } - public bool IsReadOnly - { - get - { - return false; - } - } + public bool IsReadOnly => false; public Cache(int max_capacity) { @@ -97,7 +91,7 @@ private void AddInternal(TKey key, TValue item) { if (InnerDictionary.Count >= max_capacity) { - //TODO: 对PLINQ查询进行性能测试,以便确定此处使用何种算法更优(并行或串行) + //TODO: Perform a performance test on the PLINQ query to determine which algorithm is better here (parallel or not) foreach (CacheItem item_del in InnerDictionary.Values.AsParallel().OrderBy(p => p.Time).Take(InnerDictionary.Count - max_capacity + 1)) { RemoveInternal(item_del); From 0a382a99c414a82c1f89b22ddb61ef223d89f3e1 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 5 Aug 2019 14:02:48 +0800 Subject: [PATCH 18/54] Fixes `GetRegisteredValidators()` (#991) --- .../Native/Tokens/UT_NeoToken.cs | 16 +++++++++++++++- neo/Ledger/StorageKey.cs | 19 +++++++++++++++++++ neo/SmartContract/InteropService.NEO.cs | 18 +----------------- neo/SmartContract/Native/Tokens/NeoToken.cs | 3 ++- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 9a22bab3c4..efa3c2446c 100644 --- a/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -128,6 +128,20 @@ public void Check_RegisterValidator() ret.Result.Should().BeTrue(); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 1); // New validator + + // Check GetRegisteredValidators + + var validators = NativeContract.NEO.GetRegisteredValidators(snapshot).OrderBy(u => u.PublicKey).ToArray(); + var check = Blockchain.StandbyValidators.Select(u => u.EncodePoint(true)).ToList(); + check.Add(point); // Add the new member + + for (int x = 0; x < validators.Length; x++) + { + Assert.AreEqual(1, check.RemoveAll(u => u.SequenceEqual(validators[x].PublicKey.EncodePoint(true)))); + Assert.AreEqual(0, validators[x].Votes); + } + + Assert.AreEqual(0, check.Count); } [TestMethod] @@ -357,4 +371,4 @@ internal static void CheckBalance(byte[] account, DataCache, ISerializable int ISerializable.Size => ScriptHash.Size + (Key.Length / 16 + 1) * 17; + internal static byte[] CreateSearchPrefix(UInt160 hash, byte[] prefix) + { + using (MemoryStream ms = new MemoryStream()) + { + int index = 0; + int remain = prefix.Length; + while (remain >= 16) + { + ms.Write(prefix, index, 16); + ms.WriteByte(16); + index += 16; + remain -= 16; + } + if (remain > 0) + ms.Write(prefix, index, remain); + return hash.ToArray().Concat(ms.ToArray()).ToArray(); + } + } + void ISerializable.Deserialize(BinaryReader reader) { ScriptHash = reader.ReadSerializable(); diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index 669a9b7073..91b941649f 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -10,7 +10,6 @@ using Neo.VM; using Neo.VM.Types; using System; -using System.IO; using System.Linq; using VMArray = Neo.VM.Types.Array; @@ -345,22 +344,7 @@ private static bool Storage_Find(ApplicationEngine engine) StorageContext context = _interface.GetInterface(); if (!CheckStorageContext(engine, context)) return false; byte[] prefix = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); - byte[] prefix_key; - using (MemoryStream ms = new MemoryStream()) - { - int index = 0; - int remain = prefix.Length; - while (remain >= 16) - { - ms.Write(prefix, index, 16); - ms.WriteByte(16); - index += 16; - remain -= 16; - } - if (remain > 0) - ms.Write(prefix, index, remain); - prefix_key = context.ScriptHash.ToArray().Concat(ms.ToArray()).ToArray(); - } + byte[] prefix_key = StorageKey.CreateSearchPrefix(context.ScriptHash, prefix); StorageIterator iterator = engine.AddDisposable(new StorageIterator(engine.Snapshot.Storages.Find(prefix_key).Where(p => p.Key.Key.Take(prefix.Length).SequenceEqual(prefix)).GetEnumerator())); engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(iterator)); return true; diff --git a/neo/SmartContract/Native/Tokens/NeoToken.cs b/neo/SmartContract/Native/Tokens/NeoToken.cs index d9e2dd2d4f..7b28bd0923 100644 --- a/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -201,7 +201,8 @@ private StackItem GetRegisteredValidators(ApplicationEngine engine, VMArray args public IEnumerable<(ECPoint PublicKey, BigInteger Votes)> GetRegisteredValidators(Snapshot snapshot) { - return snapshot.Storages.Find(new[] { Prefix_Validator }).Select(p => + byte[] prefix_key = StorageKey.CreateSearchPrefix(Hash, new[] { Prefix_Validator }); + return snapshot.Storages.Find(prefix_key).Select(p => ( p.Key.Key.Skip(1).ToArray().AsSerializable(), ValidatorState.FromByteArray(p.Value.Value).Votes From 48b216c3d5467da07b9e4d715bb8a6811e88a097 Mon Sep 17 00:00:00 2001 From: zhangtao Date: Tue, 6 Aug 2019 15:00:48 +0800 Subject: [PATCH 19/54] Fix/travis parallel jobs (#987) * testDemo * add dll lib * add dbsnapshot dispose * test get blocks in levelDBStore * add levelDBStore test funcs * fix levelDBStore funcs * add DbCache addInternal * differ db path * space * fix delete internal test * add test getInternal tryGetInternal move libleveldb.dll * add dbCache method test * add store test * add cache unit tests * add cache unit tests * up readonly max_capacity * fix leveldbexception * fix comment on UT_Cache * format * fix multithread test problem * up cache * update travis config * update travis.yml * test DbMetaDataCache * fix db directory * format and update travis for maxos * fix mac env travis * 2019/7/12 10:34 * 2019/7/12 11:01 * remove commented line * test BigDecimal * fix format and csproj * rm coverage.opencover.xml * update method name * add UT_P_Helper * modify UT_P_Helper * modify UT_P_helper * Clean ut * test Base58 & BloomFilter * Update UT_Cache.cs * Correct Typo * test JsonArray * update namespace * update namespace * update format * update format * organise folder structure * add UT_JString * test JBoolean JNumber & JObject * 2019/7/16 10:30 add some test case for UInt32Wrapper and SerializableWrapper * fix timestamp * test ECDsa and Crypto * test OrderedDictionary & complete IO.Json tests * 2019/7/16 17:33 add some test case of SQLiteWallet * test FIFOSet * add CloneCache and DataCache unit tests * fix namespace * add UT_Cryptography_Helper * format UT_CloneCache and UT_DataCache * add UT_DataCache.GetAndChange unit test * update namespace * remove comment code * delete Persistence part * 2019/7/19 11:07 add some test case for Helper in VM * Fix Base58 Test * 2019/7/19 11:33 change some format * update IOHelper exception assert * 2019/7/19 14:22 change format * format IOHelper * review IO.Wrapper * review Wallets.SQLite UT * Test ECFieldElement ECPoint * refactor package * format ECDsa * update namespace * Code fix * review cache * modify UT_JString * fomat * using Actin replace with try-catch * add UT_CloneMetaCache and UT_MetaDataCache * update namespace * format UT_DataCache.cs * Code Fix * format * update csproj * Code fix for UT_ECFieldElement and UT_ECPoint * Code fix * format * update travis * delete deleteFiles * fix path and comment * update travis * delete test ToTimeStamp * format UT_*Cache * update format * fomat * use hex extensions in Cryptography_Helper * remove reflection * optimization of UT_DataCache * update namespace * modify TestSha256 * update UT in crypto module * Rename UT_Scrypt.cs to UT_SCrypt.cs * format * update UT_Murmur3 * split travis jobs * add -v n --- .travis.yml | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 516dd5855c..aaf9dd660d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,16 +10,26 @@ osx_image: xcode9.1 mono: none dotnet: 2.2.300 +env: +- TEST_SUITE="without-cultures" +- TEST_SUITE="cultures" + before_install: - cd neo.UnitTests - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ulimit -n 2048; fi +script: | + if [[ "$TEST_SUITE" == cultures ]]; then + dotnet restore + dotnet test + else + dotnet restore + find * -name *.csproj | xargs -I % dotnet add % package coverlet.msbuild + dotnet test -v n --filter FullyQualifiedName!=Neo.UnitTests.UT_Culture.All_Tests_Cultures /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + fi +after_success: | + if [[ "$TEST_SUITE" == "without-cultures" ]]; then + echo "Test Success - Branch($TRAVIS_BRANCH) Pull Request($TRAVIS_PULL_REQUEST) Tag($TRAVIS_TAG)" + bash <(curl -s https://codecov.io/bash) -v + fi -script: - - dotnet restore - - find * -name *.csproj | xargs -I % dotnet add % package coverlet.msbuild - - dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover -after_success: - # After all tests OK, Send CodeDov report - - echo "Test Success - Branch($TRAVIS_BRANCH) Pull Request($TRAVIS_PULL_REQUEST) Tag($TRAVIS_TAG)" - - bash <(curl -s https://codecov.io/bash) -v From 2ef5d34cd88facbdfd13fd81edd8ad25012879b3 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Tue, 6 Aug 2019 16:25:12 +0800 Subject: [PATCH 20/54] Fixes #999 --- neo/Wallets/Wallet.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/neo/Wallets/Wallet.cs b/neo/Wallets/Wallet.cs index fc490dbea7..310d11032a 100644 --- a/neo/Wallets/Wallet.cs +++ b/neo/Wallets/Wallet.cs @@ -322,17 +322,17 @@ private Transaction MakeTransaction(Snapshot snapshot, TransactionAttribute[] at int size = Transaction.HeaderSize + attributes.GetVarSize() + script.GetVarSize() + IO.Helper.GetVarSize(hashes.Length); foreach (UInt160 hash in hashes) { - script = GetAccount(hash)?.Contract?.Script ?? snapshot.Contracts.TryGet(hash)?.Script; - if (script is null) continue; - if (script.IsSignatureContract()) + byte[] witness_script = GetAccount(hash)?.Contract?.Script ?? snapshot.Contracts.TryGet(hash)?.Script; + if (witness_script is null) continue; + if (witness_script.IsSignatureContract()) { - size += 66 + script.GetVarSize(); + size += 66 + witness_script.GetVarSize(); tx.NetworkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES64] + ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES33] + InteropService.GetPrice(InteropService.Neo_Crypto_CheckSig, null); } - else if (script.IsMultiSigContract(out int m, out int n)) + else if (witness_script.IsMultiSigContract(out int m, out int n)) { int size_inv = 65 * m; - size += IO.Helper.GetVarSize(size_inv) + size_inv + script.GetVarSize(); + size += IO.Helper.GetVarSize(size_inv) + size_inv + witness_script.GetVarSize(); tx.NetworkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES64] * m; using (ScriptBuilder sb = new ScriptBuilder()) tx.NetworkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(m).ToArray()[0]]; From 68271a961972c1acbc603f360b8dea3c58472af0 Mon Sep 17 00:00:00 2001 From: Charis Zhao Date: Wed, 7 Aug 2019 18:20:18 +0800 Subject: [PATCH 21/54] Add and update some Unit tests in IO module (#998) * testDemo * add dll lib * add dbsnapshot dispose * test get blocks in levelDBStore * add levelDBStore test funcs * fix levelDBStore funcs * add DbCache addInternal * differ db path * space * fix delete internal test * add test getInternal tryGetInternal move libleveldb.dll * add dbCache method test * add store test * add cache unit tests * add cache unit tests * up readonly max_capacity * fix leveldbexception * fix comment on UT_Cache * format * fix multithread test problem * up cache * update travis config * update travis.yml * test DbMetaDataCache * fix db directory * format and update travis for maxos * fix mac env travis * 2019/7/12 10:34 * 2019/7/12 11:01 * remove commented line * test BigDecimal * fix format and csproj * rm coverage.opencover.xml * update method name * add UT_P_Helper * modify UT_P_Helper * modify UT_P_helper * Clean ut * test Base58 & BloomFilter * Update UT_Cache.cs * Correct Typo * test JsonArray * update namespace * update namespace * update format * update format * organise folder structure * add UT_JString * test JBoolean JNumber & JObject * 2019/7/16 10:30 add some test case for UInt32Wrapper and SerializableWrapper * fix timestamp * test ECDsa and Crypto * test OrderedDictionary & complete IO.Json tests * 2019/7/16 17:33 add some test case of SQLiteWallet * test FIFOSet * add CloneCache and DataCache unit tests * fix namespace * add UT_Cryptography_Helper * format UT_CloneCache and UT_DataCache * add UT_DataCache.GetAndChange unit test * update namespace * remove comment code * delete Persistence part * 2019/7/19 11:07 add some test case for Helper in VM * Fix Base58 Test * 2019/7/19 11:33 change some format * update IOHelper exception assert * 2019/7/19 14:22 change format * format IOHelper * review IO.Wrapper * review Wallets.SQLite UT * Test ECFieldElement ECPoint * refactor package * format ECDsa * update namespace * Code fix * review cache * modify UT_JString * fomat * using Actin replace with try-catch * add UT_CloneMetaCache and UT_MetaDataCache * update namespace * format UT_DataCache.cs * Code Fix * format * update csproj * Code fix for UT_ECFieldElement and UT_ECPoint * Code fix * format * update travis * delete deleteFiles * fix path and comment * update travis * delete test ToTimeStamp * format UT_*Cache * update format * fomat * use hex extensions in Cryptography_Helper * remove reflection * optimization of UT_DataCache * update namespace * modify TestSha256 * update UT in crypto module * Rename UT_Scrypt.cs to UT_SCrypt.cs * format * update UT_Murmur3 * update IO module test * delete empty line * changename * delete empty line * revert commit --- .../Caching/{UT_FifoSet.cs => UT_FIFOSet.cs} | 43 +- .../IO/Caching/UT_OrderedDictionary.cs | 42 ++ .../IO/Caching/UT_ReflectionCache.cs | 80 ++++ neo.UnitTests/IO/Caching/UT_RelayCache.cs | 41 ++ neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs | 408 ++++++++++++++++++ neo.UnitTests/IO/Json/UT_JArray.cs | 21 +- neo.UnitTests/IO/Json/UT_JObject.cs | 1 - 7 files changed, 619 insertions(+), 17 deletions(-) rename neo.UnitTests/IO/Caching/{UT_FifoSet.cs => UT_FIFOSet.cs} (78%) create mode 100644 neo.UnitTests/IO/Caching/UT_ReflectionCache.cs create mode 100644 neo.UnitTests/IO/Caching/UT_RelayCache.cs create mode 100644 neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs diff --git a/neo.UnitTests/IO/Caching/UT_FifoSet.cs b/neo.UnitTests/IO/Caching/UT_FIFOSet.cs similarity index 78% rename from neo.UnitTests/IO/Caching/UT_FifoSet.cs rename to neo.UnitTests/IO/Caching/UT_FIFOSet.cs index cbbafae402..f36984b89f 100644 --- a/neo.UnitTests/IO/Caching/UT_FifoSet.cs +++ b/neo.UnitTests/IO/Caching/UT_FIFOSet.cs @@ -2,6 +2,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; using System; +using System.Collections; using System.Linq; namespace Neo.UnitTests.IO.Caching @@ -81,12 +82,38 @@ public void TestAdd() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }); - var set = new FIFOSet(1, 1); - set.Add(a); - set.Add(b); + var set = new FIFOSet(1, 1) + { + a, + b + }; CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { b }); } + [TestMethod] + public void TestGetEnumerator() + { + var a = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01 + }); + var b = new UInt256(new byte[32] { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02 + }); + var set = new FIFOSet(1, 1) + { + a, + b + }; + IEnumerable ie = set; + ie.GetEnumerator().Should().NotBeNull(); + } + [TestMethod] public void TestExceptWith() { @@ -109,10 +136,12 @@ public void TestExceptWith() 0x01, 0x03 }); - var set = new FIFOSet(10); - set.Add(a); - set.Add(b); - set.Add(c); + var set = new FIFOSet(10) + { + a, + b, + c + }; set.ExceptWith(new UInt256[] { b, c }); CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a }); } diff --git a/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs b/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs index 94d7b70ce1..262528cd88 100644 --- a/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs +++ b/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs @@ -1,6 +1,8 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; +using System.Collections; +using System.Collections.Generic; namespace Neo.UnitTests.IO.Caching { @@ -83,5 +85,45 @@ public void TestTryGetValue() od.TryGetValue("d", out uint j).Should().BeFalse(); j.Should().Be(0); } + + [TestMethod] + public void TestCollectionAddAndContains() + { + var pair = new KeyValuePair("d", 4); + ICollection> collection = od; + collection.Add(pair); + collection.Contains(pair).Should().BeTrue(); + } + + [TestMethod] + public void TestCollectionCopyTo() + { + var arr = new KeyValuePair[3]; + ICollection> collection = od; + collection.CopyTo(arr, 0); + arr[0].Key.Should().Be("a"); + arr[0].Value.Should().Be(1); + arr[1].Key.Should().Be("b"); + arr[1].Value.Should().Be(2); + arr[2].Key.Should().Be("c"); + arr[2].Value.Should().Be(3); + } + + [TestMethod] + public void TestCollectionRemove() + { + ICollection> collection = od; + var pair = new KeyValuePair("a", 1); + collection.Remove(pair); + collection.Contains(pair).Should().BeFalse(); + collection.Count.Should().Be(2); + } + + [TestMethod] + public void TestGetEnumerator() + { + IEnumerable collection = od; + collection.GetEnumerator().MoveNext().Should().BeTrue(); + } } } \ No newline at end of file diff --git a/neo.UnitTests/IO/Caching/UT_ReflectionCache.cs b/neo.UnitTests/IO/Caching/UT_ReflectionCache.cs new file mode 100644 index 0000000000..e7de68f3c1 --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_ReflectionCache.cs @@ -0,0 +1,80 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Caching; +using System; + +namespace Neo.UnitTests.IO.Caching +{ + public class TestItem { } + + public class TestItem1 : TestItem { } + + public class TestItem2 : TestItem { } + + public enum MyTestEnum : byte + { + [ReflectionCache(typeof(TestItem1))] + Item1 = 0x00, + + [ReflectionCache(typeof(TestItem2))] + Item2 = 0x01, + } + + public enum MyEmptyEnum : byte { } + + [TestClass] + public class UT_ReflectionCache + { + ReflectionCache reflectionCache; + + [TestInitialize] + public void SetUp() + { + reflectionCache = ReflectionCache.CreateFromEnum(); + } + + [TestMethod] + public void TestCreateFromEnum() + { + reflectionCache.Should().NotBeNull(); + } + + [TestMethod] + public void TestCreateFromObjectNotEnum() + { + Action action = () => ReflectionCache.CreateFromEnum(); + action.ShouldThrow(); + } + + [TestMethod] + public void TestCreateFromEmptyEnum() + { + reflectionCache = ReflectionCache.CreateFromEnum(); + reflectionCache.Count.Should().Be(0); + } + + [TestMethod] + public void TestCreateInstance() + { + object item1 = reflectionCache.CreateInstance((byte)MyTestEnum.Item1, null); + (item1 is TestItem1).Should().BeTrue(); + + object item2 = reflectionCache.CreateInstance((byte)MyTestEnum.Item2, null); + (item2 is TestItem2).Should().BeTrue(); + + object item3 = reflectionCache.CreateInstance(0x02, null); + item3.Should().BeNull(); + } + + [TestMethod] + public void TestCreateInstance2() + { + TestItem defaultItem = new TestItem1(); + object item2 = reflectionCache.CreateInstance((byte)MyTestEnum.Item2, defaultItem); + (item2 is TestItem2).Should().BeTrue(); + + object item1 = reflectionCache.CreateInstance(0x02, new TestItem1()); + (item1 is TestItem1).Should().BeTrue(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Caching/UT_RelayCache.cs b/neo.UnitTests/IO/Caching/UT_RelayCache.cs new file mode 100644 index 0000000000..537305e2ee --- /dev/null +++ b/neo.UnitTests/IO/Caching/UT_RelayCache.cs @@ -0,0 +1,41 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Caching; +using Neo.Network.P2P.Payloads; + +namespace Neo.UnitTests.IO.Caching +{ + [TestClass] + public class UT_RelayCache + { + RelayCache relayCache; + + [TestInitialize] + public void SetUp() + { + relayCache = new RelayCache(10); + } + + [TestMethod] + public void TestGetKeyForItem() + { + Transaction tx = new Transaction() + { + Version = 0, + Nonce = 1, + Sender = UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), + SystemFee = 0, + NetworkFee = 0, + ValidUntilBlock = 100, + Attributes = new TransactionAttribute[0], + Script = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 }, + Witnesses = new Witness[0] + }; + relayCache.Add(tx); + + relayCache.Contains(tx).Should().BeTrue(); + relayCache.TryGet(tx.Hash, out IInventory tmp).Should().BeTrue(); + (tmp is Transaction).Should().BeTrue(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs b/neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs new file mode 100644 index 0000000000..21dea9f1d1 --- /dev/null +++ b/neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs @@ -0,0 +1,408 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.IO.Data.LevelDB; +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Neo.UnitTests.IO.Data.LevelDb +{ + public class Test { } + + [TestClass] + public class UT_Slice + { + private Slice sliceTest; + + [TestMethod] + public void TestConstructor() + { + IntPtr parr = Marshal.AllocHGlobal(1); + Marshal.WriteByte(parr, 0x01); + UIntPtr plength = new UIntPtr(1); + sliceTest = new Slice(parr, plength); + Assert.IsNotNull(sliceTest); + Assert.IsInstanceOfType(sliceTest, typeof(Slice)); + Slice slice = (byte)0x01; + Assert.AreEqual(slice, sliceTest); + Marshal.FreeHGlobal(parr); + } + + [TestMethod] + public void TestCompareTo() + { + Slice slice = new byte[] { 0x01, 0x02 }; + sliceTest = new byte[] { 0x01, 0x02 }; + int result = sliceTest.CompareTo(slice); + Assert.AreEqual(0, result); + sliceTest = new byte[] { 0x01 }; + result = sliceTest.CompareTo(slice); + Assert.AreEqual(-1, result); + sliceTest = new byte[] { 0x01, 0x02, 0x03 }; + result = sliceTest.CompareTo(slice); + Assert.AreEqual(1, result); + sliceTest = new byte[] { 0x01, 0x03 }; + result = sliceTest.CompareTo(slice); + Assert.AreEqual(1, result); + sliceTest = new byte[] { 0x01, 0x01 }; + result = sliceTest.CompareTo(slice); + Assert.AreEqual(-1, result); + } + + [TestMethod] + public void TestEqualsSlice() + { + byte[] arr1 = { 0x01, 0x02 }; + byte[] arr2 = { 0x01, 0x02 }; + Slice slice = arr1; + sliceTest = arr1; + Assert.IsTrue(sliceTest.Equals(slice)); + sliceTest = arr2; + Assert.IsTrue(sliceTest.Equals(slice)); + sliceTest = new byte[] { 0x01, 0x03 }; + Assert.IsFalse(sliceTest.Equals(slice)); + } + + [TestMethod] + public void TestEqualsObj() + { + sliceTest = new byte[] { 0x01 }; + object slice = null; + bool result = sliceTest.Equals(slice); + Assert.AreEqual(false, result); + slice = new Test(); + result = sliceTest.Equals(slice); + Assert.AreEqual(false, result); + slice = sliceTest; + result = sliceTest.Equals(slice); + Assert.AreEqual(true, result); + Slice s = new byte[] { 0x01 }; + result = sliceTest.Equals(s); + Assert.AreEqual(true, result); + s = new byte[] { 0x01, 0x02 }; + result = sliceTest.Equals(s); + Assert.AreEqual(false, result); + } + + [TestMethod] + public void TestGetHashCode() + { + byte[] arr = new byte[] { 0x01, 0x02 }; + sliceTest = arr; + int hash1 = (int)arr.Murmur32(0); + int hash2 = sliceTest.GetHashCode(); + Assert.AreEqual(hash2, hash1); + } + + [TestMethod] + public void TestFromArray() + { + byte[] arr = new byte[]{ + 0x01,0x01,0x01,0x01, + }; + IntPtr parr = Marshal.AllocHGlobal(arr.Length); + for (int i = 0; i < arr.Length; i++) + { + Marshal.WriteByte(parr + i, 0x01); + } + UIntPtr plength = new UIntPtr((uint)arr.Length); + Slice slice = new Slice(parr, plength); + sliceTest = arr; + Assert.AreEqual(slice, sliceTest); + Marshal.FreeHGlobal(parr); + } + + [TestMethod] + public void TestToArray() + { + sliceTest = new Slice(); + byte[] arr = sliceTest.ToArray(); + Assert.AreEqual(0, arr.Length); + arr = new byte[] { 0x01, 0x02 }; + sliceTest = arr; + byte[] parr = sliceTest.ToArray(); + Assert.AreSame(parr, arr); + } + + [TestMethod] + public void TestToBoolean() + { + sliceTest = new byte[] { 0x01, 0x02 }; + Assert.ThrowsException(() => sliceTest.ToBoolean()); + sliceTest = (byte)0x01; + bool result = sliceTest.ToBoolean(); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestToByte() + { + sliceTest = new byte[] { 0x01, 0x02 }; + Assert.ThrowsException(() => sliceTest.ToByte()); + sliceTest = (byte)0x01; + byte result = sliceTest.ToByte(); + Assert.AreEqual((byte)0x01, result); + } + + [TestMethod] + public void TestToDouble() + { + sliceTest = new byte[] { 0x01 }; + Assert.ThrowsException(() => sliceTest.ToDouble()); + byte[] arr = new byte[sizeof(double)]; + sliceTest = arr; + double result = sliceTest.ToDouble(); + Assert.AreEqual(0D, result); + sliceTest = 0.5D; + Assert.AreEqual(0.5D, sliceTest.ToDouble()); + } + + [TestMethod] + public void TestToInt16() + { + sliceTest = new byte[] { 0x01 }; + Assert.ThrowsException(() => sliceTest.ToInt16()); + sliceTest = (Int16)(-15); + Assert.AreEqual((Int16)(-15), sliceTest.ToInt16()); + } + + [TestMethod] + public void TestToInt32() + { + sliceTest = new byte[] { 0x01 }; + Assert.ThrowsException(() => sliceTest.ToInt32()); + sliceTest = (Int32)(-15); + Assert.AreEqual((Int32)(-15), sliceTest.ToInt32()); + } + + [TestMethod] + public void TestToInt64() + { + sliceTest = new byte[] { 0x01 }; + Assert.ThrowsException(() => sliceTest.ToInt64()); + sliceTest = Int64.MaxValue; + Assert.AreEqual(Int64.MaxValue, sliceTest.ToInt64()); + } + + [TestMethod] + public void TestToSingle() + { + sliceTest = new byte[] { 0x01 }; + Assert.ThrowsException(() => sliceTest.ToSingle()); + sliceTest = (float)(-15.5); + Assert.AreEqual((float)(-15.5), sliceTest.ToSingle()); + } + + [TestMethod] + public void TestToString() + { + sliceTest = "abc你好"; + Assert.AreEqual("abc你好", sliceTest.ToString()); + } + + [TestMethod] + public void TestToUint16() + { + sliceTest = new byte[] { 0x01 }; + Assert.ThrowsException(() => sliceTest.ToUInt16()); + sliceTest = (UInt16)(25); + Assert.AreEqual((UInt16)25, sliceTest.ToUInt16()); + } + + [TestMethod] + public void TestToUint32() + { + sliceTest = new byte[] { 0x01 }; + Assert.ThrowsException(() => sliceTest.ToUInt32()); + sliceTest = (UInt32)(2525252525); + Assert.AreEqual((UInt32)2525252525, sliceTest.ToUInt32()); + } + + [TestMethod] + public void TestToUint64() + { + sliceTest = new byte[] { 0x01 }; + Assert.ThrowsException(() => sliceTest.ToUInt64()); + sliceTest = (UInt64)(0x2525252525252525); + Assert.AreEqual((UInt64)(0x2525252525252525), sliceTest.ToUInt64()); + } + + [TestMethod] + public void TestFromBool() + { + byte[] arr = { 0x01 }; + Slice slice = arr; + sliceTest = true; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromByte() + { + sliceTest = (byte)0x01; + byte[] arr = { 0x01 }; + Slice slice = arr; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromDouble() + { + Slice slice = BitConverter.GetBytes(1.23D); + sliceTest = 1.23D; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromShort() + { + Slice slice = BitConverter.GetBytes((short)1234); + sliceTest = (short)1234; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromInt() + { + Slice slice = BitConverter.GetBytes(-1234); + sliceTest = -1234; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromLong() + { + Slice slice = BitConverter.GetBytes(-1234L); + sliceTest = -1234L; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromFloat() + { + Slice slice = BitConverter.GetBytes(1.234F); + sliceTest = 1.234F; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromString() + { + string str = "abcdefghijklmnopqrstuvwxwz!@#$%^&*&()_+?><你好"; + Slice slice = Encoding.UTF8.GetBytes(str); + sliceTest = str; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromUnshort() + { + Slice slice = BitConverter.GetBytes((ushort)12345); + sliceTest = (ushort)12345; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromUint() + { + Slice slice = BitConverter.GetBytes((uint)12345); + sliceTest = (uint)12345; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestFromUlong() + { + Slice slice = BitConverter.GetBytes(12345678UL); + sliceTest = 12345678UL; + Assert.AreEqual(slice, sliceTest); + } + + [TestMethod] + public void TestLessThan() + { + sliceTest = new byte[] { 0x01 }; + Slice slice = new byte[] { 0x02 }; + bool result = sliceTest < slice; + Assert.AreEqual(true, result); + slice = new byte[] { 0x01 }; + result = sliceTest < slice; + Assert.AreEqual(false, result); + slice = new byte[] { 0x00 }; + result = sliceTest < slice; + Assert.AreEqual(false, result); + } + + [TestMethod] + public void TestLessThanAndEqual() + { + sliceTest = new byte[] { 0x01 }; + Slice slice = new byte[] { 0x02 }; + bool result = sliceTest <= slice; + Assert.AreEqual(true, result); + slice = new byte[] { 0x01 }; + result = sliceTest <= slice; + Assert.AreEqual(true, result); + slice = new byte[] { 0x00 }; + result = sliceTest <= slice; + Assert.AreEqual(false, result); + } + + [TestMethod] + public void TestGreatThan() + { + sliceTest = new byte[] { 0x01 }; + Slice slice = new byte[] { 0x00 }; + bool result = sliceTest > slice; + Assert.AreEqual(true, result); + slice = new byte[] { 0x01 }; + result = sliceTest > slice; + Assert.AreEqual(false, result); + slice = new byte[] { 0x02 }; + result = sliceTest > slice; + Assert.AreEqual(false, result); + } + + [TestMethod] + public void TestGreatThanAndEqual() + { + sliceTest = new byte[] { 0x01 }; + Slice slice = new byte[] { 0x00 }; + bool result = sliceTest >= slice; + Assert.AreEqual(true, result); + slice = new byte[] { 0x01 }; + result = sliceTest >= slice; + Assert.AreEqual(true, result); + slice = new byte[] { 0x02 }; + result = sliceTest >= slice; + Assert.AreEqual(false, result); + } + + [TestMethod] + public void TestEqual() + { + sliceTest = new byte[] { 0x01 }; + Slice slice = new byte[] { 0x00 }; + bool result = sliceTest == slice; + Assert.AreEqual(false, result); + slice = new byte[] { 0x01 }; + result = sliceTest == slice; + Assert.AreEqual(true, result); + slice = new byte[] { 0x02 }; + result = sliceTest == slice; + Assert.AreEqual(false, result); + } + + [TestMethod] + public void TestUnequal() + { + sliceTest = new byte[] { 0x01 }; + Slice slice = new byte[] { 0x00 }; + bool result = sliceTest != slice; + Assert.AreEqual(true, result); + slice = new byte[] { 0x01 }; + result = sliceTest != slice; + Assert.AreEqual(false, result); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/IO/Json/UT_JArray.cs b/neo.UnitTests/IO/Json/UT_JArray.cs index 7e6e81c8d3..1bb165f224 100644 --- a/neo.UnitTests/IO/Json/UT_JArray.cs +++ b/neo.UnitTests/IO/Json/UT_JArray.cs @@ -1,9 +1,9 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; -using FluentAssertions; using System; -using System.Linq; using System.Collections; +using System.Linq; namespace Neo.UnitTests.IO.Json { @@ -48,9 +48,11 @@ public void SetUp() [TestMethod] public void TestAdd() { - var jArray = new JArray(); - jArray.Add(alice); - jArray.Add(bob); + var jArray = new JArray + { + alice, + bob + }; var jAlice = jArray[0]; var jBob = jArray[1]; jAlice["name"].ToString().Should().Be(alice["name"].ToString()); @@ -104,9 +106,10 @@ public void TestClear() [TestMethod] public void TestContains() { - var jArray = new JArray(); - jArray.Add(alice); - + var jArray = new JArray + { + alice + }; jArray.Contains(alice).Should().BeTrue(); jArray.Contains(bob).Should().BeFalse(); } diff --git a/neo.UnitTests/IO/Json/UT_JObject.cs b/neo.UnitTests/IO/Json/UT_JObject.cs index 38781ed96a..3c8dff0b46 100644 --- a/neo.UnitTests/IO/Json/UT_JObject.cs +++ b/neo.UnitTests/IO/Json/UT_JObject.cs @@ -3,7 +3,6 @@ using Neo.IO.Json; using System; using System.IO; -using System.Reflection; namespace Neo.UnitTests.IO.Json { From a78d474671cfbfe6d44e2f046553056fa7f31a8d Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 8 Aug 2019 11:14:01 +0200 Subject: [PATCH 22/54] Fix (#1008) --- neo/Wallets/Wallet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/Wallets/Wallet.cs b/neo/Wallets/Wallet.cs index 310d11032a..b68733bb71 100644 --- a/neo/Wallets/Wallet.cs +++ b/neo/Wallets/Wallet.cs @@ -303,7 +303,7 @@ private Transaction MakeTransaction(Snapshot snapshot, TransactionAttribute[] at ValidUntilBlock = snapshot.Height + Transaction.MaxValidUntilBlockIncrement, Attributes = attributes }; - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, tx, testMode: true)) + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot.Clone(), tx, testMode: true)) { if (engine.State.HasFlag(VMState.FAULT)) throw new InvalidOperationException($"Failed execution for '{script.ToHexString()}'"); From 2bbcb1448dc01345dfd102cdfccb8f216a72f648 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 8 Aug 2019 13:46:39 +0200 Subject: [PATCH 23/54] Fix for 1005 (#1006) --- neo/SmartContract/Native/Tokens/Nep5AccountState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/SmartContract/Native/Tokens/Nep5AccountState.cs b/neo/SmartContract/Native/Tokens/Nep5AccountState.cs index 2cc19f4619..c775f044ec 100644 --- a/neo/SmartContract/Native/Tokens/Nep5AccountState.cs +++ b/neo/SmartContract/Native/Tokens/Nep5AccountState.cs @@ -19,7 +19,7 @@ public Nep5AccountState(byte[] data) public void FromByteArray(byte[] data) { - FromStruct((Struct)data.DeserializeStackItem(16, 32)); + FromStruct((Struct)data.DeserializeStackItem(16, 34)); } protected virtual void FromStruct(Struct @struct) From 87b7a302092cabd1af11022939423a322f6d598d Mon Sep 17 00:00:00 2001 From: belane Date: Sat, 10 Aug 2019 20:38:59 +0200 Subject: [PATCH 24/54] Fix null values during ChangeViewReason (#1016) --- neo/Consensus/ConsensusService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index e4983830a4..8723b2c70b 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -551,7 +551,7 @@ private void OnTimer(Timer timer) { var reason = ChangeViewReason.Timeout; - if (context.Block != null && context.TransactionHashes.Count() > context.Transactions.Count) + if (context.Block != null && context.TransactionHashes?.Count() > context.Transactions?.Count) { reason = ChangeViewReason.TxNotFound; } From 5076573fb5820b7581cb69708d36d535d6dc4355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?= Date: Sun, 11 Aug 2019 10:06:31 -0300 Subject: [PATCH 25/54] Avoid processing own hashes (3x) (#1009) * Avoid processing own hashes * Shargon's suggestion I * Shargon's suggestion II * rename --- neo/IO/Caching/FIFOSet.cs | 5 +++++ neo/Network/P2P/ProtocolHandler.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/neo/IO/Caching/FIFOSet.cs b/neo/IO/Caching/FIFOSet.cs index 7769cb5ad5..aba54463ae 100644 --- a/neo/IO/Caching/FIFOSet.cs +++ b/neo/IO/Caching/FIFOSet.cs @@ -41,6 +41,11 @@ public bool Add(T item) return true; } + public bool Contains(T item) + { + return dictionary.Contains(item); + } + public void ExceptWith(IEnumerable hashes) { foreach (var hash in hashes) diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index 7f9821709b..234c42d9ef 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -248,7 +248,7 @@ private void OnInventoryReceived(IInventory inventory) private void OnInvMessageReceived(InvPayload payload) { - UInt256[] hashes = payload.Hashes.Where(p => knownHashes.Add(p)).ToArray(); + UInt256[] hashes = payload.Hashes.Where(p => knownHashes.Add(p) && !sentHashes.Contains(p)).ToArray(); if (hashes.Length == 0) return; switch (payload.Type) { From 1d6ca8471b6a00c1260c46ad634c863f488ab5e8 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 12 Aug 2019 09:34:39 +0300 Subject: [PATCH 26/54] Scoped signatures (#968) * Base * Check Witness * Fix some unit tests * More ut fixes * Clean code * Fix more unit tests * Fake witness for make transfer * Fix ut * Simplifying if * rename to RootAccess * adding scope type, preparing for cosigners * reading scope from stream * attaching CosignerUsage * calculate scope size * Finish cosigner usage * Global constant * Clean * AsSerializable @erikzhang * avoiding empty scope data serialization * fix logic * moved scopes to Transaction * fixed tests * Change CheckWitness * Follow the standard * rename var * Remove FakeWitness * Fix cosigner ussage * Clean * Fix CosignerUsage * fix RootAccess * removed not null * fixed malformed tx generation * no need for attribute on all test tx * testing sizes * renamed RootAccess to EntryOnly, and explained enum compositions * discovering which size is wrong * Remove spaces * doubts on scope sign test * removing scopes everywhere * wrong tx size * fixed tests * remove print * more scope tests * reorder * revert changes on Witness * Modify CheckWitness * Reduce changes * Fix Cosigner usage * Combine CosignerUsage * Indent * filtering groups by pubkey * Organize * Rename ScriptHash to Account * renamed EntryOnly to CalledByEntry * dotnet format * fix file UT_CosignerUsage * tests for double cosigners * assert catch exceptions * clean and format * improvements * Format ut exceptions * Rename ut * Remove changes * Follow comment standard * Rename to Cosigner * Move cosigners outside * Clean comments * Reorder the parameters * Fix unit tests * limit max cosigners by 16 (same as attributes) * testing non-distinct cosigners * respect max cosigners * MaxSubitems * test CalledByEntry together with GAS * Update comment * Clean comments * Global=0 * Fix ut * broken test for combination Global | NEO * back to global 0x80 * global back to 0x00, as default * Update comment --- .../Cryptography/UT_Cryptography_Helper.cs | 1 + .../Nep5NativeContractExtensions.cs | 12 +- neo.UnitTests/IO/Caching/UT_RelayCache.cs | 1 + neo.UnitTests/Ledger/UT_MemoryPool.cs | 1 + neo.UnitTests/Ledger/UT_PoolItem.cs | 11 +- .../Network/P2P/Payloads/UT_Block.cs | 49 +- .../Network/P2P/Payloads/UT_Cosigner.cs | 165 ++++ .../Network/P2P/Payloads/UT_Header.cs | 29 +- .../Network/P2P/Payloads/UT_Transaction.cs | 820 +++++++++++++++++- .../Native/Tokens/UT_NeoToken.cs | 2 +- .../SmartContract/Native/UT_PolicyContract.cs | 8 +- neo.UnitTests/TestUtils.cs | 2 + neo/Ledger/Blockchain.cs | 1 + neo/Network/P2P/Payloads/Cosigner.cs | 76 ++ neo/Network/P2P/Payloads/Transaction.cs | 15 +- .../P2P/Payloads/TransactionAttributeUsage.cs | 1 - neo/Network/P2P/Payloads/WitnessScope.cs | 31 + .../ContractParametersContext.cs | 8 + neo/SmartContract/InteropService.cs | 31 +- neo/Wallets/Wallet.cs | 32 +- 20 files changed, 1204 insertions(+), 92 deletions(-) create mode 100644 neo.UnitTests/Network/P2P/Payloads/UT_Cosigner.cs create mode 100644 neo/Network/P2P/Payloads/Cosigner.cs create mode 100644 neo/Network/P2P/Payloads/WitnessScope.cs diff --git a/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index 06f672ff77..d7a3e65136 100644 --- a/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -145,6 +145,7 @@ public void TestTest() Sender = UInt160.Zero, SystemFee = 4200000000, Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], Witnesses = new[] { new Witness diff --git a/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs b/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs index 42c5c87543..a9aa8a7777 100644 --- a/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs +++ b/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs @@ -12,9 +12,9 @@ namespace Neo.UnitTests.Extensions { public static class Nep5NativeContractExtensions - { + { internal class ManualWitness : IVerifiable - { + { private readonly UInt160[] _hashForVerify; public Witness[] Witnesses @@ -34,14 +34,14 @@ public ManualWitness(params UInt160[] hashForVerify) public void DeserializeUnsigned(BinaryReader reader) { } - public UInt160[] GetScriptHashesForVerifying(Neo.Persistence.Snapshot snapshot) => _hashForVerify; + public UInt160[] GetScriptHashesForVerifying(Persistence.Snapshot snapshot) => _hashForVerify; public void Serialize(BinaryWriter writer) { } public void SerializeUnsigned(BinaryWriter writer) { } } - public static bool Transfer(this NativeContract contract, Neo.Persistence.Snapshot snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom) + public static bool Transfer(this NativeContract contract, Persistence.Snapshot snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom) { var engine = new ApplicationEngine(TriggerType.Application, new ManualWitness(signFrom ? new UInt160(from) : null), snapshot, 0, true); @@ -90,7 +90,7 @@ public static string[] SupportedStandards(this NativeContract contract) .ToArray(); } - public static BigInteger TotalSupply(this NativeContract contract, Neo.Persistence.Snapshot snapshot) + public static BigInteger TotalSupply(this NativeContract contract, Persistence.Snapshot snapshot) { var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); @@ -110,7 +110,7 @@ public static BigInteger TotalSupply(this NativeContract contract, Neo.Persisten return (result as VM.Types.Integer).GetBigInteger(); } - public static BigInteger BalanceOf(this NativeContract contract, Neo.Persistence.Snapshot snapshot, byte[] account) + public static BigInteger BalanceOf(this NativeContract contract, Persistence.Snapshot snapshot, byte[] account) { var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); diff --git a/neo.UnitTests/IO/Caching/UT_RelayCache.cs b/neo.UnitTests/IO/Caching/UT_RelayCache.cs index 537305e2ee..ed41c1128a 100644 --- a/neo.UnitTests/IO/Caching/UT_RelayCache.cs +++ b/neo.UnitTests/IO/Caching/UT_RelayCache.cs @@ -27,6 +27,7 @@ public void TestGetKeyForItem() SystemFee = 0, NetworkFee = 0, ValidUntilBlock = 100, + Cosigners = new Cosigner[0], Attributes = new TransactionAttribute[0], Script = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04 }, Witnesses = new Witness[0] diff --git a/neo.UnitTests/Ledger/UT_MemoryPool.cs b/neo.UnitTests/Ledger/UT_MemoryPool.cs index 1b5af16240..96b0e99a19 100644 --- a/neo.UnitTests/Ledger/UT_MemoryPool.cs +++ b/neo.UnitTests/Ledger/UT_MemoryPool.cs @@ -54,6 +54,7 @@ private Transaction CreateTransactionWithFee(long fee) mock.Object.Sender = UInt160.Zero; mock.Object.NetworkFee = fee; mock.Object.Attributes = new TransactionAttribute[0]; + mock.Object.Cosigners = new Cosigner[0]; mock.Object.Witnesses = new[] { new Witness diff --git a/neo.UnitTests/Ledger/UT_PoolItem.cs b/neo.UnitTests/Ledger/UT_PoolItem.cs index d8f4e4f696..e87aad3ffe 100644 --- a/neo.UnitTests/Ledger/UT_PoolItem.cs +++ b/neo.UnitTests/Ledger/UT_PoolItem.cs @@ -2,6 +2,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Neo.Ledger; +using Neo.IO; using Neo.Network.P2P.Payloads; using System; @@ -36,10 +37,10 @@ public void TestCleanup() [TestMethod] public void PoolItem_CompareTo_Fee() { - int size1 = 50; + int size1 = 51; int netFeeSatoshi1 = 1; var tx1 = GenerateTx(netFeeSatoshi1, size1); - int size2 = 50; + int size2 = 51; int netFeeSatoshi2 = 2; var tx2 = GenerateTx(netFeeSatoshi2, size2); @@ -56,7 +57,7 @@ public void PoolItem_CompareTo_Fee() [TestMethod] public void PoolItem_CompareTo_Hash() { - int sizeFixed = 50; + int sizeFixed = 51; int netFeeSatoshiFixed = 1; for (int testRuns = 0; testRuns < 30; testRuns++) @@ -122,6 +123,7 @@ public static Transaction GenerateTx(long networkFee, int size, byte[] overrideS Sender = UInt160.Zero, NetworkFee = networkFee, Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], Witnesses = new[] { new Witness @@ -132,6 +134,9 @@ public static Transaction GenerateTx(long networkFee, int size, byte[] overrideS } }; + tx.Attributes.Length.Should().Be(0); + tx.Cosigners.Length.Should().Be(0); + int diff = size - tx.Size; if (diff < 0) throw new ArgumentException(); if (diff > 0) diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs index 6736d8f936..f27421dd74 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs @@ -1,9 +1,9 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO; using Neo.IO.Json; using Neo.Network.P2P.Payloads; using System.IO; -using System.Text; namespace Neo.UnitTests.Network.P2P.Payloads { @@ -43,7 +43,7 @@ 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 + 64 + 32 + 4 + 4 + 20 + 4 + // blockbase 4 + 64 + 1 + 32 + 4 + 4 + 20 + 4 // block 9 + 1 uut.Size.Should().Be(114); } @@ -59,7 +59,7 @@ public void Size_Get_1_Transaction() TestUtils.GetTransaction() }; - uut.Size.Should().Be(165); + uut.Size.Should().Be(166); } [TestMethod] @@ -75,7 +75,7 @@ public void Size_Get_3_Transaction() TestUtils.GetTransaction() }; - uut.Size.Should().Be(267); + uut.Size.Should().Be(270); } [TestMethod] @@ -84,22 +84,8 @@ public void Serialize() UInt256 val256 = UInt256.Zero; TestUtils.SetupBlockWithValues(uut, val256, out var _, out var _, out var _, out var _, out var _, out var _, 1); - byte[] data; - using (MemoryStream stream = new MemoryStream()) - { - using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true)) - { - uut.Serialize(writer); - data = stream.ToArray(); - } - } - - 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++) - { - data[i].Should().Be(requiredData[i]); - } + var hex = "0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d8e913ff854c000000000000000000000000000000000000000000000000000000010001510200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000"; + uut.ToArray().ToHexString().Should().Be(hex); } [TestMethod] @@ -108,17 +94,13 @@ public void Deserialize() UInt256 val256 = UInt256.Zero; TestUtils.SetupBlockWithValues(new Block(), val256, out var merkRoot, out var val160, out var timestampVal, out var indexVal, out var scriptVal, out var transactionsVal, 1); - 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, 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 }; + var hex = "0000000000000000000000000000000000000000000000000000000000000000000000007227ba7b747f1a98f68679d4a98b68927646ab195a6f56b542ca5a0e6a412662e913ff854c000000000000000000000000000000000000000000000000000000010001510200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000"; - int index = 0; - using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false)) + using (MemoryStream ms = new MemoryStream(hex.HexToBytes(), false)) + using (BinaryReader reader = new BinaryReader(ms)) { - using (BinaryReader reader = new BinaryReader(ms)) - { - uut.Deserialize(reader); - } + uut.Deserialize(reader); + merkRoot = uut.MerkleRoot; } assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal, transactionsVal); @@ -218,7 +200,7 @@ public void ToJson() JObject jObj = uut.ToJson(); jObj.Should().NotBeNull(); jObj["hash"].AsString().Should().Be("0x4e1d8392e7c44830e7e45c18e5e0e3ef3c36af883868846d3691a436a62494b2"); - jObj["size"].AsNumber().Should().Be(165); + jObj["size"].AsNumber().Should().Be(166); jObj["version"].AsNumber().Should().Be(0); jObj["previousblockhash"].AsString().Should().Be("0x0000000000000000000000000000000000000000000000000000000000000000"); jObj["merkleroot"].AsString().Should().Be("0xd841af3d6bd7adb4bca24306725f9aec363edb10de3cafc5f8cca948d7b0290f"); @@ -232,10 +214,11 @@ public void ToJson() jObj["tx"].Should().NotBeNull(); JArray txObj = (JArray)jObj["tx"]; - txObj[0]["hash"].AsString().Should().Be("0x64ed4e0d79407c60bde534feb44fbbd19bd065282d27ecd3a1a7a647f66affa6"); - txObj[0]["size"].AsNumber().Should().Be(51); + txObj[0]["hash"].AsString().Should().Be("0xf374032ea013e3d9272f7a25dc1fe497a489ae36e94aa06270b26e60ab693435"); + txObj[0]["size"].AsNumber().Should().Be(52); txObj[0]["version"].AsNumber().Should().Be(0); ((JArray)txObj[0]["attributes"]).Count.Should().Be(0); + ((JArray)txObj[0]["cosigners"]).Count.Should().Be(0); txObj[0]["net_fee"].AsString().Should().Be("0"); } } diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Cosigner.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Cosigner.cs new file mode 100644 index 0000000000..ef6124b3a8 --- /dev/null +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Cosigner.cs @@ -0,0 +1,165 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.IO.Json; +using Neo.Network.P2P.Payloads; + +namespace Neo.UnitTests.Network.P2P.Payloads +{ + [TestClass] + public class UT_Cosigner + { + [TestMethod] + public void Serialize_Deserialize_Global() + { + var attr = new Cosigner() + { + Scopes = WitnessScope.Global, + Account = UInt160.Zero + }; + + var hex = "000000000000000000000000000000000000000000"; + attr.ToArray().ToHexString().Should().Be(hex); + + var copy = hex.HexToBytes().AsSerializable(); + + Assert.AreEqual(attr.Scopes, copy.Scopes); + Assert.AreEqual(attr.Account, copy.Account); + } + + [TestMethod] + public void Serialize_Deserialize_CalledByEntry() + { + var attr = new Cosigner() + { + Scopes = WitnessScope.CalledByEntry, + Account = UInt160.Zero + }; + + var hex = "000000000000000000000000000000000000000001"; + attr.ToArray().ToHexString().Should().Be(hex); + + var copy = hex.HexToBytes().AsSerializable(); + + Assert.AreEqual(attr.Scopes, copy.Scopes); + Assert.AreEqual(attr.Account, copy.Account); + } + + [TestMethod] + public void Serialize_Deserialize_CustomContracts() + { + var attr = new Cosigner() + { + Scopes = WitnessScope.CustomContracts, + AllowedContracts = new[] { UInt160.Zero }, + Account = UInt160.Zero + }; + + var hex = "000000000000000000000000000000000000000010010000000000000000000000000000000000000000"; + attr.ToArray().ToHexString().Should().Be(hex); + + var copy = hex.HexToBytes().AsSerializable(); + + Assert.AreEqual(attr.Scopes, copy.Scopes); + CollectionAssert.AreEqual(attr.AllowedContracts, copy.AllowedContracts); + Assert.AreEqual(attr.Account, copy.Account); + } + + [TestMethod] + public void Serialize_Deserialize_CustomGroups() + { + var attr = new Cosigner() + { + Scopes = WitnessScope.CustomGroups, + AllowedGroups = new[] { ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1) }, + Account = UInt160.Zero + }; + + var hex = "0000000000000000000000000000000000000000200103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"; + attr.ToArray().ToHexString().Should().Be(hex); + + var copy = hex.HexToBytes().AsSerializable(); + + Assert.AreEqual(attr.Scopes, copy.Scopes); + CollectionAssert.AreEqual(attr.AllowedGroups, copy.AllowedGroups); + Assert.AreEqual(attr.Account, copy.Account); + } + + [TestMethod] + public void Json_Global() + { + var attr = new Cosigner() + { + Scopes = WitnessScope.Global, + Account = UInt160.Zero + }; + + var json = "{\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"Global\"}"; + attr.ToJson().ToString().Should().Be(json); + + var copy = Cosigner.FromJson(JObject.Parse(json)); + + Assert.AreEqual(attr.Scopes, copy.Scopes); + Assert.AreEqual(attr.Account, copy.Account); + } + + [TestMethod] + public void Json_CalledByEntry() + { + var attr = new Cosigner() + { + Scopes = WitnessScope.CalledByEntry, + Account = UInt160.Zero + }; + + var json = "{\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"CalledByEntry\"}"; + attr.ToJson().ToString().Should().Be(json); + + var copy = Cosigner.FromJson(JObject.Parse(json)); + + Assert.AreEqual(attr.Scopes, copy.Scopes); + Assert.AreEqual(attr.Account, copy.Account); + } + + [TestMethod] + public void Json_CustomContracts() + { + var attr = new Cosigner() + { + Scopes = WitnessScope.CustomContracts, + AllowedContracts = new[] { UInt160.Zero }, + Account = UInt160.Zero + }; + + var json = "{\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"CustomContracts\",\"allowedContracts\":[\"0x0000000000000000000000000000000000000000\"]}"; + attr.ToJson().ToString().Should().Be(json); + + var copy = Cosigner.FromJson(JObject.Parse(json)); + + Assert.AreEqual(attr.Scopes, copy.Scopes); + CollectionAssert.AreEqual(attr.AllowedContracts, copy.AllowedContracts); + Assert.AreEqual(attr.Account, copy.Account); + } + + [TestMethod] + public void Json_CustomGroups() + { + var attr = new Cosigner() + { + Scopes = WitnessScope.CustomGroups, + AllowedGroups = new[] { ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1) }, + Account = UInt160.Zero + }; + + var json = "{\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"CustomGroups\",\"allowedGroups\":[\"03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c\"]}"; + attr.ToJson().ToString().Should().Be(json); + + var copy = Cosigner.FromJson(JObject.Parse(json)); + + Assert.AreEqual(attr.Scopes, copy.Scopes); + CollectionAssert.AreEqual(attr.AllowedGroups, copy.AllowedGroups); + Assert.AreEqual(attr.Account, copy.Account); + } + } +} diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs index 8002f4b196..b367a3efbd 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs @@ -1,8 +1,8 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO; using Neo.Network.P2P.Payloads; using System.IO; -using System.Text; namespace Neo.UnitTests.Network.P2P.Payloads { @@ -22,7 +22,7 @@ public void Size_Get() { UInt256 val256 = UInt256.Zero; TestUtils.SetupHeaderWithValues(uut, val256, out _, out _, out _, out _, out _); - // blockbase 4 + 64 + 32 + 4 + 4 + 20 + 4 + // blockbase 4 + 64 + 1 + 32 + 4 + 4 + 20 + 4 // header 1 uut.Size.Should().Be(105); } @@ -35,10 +35,9 @@ public void Deserialize() uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid - 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 }; + var hex = "0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d8e913ff854c0000000000000000000000000000000000000000000000000000000100015100"; - int index = 0; - using (MemoryStream ms = new MemoryStream(requiredData, index, requiredData.Length - index, false)) + using (MemoryStream ms = new MemoryStream(hex.HexToBytes(), false)) { using (BinaryReader reader = new BinaryReader(ms)) { @@ -97,24 +96,8 @@ public void Serialize() UInt256 val256 = UInt256.Zero; TestUtils.SetupHeaderWithValues(uut, val256, out _, out _, out _, out _, out _); - byte[] data; - using (MemoryStream stream = new MemoryStream()) - { - using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true)) - { - uut.Serialize(writer); - data = stream.ToArray(); - } - } - - 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]); - } + var hex = "0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d8e913ff854c0000000000000000000000000000000000000000000000000000000100015100"; + uut.ToArray().ToHexString().Should().Be(hex); } } } diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index 2dfa8b4c35..2c81e91537 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -12,6 +12,8 @@ using Neo.VM; using Neo.Wallets; using Neo.Wallets.NEP6; +using System; +using System.Numerics; namespace Neo.UnitTests.Network.P2P.Payloads { @@ -66,6 +68,7 @@ public void Size_Get() uut.Script = TestUtils.GetByteArray(32, 0x42); uut.Sender = UInt160.Zero; uut.Attributes = new TransactionAttribute[0]; + uut.Cosigners = new Cosigner[0]; uut.Witnesses = new[] { new Witness @@ -78,7 +81,7 @@ public void Size_Get() uut.Version.Should().Be(0); uut.Script.Length.Should().Be(32); uut.Script.GetVarSize().Should().Be(33); - uut.Size.Should().Be(82); + uut.Size.Should().Be(83); } private NEP6Wallet GenerateTestWallet() @@ -175,12 +178,15 @@ public void FeeIsMultiSigContract() } var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); - Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); + Assert.AreEqual(verificationGas, 2000540); + Assert.AreEqual(sizeGas, 358000); + Assert.AreEqual(verificationGas + sizeGas, 2358540); + Assert.AreEqual(tx.NetworkFee, 2358540); } } [TestMethod] - public void FeeIsSignatureContract() + public void FeeIsSignatureContractDetailed() { var wallet = GenerateTestWallet(); var snapshot = store.GetSnapshot(); @@ -206,6 +212,7 @@ public void FeeIsSignatureContract() // Make transaction + // self-transfer of 1e-8 GAS var tx = wallet.MakeTransaction(new TransferOutput[] { new TransferOutput() @@ -217,12 +224,26 @@ public void FeeIsSignatureContract() }, acc.ScriptHash); Assert.IsNotNull(tx); + Assert.IsNull(tx.Witnesses); + + // check pre-computed network fee (already guessing signature sizes) + tx.NetworkFee.Should().Be(1257240); + // ---- // Sign + // ---- var data = new ContractParametersContext(tx); - Assert.IsTrue(wallet.Sign(data)); + // 'from' is always required as witness + // if not included on cosigner with a scope, its scope should be considered 'CalledByEntry' + data.ScriptHashes.Count.Should().Be(1); + data.ScriptHashes[0].ShouldBeEquivalentTo(acc.ScriptHash); + // will sign tx + bool signed = wallet.Sign(data); + Assert.IsTrue(signed); + // get witnesses from signed 'data' tx.Witnesses = data.GetWitnesses(); + tx.Witnesses.Length.Should().Be(1); // Fast check @@ -243,8 +264,791 @@ public void FeeIsSignatureContract() verificationGas += engine.GasConsumed; } } + Assert.AreEqual(verificationGas, 1000240); + + // ------------------ + // check tx_size cost + // ------------------ + Assert.AreEqual(tx.Size, 257); + + // will verify tx size, step by step + + // Part I + Assert.AreEqual(Transaction.HeaderSize, 45); + // Part II + Assert.AreEqual(tx.Attributes.GetVarSize(), 1); + Assert.AreEqual(tx.Attributes.Length, 0); + Assert.AreEqual(tx.Cosigners.Length, 1); + Assert.AreEqual(tx.Cosigners.GetVarSize(), 22); + // Note that Data size and Usage size are different (because of first byte on GetVarSize()) + Assert.AreEqual(tx.Cosigners[0].Size, 21); + // Part III + Assert.AreEqual(tx.Script.GetVarSize(), 82); + // Part IV + Assert.AreEqual(tx.Witnesses.GetVarSize(), 107); + // I + II + III + IV + Assert.AreEqual(tx.Size, 45 + 23 + 82 + 107); + + Assert.AreEqual(NativeContract.Policy.GetFeePerByte(snapshot), 1000); + var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); + Assert.AreEqual(sizeGas, 257000); + + // final check on sum: verification_cost + tx_size + Assert.AreEqual(verificationGas + sizeGas, 1257240); + // final assert + Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); + } + } + + [TestMethod] + public void FeeIsSignatureContract_TestScope_Global() + { + var wallet = GenerateTestWallet(); + var snapshot = store.GetSnapshot(); + + // no password on this wallet + using (var unlock = wallet.Unlock("")) + { + var acc = wallet.CreateAccount(); + + // Fake balance + + var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); + + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + // Make transaction + // Manually creating script + + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + // self-transfer of 1e-8 GAS + System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; + sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.Emit(OpCode.THROWIFNOT); + script = sb.ToArray(); + } + + // trying global scope + var cosigners = new Cosigner[]{ new Cosigner + { + Account = acc.ScriptHash, + Scopes = WitnessScope.Global + } }; + + // using this... + + var tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners); + + Assert.IsNotNull(tx); + Assert.IsNull(tx.Witnesses); + + // ---- + // Sign + // ---- + + var data = new ContractParametersContext(tx); + bool signed = wallet.Sign(data); + Assert.IsTrue(signed); + + // get witnesses from signed 'data' + tx.Witnesses = data.GetWitnesses(); + tx.Witnesses.Length.Should().Be(1); + + // Fast check + Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); + + // Check + long verificationGas = 0; + foreach (var witness in tx.Witnesses) + { + using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false)) + { + engine.LoadScript(witness.VerificationScript); + engine.LoadScript(witness.InvocationScript); + Assert.AreEqual(VMState.HALT, engine.Execute()); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); + verificationGas += engine.GasConsumed; + } + } + // get sizeGas + var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); + // final check on sum: verification_cost + tx_size + Assert.AreEqual(verificationGas + sizeGas, 1257240); + // final assert + Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); + } + } + + [TestMethod] + public void FeeIsSignatureContract_TestScope_CurrentHash_GAS() + { + var wallet = GenerateTestWallet(); + var snapshot = store.GetSnapshot(); + + // no password on this wallet + using (var unlock = wallet.Unlock("")) + { + var acc = wallet.CreateAccount(); + + // Fake balance + + var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); + + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + // Make transaction + // Manually creating script + + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + // self-transfer of 1e-8 GAS + System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; + sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.Emit(OpCode.THROWIFNOT); + script = sb.ToArray(); + } + + // trying global scope + var cosigners = new Cosigner[]{ new Cosigner + { + Account = acc.ScriptHash, + Scopes = WitnessScope.CustomContracts, + AllowedContracts = new[] { NativeContract.GAS.Hash } + } }; + + // using this... + + var tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners); + + Assert.IsNotNull(tx); + Assert.IsNull(tx.Witnesses); + + // ---- + // Sign + // ---- + + var data = new ContractParametersContext(tx); + bool signed = wallet.Sign(data); + Assert.IsTrue(signed); + + // get witnesses from signed 'data' + tx.Witnesses = data.GetWitnesses(); + tx.Witnesses.Length.Should().Be(1); + + // Fast check + Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); + + // Check + long verificationGas = 0; + foreach (var witness in tx.Witnesses) + { + using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false)) + { + engine.LoadScript(witness.VerificationScript); + engine.LoadScript(witness.InvocationScript); + Assert.AreEqual(VMState.HALT, engine.Execute()); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); + verificationGas += engine.GasConsumed; + } + } + // get sizeGas + var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); + // final check on sum: verification_cost + tx_size + Assert.AreEqual(verificationGas + sizeGas, 1278240); + // final assert + Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); + } + } + [TestMethod] + public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() + { + var wallet = GenerateTestWallet(); + var snapshot = store.GetSnapshot(); + + // no password on this wallet + using (var unlock = wallet.Unlock("")) + { + var acc = wallet.CreateAccount(); + + // Fake balance + + var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); + + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + // Make transaction + // Manually creating script + + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + // self-transfer of 1e-8 GAS + System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; + sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.Emit(OpCode.THROWIFNOT); + script = sb.ToArray(); + } + + // trying CalledByEntry together with GAS + var cosigners = new Cosigner[]{ new Cosigner + { + Account = acc.ScriptHash, + // This combination is supposed to actually be an OR, + // where it's valid in both Entry and also for Custom hash provided (in any execution level) + // it would be better to test this in the future including situations where a deeper call level uses this custom witness successfully + Scopes = WitnessScope.CustomContracts | WitnessScope.CalledByEntry, + AllowedContracts = new[] { NativeContract.GAS.Hash } + } }; + + // using this... + + var tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners); + + Assert.IsNotNull(tx); + Assert.IsNull(tx.Witnesses); + + // ---- + // Sign + // ---- + + var data = new ContractParametersContext(tx); + bool signed = wallet.Sign(data); + Assert.IsTrue(signed); + + // get witnesses from signed 'data' + tx.Witnesses = data.GetWitnesses(); + tx.Witnesses.Length.Should().Be(1); + + // Fast check + Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); + + // Check + long verificationGas = 0; + foreach (var witness in tx.Witnesses) + { + using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false)) + { + engine.LoadScript(witness.VerificationScript); + engine.LoadScript(witness.InvocationScript); + Assert.AreEqual(VMState.HALT, engine.Execute()); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); + verificationGas += engine.GasConsumed; + } + } + // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); + // final check on sum: verification_cost + tx_size + Assert.AreEqual(verificationGas + sizeGas, 1278240); + // final assert + Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); + } + } + + [TestMethod] + public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_FAULT() + { + var wallet = GenerateTestWallet(); + var snapshot = store.GetSnapshot(); + + // no password on this wallet + using (var unlock = wallet.Unlock("")) + { + var acc = wallet.CreateAccount(); + + // Fake balance + + var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); + + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + // Make transaction + // Manually creating script + + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + // self-transfer of 1e-8 GAS + System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; + sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.Emit(OpCode.THROWIFNOT); + script = sb.ToArray(); + } + + // trying global scope + var cosigners = new Cosigner[]{ new Cosigner + { + Account = acc.ScriptHash, + Scopes = WitnessScope.CustomContracts, + AllowedContracts = new[] { NativeContract.NEO.Hash } + } }; + + // using this... + + // expects FAULT on execution of 'transfer' Application script + // due to lack of a valid witness validation + Transaction tx = null; + Assert.ThrowsException(() => + tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners)); + Assert.IsNull(tx); + } + } + + [TestMethod] + public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() + { + var wallet = GenerateTestWallet(); + var snapshot = store.GetSnapshot(); + + // no password on this wallet + using (var unlock = wallet.Unlock("")) + { + var acc = wallet.CreateAccount(); + + // Fake balance + + var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); + + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + // Make transaction + // Manually creating script + + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + // self-transfer of 1e-8 GAS + System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; + sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.Emit(OpCode.THROWIFNOT); + script = sb.ToArray(); + } + + // trying two custom hashes, for same target account + var cosigners = new Cosigner[]{ new Cosigner + { + Account = acc.ScriptHash, + Scopes = WitnessScope.CustomContracts, + AllowedContracts = new[] { NativeContract.NEO.Hash, NativeContract.GAS.Hash } + } }; + + // using this... + + var tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners); + + Assert.IsNotNull(tx); + Assert.IsNull(tx.Witnesses); + + // ---- + // Sign + // ---- + + var data = new ContractParametersContext(tx); + bool signed = wallet.Sign(data); + Assert.IsTrue(signed); + + // get witnesses from signed 'data' + tx.Witnesses = data.GetWitnesses(); + // only a single witness should exist + tx.Witnesses.Length.Should().Be(1); + // no attributes must exist + tx.Attributes.Length.Should().Be(0); + // one cosigner must exist + tx.Cosigners.Length.Should().Be(1); + + // Fast check + Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); + + // Check + long verificationGas = 0; + foreach (var witness in tx.Witnesses) + { + using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false)) + { + engine.LoadScript(witness.VerificationScript); + engine.LoadScript(witness.InvocationScript); + Assert.AreEqual(VMState.HALT, engine.Execute()); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); + verificationGas += engine.GasConsumed; + } + } + // get sizeGas + var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); + // final check on sum: verification_cost + tx_size + Assert.AreEqual(verificationGas + sizeGas, 1298240); + // final assert + Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); + } + } + + [TestMethod] + public void FeeIsSignatureContract_TestScope_NoScopeFAULT() + { + var wallet = GenerateTestWallet(); + var snapshot = store.GetSnapshot(); + + // no password on this wallet + using (var unlock = wallet.Unlock("")) + { + var acc = wallet.CreateAccount(); + + // Fake balance + + var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); + + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + // Make transaction + // Manually creating script + + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + // self-transfer of 1e-8 GAS + System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; + sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.Emit(OpCode.THROWIFNOT); + script = sb.ToArray(); + } + + // trying with no scope + var attributes = new TransactionAttribute[] { }; + var cosigners = new Cosigner[] { }; + + // using this... + + // expects FAULT on execution of 'transfer' Application script + // due to lack of a valid witness validation + Transaction tx = null; + Assert.ThrowsException(() => tx = wallet.MakeTransaction(script, acc.ScriptHash, attributes, cosigners)); + Assert.IsNull(tx); + } + } + + [TestMethod] + public void Transaction_Serialize_Deserialize_Simple() + { + // good and simple transaction + Transaction txSimple = new Transaction + { + Version = 0x00, + Nonce = 0x01020304, + Sender = UInt160.Zero, + SystemFee = (long)BigInteger.Pow(10, 8), // 1 GAS + NetworkFee = 0x0000000000000001, + ValidUntilBlock = 0x01020304, + Attributes = new TransactionAttribute[0] { }, + Cosigners = new Cosigner[0] { }, + Script = new byte[] { (byte)OpCode.PUSH1 }, + Witnesses = new Witness[0] { } + }; + + byte[] sTx = txSimple.ToArray(); + + // detailed hexstring info (basic checking) + sTx.ToHexString().Should().Be("00" + // version + "04030201" + // nonce + "0000000000000000000000000000000000000000" + // sender + "00e1f50500000000" + // system fee (1 GAS) + "0100000000000000" + // network fee (1 satoshi) + "04030201" + // timelimit + "00" + // no attributes + "00" + // no cosigners + "0151" + // push1 script + "00"); // no witnesses + + // try to deserialize + Transaction tx2 = Neo.IO.Helper.AsSerializable(sTx); + + tx2.Version.Should().Be(0x00); + tx2.Nonce.Should().Be(0x01020304); + tx2.Sender.Should().Be(UInt160.Zero); + tx2.SystemFee.Should().Be(0x0000000005f5e100); // 1 GAS (long)BigInteger.Pow(10, 8) + tx2.NetworkFee.Should().Be(0x0000000000000001); + tx2.ValidUntilBlock.Should().Be(0x01020304); + tx2.Attributes.Should().BeEquivalentTo(new TransactionAttribute[0] { }); + tx2.Cosigners.Should().BeEquivalentTo(new Cosigner[0] { }); + tx2.Script.Should().BeEquivalentTo(new byte[] { (byte)OpCode.PUSH1 }); + tx2.Witnesses.Should().BeEquivalentTo(new Witness[0] { }); + } + + [TestMethod] + public void Transaction_Serialize_Deserialize_DistinctCosigners() + { + // cosigners must be distinct (regarding account) + + Transaction txDoubleCosigners = new Transaction + { + Version = 0x00, + Nonce = 0x01020304, + Sender = UInt160.Zero, + SystemFee = (long)BigInteger.Pow(10, 8), // 1 GAS + NetworkFee = 0x0000000000000001, + ValidUntilBlock = 0x01020304, + Attributes = new TransactionAttribute[0] { }, + Cosigners = new Cosigner[] { + new Cosigner + { + Account = UInt160.Parse("0x0001020304050607080900010203040506070809"), + Scopes = WitnessScope.Global + }, + new Cosigner + { + Account = UInt160.Parse("0x0001020304050607080900010203040506070809"), // same account as above + Scopes = WitnessScope.CalledByEntry // different scope, but still, same account (cannot do that) + } + }, + Script = new byte[] { (byte)OpCode.PUSH1 }, + Witnesses = new Witness[0] { } + }; + + byte[] sTx = txDoubleCosigners.ToArray(); + + // no need for detailed hexstring here (see basic tests for it) + sTx.ToHexString().Should().Be("0004030201000000000000000000000000000000000000000000e1f505000000000100000000000000040302010002090807060504030201000908070605040302010000090807060504030201000908070605040302010001015100"); + + // back to transaction (should fail, due to non-distinct cosigners) + Transaction tx2 = null; + Assert.ThrowsException(() => + tx2 = Neo.IO.Helper.AsSerializable(sTx) + ); + Assert.IsNull(tx2); + } + + + [TestMethod] + public void Transaction_Serialize_Deserialize_MaxSizeCosigners() + { + // cosigners must respect count + + int maxCosigners = 16; + + // -------------------------------------- + // this should pass (respecting max size) + + var cosigners1 = new Cosigner[maxCosigners]; + for (int i = 0; i < cosigners1.Length; i++) + { + string hex = i.ToString("X4"); + while (hex.Length < 40) + hex = hex.Insert(0, "0"); + cosigners1[i] = new Cosigner + { + Account = UInt160.Parse(hex) + }; + } + + Transaction txCosigners1 = new Transaction + { + Version = 0x00, + Nonce = 0x01020304, + Sender = UInt160.Zero, + SystemFee = (long)BigInteger.Pow(10, 8), // 1 GAS + NetworkFee = 0x0000000000000001, + ValidUntilBlock = 0x01020304, + Attributes = new TransactionAttribute[0] { }, + Cosigners = cosigners1, // max + 1 (should fail) + Script = new byte[] { (byte)OpCode.PUSH1 }, + Witnesses = new Witness[0] { } + }; + + byte[] sTx1 = txCosigners1.ToArray(); + + // back to transaction (should fail, due to non-distinct cosigners) + Transaction tx1 = Neo.IO.Helper.AsSerializable(sTx1); + Assert.IsNotNull(tx1); + + // ---------------------------- + // this should fail (max + 1) + + var cosigners = new Cosigner[maxCosigners + 1]; + for (var i = 0; i < maxCosigners + 1; i++) + { + string hex = i.ToString("X4"); + while (hex.Length < 40) + hex = hex.Insert(0, "0"); + cosigners[i] = new Cosigner + { + Account = UInt160.Parse(hex) + }; + } + + Transaction txCosigners = new Transaction + { + Version = 0x00, + Nonce = 0x01020304, + Sender = UInt160.Zero, + SystemFee = (long)BigInteger.Pow(10, 8), // 1 GAS + NetworkFee = 0x0000000000000001, + ValidUntilBlock = 0x01020304, + Attributes = new TransactionAttribute[0] { }, + Cosigners = cosigners, // max + 1 (should fail) + Script = new byte[] { (byte)OpCode.PUSH1 }, + Witnesses = new Witness[0] { } + }; + + byte[] sTx2 = txCosigners.ToArray(); + + // back to transaction (should fail, due to non-distinct cosigners) + Transaction tx2 = null; + Assert.ThrowsException(() => + tx2 = Neo.IO.Helper.AsSerializable(sTx2) + ); + Assert.IsNull(tx2); + } + + [TestMethod] + public void FeeIsSignatureContract_TestScope_Global_Default() + { + // Global is supposed to be default + + Cosigner cosigner = new Cosigner(); + cosigner.Scopes.Should().Be(WitnessScope.Global); + + var wallet = GenerateTestWallet(); + var snapshot = store.GetSnapshot(); + + // no password on this wallet + using (var unlock = wallet.Unlock("")) + { + var acc = wallet.CreateAccount(); + + // Fake balance + + var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); + + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + // Make transaction + // Manually creating script + + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + // self-transfer of 1e-8 GAS + System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; + sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.Emit(OpCode.THROWIFNOT); + script = sb.ToArray(); + } + + // default to global scope + var cosigners = new Cosigner[]{ new Cosigner + { + Account = acc.ScriptHash + } }; + + // using this... + + var tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners); + + Assert.IsNotNull(tx); + Assert.IsNull(tx.Witnesses); + + // ---- + // Sign + // ---- + + var data = new ContractParametersContext(tx); + bool signed = wallet.Sign(data); + Assert.IsTrue(signed); + + // get witnesses from signed 'data' + tx.Witnesses = data.GetWitnesses(); + tx.Witnesses.Length.Should().Be(1); + + // Fast check + Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); + + // Check + long verificationGas = 0; + foreach (var witness in tx.Witnesses) + { + using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false)) + { + engine.LoadScript(witness.VerificationScript); + engine.LoadScript(witness.InvocationScript); + Assert.AreEqual(VMState.HALT, engine.Execute()); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); + verificationGas += engine.GasConsumed; + } + } + // get sizeGas + var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); + // final check on sum: verification_cost + tx_size + Assert.AreEqual(verificationGas + sizeGas, 1257240); + // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } } @@ -255,7 +1059,8 @@ public void ToJson() uut.Script = TestUtils.GetByteArray(32, 0x42); uut.Sender = UInt160.Zero; uut.SystemFee = 4200000000; - uut.Attributes = new TransactionAttribute[0]; + uut.Attributes = new TransactionAttribute[] { }; + uut.Cosigners = new Cosigner[] { }; uut.Witnesses = new[] { new Witness @@ -267,10 +1072,11 @@ public void ToJson() JObject jObj = uut.ToJson(); jObj.Should().NotBeNull(); - jObj["hash"].AsString().Should().Be("0xee00d595ccd48a650f62adaccbb9c979e2dc7ef66fb5b1413f0f74d563a2d9c6"); - jObj["size"].AsNumber().Should().Be(82); + jObj["hash"].AsString().Should().Be("0x11e3ee692015f0cd3cb8b6db7a4fc37568540f020cb9ca497a9917c81f20b62f"); + jObj["size"].AsNumber().Should().Be(83); jObj["version"].AsNumber().Should().Be(0); ((JArray)jObj["attributes"]).Count.Should().Be(0); + ((JArray)jObj["cosigners"]).Count.Should().Be(0); jObj["net_fee"].AsString().Should().Be("0"); jObj["script"].AsString().Should().Be("4220202020202020202020202020202020202020202020202020202020202020"); jObj["sys_fee"].AsNumber().Should().Be(42); diff --git a/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index efa3c2446c..f7b216544c 100644 --- a/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -128,7 +128,7 @@ public void Check_RegisterValidator() ret.Result.Should().BeTrue(); snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 1); // New validator - + // Check GetRegisteredValidators var validators = NativeContract.NEO.GetRegisteredValidators(snapshot).OrderBy(u => u.PublicKey).ToArray(); diff --git a/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index 0f353e37da..b77030d554 100644 --- a/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -61,7 +61,7 @@ public void Check_SetMaxTransactionsPerBlock() // Without signature - var ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(null), + var ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), "setMaxTransactionsPerBlock", new ContractParameter(ContractParameterType.Integer) { Value = 1 }); ret.Should().BeOfType(); ret.GetBoolean().Should().BeFalse(); @@ -96,7 +96,7 @@ public void Check_SetFeePerByte() // Without signature - var ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(null), + var ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), "setFeePerByte", new ContractParameter(ContractParameterType.Integer) { Value = 1 }); ret.Should().BeOfType(); ret.GetBoolean().Should().BeFalse(); @@ -131,7 +131,7 @@ public void Check_Block_UnblockAccount() // Block without signature - var ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(null), + var ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), "blockAccount", new ContractParameter(ContractParameterType.Hash160) { Value = UInt160.Zero }); ret.Should().BeOfType(); ret.GetBoolean().Should().BeFalse(); @@ -154,7 +154,7 @@ public void Check_Block_UnblockAccount() // Unblock without signature - ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(null), + ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(), "unblockAccount", new ContractParameter(ContractParameterType.Hash160) { Value = UInt160.Zero }); ret.Should().BeOfType(); ret.GetBoolean().Should().BeFalse(); diff --git a/neo.UnitTests/TestUtils.cs b/neo.UnitTests/TestUtils.cs index fd06f0ba1b..44cb55047d 100644 --- a/neo.UnitTests/TestUtils.cs +++ b/neo.UnitTests/TestUtils.cs @@ -28,6 +28,7 @@ public static Transaction GetTransaction() Script = new byte[1], Sender = UInt160.Zero, Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], Witnesses = new Witness[]{ new Witness { InvocationScript = new byte[0], @@ -86,6 +87,7 @@ public static Transaction CreateRandomHashTransaction() Script = randomBytes, Sender = UInt160.Zero, Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], Witnesses = new[] { new Witness diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index 663d142d62..f5c1d6bc93 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -153,6 +153,7 @@ private static Transaction DeployNativeContracts() Sender = (new[] { (byte)OpCode.PUSHT }).ToScriptHash(), SystemFee = 0, Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], Witnesses = new[] { new Witness diff --git a/neo/Network/P2P/Payloads/Cosigner.cs b/neo/Network/P2P/Payloads/Cosigner.cs new file mode 100644 index 0000000000..2d1f42039c --- /dev/null +++ b/neo/Network/P2P/Payloads/Cosigner.cs @@ -0,0 +1,76 @@ +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.IO.Json; +using System; +using System.IO; +using System.Linq; + +namespace Neo.Network.P2P.Payloads +{ + public class Cosigner : ISerializable + { + public UInt160 Account; + public WitnessScope Scopes; + public UInt160[] AllowedContracts; + public ECPoint[] AllowedGroups; + + public Cosigner() + { + this.Scopes = WitnessScope.Global; + } + + // This limits maximum number of AllowedContracts or AllowedGroups here + private int MaxSubitems = 16; + + public int Size => + /*Account*/ UInt160.Length + + /*Scopes*/ sizeof(WitnessScope) + + /*AllowedContracts*/ (Scopes.HasFlag(WitnessScope.CustomContracts) ? AllowedContracts.GetVarSize() : 0) + + /*AllowedGroups*/ (Scopes.HasFlag(WitnessScope.CustomGroups) ? AllowedGroups.GetVarSize() : 0); + + void ISerializable.Deserialize(BinaryReader reader) + { + Account = reader.ReadSerializable(); + Scopes = (WitnessScope)reader.ReadByte(); + AllowedContracts = Scopes.HasFlag(WitnessScope.CustomContracts) + ? reader.ReadSerializableArray(MaxSubitems) + : new UInt160[0]; + AllowedGroups = Scopes.HasFlag(WitnessScope.CustomGroups) + ? reader.ReadSerializableArray(MaxSubitems) + : new ECPoint[0]; + } + + void ISerializable.Serialize(BinaryWriter writer) + { + writer.Write(Account); + writer.Write((byte)Scopes); + if (Scopes.HasFlag(WitnessScope.CustomContracts)) + writer.Write(AllowedContracts); + if (Scopes.HasFlag(WitnessScope.CustomGroups)) + writer.Write(AllowedGroups); + } + + public JObject ToJson() + { + JObject json = new JObject(); + json["account"] = Account.ToString(); + json["scopes"] = Scopes; + if (Scopes.HasFlag(WitnessScope.CustomContracts)) + json["allowedContracts"] = AllowedContracts.Select(p => (JObject)p.ToString()).ToArray(); + if (Scopes.HasFlag(WitnessScope.CustomGroups)) + json["allowedGroups"] = AllowedGroups.Select(p => (JObject)p.ToString()).ToArray(); + return json; + } + + public static Cosigner FromJson(JObject json) + { + return new Cosigner + { + Account = UInt160.Parse(json["account"].AsString()), + Scopes = (WitnessScope)Enum.Parse(typeof(WitnessScope), json["scopes"].AsString()), + AllowedContracts = ((JArray)json["allowedContracts"])?.Select(p => UInt160.Parse(p.AsString())).ToArray(), + AllowedGroups = ((JArray)json["allowedGroups"])?.Select(p => ECPoint.Parse(p.AsString(), ECCurve.Secp256r1)).ToArray() + }; + } + } +} diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs index 40efe0e9d3..b83cbd977d 100644 --- a/neo/Network/P2P/Payloads/Transaction.cs +++ b/neo/Network/P2P/Payloads/Transaction.cs @@ -21,6 +21,10 @@ public class Transaction : IEquatable, IInventory /// Maximum number of attributes that can be contained within a transaction /// private const int MaxTransactionAttributes = 16; + /// + /// Maximum number of cosigners that can be contained within a transaction + /// + private const int MaxCosigners = 16; public byte Version; public uint Nonce; @@ -35,6 +39,7 @@ public class Transaction : IEquatable, IInventory public long NetworkFee; public uint ValidUntilBlock; public TransactionAttribute[] Attributes; + public Cosigner[] Cosigners { get; set; } public byte[] Script; public Witness[] Witnesses { get; set; } @@ -69,6 +74,7 @@ public UInt256 Hash public int Size => HeaderSize + Attributes.GetVarSize() + //Attributes + Cosigners.GetVarSize() + //Cosigners Script.GetVarSize() + //Script Witnesses.GetVarSize(); //Witnesses @@ -92,8 +98,8 @@ public void DeserializeUnsigned(BinaryReader reader) if (SystemFee + NetworkFee < SystemFee) throw new FormatException(); ValidUntilBlock = reader.ReadUInt32(); Attributes = reader.ReadSerializableArray(MaxTransactionAttributes); - var cosigners = Attributes.Where(p => p.Usage == TransactionAttributeUsage.Cosigner).Select(p => new UInt160(p.Data)).ToArray(); - if (cosigners.Distinct().Count() != cosigners.Length) throw new FormatException(); + Cosigners = reader.ReadSerializableArray(MaxCosigners); + if (Cosigners.Select(u => u.Account).Distinct().Count() != Cosigners.Length) throw new FormatException(); Script = reader.ReadVarBytes(ushort.MaxValue); if (Script.Length == 0) throw new FormatException(); } @@ -118,7 +124,7 @@ public override int GetHashCode() public UInt160[] GetScriptHashesForVerifying(Snapshot snapshot) { var hashes = new HashSet { Sender }; - hashes.UnionWith(Attributes.Where(p => p.Usage == TransactionAttributeUsage.Cosigner).Select(p => new UInt160(p.Data))); + hashes.UnionWith(Cosigners.Select(p => p.Account)); return hashes.OrderBy(p => p).ToArray(); } @@ -157,6 +163,7 @@ void IVerifiable.SerializeUnsigned(BinaryWriter writer) writer.Write(NetworkFee); writer.Write(ValidUntilBlock); writer.Write(Attributes); + writer.Write(Cosigners); writer.WriteVarBytes(Script); } @@ -172,6 +179,7 @@ public JObject ToJson() json["net_fee"] = new BigDecimal(NetworkFee, NativeContract.GAS.Decimals).ToString(); json["valid_until_block"] = ValidUntilBlock; json["attributes"] = Attributes.Select(p => p.ToJson()).ToArray(); + json["cosigners"] = Cosigners.Select(p => p.ToJson()).ToArray(); json["script"] = Script.ToHexString(); json["witnesses"] = Witnesses.Select(p => p.ToJson()).ToArray(); return json; @@ -187,6 +195,7 @@ public static Transaction FromJson(JObject json) tx.NetworkFee = long.Parse(json["net_fee"].AsString()); tx.ValidUntilBlock = uint.Parse(json["valid_until_block"].AsString()); tx.Attributes = ((JArray)json["attributes"]).Select(p => TransactionAttribute.FromJson(p)).ToArray(); + tx.Cosigners = ((JArray)json["cosigners"]).Select(p => Cosigner.FromJson(p)).ToArray(); tx.Script = json["script"].AsString().HexToBytes(); tx.Witnesses = ((JArray)json["witnesses"]).Select(p => Witness.FromJson(p)).ToArray(); return tx; diff --git a/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs b/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs index d878348c28..89c1a1cec2 100644 --- a/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs +++ b/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs @@ -2,7 +2,6 @@ { public enum TransactionAttributeUsage : byte { - Cosigner = 0x20, Url = 0x81 } } diff --git a/neo/Network/P2P/Payloads/WitnessScope.cs b/neo/Network/P2P/Payloads/WitnessScope.cs new file mode 100644 index 0000000000..e67706cbbf --- /dev/null +++ b/neo/Network/P2P/Payloads/WitnessScope.cs @@ -0,0 +1,31 @@ +using System; + +namespace Neo.Network.P2P.Payloads +{ + [Flags] + public enum WitnessScope : byte + { + /// + /// Global allows this witness in all contexts (default Neo2 behavior) + /// This cannot be combined with other flags + /// + Global = 0x00, + + /// + /// CalledByEntry means that this condition must hold: EntryScriptHash == CallingScriptHash + /// No params is needed, as the witness/permission/signature given on first invocation will automatically expire if entering deeper internal invokes + /// This can be default safe choice for native NEO/GAS (previously used on Neo 2 as "attach" mode) + /// + CalledByEntry = 0x01, + + /// + /// Custom hash for contract-specific + /// + CustomContracts = 0x10, + + /// + /// Custom pubkey for group members + /// + CustomGroups = 0x20 + } +} diff --git a/neo/SmartContract/ContractParametersContext.cs b/neo/SmartContract/ContractParametersContext.cs index 8fda2c8450..35a2c36898 100644 --- a/neo/SmartContract/ContractParametersContext.cs +++ b/neo/SmartContract/ContractParametersContext.cs @@ -72,7 +72,15 @@ public bool Completed } } + /// + /// Cache for public ScriptHashes field + /// private UInt160[] _ScriptHashes = null; + + /// + /// ScriptHashes are the verifiable ScriptHashes from Verifiable element + /// Equivalent to: Verifiable.GetScriptHashesForVerifying(Blockchain.Singleton.GetSnapshot()) + /// public IReadOnlyList ScriptHashes { get diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index c4daa8a89b..9fbb5c6675 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -143,8 +143,35 @@ private static bool Runtime_GetTrigger(ApplicationEngine engine) internal static bool CheckWitness(ApplicationEngine engine, UInt160 hash) { - var _hashes_for_verifying = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot); - return _hashes_for_verifying.Contains(hash); + if (engine.ScriptContainer is Transaction tx) + { + Cosigner usage = tx.Cosigners.FirstOrDefault(p => p.Account.Equals(hash)); + if (usage is null) return false; + if (usage.Scopes == WitnessScope.Global) return true; + if (usage.Scopes.HasFlag(WitnessScope.CalledByEntry)) + { + if (engine.CallingScriptHash == engine.EntryScriptHash) + return true; + } + if (usage.Scopes.HasFlag(WitnessScope.CustomContracts)) + { + if (usage.AllowedContracts.Contains(engine.CurrentScriptHash)) + return true; + } + if (usage.Scopes.HasFlag(WitnessScope.CustomGroups)) + { + var contract = engine.Snapshot.Contracts[engine.CallingScriptHash]; + // check if current group is the required one + if (contract.Manifest.Groups.Select(p => p.PubKey).Intersect(usage.AllowedGroups).Any()) + return true; + } + return false; + } + + // only for non-Transaction types (Block, etc) + + var hashes_for_verifying = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot); + return hashes_for_verifying.Contains(hash); } private static bool CheckWitness(ApplicationEngine engine, ECPoint pubkey) diff --git a/neo/Wallets/Wallet.cs b/neo/Wallets/Wallet.cs index b68733bb71..7912ca97b6 100644 --- a/neo/Wallets/Wallet.cs +++ b/neo/Wallets/Wallet.cs @@ -223,7 +223,7 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null } using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) { - HashSet cosigners = new HashSet(); + HashSet cosignerList = new HashSet(); byte[] script; List<(UInt160 Account, BigInteger Value)> balances_gas = null; using (ScriptBuilder sb = new ScriptBuilder()) @@ -250,7 +250,7 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null { balances = balances.OrderBy(p => p.Value).ToList(); var balances_used = FindPayingAccounts(balances, output.Value.Value); - cosigners.UnionWith(balances_used.Select(p => p.Account)); + cosignerList.UnionWith(balances_used.Select(p => p.Account)); foreach (var (account, value) in balances_used) { sb.EmitAppCall(output.AssetId, "transfer", account, output.ScriptHash, value); @@ -264,12 +264,20 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null } if (balances_gas is null) balances_gas = accounts.Select(p => (Account: p, Value: NativeContract.GAS.BalanceOf(snapshot, p))).Where(p => p.Value.Sign > 0).ToList(); - TransactionAttribute[] attributes = cosigners.Select(p => new TransactionAttribute { Usage = TransactionAttributeUsage.Cosigner, Data = p.ToArray() }).ToArray(); - return MakeTransaction(snapshot, attributes, script, balances_gas); + + var cosigners = cosignerList.Select(p => + new Cosigner() + { + // default access for transfers should be valid only for first invocation + Scopes = WitnessScope.CalledByEntry, + Account = new UInt160(p.ToArray()) + }).ToArray(); + + return MakeTransaction(snapshot, script, new TransactionAttribute[0], cosigners, balances_gas); } } - public Transaction MakeTransaction(TransactionAttribute[] attributes, byte[] script, UInt160 sender = null) + public Transaction MakeTransaction(byte[] script, UInt160 sender = null, TransactionAttribute[] attributes = null, Cosigner[] cosigners = null) { UInt160[] accounts; if (sender is null) @@ -285,11 +293,11 @@ public Transaction MakeTransaction(TransactionAttribute[] attributes, byte[] scr using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) { var balances_gas = accounts.Select(p => (Account: p, Value: NativeContract.GAS.BalanceOf(snapshot, p))).Where(p => p.Value.Sign > 0).ToList(); - return MakeTransaction(snapshot, attributes, script, balances_gas); + return MakeTransaction(snapshot, script, attributes ?? new TransactionAttribute[0], cosigners ?? new Cosigner[0], balances_gas); } } - private Transaction MakeTransaction(Snapshot snapshot, TransactionAttribute[] attributes, byte[] script, List<(UInt160 Account, BigInteger Value)> balances_gas) + private Transaction MakeTransaction(Snapshot snapshot, byte[] script, TransactionAttribute[] attributes, Cosigner[] cosigners, List<(UInt160 Account, BigInteger Value)> balances_gas) { Random rand = new Random(); foreach (var (account, value) in balances_gas) @@ -301,8 +309,10 @@ private Transaction MakeTransaction(Snapshot snapshot, TransactionAttribute[] at Script = script, Sender = account, ValidUntilBlock = snapshot.Height + Transaction.MaxValidUntilBlockIncrement, - Attributes = attributes + Attributes = attributes, + Cosigners = cosigners }; + // will try to execute 'transfer' script to check if it works using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot.Clone(), tx, testMode: true)) { if (engine.State.HasFlag(VMState.FAULT)) @@ -318,8 +328,12 @@ private Transaction MakeTransaction(Snapshot snapshot, TransactionAttribute[] at tx.SystemFee -= remainder; } } + UInt160[] hashes = tx.GetScriptHashesForVerifying(snapshot); - int size = Transaction.HeaderSize + attributes.GetVarSize() + script.GetVarSize() + IO.Helper.GetVarSize(hashes.Length); + + // base size for transaction: includes const_header + attributes + cosigners with scopes + script + hashes + int size = Transaction.HeaderSize + attributes.GetVarSize() + cosigners.GetVarSize() + script.GetVarSize() + IO.Helper.GetVarSize(hashes.Length); + foreach (UInt160 hash in hashes) { byte[] witness_script = GetAccount(hash)?.Contract?.Script ?? snapshot.Contracts.TryGet(hash)?.Script; From cf768c63a3e2c07cda839495f8b836223832c634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?= Date: Mon, 12 Aug 2019 12:00:34 -0300 Subject: [PATCH 27/54] Improving the use of `RelayCache` on `ProtocolHandler` (#1014) * Refactoring and simplifing the use of relaycache * Standarzing name * simplify --- neo/Ledger/Blockchain.cs | 4 ++-- neo/Network/P2P/ProtocolHandler.cs | 19 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index f5c1d6bc93..889d4b18bb 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -60,7 +60,7 @@ public class FillCompleted { } private uint stored_header_count = 0; private readonly Dictionary block_cache = new Dictionary(); private readonly Dictionary> block_cache_unverified = new Dictionary>(); - internal readonly RelayCache RelayCache = new RelayCache(100); + internal readonly RelayCache ConsensusRelayCache = new RelayCache(100); private Snapshot currentSnapshot; public Store Store { get; } @@ -328,7 +328,7 @@ private RelayResultReason OnNewConsensus(ConsensusPayload payload) { if (!payload.Verify(currentSnapshot)) return RelayResultReason.Invalid; system.Consensus?.Tell(payload); - RelayCache.Add(payload); + ConsensusRelayCache.Add(payload); system.LocalNode.Tell(new LocalNode.RelayDirectly { Inventory = payload }); return RelayResultReason.Succeed; } diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index 234c42d9ef..63ecbe3318 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -180,23 +180,20 @@ private void OnGetDataMessageReceived(InvPayload payload) UInt256[] hashes = payload.Hashes.Where(p => sentHashes.Add(p)).ToArray(); foreach (UInt256 hash in hashes) { - Blockchain.Singleton.RelayCache.TryGet(hash, out IInventory inventory); switch (payload.Type) { case InventoryType.TX: - if (inventory == null) - inventory = Blockchain.Singleton.GetTransaction(hash); - if (inventory is Transaction) - Context.Parent.Tell(Message.Create(MessageCommand.Transaction, inventory)); + Transaction tx = Blockchain.Singleton.GetTransaction(hash); + if (tx != null) + Context.Parent.Tell(Message.Create(MessageCommand.Transaction, tx)); break; case InventoryType.Block: - if (inventory == null) - inventory = Blockchain.Singleton.GetBlock(hash); - if (inventory is Block block) + Block block = Blockchain.Singleton.GetBlock(hash); + if (block != null) { if (bloom_filter == null) { - Context.Parent.Tell(Message.Create(MessageCommand.Block, inventory)); + Context.Parent.Tell(Message.Create(MessageCommand.Block, block)); } else { @@ -206,8 +203,8 @@ private void OnGetDataMessageReceived(InvPayload payload) } break; case InventoryType.Consensus: - if (inventory != null) - Context.Parent.Tell(Message.Create(MessageCommand.Consensus, inventory)); + if (Blockchain.Singleton.ConsensusRelayCache.TryGet(hash, out IInventory inventoryConsensus)) + Context.Parent.Tell(Message.Create(MessageCommand.Consensus, inventoryConsensus)); break; } } From d959efcc4974eab11e411b8e614faac44a613dcc Mon Sep 17 00:00:00 2001 From: Yongjie Ma <20391402+yongjiema@users.noreply.github.com> Date: Fri, 16 Aug 2019 19:25:06 +0800 Subject: [PATCH 28/54] Fix the potential risk to get null CurrentHeaderHash from Blockchain (#1033) --- neo/Ledger/Blockchain.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index 889d4b18bb..7d0b72402d 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -66,9 +66,9 @@ public class FillCompleted { } public Store Store { get; } public MemoryPool MemPool { get; } public uint Height => currentSnapshot.Height; - public uint HeaderHeight => (uint)header_index.Count - 1; + public uint HeaderHeight => currentSnapshot.HeaderHeight; public UInt256 CurrentBlockHash => currentSnapshot.CurrentBlockHash; - public UInt256 CurrentHeaderHash => header_index[header_index.Count - 1]; + public UInt256 CurrentHeaderHash => currentSnapshot.CurrentHeaderHash; private static Blockchain singleton; public static Blockchain Singleton From 1fd9239a54217212e9b319ff630497834439f15d Mon Sep 17 00:00:00 2001 From: Charis Zhao Date: Fri, 16 Aug 2019 23:08:26 +0800 Subject: [PATCH 29/54] Unit Test for Wallets Module (#1018) * testDemo * add dll lib * add dbsnapshot dispose * test get blocks in levelDBStore * add levelDBStore test funcs * fix levelDBStore funcs * add DbCache addInternal * differ db path * space * fix delete internal test * add test getInternal tryGetInternal move libleveldb.dll * add dbCache method test * add store test * add cache unit tests * add cache unit tests * up readonly max_capacity * fix leveldbexception * fix comment on UT_Cache * format * fix multithread test problem * up cache * update travis config * update travis.yml * test DbMetaDataCache * fix db directory * format and update travis for maxos * fix mac env travis * 2019/7/12 10:34 * 2019/7/12 11:01 * remove commented line * test BigDecimal * fix format and csproj * rm coverage.opencover.xml * update method name * add UT_P_Helper * modify UT_P_Helper * modify UT_P_helper * Clean ut * test Base58 & BloomFilter * Update UT_Cache.cs * Correct Typo * test JsonArray * update namespace * update namespace * update format * update format * organise folder structure * add UT_JString * test JBoolean JNumber & JObject * 2019/7/16 10:30 add some test case for UInt32Wrapper and SerializableWrapper * fix timestamp * test ECDsa and Crypto * test OrderedDictionary & complete IO.Json tests * 2019/7/16 17:33 add some test case of SQLiteWallet * test FIFOSet * add CloneCache and DataCache unit tests * fix namespace * add UT_Cryptography_Helper * format UT_CloneCache and UT_DataCache * add UT_DataCache.GetAndChange unit test * update namespace * remove comment code * delete Persistence part * 2019/7/19 11:07 add some test case for Helper in VM * Fix Base58 Test * 2019/7/19 11:33 change some format * update IOHelper exception assert * 2019/7/19 14:22 change format * format IOHelper * review IO.Wrapper * review Wallets.SQLite UT * Test ECFieldElement ECPoint * refactor package * format ECDsa * update namespace * Code fix * review cache * modify UT_JString * fomat * using Actin replace with try-catch * add UT_CloneMetaCache and UT_MetaDataCache * update namespace * format UT_DataCache.cs * Code Fix * format * update csproj * Code fix for UT_ECFieldElement and UT_ECPoint * Code fix * format * update travis * delete deleteFiles * fix path and comment * update travis * delete test ToTimeStamp * format UT_*Cache * update format * fomat * use hex extensions in Cryptography_Helper * remove reflection * optimization of UT_DataCache * update namespace * modify TestSha256 * update UT in crypto module * Rename UT_Scrypt.cs to UT_SCrypt.cs * format * update UT_Murmur3 * update IO module test * delete empty line * changename * delete empty line * revert commit * add wallet test * update testUtil * delete empty line * Update UT_NEP6Wallet.cs * update ut * Optimize wallet test * fix * add change * fix nep6wallet * Fix * Optimize * fix optimize * fix * Optimize --- .../Network/P2P/Payloads/UT_Transaction.cs | 32 +- neo.UnitTests/TestUtils.cs | 38 +- neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs | 139 ++++++ neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs | 67 +++ neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs | 379 ++++++++++++++- .../Wallets/NEP6/UT_ScryptParameters.cs | 10 + neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs | 210 +++++++++ .../Wallets/SQLite/UT_UserWalletAccount.cs | 31 ++ .../Wallets/SQLite/UT_VerificationContract.cs | 148 ++++++ neo.UnitTests/Wallets/UT_AssetDescriptor.cs | 13 + neo.UnitTests/Wallets/UT_KeyPair.cs | 114 +++++ neo.UnitTests/Wallets/UT_Wallet.cs | 436 ++++++++++++++++++ neo.UnitTests/Wallets/UT_WalletAccount.cs | 48 ++ neo.UnitTests/Wallets/UT_Wallets_Helper.cs | 32 ++ neo/Wallets/NEP6/NEP6Wallet.cs | 4 +- neo/Wallets/SQLite/UserWallet.cs | 4 +- neo/Wallets/Wallet.cs | 4 +- 17 files changed, 1669 insertions(+), 40 deletions(-) create mode 100644 neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs create mode 100644 neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs create mode 100644 neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs create mode 100644 neo.UnitTests/Wallets/SQLite/UT_UserWalletAccount.cs create mode 100644 neo.UnitTests/Wallets/SQLite/UT_VerificationContract.cs create mode 100644 neo.UnitTests/Wallets/UT_KeyPair.cs create mode 100644 neo.UnitTests/Wallets/UT_Wallet.cs create mode 100644 neo.UnitTests/Wallets/UT_WalletAccount.cs create mode 100644 neo.UnitTests/Wallets/UT_Wallets_Helper.cs diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index 2c81e91537..c357541d7e 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -84,24 +84,12 @@ public void Size_Get() uut.Size.Should().Be(83); } - private NEP6Wallet GenerateTestWallet() - { - JObject wallet = new JObject(); - wallet["name"] = "noname"; - wallet["version"] = new System.Version().ToString(); - wallet["scrypt"] = new ScryptParameters(0, 0, 0).ToJson(); - wallet["accounts"] = new JArray(); - wallet["extra"] = null; - wallet.ToString().Should().Be("{\"name\":\"noname\",\"version\":\"0.0\",\"scrypt\":{\"n\":0,\"r\":0,\"p\":0},\"accounts\":[],\"extra\":null}"); - return new NEP6Wallet(wallet); - } - [TestMethod] public void FeeIsMultiSigContract() { var store = TestBlockchain.GetStore(); - var walletA = GenerateTestWallet(); - var walletB = GenerateTestWallet(); + var walletA = TestUtils.GenerateTestWallet(); + var walletB = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); using (var unlockA = walletA.Unlock("123")) @@ -188,7 +176,7 @@ public void FeeIsMultiSigContract() [TestMethod] public void FeeIsSignatureContractDetailed() { - var wallet = GenerateTestWallet(); + var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); using (var unlock = wallet.Unlock("123")) @@ -303,7 +291,7 @@ public void FeeIsSignatureContractDetailed() [TestMethod] public void FeeIsSignatureContract_TestScope_Global() { - var wallet = GenerateTestWallet(); + var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet @@ -394,7 +382,7 @@ public void FeeIsSignatureContract_TestScope_Global() [TestMethod] public void FeeIsSignatureContract_TestScope_CurrentHash_GAS() { - var wallet = GenerateTestWallet(); + var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet @@ -486,7 +474,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_GAS() [TestMethod] public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() { - var wallet = GenerateTestWallet(); + var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet @@ -581,7 +569,7 @@ public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() [TestMethod] public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_FAULT() { - var wallet = GenerateTestWallet(); + var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet @@ -639,7 +627,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_FAULT() [TestMethod] public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() { - var wallet = GenerateTestWallet(); + var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet @@ -736,7 +724,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() [TestMethod] public void FeeIsSignatureContract_TestScope_NoScopeFAULT() { - var wallet = GenerateTestWallet(); + var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet @@ -966,7 +954,7 @@ public void FeeIsSignatureContract_TestScope_Global_Default() Cosigner cosigner = new Cosigner(); cosigner.Scopes.Should().Be(WitnessScope.Global); - var wallet = GenerateTestWallet(); + var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet diff --git a/neo.UnitTests/TestUtils.cs b/neo.UnitTests/TestUtils.cs index 44cb55047d..086098a8ec 100644 --- a/neo.UnitTests/TestUtils.cs +++ b/neo.UnitTests/TestUtils.cs @@ -1,6 +1,11 @@ -using Neo.IO; +using FluentAssertions; +using Neo.IO; +using Neo.IO.Json; +using Neo.Ledger; using Neo.Network.P2P.Payloads; +using Neo.SmartContract.Manifest; using Neo.VM; +using Neo.Wallets.NEP6; using System; using System.IO; @@ -21,6 +26,18 @@ public static byte[] GetByteArray(int length, byte firstByte) return array; } + public static NEP6Wallet GenerateTestWallet() + { + JObject wallet = new JObject(); + wallet["name"] = "noname"; + wallet["version"] = new System.Version().ToString(); + wallet["scrypt"] = new ScryptParameters(0, 0, 0).ToJson(); + wallet["accounts"] = new JArray(); + wallet["extra"] = null; + wallet.ToString().Should().Be("{\"name\":\"noname\",\"version\":\"0.0\",\"scrypt\":{\"n\":0,\"r\":0,\"p\":0},\"accounts\":[],\"extra\":null}"); + return new NEP6Wallet(wallet); + } + public static Transaction GetTransaction() { return new Transaction @@ -37,6 +54,15 @@ public static Transaction GetTransaction() }; } + internal static ContractState GetContract() + { + return new ContractState + { + Script = new byte[] { 0x01, 0x01, 0x01, 0x01 }, + Manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")) + }; + } + 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); @@ -109,5 +135,13 @@ public static Transaction CreateRandomHashTransaction() return newObj; } + + public static void DeleteFile(string file) + { + if (File.Exists(file)) + { + File.Delete(file); + } + } } -} +} \ No newline at end of file diff --git a/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs new file mode 100644 index 0000000000..c531c8c138 --- /dev/null +++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs @@ -0,0 +1,139 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.IO.Json; +using Neo.SmartContract; +using Neo.Wallets; +using Neo.Wallets.NEP6; + +namespace Neo.UnitTests.Wallets.NEP6 +{ + [TestClass] + public class UT_NEP6Account + { + NEP6Account account; + UInt160 hash; + NEP6Wallet wallet; + private static string nep2; + private static KeyPair keyPair; + + [ClassInitialize] + public static void ClassSetup(TestContext context) { + byte[] privateKey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + keyPair = new KeyPair(privateKey); + nep2 = keyPair.Export("Satoshi", 0, 0, 0); + } + + [TestInitialize] + public void TestSetup() + { + wallet = TestUtils.GenerateTestWallet(); + byte[] array1 = { 0x01 }; + hash = new UInt160(Crypto.Default.Hash160(array1)); + account = new NEP6Account(wallet, hash); + } + + [TestMethod] + public void TestConstructorWithNep2Key() + { + account.ScriptHash.Should().Be(hash); + account.Decrypted.Should().BeTrue(); + account.HasKey.Should().BeFalse(); + } + + [TestMethod] + public void TestConstructorWithKeyPair() + { + NEP6Wallet wallet = new NEP6Wallet("a"); + byte[] array1 = { 0x01 }; + var hash = new UInt160(Crypto.Default.Hash160(array1)); + string password = "hello world"; + NEP6Account account = new NEP6Account(wallet, hash, keyPair, password); + account.ScriptHash.Should().Be(hash); + account.Decrypted.Should().BeTrue(); + account.HasKey.Should().BeTrue(); + } + + [TestMethod] + public void TestFromJson() + { + JObject json = new JObject(); + json["address"] = "ARxgjcH2K1yeW5f5ryuRQNaBzSa9TZzmVS"; + json["key"] = null; + json["label"] = null; + json["isDefault"] = true; + json["lock"] = false; + json["contract"] = null; + json["extra"] = null; + NEP6Account account = NEP6Account.FromJson(json, wallet); + account.ScriptHash.Should().Be("ARxgjcH2K1yeW5f5ryuRQNaBzSa9TZzmVS".ToScriptHash()); + account.Label.Should().BeNull(); + account.IsDefault.Should().BeTrue(); + account.Lock.Should().BeFalse(); + account.Contract.Should().BeNull(); + account.Extra.Should().BeNull(); + account.GetKey().Should().BeNull(); + + json["key"] = "6PYRjVE1gAbCRyv81FTiFz62cxuPGw91vMjN4yPa68bnoqJtioreTznezn"; + json["label"] = "label"; + account = NEP6Account.FromJson(json, wallet); + account.Label.Should().Be("label"); + account.HasKey.Should().BeTrue(); + } + + [TestMethod] + public void TestGetKey() + { + account.GetKey().Should().BeNull(); + wallet.Unlock("Satoshi"); + account = new NEP6Account(wallet, hash, nep2); + account.GetKey().Should().Be(keyPair); + } + + [TestMethod] + public void TestGetKeyWithString() + { + account.GetKey("Satoshi").Should().BeNull(); + account = new NEP6Account(wallet, hash, nep2); + account.GetKey("Satoshi").Should().Be(keyPair); + } + + [TestMethod] + public void TestToJson() + { + JObject nep6contract = new JObject(); + nep6contract["script"] = "2103603f3880eb7aea0ad4500893925e4a42fea48a44ee6f898a10b3c7ce05d2a267ac"; + JObject parameters = new JObject(); + parameters["type"] = 0x00; + parameters["name"] = "Sig"; + JArray array = new JArray + { + parameters + }; + nep6contract["parameters"] = array; + nep6contract["deployed"] = false; + account.Contract = NEP6Contract.FromJson(nep6contract); + JObject json = account.ToJson(); + json["address"].Should().Equals("AZk5bAanTtD6AvpeesmYgL8CLRYUt5JQsX"); + json["label"].Should().BeNull(); + json["isDefault"].ToString().Should().Be("false"); + json["lock"].ToString().Should().Be("false"); + json["key"].Should().BeNull(); + json["contract"]["script"].ToString().Should().Be("\"2103603f3880eb7aea0ad4500893925e4a42fea48a44ee6f898a10b3c7ce05d2a267ac\""); + json["extra"].Should().BeNull(); + + account.Contract = null; + json = account.ToJson(); + json["contract"].Should().BeNull(); + } + + [TestMethod] + public void TestVerifyPassword() + { + account = new NEP6Account(wallet, hash, nep2); + account.VerifyPassword("Satoshi").Should().BeTrue(); + account.VerifyPassword("b").Should().BeFalse(); + } + } +} diff --git a/neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs new file mode 100644 index 0000000000..6dc7f714d5 --- /dev/null +++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs @@ -0,0 +1,67 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO.Json; +using Neo.SmartContract; +using Neo.Wallets.NEP6; + +namespace Neo.UnitTests.Wallets.NEP6 +{ + [TestClass] + public class UT_NEP6Contract + { + [TestMethod] + public void TestFromNullJson() + { + NEP6Contract nep6Contract = NEP6Contract.FromJson(null); + nep6Contract.Should().BeNull(); + } + + [TestMethod] + public void TestFromJson() + { + string json = "{\"script\":\"2103ef891df4c0b7eefb937d21ea0fb88cde8e0d82a7ff11872b5e7047969dafb4eb68747476aa\"," + + "\"parameters\":[{\"name\":\"signature\",\"type\":\"Signature\"}],\"deployed\":false}"; + JObject @object = JObject.Parse(json); + + NEP6Contract nep6Contract = NEP6Contract.FromJson(@object); + nep6Contract.Script.Should().BeEquivalentTo("2103ef891df4c0b7eefb937d21ea0fb88cde8e0d82a7ff11872b5e7047969dafb4eb68747476aa".HexToBytes()); + nep6Contract.ParameterList.Length.Should().Be(1); + nep6Contract.ParameterList[0].Should().Be(ContractParameterType.Signature); + nep6Contract.ParameterNames.Length.Should().Be(1); + nep6Contract.ParameterNames[0].Should().Be("signature"); + nep6Contract.Deployed.Should().BeFalse(); + } + + [TestMethod] + public void TestToJson() + { + NEP6Contract nep6Contract = new NEP6Contract() + { + Script = new byte[] { 0x00, 0x01 }, + ParameterList = new ContractParameterType[] { ContractParameterType.Boolean, ContractParameterType.Integer }, + ParameterNames = new string[] { "param1", "param2" }, + Deployed = false + }; + + JObject @object = nep6Contract.ToJson(); + JString jString = (JString)@object["script"]; + jString.Value.Should().Be(nep6Contract.Script.ToHexString()); + + JBoolean jBoolean = (JBoolean)@object["deployed"]; + jBoolean.Value.Should().BeFalse(); + + JArray parameters = (JArray)@object["parameters"]; + parameters.Count.Should().Be(2); + + jString = (JString)(parameters[0]["name"]); + jString.Value.Should().Be("param1"); + jString = (JString)(parameters[0]["type"]); + jString.Value.Should().Be(ContractParameterType.Boolean.ToString()); + + jString = (JString)(parameters[1]["name"]); + jString.Value.Should().Be("param2"); + jString = (JString)(parameters[1]["type"]); + jString.Value.Should().Be(ContractParameterType.Integer.ToString()); + } + } +} diff --git a/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs index 9bac3de4ac..89499e7c57 100644 --- a/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs @@ -1,41 +1,400 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; +using Neo.Wallets; using Neo.Wallets.NEP6; +using Neo.Wallets.SQLite; using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Threading; namespace Neo.UnitTests.Wallets.NEP6 { [TestClass] public class UT_NEP6Wallet { - NEP6Wallet uut; + private NEP6Wallet uut; + private static string wPath; + private static KeyPair keyPair; + private static string nep2key; + private static UInt160 testScriptHash; + + public static string GetRandomPath() + { + string threadName = Thread.CurrentThread.ManagedThreadId.ToString(); + return Path.GetFullPath(string.Format("Wallet_{0}", new Random().Next(1, 1000000).ToString("X8")) + threadName); + } + + [ClassInitialize] + public static void ClassInit(TestContext context) + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + keyPair = new KeyPair(privateKey); + testScriptHash = Neo.SmartContract.Contract.CreateSignatureContract(keyPair.PublicKey).ScriptHash; + nep2key = keyPair.Export("123", 0, 0, 0); + } + + private NEP6Wallet CreateWallet() + { + return TestUtils.GenerateTestWallet(); + } + + private string CreateWalletFile() + { + string path = GetRandomPath(); + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path = Path.Combine(path, "wallet.json"); + File.WriteAllText(path, "{\"name\":\"name\",\"version\":\"0.0\",\"scrypt\":{\"n\":0,\"r\":0,\"p\":0},\"accounts\":[],\"extra\":{}}"); + return path; + } [TestInitialize] public void TestSetup() + { + uut = CreateWallet(); + wPath = CreateWalletFile(); + } + + [TestCleanup] + public void TestCleanUp() + { + if (File.Exists(wPath)) File.Delete(wPath); + } + + [TestMethod] + public void TestConstructorWithPathAndName() + { + NEP6Wallet wallet = new NEP6Wallet(wPath); + Assert.AreEqual("name", wallet.Name); + Assert.AreEqual(new ScryptParameters(0, 0, 0).ToJson().ToString(), wallet.Scrypt.ToJson().ToString()); + Assert.AreEqual(new Version().ToString(), wallet.Version.ToString()); + wallet = new NEP6Wallet("", "test"); + Assert.AreEqual("test", wallet.Name); + Assert.AreEqual(ScryptParameters.Default.ToJson().ToString(), wallet.Scrypt.ToJson().ToString()); + Assert.AreEqual(Version.Parse("1.0"), wallet.Version); + } + + [TestMethod] + public void TestConstructorWithJObject() + { + JObject wallet = new JObject(); + wallet["name"] = "test"; + wallet["version"] = Version.Parse("1.0").ToString(); + wallet["scrypt"] = ScryptParameters.Default.ToJson(); + wallet["accounts"] = new JArray(); + wallet["extra"] = new JObject(); + wallet.ToString().Should().Be("{\"name\":\"test\",\"version\":\"1.0\",\"scrypt\":{\"n\":16384,\"r\":8,\"p\":8},\"accounts\":[],\"extra\":{}}"); + NEP6Wallet w = new NEP6Wallet(wallet); + Assert.AreEqual("test", w.Name); + Assert.AreEqual(Version.Parse("1.0").ToString(), w.Version.ToString()); + } + + [TestMethod] + public void TestGetName() + { + Assert.AreEqual("noname", uut.Name); + } + + [TestMethod] + public void TestGetVersion() + { + Assert.AreEqual(new System.Version().ToString(), uut.Version.ToString()); + } + + [TestMethod] + public void TestContains() + { + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.CreateAccount(testScriptHash); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestAddCount() + { + uut.CreateAccount(testScriptHash); + Assert.IsTrue(uut.Contains(testScriptHash)); + WalletAccount account = uut.GetAccount(testScriptHash); + Assert.IsTrue(account.WatchOnly); + Assert.IsFalse(account.HasKey); + uut.Unlock("123"); + uut.CreateAccount(keyPair.PrivateKey); + account = uut.GetAccount(testScriptHash); + Assert.IsFalse(account.WatchOnly); + Assert.IsTrue(account.HasKey); + uut.CreateAccount(testScriptHash); + account = uut.GetAccount(testScriptHash); + Assert.IsFalse(account.WatchOnly); + Assert.IsFalse(account.HasKey); + uut.CreateAccount(keyPair.PrivateKey); + account = uut.GetAccount(testScriptHash); + Assert.IsFalse(account.WatchOnly); + Assert.IsTrue(account.HasKey); + } + + [TestMethod] + public void TestCreateAccountWithPrivateKey() + { + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.Unlock("123"); + uut.CreateAccount(keyPair.PrivateKey); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestCreateAccountWithKeyPair() + { + Neo.SmartContract.Contract contract = Neo.SmartContract.Contract.CreateSignatureContract(keyPair.PublicKey); + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.CreateAccount(contract); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + uut.DeleteAccount(testScriptHash); + result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.Unlock("123"); + uut.CreateAccount(contract, keyPair); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestCreateAccountWithScriptHash() + { + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.CreateAccount(testScriptHash); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestDecryptKey() + { + string nep2key = keyPair.Export("123", 0, 0, 0); + uut.Unlock("123"); + KeyPair key1 = uut.DecryptKey(nep2key); + bool result = key1.Equals(keyPair); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestDeleteAccount() + { + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.CreateAccount(testScriptHash); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + uut.DeleteAccount(testScriptHash); + result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + } + + [TestMethod] + public void TestGetAccount() + { + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.Unlock("123"); + uut.CreateAccount(keyPair.PrivateKey); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + WalletAccount account = uut.GetAccount(testScriptHash); + Assert.AreEqual(Neo.SmartContract.Contract.CreateSignatureContract(keyPair.PublicKey).Address, account.Address); + } + + [TestMethod] + public void TestGetAccounts() + { + Dictionary keys = new Dictionary(); + uut.Unlock("123"); + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + KeyPair key = new KeyPair(privateKey); + Neo.SmartContract.Contract contract = Neo.SmartContract.Contract.CreateSignatureContract(key.PublicKey); + keys.Add(contract.Address, key); + keys.Add(Neo.SmartContract.Contract.CreateSignatureContract(keyPair.PublicKey).Address, keyPair); + uut.CreateAccount(key.PrivateKey); + uut.CreateAccount(keyPair.PrivateKey); + foreach (var account in uut.GetAccounts()) + { + if (!keys.TryGetValue(account.Address, out KeyPair k)) + { + Assert.Fail(); + } + } + } + + public X509Certificate2 NewCertificate() + { + ECDsa key = ECDsa.Create(ECCurve.NamedCurves.nistP256); + CertificateRequest request = new CertificateRequest( + "CN=Self-Signed ECDSA", + key, + HashAlgorithmName.SHA256); + request.CertificateExtensions.Add( + new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, critical: false)); + request.CertificateExtensions.Add( + new X509BasicConstraintsExtension(false, false, 0, false)); + DateTimeOffset start = DateTimeOffset.UtcNow; + X509Certificate2 cert = request.CreateSelfSigned(notBefore: start, notAfter: start.AddMonths(3)); + return cert; + } + + [TestMethod] + public void TestImportCert() + { + X509Certificate2 cert = NewCertificate(); + Assert.IsNotNull(cert); + Assert.AreEqual(true, cert.HasPrivateKey); + uut.Unlock("123"); + WalletAccount account = uut.Import(cert); + Assert.IsNotNull(account); + } + + [TestMethod] + public void TestImportWif() + { + string wif = keyPair.Export(); + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.Unlock("123"); + uut.Import(wif); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestImportNep2() + { + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.Import(nep2key, "123", 0, 0, 0); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + uut.DeleteAccount(testScriptHash); + result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + JObject wallet = new JObject(); + wallet["name"] = "name"; + wallet["version"] = new Version().ToString(); + wallet["scrypt"] = new ScryptParameters(0, 0, 0).ToJson(); + wallet["accounts"] = new JArray(); + wallet["extra"] = new JObject(); + uut = new NEP6Wallet(wallet); + result = uut.Contains(testScriptHash); + Assert.AreEqual(false, result); + uut.Import(nep2key, "123", 0, 0, 0); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestLock() + { + Assert.ThrowsException(() => uut.CreateAccount(keyPair.PrivateKey)); + uut.Unlock("123"); + uut.CreateAccount(keyPair.PrivateKey); + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + uut.DeleteAccount(testScriptHash); + uut.Lock(); + Assert.ThrowsException(() => uut.CreateAccount(keyPair.PrivateKey)); + } + + [TestMethod] + public void TestMigrate() + { + string path = GetRandomPath(); + UserWallet uw = UserWallet.Create(path, "123"); + uw.CreateAccount(keyPair.PrivateKey); + string npath = Path.Combine(path, "w.json"); + NEP6Wallet nw = NEP6Wallet.Migrate(npath, path, "123"); + bool result = nw.Contains(testScriptHash); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestSave() { JObject wallet = new JObject(); wallet["name"] = "name"; wallet["version"] = new System.Version().ToString(); - wallet["scrypt"] = ScryptParameters.Default.ToJson(); - // test minimally scryptparameters parsing here - ScryptParameters.FromJson(wallet["scrypt"]).Should().NotBeNull(); - ScryptParameters.FromJson(wallet["scrypt"]).N.Should().Be(ScryptParameters.Default.N); + wallet["scrypt"] = new ScryptParameters(0, 0, 0).ToJson(); + wallet["accounts"] = new JArray(); + wallet["extra"] = new JObject(); + File.WriteAllText(wPath, wallet.ToString()); + uut = new NEP6Wallet(wPath); + uut.Unlock("123"); + uut.CreateAccount(keyPair.PrivateKey); + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + uut.Save(); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + } + + [TestMethod] + public void TestUnlock() + { + Assert.ThrowsException(() => uut.CreateAccount(keyPair.PrivateKey)); + uut.Unlock("123"); + uut.CreateAccount(keyPair.PrivateKey); + bool result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + Assert.ThrowsException(() => uut.Unlock("1")); + } + + [TestMethod] + public void TestVerifyPassword() + { + bool result = uut.VerifyPassword("123"); + Assert.AreEqual(true, result); + Assert.ThrowsException(() => uut.CreateAccount(keyPair.PrivateKey)); + uut.Unlock("123"); + uut.CreateAccount(keyPair.PrivateKey); + result = uut.Contains(testScriptHash); + Assert.AreEqual(true, result); + result = uut.VerifyPassword("123"); + Assert.AreEqual(true, result); + uut.DeleteAccount(testScriptHash); + Assert.AreEqual(false, uut.Contains(testScriptHash)); + JObject wallet = new JObject(); + wallet["name"] = "name"; + wallet["version"] = new Version().ToString(); + wallet["scrypt"] = new ScryptParameters(0, 0, 0).ToJson(); wallet["accounts"] = new JArray(); - //accounts = ((JArray)wallet["accounts"]).Select(p => NEP6Account.FromJson(p, this)).ToDictionary(p => p.ScriptHash); wallet["extra"] = new JObject(); - // check string json - wallet.ToString().Should().Be("{\"name\":\"name\",\"version\":\"0.0\",\"scrypt\":{\"n\":16384,\"r\":8,\"p\":8},\"accounts\":[],\"extra\":{}}"); uut = new NEP6Wallet(wallet); + nep2key = keyPair.Export("123", 0, 0, 0); + uut.Import(nep2key, "123", 0, 0, 0); + Assert.IsFalse(uut.VerifyPassword("1")); + Assert.IsTrue(uut.VerifyPassword("123")); } [TestMethod] public void Test_NEP6Wallet_Json() { - uut.Name.Should().Be("name"); + uut.Name.Should().Be("noname"); uut.Version.Should().Be(new Version()); uut.Scrypt.Should().NotBeNull(); - uut.Scrypt.N.Should().Be(ScryptParameters.Default.N); + uut.Scrypt.N.Should().Be(new ScryptParameters(0, 0, 0).N); } } } diff --git a/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs b/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs index 3d4550a48d..adac8a13a2 100644 --- a/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs @@ -46,5 +46,15 @@ public void Test_Default_ScryptParameters_FromJson() uut2.R.Should().Be(ScryptParameters.Default.R); uut2.P.Should().Be(ScryptParameters.Default.P); } + + [TestMethod] + public void TestScryptParametersConstructor() + { + int n = 1, r = 2, p = 3; + ScryptParameters parameter = new ScryptParameters(n, r, p); + parameter.N.Should().Be(n); + parameter.R.Should().Be(r); + parameter.P.Should().Be(p); + } } } diff --git a/neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs b/neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs new file mode 100644 index 0000000000..70f3a649cf --- /dev/null +++ b/neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs @@ -0,0 +1,210 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.SmartContract; +using Neo.Wallets; +using Neo.Wallets.SQLite; +using System; +using System.IO; +using System.Security; +using System.Security.Cryptography; +using System.Threading; +using Contract = Neo.SmartContract.Contract; + +namespace Neo.UnitTests.Wallets.SQLite +{ + [TestClass] + public class UT_UserWallet + { + private string path; + private UserWallet wallet; + public static string GetRandomPath() + { + string threadName = Thread.CurrentThread.ManagedThreadId.ToString(); + return Path.GetFullPath(string.Format("Wallet_{0}", new Random().Next(1, 1000000).ToString("X8")) + threadName); + } + + [TestInitialize] + public void Setup() + { + path = GetRandomPath(); + wallet = UserWallet.Create(path, "123456"); + } + + [TestCleanup] + public void Cleanup() + { + TestUtils.DeleteFile(path); + } + + [TestMethod] + public void TestGetName() + { + wallet.Name.Should().Be(Path.GetFileNameWithoutExtension(path)); + } + + [TestMethod] + public void TestGetVersion() + { + Action action = () => wallet.Version.ToString(); + action.ShouldNotThrow(); + } + + [TestMethod] + public void TestCreateAndOpenSecureString() + { + string myPath = GetRandomPath(); + var ss = new SecureString(); + ss.AppendChar('a'); + ss.AppendChar('b'); + ss.AppendChar('c'); + + var w1 = UserWallet.Create(myPath, ss); + w1.Should().NotBeNull(); + + var w2 = UserWallet.Open(myPath, ss); + w2.Should().NotBeNull(); + + ss.AppendChar('d'); + Action action = () => UserWallet.Open(myPath, ss); + action.ShouldThrow(); + + TestUtils.DeleteFile(myPath); + } + + [TestMethod] + public void TestOpen() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + var account = wallet.CreateAccount(privateKey); + var w1 = UserWallet.Open(path, "123456"); + w1.Should().NotBeNull(); + + Action action = () => UserWallet.Open(path, "123"); + action.ShouldThrow(); + } + + [TestMethod] + public void TestCreateAccountAndGetByPrivateKey() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + var account = wallet.CreateAccount(privateKey); + var dbAccount = wallet.GetAccount(account.ScriptHash); + account.Should().Be(dbAccount); + + var account1 = wallet.CreateAccount(privateKey); + var dbAccount1 = wallet.GetAccount(account1.ScriptHash); + account1.Should().Be(dbAccount1); + } + + [TestMethod] + public void TestCreateAccountByScriptHash() + { + var account = wallet.CreateAccount(UInt160.Parse("0xa6ee944042f3c7ea900481a95d65e4a887320cf0")); + var dbAccount = wallet.GetAccount(account.ScriptHash); + account.Should().Be(dbAccount); + } + + [TestMethod] + public void TestCreateAccountBySmartContract() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + KeyPair key = new KeyPair(privateKey); + VerificationContract contract = new VerificationContract + { + Script = Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + var account = wallet.CreateAccount(contract, key); + var dbAccount = wallet.GetAccount(account.ScriptHash); + account.Should().Be(dbAccount); + + byte[] privateKey2 = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey2); + } + KeyPair key2 = new KeyPair(privateKey2); + Contract contract2 = new Contract + { + Script = Contract.CreateSignatureRedeemScript(key2.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + var account2 = wallet.CreateAccount(contract2, key2); + var dbAccount2 = wallet.GetAccount(account2.ScriptHash); + account2.Should().Be(dbAccount2); + } + + [TestMethod] + public void TestDeleteAccount() + { + bool ret = wallet.DeleteAccount(UInt160.Parse("0xa6ee944042f3c7ea900481a95d65e4a887320cf0")); + ret.Should().BeFalse(); + + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + var account = wallet.CreateAccount(privateKey); + bool ret2 = wallet.DeleteAccount(account.ScriptHash); + ret2.Should().BeTrue(); + } + + [TestMethod] + public void TestChangePassword() + { + wallet.ChangePassword("123455", "654321").Should().BeFalse(); + wallet.ChangePassword("123456", "654321").Should().BeTrue(); + } + + [TestMethod] + public void TestContains() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + var account = wallet.CreateAccount(privateKey); + wallet.Contains(account.ScriptHash).Should().BeTrue(); + } + + [TestMethod] + public void TestGetAccounts() + { + var ret = wallet.GetAccounts(); + ret.Should().BeNullOrEmpty(); + + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + var account = wallet.CreateAccount(privateKey); + ret = wallet.GetAccounts(); + foreach (var dbAccount in ret) + { + dbAccount.Should().Be(account); + } + } + + [TestMethod] + public void TestVerifyPassword() + { + wallet.VerifyPassword("123456").Should().BeTrue(); + wallet.VerifyPassword("123").Should().BeFalse(); + } + } +} diff --git a/neo.UnitTests/Wallets/SQLite/UT_UserWalletAccount.cs b/neo.UnitTests/Wallets/SQLite/UT_UserWalletAccount.cs new file mode 100644 index 0000000000..2a0dfd3f1d --- /dev/null +++ b/neo.UnitTests/Wallets/SQLite/UT_UserWalletAccount.cs @@ -0,0 +1,31 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Wallets.SQLite; +using System.Text; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_UserWalletAccount + { + [TestMethod] + public void TestGenerator() + { + UserWalletAccount account = new UserWalletAccount(UInt160.Zero); + Assert.IsNotNull(account); + } + + [TestMethod] + public void TestGetHasKey() + { + UserWalletAccount account = new UserWalletAccount(UInt160.Zero); + Assert.AreEqual(false, account.HasKey); + } + + [TestMethod] + public void TestGetKey() + { + UserWalletAccount account = new UserWalletAccount(UInt160.Zero); + Assert.AreEqual(null, account.GetKey()); + } + } +} diff --git a/neo.UnitTests/Wallets/SQLite/UT_VerificationContract.cs b/neo.UnitTests/Wallets/SQLite/UT_VerificationContract.cs new file mode 100644 index 0000000000..d590640fe5 --- /dev/null +++ b/neo.UnitTests/Wallets/SQLite/UT_VerificationContract.cs @@ -0,0 +1,148 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.SmartContract; +using Neo.Wallets; +using Neo.Wallets.SQLite; +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_VerificationContract + { + [TestMethod] + public void TestGenerator() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + KeyPair key = new KeyPair(privateKey); + VerificationContract contract = new VerificationContract + { + Script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + Assert.IsNotNull(contract); + } + + [TestMethod] + public void TestDeserialize() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + KeyPair key = new KeyPair(privateKey); + VerificationContract contract1 = new VerificationContract + { + Script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + BinaryReader reader = new BinaryReader(stream); + contract1.Serialize(writer); + stream.Seek(0, SeekOrigin.Begin); + VerificationContract contract2 = new VerificationContract(); + contract2.Deserialize(reader); + Assert.AreEqual(Encoding.Default.GetString(contract2.Script), Encoding.Default.GetString(contract1.Script)); + Assert.AreEqual(1, contract2.ParameterList.Length); + Assert.AreEqual(ContractParameterType.Signature, contract2.ParameterList[0]); + } + + [TestMethod] + public void TestEquals() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + KeyPair key = new KeyPair(privateKey); + VerificationContract contract1 = new VerificationContract + { + Script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + object tempObject = contract1; + VerificationContract contract2 = new VerificationContract + { + Script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + Assert.AreEqual(true, contract1.Equals(tempObject)); + Assert.AreEqual(true, contract1.Equals(contract1)); + Assert.AreEqual(false, contract1.Equals(null)); + Assert.AreEqual(true, contract1.Equals(contract2)); + } + + [TestMethod] + public void TestGetHashCode() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + KeyPair key = new KeyPair(privateKey); + VerificationContract contract1 = new VerificationContract + { + Script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + byte[] script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey); + Assert.AreEqual(script.ToScriptHash().GetHashCode(), contract1.GetHashCode()); + } + + [TestMethod] + public void TestSerialize() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + KeyPair key = new KeyPair(privateKey); + VerificationContract contract1 = new VerificationContract + { + Script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + contract1.Serialize(writer); + stream.Seek(0, SeekOrigin.Begin); + byte[] byteArray = new byte[stream.Length]; + stream.Read(byteArray, 0, (int)stream.Length); + byte[] script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey); + byte[] result = new byte[62]; + result[20] = 0x01; + result[21] = 0x00; + result[22] = 0x27; + Array.Copy(script, 0, result, 23, 39); + Assert.AreEqual(Encoding.Default.GetString(result), Encoding.Default.GetString(byteArray)); + } + + [TestMethod] + public void TestGetSize() + { + byte[] privateKey = new byte[32]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + KeyPair key = new KeyPair(privateKey); + VerificationContract contract1 = new VerificationContract + { + Script = Neo.SmartContract.Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + Assert.AreEqual(62, contract1.Size); + } + } +} diff --git a/neo.UnitTests/Wallets/UT_AssetDescriptor.cs b/neo.UnitTests/Wallets/UT_AssetDescriptor.cs index 6630a8450b..ca80f27b28 100644 --- a/neo.UnitTests/Wallets/UT_AssetDescriptor.cs +++ b/neo.UnitTests/Wallets/UT_AssetDescriptor.cs @@ -2,6 +2,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Persistence; using Neo.SmartContract.Native; +using System; namespace Neo.UnitTests.Wallets { @@ -17,12 +18,23 @@ public void TestSetup() Store = TestBlockchain.GetStore(); } + [TestMethod] + public void TestConstructorWithNonexistAssetId() + { + Action action = () => + { + var descriptor = new Neo.Wallets.AssetDescriptor(UInt160.Parse("01ff00ff00ff00ff00ff00ff00ff00ff00ff00a4")); + }; + action.ShouldThrow(); + } + [TestMethod] public void Check_GAS() { var descriptor = new Neo.Wallets.AssetDescriptor(NativeContract.GAS.Hash); descriptor.AssetId.Should().Be(NativeContract.GAS.Hash); descriptor.AssetName.Should().Be("GAS"); + descriptor.ToString().Should().Be("GAS"); descriptor.Decimals.Should().Be(8); } @@ -32,6 +44,7 @@ public void Check_NEO() var descriptor = new Neo.Wallets.AssetDescriptor(NativeContract.NEO.Hash); descriptor.AssetId.Should().Be(NativeContract.NEO.Hash); descriptor.AssetName.Should().Be("NEO"); + descriptor.ToString().Should().Be("NEO"); descriptor.Decimals.Should().Be(0); } } diff --git a/neo.UnitTests/Wallets/UT_KeyPair.cs b/neo.UnitTests/Wallets/UT_KeyPair.cs new file mode 100644 index 0000000000..dc67599111 --- /dev/null +++ b/neo.UnitTests/Wallets/UT_KeyPair.cs @@ -0,0 +1,114 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.Cryptography.ECC; +using Neo.Wallets; +using System; +using System.Linq; + +namespace Neo.UnitTests.Wallets +{ + [TestClass] + public class UT_KeyPair + { + [TestMethod] + public void TestConstructor() + { + Random random = new Random(); + byte[] privateKey = new byte[32]; + for (int i = 0; i < privateKey.Length; i++) + privateKey[i] = (byte)random.Next(256); + KeyPair keyPair = new KeyPair(privateKey); + ECPoint publicKey = ECCurve.Secp256r1.G * privateKey; + keyPair.PrivateKey.Should().BeEquivalentTo(privateKey); + keyPair.PublicKey.Should().Be(publicKey); + + byte[] privateKey96 = new byte[96]; + for (int i = 0; i < privateKey96.Length; i++) + privateKey96[i] = (byte)random.Next(256); + keyPair = new KeyPair(privateKey96); + publicKey = ECPoint.DecodePoint(new byte[] { 0x04 }.Concat(privateKey96.Skip(privateKey96.Length - 96).Take(64)).ToArray(), ECCurve.Secp256r1); + keyPair.PrivateKey.Should().BeEquivalentTo(privateKey96.Skip(64).Take(32)); + keyPair.PublicKey.Should().Be(publicKey); + + byte[] privateKey31 = new byte[31]; + for (int i = 0; i < privateKey31.Length; i++) + privateKey31[i] = (byte)random.Next(256); + Action action = () => new KeyPair(privateKey31); + action.ShouldThrow(); + } + + [TestMethod] + public void TestEquals() + { + Random random = new Random(); + byte[] privateKey = new byte[32]; + for (int i = 0; i < privateKey.Length; i++) + privateKey[i] = (byte)random.Next(256); + KeyPair keyPair = new KeyPair(privateKey); + KeyPair keyPair2 = keyPair; + keyPair.Equals(keyPair2).Should().BeTrue(); + + KeyPair keyPair3 = null; + keyPair.Equals(keyPair3).Should().BeFalse(); + + byte[] privateKey1 = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + byte[] privateKey2 = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02}; + KeyPair keyPair4 = new KeyPair(privateKey1); + KeyPair keyPair5 = new KeyPair(privateKey2); + keyPair4.Equals(keyPair5).Should().BeFalse(); + } + + [TestMethod] + public void TestEqualsWithObj() + { + Random random = new Random(); + byte[] privateKey = new byte[32]; + for (int i = 0; i < privateKey.Length; i++) + privateKey[i] = (byte)random.Next(256); + KeyPair keyPair = new KeyPair(privateKey); + Object keyPair2 = keyPair as Object; + keyPair.Equals(keyPair2).Should().BeTrue(); + } + + [TestMethod] + public void TestExport() + { + byte[] privateKey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + byte[] data = { 0x80, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + KeyPair keyPair = new KeyPair(privateKey); + keyPair.Export().Should().Be(data.Base58CheckEncode()); + } + + [TestMethod] + public void TestGetPublicKeyHash() + { + byte[] privateKey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + KeyPair keyPair = new KeyPair(privateKey); + keyPair.PublicKeyHash.ToString().Should().Be("0x4ab3d6ac3a0609e87af84599c93d57c2d0890406"); + } + + [TestMethod] + public void TestGetHashCode() + { + byte[] privateKey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + KeyPair keyPair = new KeyPair(privateKey); + keyPair.GetHashCode().Should().Be(1544360595); + } + + [TestMethod] + public void TestToString() + { + byte[] privateKey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + KeyPair keyPair = new KeyPair(privateKey); + keyPair.ToString().Should().Be("026ff03b949241ce1dadd43519e6960e0a85b41a69a05c328103aa2bce1594ca16"); + } + } +} diff --git a/neo.UnitTests/Wallets/UT_Wallet.cs b/neo.UnitTests/Wallets/UT_Wallet.cs new file mode 100644 index 0000000000..59289ae548 --- /dev/null +++ b/neo.UnitTests/Wallets/UT_Wallet.cs @@ -0,0 +1,436 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.ECC; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.SmartContract.Native.Tokens; +using Neo.UnitTests.Cryptography; +using Neo.Wallets; +using System; +using System.Collections.Generic; + +namespace Neo.UnitTests.Wallets +{ + internal class MyWallet : Wallet + { + public override string Name => "MyWallet"; + + public override Version Version => Version.Parse("0.0.1"); + + Dictionary accounts = new Dictionary(); + + public override bool Contains(UInt160 scriptHash) + { + return accounts.ContainsKey(scriptHash); + } + + public void AddAccount(WalletAccount account) + { + accounts.Add(account.ScriptHash, account); + } + + public override WalletAccount CreateAccount(byte[] privateKey) + { + KeyPair key = new KeyPair(privateKey); + Neo.Wallets.SQLite.VerificationContract contract = new Neo.Wallets.SQLite.VerificationContract + { + Script = Contract.CreateSignatureRedeemScript(key.PublicKey), + ParameterList = new[] { ContractParameterType.Signature } + }; + MyWalletAccount account = new MyWalletAccount(contract.ScriptHash); + account.SetKey(key); + account.Contract = contract; + AddAccount(account); + return account; + } + + public override WalletAccount CreateAccount(Contract contract, KeyPair key = null) + { + MyWalletAccount account = new MyWalletAccount(contract.ScriptHash) + { + Contract = contract + }; + account.SetKey(key); + AddAccount(account); + return account; + } + + public override WalletAccount CreateAccount(UInt160 scriptHash) + { + MyWalletAccount account = new MyWalletAccount(scriptHash); + AddAccount(account); + return account; + } + + public override bool DeleteAccount(UInt160 scriptHash) + { + return accounts.Remove(scriptHash); + } + + public override WalletAccount GetAccount(UInt160 scriptHash) + { + accounts.TryGetValue(scriptHash, out WalletAccount account); + return account; + } + + public override IEnumerable GetAccounts() + { + return accounts.Values; + } + + public override bool VerifyPassword(string password) + { + return true; + } + } + + [TestClass] + public class UT_Wallet + { + Store store; + private static KeyPair glkey; + private static string nep2Key; + + [ClassInitialize] + public static void ClassInit(TestContext context) + { + glkey = UT_Crypto.generateCertainKey(32); + nep2Key = glkey.Export("pwd", 0, 0, 0); + } + + [TestInitialize] + public void TestSetup() + { + store = TestBlockchain.GetStore(); + } + + [TestMethod] + public void TestContains() + { + MyWallet wallet = new MyWallet(); + Action action = () => wallet.Contains(UInt160.Zero); + action.ShouldNotThrow(); + } + + [TestMethod] + public void TestCreateAccount1() + { + MyWallet wallet = new MyWallet(); + wallet.CreateAccount(new byte[32]).Should().NotBeNull(); + } + + [TestMethod] + public void TestCreateAccount2() + { + MyWallet wallet = new MyWallet(); + Contract contract = Contract.Create(new ContractParameterType[] { ContractParameterType.Boolean }, new byte[] { 1 }); + WalletAccount account = wallet.CreateAccount(contract, UT_Crypto.generateCertainKey(32).PrivateKey); + account.Should().NotBeNull(); + + wallet = new MyWallet(); + account = wallet.CreateAccount(contract, (byte[])(null)); + account.Should().NotBeNull(); + } + + [TestMethod] + public void TestCreateAccount3() + { + MyWallet wallet = new MyWallet(); + Contract contract = Contract.Create(new ContractParameterType[] { ContractParameterType.Boolean }, new byte[] { 1 }); + wallet.CreateAccount(contract, glkey).Should().NotBeNull(); + } + + [TestMethod] + public void TestCreateAccount4() + { + MyWallet wallet = new MyWallet(); + wallet.CreateAccount(UInt160.Zero).Should().NotBeNull(); + } + + [TestMethod] + public void TestGetName() + { + MyWallet wallet = new MyWallet(); + wallet.Name.Should().Be("MyWallet"); + } + + [TestMethod] + public void TestGetVersion() + { + MyWallet wallet = new MyWallet(); + wallet.Version.Should().Be(Version.Parse("0.0.1")); + } + + [TestMethod] + public void TestGetAccount1() + { + MyWallet wallet = new MyWallet(); + wallet.CreateAccount(UInt160.Parse("522a2b818c308c7a2c77cfdda11763fe043bfb40")); + WalletAccount account = wallet.GetAccount(ECCurve.Secp256r1.G); + account.ScriptHash.Should().Be(UInt160.Parse("0x522a2b818c308c7a2c77cfdda11763fe043bfb40")); + } + + [TestMethod] + public void TestGetAccount2() + { + MyWallet wallet = new MyWallet(); + Action action = () => wallet.GetAccount(UInt160.Zero); + action.ShouldNotThrow(); + } + + [TestMethod] + public void TestGetAccounts() + { + MyWallet wallet = new MyWallet(); + Action action = () => wallet.GetAccounts(); + action.ShouldNotThrow(); + } + + [TestMethod] + public void TestGetAvailable() + { + MyWallet wallet = new MyWallet(); + Contract contract = Contract.Create(new ContractParameterType[] { ContractParameterType.Boolean }, new byte[] { 1 }); + WalletAccount account = wallet.CreateAccount(contract, glkey.PrivateKey); + account.Lock = false; + + // Fake balance + var snapshot = store.GetSnapshot(); + var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + wallet.GetAvailable(NativeContract.GAS.Hash).Should().Be(new BigDecimal(1000000000000, 8)); + + entry.Value = new Nep5AccountState() + { + Balance = 0 + } + .ToByteArray(); + } + + [TestMethod] + public void TestGetBalance() + { + MyWallet wallet = new MyWallet(); + Contract contract = Contract.Create(new ContractParameterType[] { ContractParameterType.Boolean }, new byte[] { 1 }); + WalletAccount account = wallet.CreateAccount(contract, glkey.PrivateKey); + account.Lock = false; + + // Fake balance + var snapshot = store.GetSnapshot(); + var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + wallet.GetBalance(UInt160.Zero, new UInt160[] { account.ScriptHash }).Should().Be(new BigDecimal(0, 0)); + wallet.GetBalance(NativeContract.GAS.Hash, new UInt160[] { account.ScriptHash }).Should().Be(new BigDecimal(1000000000000, 8)); + + entry.Value = new Nep5AccountState() + { + Balance = 0 + } + .ToByteArray(); + } + + [TestMethod] + public void TestGetPrivateKeyFromNEP2() + { + Action action = () => Wallet.GetPrivateKeyFromNEP2(null, null, 0, 0, 0); + action.ShouldThrow(); + + action = () => Wallet.GetPrivateKeyFromNEP2("TestGetPrivateKeyFromNEP2", null, 0, 0, 0); + action.ShouldThrow(); + + action = () => Wallet.GetPrivateKeyFromNEP2("3vQB7B6MrGQZaxCuFg4oh", "TestGetPrivateKeyFromNEP2", 0, 0, 0); + action.ShouldThrow(); + + action = () => Wallet.GetPrivateKeyFromNEP2(nep2Key, "Test", 0, 0, 0); + action.ShouldThrow(); + + Wallet.GetPrivateKeyFromNEP2(nep2Key, "pwd", 0, 0, 0).Should().BeEquivalentTo(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }); + } + + [TestMethod] + public void TestGetPrivateKeyFromWIF() + { + Action action = () => Wallet.GetPrivateKeyFromWIF(null); + action.ShouldThrow(); + + action = () => Wallet.GetPrivateKeyFromWIF("3vQB7B6MrGQZaxCuFg4oh"); + action.ShouldThrow(); + + Wallet.GetPrivateKeyFromWIF("L3tgppXLgdaeqSGSFw1Go3skBiy8vQAM7YMXvTHsKQtE16PBncSU").Should().BeEquivalentTo(new byte[] { 199, 19, 77, 111, 216, 231, 61, 129, 158, 130, 117, 92, 100, 201, 55, 136, 216, 219, 9, 97, 146, 158, 2, 90, 83, 54, 60, 76, 192, 42, 105, 98 }); + } + + [TestMethod] + public void TestImport1() + { + MyWallet wallet = new MyWallet(); + wallet.Import("L3tgppXLgdaeqSGSFw1Go3skBiy8vQAM7YMXvTHsKQtE16PBncSU").Should().NotBeNull(); + } + + [TestMethod] + public void TestImport2() + { + MyWallet wallet = new MyWallet(); + wallet.Import(nep2Key, "pwd", 0, 0, 0).Should().NotBeNull(); + } + + [TestMethod] + public void TestMakeTransaction1() + { + MyWallet wallet = new MyWallet(); + Contract contract = Contract.Create(new ContractParameterType[] { ContractParameterType.Boolean }, new byte[] { 1 }); + WalletAccount account = wallet.CreateAccount(contract, glkey.PrivateKey); + account.Lock = false; + + Action action = () => wallet.MakeTransaction(new TransferOutput[] + { + new TransferOutput() + { + AssetId = NativeContract.GAS.Hash, + ScriptHash = account.ScriptHash, + Value = new BigDecimal(1,8) + } + }, UInt160.Zero); + action.ShouldThrow(); + + action = () => wallet.MakeTransaction(new TransferOutput[] + { + new TransferOutput() + { + AssetId = NativeContract.GAS.Hash, + ScriptHash = account.ScriptHash, + Value = new BigDecimal(1,8) + } + }, account.ScriptHash); + action.ShouldThrow(); + + action = () => wallet.MakeTransaction(new TransferOutput[] + { + new TransferOutput() + { + AssetId = UInt160.Zero, + ScriptHash = account.ScriptHash, + Value = new BigDecimal(1,8) + } + }, account.ScriptHash); + action.ShouldThrow(); + + // Fake balance + var snapshot = store.GetSnapshot(); + var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + entry.Value = new Nep5AccountState() + { + Balance = 10000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + key = NativeContract.NEO.CreateStorageKey(20, account.ScriptHash); + entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + entry.Value = new NeoToken.AccountState() + { + Balance = 10000 * NativeContract.NEO.Factor + } + .ToByteArray(); + + var tx = wallet.MakeTransaction(new TransferOutput[] + { + new TransferOutput() + { + AssetId = NativeContract.GAS.Hash, + ScriptHash = account.ScriptHash, + Value = new BigDecimal(1,8) + } + }); + tx.Should().NotBeNull(); + + tx = wallet.MakeTransaction(new TransferOutput[] + { + new TransferOutput() + { + AssetId = NativeContract.NEO.Hash, + ScriptHash = account.ScriptHash, + Value = new BigDecimal(1,8) + } + }); + tx.Should().NotBeNull(); + + entry.Value = new NeoToken.AccountState() + { + Balance = 0 + } + .ToByteArray(); + } + + [TestMethod] + public void TestMakeTransaction2() + { + MyWallet wallet = new MyWallet(); + Action action = () => wallet.MakeTransaction(new byte[] { }, UInt160.Zero, new TransactionAttribute[] { }); + action.ShouldThrow(); + + Contract contract = Contract.Create(new ContractParameterType[] { ContractParameterType.Boolean }, new byte[] { 1 }); + WalletAccount account = wallet.CreateAccount(contract, glkey.PrivateKey); + account.Lock = false; + + // Fake balance + var snapshot = store.GetSnapshot(); + var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash); + var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem + { + Value = new Nep5AccountState().ToByteArray() + }); + entry.Value = new Nep5AccountState() + { + Balance = 1000000 * NativeContract.GAS.Factor + } + .ToByteArray(); + + var tx = wallet.MakeTransaction(new byte[] { }, account.ScriptHash, new TransactionAttribute[] { }); + tx.Should().NotBeNull(); + + tx = wallet.MakeTransaction(new byte[] { }, null, new TransactionAttribute[] { }); + tx.Should().NotBeNull(); + + entry.Value = new NeoToken.AccountState() + { + Balance = 0 + } + .ToByteArray(); + } + + [TestMethod] + public void TestVerifyPassword() + { + MyWallet wallet = new MyWallet(); + Action action = () => wallet.VerifyPassword("Test"); + action.ShouldNotThrow(); + } + } +} \ No newline at end of file diff --git a/neo.UnitTests/Wallets/UT_WalletAccount.cs b/neo.UnitTests/Wallets/UT_WalletAccount.cs new file mode 100644 index 0000000000..15e2bd1974 --- /dev/null +++ b/neo.UnitTests/Wallets/UT_WalletAccount.cs @@ -0,0 +1,48 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.SmartContract; +using Neo.Wallets; + +namespace Neo.UnitTests.Wallets +{ + public class MyWalletAccount : WalletAccount + { + private KeyPair key = null; + public override bool HasKey => key != null; + + public MyWalletAccount(UInt160 scriptHash) + : base(scriptHash) + { + } + + public override KeyPair GetKey() + { + return key; + } + + public void SetKey(KeyPair inputKey) + { + key = inputKey; + } + } + + [TestClass] + public class UT_WalletAccount + { + [TestMethod] + public void TestGetAddress() + { + MyWalletAccount walletAccount = new MyWalletAccount(UInt160.Zero); + walletAccount.Address.Should().Be("AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM"); + } + + [TestMethod] + public void TestGetWatchOnly() + { + MyWalletAccount walletAccount = new MyWalletAccount(UInt160.Zero); + walletAccount.WatchOnly.Should().BeTrue(); + walletAccount.Contract = new Contract(); + walletAccount.WatchOnly.Should().BeFalse(); + } + } +} diff --git a/neo.UnitTests/Wallets/UT_Wallets_Helper.cs b/neo.UnitTests/Wallets/UT_Wallets_Helper.cs new file mode 100644 index 0000000000..01f47fea16 --- /dev/null +++ b/neo.UnitTests/Wallets/UT_Wallets_Helper.cs @@ -0,0 +1,32 @@ +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.Wallets; +using System; + +namespace Neo.UnitTests.Wallets +{ + [TestClass] + public class UT_Wallets_Helper + { + [TestMethod] + public void TestToScriptHash() + { + byte[] array = { 0x01 }; + UInt160 scriptHash = new UInt160(Crypto.Default.Hash160(array)); + "AZk5bAanTtD6AvpeesmYgL8CLRYUt5JQsX".ToScriptHash().Should().Be(scriptHash); + + Action action = () => "3vQB7B6MrGQZaxCuFg4oh".ToScriptHash(); + action.ShouldThrow(); + + var address = scriptHash.ToAddress(); + byte[] data = new byte[21]; + // NEO version is 0x17 + data[0] = 0x01; + Buffer.BlockCopy(scriptHash.ToArray(), 0, data, 1, 20); + address = data.Base58CheckEncode(); + action = () => address.ToScriptHash(); + action.ShouldThrow(); + } + } +} diff --git a/neo/Wallets/NEP6/NEP6Wallet.cs b/neo/Wallets/NEP6/NEP6Wallet.cs index 9fe133d9ce..9f0d0a1315 100644 --- a/neo/Wallets/NEP6/NEP6Wallet.cs +++ b/neo/Wallets/NEP6/NEP6Wallet.cs @@ -216,9 +216,9 @@ public override WalletAccount Import(string wif) return account; } - public override WalletAccount Import(string nep2, string passphrase) + public override WalletAccount Import(string nep2, string passphrase, int N = 16384, int r = 8, int p = 8) { - KeyPair key = new KeyPair(GetPrivateKeyFromNEP2(nep2, passphrase)); + KeyPair key = new KeyPair(GetPrivateKeyFromNEP2(nep2, passphrase, N, r, p)); NEP6Contract contract = new NEP6Contract { Script = Contract.CreateSignatureRedeemScript(key.PublicKey), diff --git a/neo/Wallets/SQLite/UserWallet.cs b/neo/Wallets/SQLite/UserWallet.cs index c66734f172..df4cccfe08 100644 --- a/neo/Wallets/SQLite/UserWallet.cs +++ b/neo/Wallets/SQLite/UserWallet.cs @@ -123,12 +123,12 @@ private void AddAccount(UserWalletAccount account, bool is_import) } //add address { - Address db_address = ctx.Addresses.FirstOrDefault(p => p.ScriptHash == account.Contract.ScriptHash.ToArray()); + Address db_address = ctx.Addresses.FirstOrDefault(p => p.ScriptHash == account.ScriptHash.ToArray()); if (db_address == null) { ctx.Addresses.Add(new Address { - ScriptHash = account.Contract.ScriptHash.ToArray() + ScriptHash = account.ScriptHash.ToArray() }); } } diff --git a/neo/Wallets/Wallet.cs b/neo/Wallets/Wallet.cs index 7912ca97b6..d22c8ff128 100644 --- a/neo/Wallets/Wallet.cs +++ b/neo/Wallets/Wallet.cs @@ -200,9 +200,9 @@ public virtual WalletAccount Import(string wif) return account; } - public virtual WalletAccount Import(string nep2, string passphrase) + public virtual WalletAccount Import(string nep2, string passphrase, int N = 16384, int r = 8, int p = 8) { - byte[] privateKey = GetPrivateKeyFromNEP2(nep2, passphrase); + byte[] privateKey = GetPrivateKeyFromNEP2(nep2, passphrase, N, r, p); WalletAccount account = CreateAccount(privateKey); Array.Clear(privateKey, 0, privateKey.Length); return account; From a705b43ca9a62b3a951898ba1b9550aa461160e9 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 19 Aug 2019 10:52:20 +0200 Subject: [PATCH 30/54] Revert Console.WriteLine (#986) --- neo/Consensus/ConsensusService.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index 8723b2c70b..0bc77f0fff 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -175,7 +175,6 @@ private void InitializeConsensus(byte viewNumber) private void Log(string message, LogLevel level = LogLevel.Info) { - Console.WriteLine($"[{DateTime.Now.TimeOfDay:hh\\:mm\\:ss\\.fff}] {message}"); Plugin.Log(nameof(ConsensusService), level, message); } From e7928986c7f724c857c194cd68c6263b135b75c1 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 20 Aug 2019 09:08:18 +0200 Subject: [PATCH 31/54] Set max block size (#953) * Draft * Take into account p2p max payload * Move max allowed to policy * Check block size on prepResponse * Change reason * Prevent overflow * Optimization * Reduce the length of the array * Organizing consensus code * Revert "Organizing consensus code" This reverts commit 94a29dc9dc18f9a3836db773d652e72c5e688222. * Remove Policy UT * Resolve Policy conflicts * prepare unit test * Small unit test * More ut * Add one check * Clean using * Organizing consensus and comments * Split unit test * UT check block size * Clean * Expected witness size * optimize * Remove fakeWitness * Format comments * rename var * Add (..) * Remove SetKey method * Centralize expected block size * Optimize * Fix * Add one test * Optimize `EnsureMaxBlockSize()` * Fix unit tests * Rename * Indent * Vitor suggestion * Merge with Scoped signatures * Remove extra line * Revert "Remove extra line" This reverts commit e1348813a488e3be736f177e20df79e1efa01c6c. * Remove extra line --- .../Consensus/UT_ConsensusContext.cs | 163 ++++++++++++++++++ .../SmartContract/Native/UT_PolicyContract.cs | 52 +++++- neo/Consensus/ChangeViewReason.cs | 1 + neo/Consensus/ConsensusContext.cs | 98 ++++++++++- neo/Consensus/ConsensusService.cs | 8 + neo/Network/P2P/Payloads/Block.cs | 1 - neo/Network/P2P/Payloads/BlockBase.cs | 6 +- neo/SmartContract/Native/PolicyContract.cs | 27 +++ 8 files changed, 344 insertions(+), 12 deletions(-) create mode 100644 neo.UnitTests/Consensus/UT_ConsensusContext.cs diff --git a/neo.UnitTests/Consensus/UT_ConsensusContext.cs b/neo.UnitTests/Consensus/UT_ConsensusContext.cs new file mode 100644 index 0000000000..696d6aaa0a --- /dev/null +++ b/neo.UnitTests/Consensus/UT_ConsensusContext.cs @@ -0,0 +1,163 @@ +using Akka.TestKit.Xunit2; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Neo.Consensus; +using Neo.IO; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.Wallets; +using System; +using System.Linq; + +namespace Neo.UnitTests.Consensus +{ + + [TestClass] + public class UT_ConsensusContext : TestKit + { + ConsensusContext _context; + KeyPair[] _validatorKeys; + + [TestInitialize] + public void TestSetup() + { + TestBlockchain.InitializeMockNeoSystem(); + + var rand = new Random(); + var mockWallet = new Mock(); + mockWallet.Setup(p => p.GetAccount(It.IsAny())).Returns(p => new TestWalletAccount(p)); + + // Create dummy validators + + _validatorKeys = new KeyPair[7]; + for (int x = 0; x < _validatorKeys.Length; x++) + { + var pk = new byte[32]; + rand.NextBytes(pk); + + _validatorKeys[x] = new KeyPair(pk); + } + + _context = new ConsensusContext(mockWallet.Object, TestBlockchain.GetStore()) + { + Validators = _validatorKeys.Select(u => u.PublicKey).ToArray() + }; + _context.Reset(0); + } + + [TestCleanup] + public void Cleanup() + { + Shutdown(); + } + + [TestMethod] + public void TestMaxBlockSize_Good() + { + // Only one tx, is included + + var tx1 = CreateTransactionWithSize(200); + _context.EnsureMaxBlockSize(new Transaction[] { tx1 }); + EnsureContext(_context, tx1); + + // All txs included + + var max = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(_context.Snapshot); + var txs = new Transaction[max]; + + for (int x = 0; x < max; x++) txs[x] = CreateTransactionWithSize(100); + + _context.EnsureMaxBlockSize(txs); + EnsureContext(_context, txs); + } + + [TestMethod] + public void TestMaxBlockSize_Exceed() + { + // Two tx, the last one exceed the size rule, only the first will be included + + var tx1 = CreateTransactionWithSize(200); + var tx2 = CreateTransactionWithSize(256 * 1024); + _context.EnsureMaxBlockSize(new Transaction[] { tx1, tx2 }); + EnsureContext(_context, tx1); + + // Exceed txs number, just MaxTransactionsPerBlock included + + var max = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(_context.Snapshot); + var txs = new Transaction[max + 1]; + + for (int x = 0; x < max; x++) txs[x] = CreateTransactionWithSize(100); + + _context.EnsureMaxBlockSize(txs); + EnsureContext(_context, txs.Take(max).ToArray()); + } + + private Transaction CreateTransactionWithSize(int v) + { + var r = new Random(); + var tx = new Transaction() + { + Cosigners = new Cosigner[0], + Attributes = new TransactionAttribute[0], + NetworkFee = 0, + Nonce = (uint)Environment.TickCount, + Script = new byte[0], + Sender = UInt160.Zero, + SystemFee = 0, + ValidUntilBlock = (uint)r.Next(), + Version = 0, + Witnesses = new Witness[0], + }; + + // Could be higher (few bytes) if varSize grows + tx.Script = new byte[v - tx.Size]; + return tx; + } + + private Block SignBlock(ConsensusContext context) + { + context.Block.MerkleRoot = null; + + for (int x = 0; x < _validatorKeys.Length; x++) + { + _context.MyIndex = x; + + var com = _context.MakeCommit(); + _context.CommitPayloads[_context.MyIndex] = com; + } + + // Manual block sign + + Contract contract = Contract.CreateMultiSigContract(context.M, context.Validators); + ContractParametersContext sc = new ContractParametersContext(context.Block); + for (int i = 0, j = 0; i < context.Validators.Length && j < context.M; i++) + { + if (context.CommitPayloads[i]?.ConsensusMessage.ViewNumber != context.ViewNumber) continue; + sc.AddSignature(contract, context.Validators[i], context.CommitPayloads[i].GetDeserializedMessage().Signature); + j++; + } + context.Block.Witness = sc.GetWitnesses()[0]; + context.Block.Transactions = context.TransactionHashes.Select(p => context.Transactions[p]).ToArray(); + return context.Block; + } + + private void EnsureContext(ConsensusContext context, params Transaction[] expected) + { + // Check all tx + + Assert.AreEqual(expected.Length, context.Transactions.Count); + Assert.IsTrue(expected.All(tx => context.Transactions.ContainsKey(tx.Hash))); + + Assert.AreEqual(expected.Length, context.TransactionHashes.Length); + Assert.IsTrue(expected.All(tx => context.TransactionHashes.Count(t => t == tx.Hash) == 1)); + + // Ensure length + + var block = SignBlock(context); + + Assert.AreEqual(context.GetExpectedBlockSize(), block.Size); + Assert.IsTrue(block.Size < NativeContract.Policy.GetMaxBlockSize(context.Snapshot)); + } + } +} diff --git a/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index b77030d554..b53932dbf8 100644 --- a/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -32,12 +32,16 @@ public void Check_Initialize() NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); - (keyCount + 3).Should().Be(snapshot.Storages.GetChangeSet().Count()); + (keyCount + 4).Should().Be(snapshot.Storages.GetChangeSet().Count()); var ret = NativeContract.Policy.Call(snapshot, "getMaxTransactionsPerBlock"); ret.Should().BeOfType(); ret.GetBigInteger().Should().Be(512); + ret = NativeContract.Policy.Call(snapshot, "getMaxBlockSize"); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(1024 * 256); + ret = NativeContract.Policy.Call(snapshot, "getFeePerByte"); ret.Should().BeOfType(); ret.GetBigInteger().Should().Be(1000); @@ -47,6 +51,52 @@ public void Check_Initialize() ((VM.Types.Array)ret).Count.Should().Be(0); } + [TestMethod] + public void Check_SetMaxBlockSize() + { + var snapshot = Store.GetSnapshot().Clone(); + + // Fake blockchain + + snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero }; + snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero }); + + NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue(); + + // Without signature + + var ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(null), + "setMaxBlockSize", new ContractParameter(ContractParameterType.Integer) { Value = 1024 }); + ret.Should().BeOfType(); + ret.GetBoolean().Should().BeFalse(); + + ret = NativeContract.Policy.Call(snapshot, "getMaxBlockSize"); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(1024 * 256); + + // More than expected + + ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), + "setMaxBlockSize", new ContractParameter(ContractParameterType.Integer) { Value = Neo.Network.P2P.Message.PayloadMaxSize }); + ret.Should().BeOfType(); + ret.GetBoolean().Should().BeFalse(); + + ret = NativeContract.Policy.Call(snapshot, "getMaxBlockSize"); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(1024 * 256); + + // With signature + + ret = NativeContract.Policy.Call(snapshot, new Nep5NativeContractExtensions.ManualWitness(UInt160.Zero), + "setMaxBlockSize", new ContractParameter(ContractParameterType.Integer) { Value = 1024 }); + ret.Should().BeOfType(); + ret.GetBoolean().Should().BeTrue(); + + ret = NativeContract.Policy.Call(snapshot, "getMaxBlockSize"); + ret.Should().BeOfType(); + ret.GetBigInteger().Should().Be(1024); + } + [TestMethod] public void Check_SetMaxTransactionsPerBlock() { diff --git a/neo/Consensus/ChangeViewReason.cs b/neo/Consensus/ChangeViewReason.cs index 64a2a6053e..eb06b7494a 100644 --- a/neo/Consensus/ChangeViewReason.cs +++ b/neo/Consensus/ChangeViewReason.cs @@ -7,5 +7,6 @@ public enum ChangeViewReason : byte TxNotFound = 0x2, TxRejectedByPolicy = 0x3, TxInvalid = 0x4, + BlockRejectedByPolicy = 0x5 } } \ No newline at end of file diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs index ba7edf66c5..a06c6c965b 100644 --- a/neo/Consensus/ConsensusContext.cs +++ b/neo/Consensus/ConsensusContext.cs @@ -6,6 +6,7 @@ using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; +using Neo.VM; using Neo.Wallets; using System; using System.Collections.Generic; @@ -38,10 +39,11 @@ internal class ConsensusContext : IDisposable, ISerializable public Snapshot Snapshot { get; private set; } private KeyPair keyPair; + private int _witnessSize; private readonly Wallet wallet; private readonly Store store; private readonly Random random = new Random(); - + public int F => (Validators.Length - 1) / 3; public int M => Validators.Length - F; public bool IsPrimary => MyIndex == Block.ConsensusData.PrimaryIndex; @@ -203,19 +205,84 @@ private void SignPayload(ConsensusPayload payload) return; } payload.Witness = sc.GetWitnesses()[0]; + } + + /// + /// Return the expected block size + /// + internal int GetExpectedBlockSize() + { + return GetExpectedBlockSizeWithoutTransactions(Transactions.Count) + // Base size + Transactions.Values.Sum(u => u.Size); // Sum Txs + } + + /// + /// Return the expected block size without txs + /// + /// Expected transactions + internal int GetExpectedBlockSizeWithoutTransactions(int expectedTransactions) + { + var blockSize = + // BlockBase + sizeof(uint) + //Version + UInt256.Length + //PrevHash + UInt256.Length + //MerkleRoot + sizeof(ulong) + //Timestamp + sizeof(uint) + //Index + UInt160.Length + //NextConsensus + 1 + // + _witnessSize; //Witness + + blockSize += + // Block + Block.ConsensusData.Size + //ConsensusData + IO.Helper.GetVarSize(expectedTransactions + 1); //Transactions count + + return blockSize; + } + + /// + /// Prevent that block exceed the max size + /// + /// Ordered transactions + internal void EnsureMaxBlockSize(IEnumerable txs) + { + uint maxBlockSize = NativeContract.Policy.GetMaxBlockSize(Snapshot); + uint maxTransactionsPerBlock = NativeContract.Policy.GetMaxTransactionsPerBlock(Snapshot); + + // Limit Speaker proposal to the limit `MaxTransactionsPerBlock` or all available transactions of the mempool + txs = txs.Take((int)maxTransactionsPerBlock); + List hashes = new List(); + Transactions = new Dictionary(); + Block.Transactions = new Transaction[0]; + + // We need to know the expected block size + + var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Count()); + + // Iterate transaction until reach the size + + foreach (Transaction tx in txs) + { + // Check if maximum block size has been already exceeded with the current selected set + blockSize += tx.Size; + if (blockSize > maxBlockSize) break; + + hashes.Add(tx.Hash); + Transactions.Add(tx.Hash, tx); + } + + TransactionHashes = hashes.ToArray(); } public ConsensusPayload MakePrepareRequest() { byte[] buffer = new byte[sizeof(ulong)]; random.NextBytes(buffer); - List transactions = Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions() - .Take((int)NativeContract.Policy.GetMaxTransactionsPerBlock(Snapshot)) - .ToList(); - TransactionHashes = transactions.Select(p => p.Hash).ToArray(); - Transactions = transactions.ToDictionary(p => p.Hash); - Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); Block.ConsensusData.Nonce = BitConverter.ToUInt64(buffer, 0); + EnsureMaxBlockSize(Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions()); + Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); + return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareRequest { Timestamp = Block.Timestamp, @@ -279,7 +346,24 @@ public void Reset(byte viewNumber) NextConsensus = Blockchain.GetConsensusAddress(NativeContract.NEO.GetValidators(Snapshot).ToArray()), ConsensusData = new ConsensusData() }; + var pv = Validators; Validators = NativeContract.NEO.GetNextBlockValidators(Snapshot); + if (_witnessSize == 0 || (pv != null && pv.Length != Validators.Length)) + { + // Compute the expected size of the witness + using (ScriptBuilder sb = new ScriptBuilder()) + { + for (int x = 0; x < M; x++) + { + sb.EmitPush(new byte[64]); + } + _witnessSize = new Witness + { + InvocationScript = sb.ToArray(), + VerificationScript = Contract.CreateMultiSigRedeemScript(M, Validators) + }.Size; + } + } MyIndex = -1; ChangeViewPayloads = new ConsensusPayload[Validators.Length]; LastChangeViewPayloads = new ConsensusPayload[Validators.Length]; diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index 0bc77f0fff..ee5c91d635 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -80,6 +80,14 @@ private bool AddTransaction(Transaction tx, bool verify) // previously sent prepare request, then we don't want to send a prepare response. if (context.IsPrimary || context.WatchOnly) return true; + // Check maximum block size via Native Contract policy + if (context.GetExpectedBlockSize() > NativeContract.Policy.GetMaxBlockSize(context.Snapshot)) + { + Log($"rejected block: {context.Block.Index}{Environment.NewLine} The size exceed the policy", LogLevel.Warning); + RequestChangeView(ChangeViewReason.BlockRejectedByPolicy); + return false; + } + // Timeout extension due to prepare response sent // around 2*15/M=30.0/5 ~ 40% block time (for M=5) ExtendTimerByFactor(2); diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index 3f29bb9428..75e5d7c424 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -2,7 +2,6 @@ using Neo.IO; using Neo.IO.Json; using Neo.Ledger; -using Neo.Wallets; using System; using System.Collections.Generic; using System.IO; diff --git a/neo/Network/P2P/Payloads/BlockBase.cs b/neo/Network/P2P/Payloads/BlockBase.cs index 8820c95538..20a0c98211 100644 --- a/neo/Network/P2P/Payloads/BlockBase.cs +++ b/neo/Network/P2P/Payloads/BlockBase.cs @@ -35,11 +35,11 @@ public UInt256 Hash public virtual int Size => sizeof(uint) + //Version - PrevHash.Size + //PrevHash - MerkleRoot.Size + //MerkleRoot + UInt256.Length + //PrevHash + UInt256.Length + //MerkleRoot sizeof(ulong) + //Timestamp sizeof(uint) + //Index - NextConsensus.Size + //NextConsensus + UInt160.Length + //NextConsensus 1 + // Witness.Size; //Witness diff --git a/neo/SmartContract/Native/PolicyContract.cs b/neo/SmartContract/Native/PolicyContract.cs index 239cd92200..c5820cfd15 100644 --- a/neo/SmartContract/Native/PolicyContract.cs +++ b/neo/SmartContract/Native/PolicyContract.cs @@ -21,6 +21,7 @@ public sealed class PolicyContract : NativeContract private const byte Prefix_MaxTransactionsPerBlock = 23; private const byte Prefix_FeePerByte = 10; private const byte Prefix_BlockedAccounts = 15; + private const byte Prefix_MaxBlockSize = 16; public PolicyContract() { @@ -45,6 +46,10 @@ private bool CheckValidators(ApplicationEngine engine) internal override bool Initialize(ApplicationEngine engine) { if (!base.Initialize(engine)) return false; + engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_MaxBlockSize), new StorageItem + { + Value = BitConverter.GetBytes(1024u * 256u) + }); engine.Snapshot.Storages.Add(CreateStorageKey(Prefix_MaxTransactionsPerBlock), new StorageItem { Value = BitConverter.GetBytes(512u) @@ -71,6 +76,17 @@ public uint GetMaxTransactionsPerBlock(Snapshot snapshot) return BitConverter.ToUInt32(snapshot.Storages[CreateStorageKey(Prefix_MaxTransactionsPerBlock)].Value, 0); } + [ContractMethod(0_01000000, ContractParameterType.Integer, SafeMethod = true)] + private StackItem GetMaxBlockSize(ApplicationEngine engine, VMArray args) + { + return GetMaxBlockSize(engine.Snapshot); + } + + public uint GetMaxBlockSize(Snapshot snapshot) + { + return BitConverter.ToUInt32(snapshot.Storages[CreateStorageKey(Prefix_MaxBlockSize)].Value, 0); + } + [ContractMethod(0_01000000, ContractParameterType.Integer, SafeMethod = true)] private StackItem GetFeePerByte(ApplicationEngine engine, VMArray args) { @@ -93,6 +109,17 @@ public UInt160[] GetBlockedAccounts(Snapshot snapshot) return snapshot.Storages[CreateStorageKey(Prefix_BlockedAccounts)].Value.AsSerializableArray(); } + [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] + private StackItem SetMaxBlockSize(ApplicationEngine engine, VMArray args) + { + if (!CheckValidators(engine)) return false; + uint value = (uint)args[0].GetBigInteger(); + if (Network.P2P.Message.PayloadMaxSize <= value) return false; + StorageItem storage = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_MaxBlockSize)); + storage.Value = BitConverter.GetBytes(value); + return true; + } + [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })] private StackItem SetMaxTransactionsPerBlock(ApplicationEngine engine, VMArray args) { From 7cc961b8fe4e088bea3b8f1021d92fc2e4a98439 Mon Sep 17 00:00:00 2001 From: Ricardo Prado <38396062+lock9@users.noreply.github.com> Date: Tue, 20 Aug 2019 16:13:00 -0300 Subject: [PATCH 32/54] GitHub Contribution Guide (#1028) Adding GitHub Contribution Guide --- .github/images/compiler.png | Bin 0 -> 1605 bytes .github/images/consensus.png | Bin 0 -> 1644 bytes .github/images/cosmetic.png | Bin 0 -> 1614 bytes .github/images/discussion.png | Bin 0 -> 1673 bytes .github/images/enhancement.png | Bin 0 -> 1711 bytes .github/images/house-keeping.png | Bin 0 -> 2267 bytes .github/images/ledger.png | Bin 0 -> 1270 bytes .github/images/migration.png | Bin 0 -> 1685 bytes .github/images/network-policy.png | Bin 0 -> 2383 bytes .github/images/new-feature.png | Bin 0 -> 1771 bytes .github/images/p2p.png | Bin 0 -> 816 bytes .github/images/ready-to-implement.png | Bin 0 -> 2350 bytes .github/images/rpc.png | Bin 0 -> 799 bytes .github/images/sdk.png | Bin 0 -> 917 bytes .github/images/solution-design.png | Bin 0 -> 1420 bytes .github/images/to-review.png | Bin 0 -> 1629 bytes .github/images/vm.png | Bin 0 -> 653 bytes .github/images/wallet.png | Bin 0 -> 1252 bytes CONTRIBUTING.md | 82 ++++++++++++++++++++++++++ 19 files changed, 82 insertions(+) create mode 100644 .github/images/compiler.png create mode 100644 .github/images/consensus.png create mode 100644 .github/images/cosmetic.png create mode 100644 .github/images/discussion.png create mode 100644 .github/images/enhancement.png create mode 100644 .github/images/house-keeping.png create mode 100644 .github/images/ledger.png create mode 100644 .github/images/migration.png create mode 100644 .github/images/network-policy.png create mode 100644 .github/images/new-feature.png create mode 100644 .github/images/p2p.png create mode 100644 .github/images/ready-to-implement.png create mode 100644 .github/images/rpc.png create mode 100644 .github/images/sdk.png create mode 100644 .github/images/solution-design.png create mode 100644 .github/images/to-review.png create mode 100644 .github/images/vm.png create mode 100644 .github/images/wallet.png create mode 100644 CONTRIBUTING.md diff --git a/.github/images/compiler.png b/.github/images/compiler.png new file mode 100644 index 0000000000000000000000000000000000000000..affa7ca8ac3ad4e2c35e6975f9fdab81e7f1d58d GIT binary patch literal 1605 zcmV-L2D>$?_JREUP37yU++E`8B}eDP(PcBunyplDWO=j0C-(1z^D_6D>8j zSEb6(>luRH{lr3>ni|r-j{|uH6_l0N;MUuo{7aQwE387R)jfKQWS(4Tw>}O;s(grv z%i;LRLcUz-!JY$oe7!MUIN_1klMHQUW{CTM*5u@>X<^ljjq82?TWFVVHmqIcNuOSJ z)YfS^aq2qr7abwLpaQ4PEm;@riCb?6^z|Vtr<~dI4wIfyOjjps!b1j=dr{2`-EC>- z*j)T3G$M_+r*`KBS6goWS;zZx6VcV{Sn}xr&R-~_UtfFLIa*S5;}$dLC35U|Asstd zvVP5Aw#Q_V{d+m8)n0d@WmzU9*b8ruwip@dlaW~>Y{>e(oDS_R`R1!vNIzH1fPSs0 z(P)`IJAvFh^_}EsEYcR{MjVJ8g^RNd$-i8|!On~>om�kWbK>lSHU|aP4NpfkXM| z>q~eHbQB=tChf!A+(@Kk#|~Cpx_lEoJ+QYk!^luyq-0)x1PXAK#5O ztt~j6T0~`KElNsjZ|m?M7l%^Qjiq-*T5&$R6m_|V7kk=Krq(cF%6<$C z^oWY^!>LmXZfkYy*qKG(7bm%1RMj-}f)D#LV_HvC;i+tn&ZMHUmLGPF7RH@PE5dVN zTU6m^*|P1t*b536$mG|Y`Cxt$W$GGK!Cn-XRx{(nL<;_>B>CV3TwQGN9vUOOAG>Y1 z$dah&Ova6L5{{U&AW1wMuy6oxP3g{(<-c;Zu!=Q79t~<*t=2H>-Ci6%a+$y{P6(L5 zfPqYz=*&Aaf26dmhR85ql;Dk>w3o~arO5I<3eZ@jBSU={{%R-u$Hs9s{lpP^=i9IS z@bPL-RCESoM>w$|>fBxDDmA=*?O+Zb%IDb0Ypht}-T=B?8w>n=pBHB<*`cJmt*t4o z?9Evgbd0of#e@WVl5+Ga!6Bza$=tUZgWk4jC|)nOWyt7VA~N?bWzS=fBSXi;-Q62C ztg`^!zB8M%X+nJq6>3BO%~o)jD8sCJ^S-m7k-xF zl4_POeu+0Gxw3d!N|Whr+1yx^#p=-0MDMsj<;_~5@`_M~Z%9X5FaNvJHwN9ew*yLw zTUi>jI^?tvrE#O2NI8B@r0v3w+{AD&=i_9QQc)mnZA=+HJ`NL;JL2;&&^Fd4EDZPs zV`BqmPVdEYwx;+D+li5}expK`m~@HIFTKTc!D~;U)5*-3-V^)h%!LPK?{yK^C5bJ%dU@SnN+D|`>gDWQ00000NkvXXu0mjf D*IE&+ literal 0 HcmV?d00001 diff --git a/.github/images/consensus.png b/.github/images/consensus.png new file mode 100644 index 0000000000000000000000000000000000000000..b1c6a009c5ba2b33fbe8c8d20cafe1c953f54ce7 GIT binary patch literal 1644 zcmV-y29x=TP)000yS1^@s6#g@Rx000IvNklu`}NC(&GHnHVoyuA)++SY%mKX_s{;v&1f9-qIwR z)P~xmc9V_O$z2tZEmXkL2qHj9E-G@z!?|$IuX$hAam#anKl-op{Bvf``+L6gKHvBG zKHqmNBl`%^btn zpb;2)`uO14a>|c1F?~S*f6SPIHpCN4pUTnqYB;>Bn$8vjBfN*Pa$7VJ_xs^8%!&F7 z9TK;pvI}jf*MPW2y@mUh-f0utTkFB9ojQ)~yU16c{zPxLnFn7CC3dcs-K$P>xuVl< zuGrVju-RGe8dugA%w)neFD{(8%BXR}@xRNH@*~aseRBmFd*cWQ^P;Sv2`6U=OYlSA zWoFC5Vup`!;qmM^Nm4^q7iNQ%@xdAlJ!W>NpJv(SDBL`psV#3ODB7FR6FhipVKLtq zUE`(v`v{KrrJ0nun#fvIjM$Ss+}Gz7(Q(bdU-D<##1_S-ZM~bq4=-}; zgF1TJO{DLNA#SceBDb|sZ#TE%R6 z4>b^#IF4ic>NuMHBPg&uOUJpR&A8v;%Dm^M^6jxJe3n^3dvh<#G9yWNcoOfVmteeM zVb!h}o4A{jPck{in+4B@+Qc?=_pvlH!Y)|@<(3sR(%aoH#z8^5Ems*8u;jIxRQ z#{43hYkH&_Y+(ma_aS{}v|X~U)Y{KA8!Q9M@R^V9A!4>4uO=1BIrRS_)`aXfJ#cF+ zen9|BG9x(kaXqzVZL-r&=H6=g#T&z!y*v<6l*wQr`RS=d&hbOz>xPq)Le}E{A~0f- z$J5nf#HjB-$(!-dx2x#7ZX|81&Mt1#BddZJAZ2xE%i4D)Oqv7`*CzM_tM(fOJw3$^0!n`n0rxnSICUf z%vl*EJJiM1iAQ(G*duM%m#eInRXqdW{**Ki>Qv)e1?gC*w8NosEen zaCLLCiz_--7|@~(;Wn|q+*`v_`{Nls(St)-Rnl;T6S}!OvtiD0v{UWpiuyaQ_B*28 zd)EB5{Xh?)as9Ghy4_C|oyL!Rl2?-34&i^ef~-pyI$3w{ zUc1;r!ZQ|4#9iZp$!O(9yHPsqYe|LFe>ZThU}?}xshfw3Y|-YLZuA`{IdpG^#%CD8 z(|x5IUOL|{?@~jJfDlgt!bVbE(n?#C9;@XRuqfcJcpscyoaEiEr^6(Vbf_^9wm4iL ze-Fe!|MgrH_ygq*O4d*}_Rk zBrv2l9|;}RQm}z+xK{Gl_-vM8G+4$ARqf z(ve4stQF+z8P%s*J9~0cGAOv4OLbNC3)J#|Ony*+7X^3oh>JKuV>?TRubx1{fmmX{ zi=rg2xOS7D7P**;l5!#z?4T&CfY&=Yl65nkJYCLzt9%nj8-^?$hfUk&R8~}ydj19n zJ`E)&H4_Vs6+@SKW8_m6@ws@)Qd)?{k{Wca3)>KzkaVqpEFUfw+=-7kLBfGkm|B}Z75_hy&?Ec$#trZbol6r( zH8)Nqp|WU%g{CQ2jwbNix_yjT?T4kKnk&D?BN=pz5m~o0XwpJWQC2>o)7CTO zlX2L(+H?1smXiEp)NPv!IfqPKORGLEbocEic$^K3Chfv42Fx2FWFHrKk}=;-)rm{cq|!9adx4oZf;s8(;^mQ)zXHI zp3Bf)PQ_>2$Jn}PI2Zm0&h8z!9+Sv#Ya%Jk$iv-#6zzw*v1jHMp^V940gq(g&`kBH z=U*`~!ewX|z4${WuO;KU_UYsm<7m_0m7uY!xN|Y3hH;Ge(vQ~tT-iEq6=@f5fecQ4 z+c9XN7YX}g1?bW1rU+Tz%PS=1%yp53KNFH^>SQYbCLM_*X4_$rjH!DU33-1%eIuF4 zI!1jn8ONT^q+h**RV%enQdv<6vMgiVScS^+Ret#@oO5B(_y*6`OJ42VT=c&_{54%r zPvysMoQ^~HHUy6T9PQ=XHJ(>uO67x;SYoP(IS=T7yZ=byB2IEL_*ab0RrH)V00%c` z8k(7iz6_bPj`HGChJEJ4`S2J{?>a6NrI1(RVKW2CO1b-pe6BVdb6ZQ1p!=m2H833C z{3A(G38FP08s6iT*K}@$bsIaq_@7ID=+gIj)1wRF{@b{E^a7RT_wf##fy&a9vf@%v z)v(!tT#vpa%+P)QNZOC+!Tu#7G*C69sZ%qKZ8}8Woh+0pjQn~cMVa}W{UL_l(>-2@ ze9D$BrYSC{upWFMCS|Yg)KD>&36MOlETW(`Dbx zMZ@sbel$=Sadg8$%xx`r!=p2|PG1v}?en1rRh3mlE(}3JX6SNnjLlSReSa0ol;}U( z69xS5n-5{-WJCX1o+L%ZlN@`6cjgR#A@chchloTe6C!H;e&lMI?mm4ndCio~qgJ3x zOcj2is4Q|(uqe>5EeW8-3K3sin}Tft@O6%stHe$ zmn8Pg3MBh6*(;u+Op4yq2a7&ejxsh6t=uh^8fCh?x6+rk13QXIaBRat-24U*zb}?k zp;2`5dh4n96`y)=p0VL6U@co%lbw=5S>XfId3cP>Ot5pY7jCahN~Qc>S&ep5q}QaS z4XJTADM-&nu6~hq^U0-58N153Gpu7Mc8!vPd%|QN$01i$QC?j3#A5R-{Ldx-B$V3r zi>Uld{YmS+1thPR@-joY#*!+l=1NG)HI|y%evO5kF3D1`B-dH<7vG0Zx?jFExc~qF M07*qoM6N<$f=>bzwg3PC literal 0 HcmV?d00001 diff --git a/.github/images/discussion.png b/.github/images/discussion.png new file mode 100644 index 0000000000000000000000000000000000000000..c9b09dcfe57fe5d14093cb2d0f6c8e9189cf56cb GIT binary patch literal 1673 zcmV;426p+0P)1(Zy{O^DSZH{<*(0(~0b?qKs(0s_5Q zOv`fXoR9#1=6zqxL8;v;$I`kgD1RsdJ`5}^73v~m^WV!(dgH12ueocuE)K;7NoN$ z;tU#YgX2MN6lb>)gEZfeSIrTDbTR!i8$YE;pbW)P;6>8MU?5k2#?xEjpR)j@x z=6IaSCj%tnIwdQ-)EtSDH8O>+y;Q0Z9Z-uXyL?)XVs$t@=M*OK0o~=LFtxsQ(H6)B`aHH zz|hVmJA5)xhxSBJR3wm4qsGqFK_(PC$>?q2^zk^ch)!l7RVHiMlsf+NNo#wULYg$s zB{NmMIn3_Yf;7}=EUWTKQCu)C8IqRJxo?J(>MbFuPeMS!^B#`A6`{ufmAj`n*!9aG z)my^^0~%#Je00uK*u6eP_AI9>XP(Pid2hahakHKL zt}@8}FXGQw?BSlN4)$&gF)G)N|Gx>=J{F+%WP-ran+^5%vR$B)D)s_-y8 z+fLbJqpDhi8qu>x+9+D#HHEaIpq}ZAJf=R4p;7i5pQ){PmNiMZXD)T~{rj(ouOt7T zxx~$}!!db>x3-1(gHZ?$ z6mov-T?ORLG0 zXI$Jh(ZQOz^%!ss@Y5H$89mh@rDQ~oo$Af4n)rV~8g!>kP6ILyZAM;y4) zl&=W4F+s)`rOGy|S{tP2AeCtg+#K2);iJDqF#W^?ELfnC~vH6V(ywW zy7W-^?dl+zeJyfI8VljxO(7}ZWFaOS7?va^xxCGINPOx6X;Z~%EJ^Yl*)aRLh z#hJe`-PC4JRpecad+piKvgA&A+Qof8O2wVt@*T$dQu$N^fzLE%zu-xR^sJjPdF^bs zOM>P5wnDGLR!$$g_Ro**15|q6qEd4x#>LtM+7&-ljOw^~fXca(ae@I|4uVU^xO}Is z3bm&aL_${>j5nLB_`I6!%d4%&r_lcn8%+U?Qy;}>Zc2`GtyQ?)8~3#weUt4HQpZ!t z)l)2=N^&#KuM_A~J09KIdMeS2g?zqk@H`_ho^M6Bj_2DiU0N(`hcRc zijJZ8v3ZhBi((ib;71P&3oaBEvvPX|m#>%OJHVNgQEMKwX25H9In? ztkJS*VKk)`Rk%C##mT-8+Ik&H=^t|9>+|RuoA|ZgAeP5WCBSbG3JOoOc#zirV@b;kTPBUL$C}8bdnG}^*&>7tYB{%UOQzR%TC^-tj2 z$#gSCA#2MD3Fp$aQf_PN816HG+cjEZ*X=;~wy=GP@Xf^n*1WYJhdwq&V@I!1 zQGD|jS(_6ic(LBWt~Z0-oya|Njt%c*leQwZQ@XF;xP{oKqrEMb7UuH$i^KQva6x@r zL;U)kY*-lGsaXHdKdKmHH6HtJCpM1gYLnpXZU27cr^C7<>DK?DH@-MP2<74Sd zf1dXTqMi+6(cj*sUf0Ohr7uXJ%TnH>uvATY;#?*MKE>uehnPD(q}{n0t5Q%`X?Szh zJVZ8R<$Q@oThE8DFJ+jQJ5j5*)6>dQLT@j&SRXRVpSfWZcso0XeaBA9^#`^j;M~ui zBVXhb9z423-M6Z1NJ!nowekuMtCI2abYnYMVMPpuxz7Dvg#kaS=pKep+UF z-1HERpZ=De**Wrb#evOwHb_D}cjX$6cD!Ubs5gV`pPcovx7?i79uXw-;Mv zP~7i>d2Y-|W+tWb?d76-{J68aKRJDto!Pl^e;=nMVcpA$1sndsmEv-CB+Vmu)KD%K zmf+{wsU-3EHw?q#jK zC1Z$Mt)f(2Mdrq(3>oN3S;cK>H-p{#)62?=S;=X4p|@S%8e42;abzgtNBZ%6;x?I? zZHFnk1$1*WGnQ<92jTUt(2H+WGQiovBnBoy7ey{^dN6P7KgLHnr>LoG;J3pDGiT~E z>^gWtdZ5@~dth2K-5B&qflu+`v|z;HWgb68jkf+Lk9O@8bYXGf!GWwu+e6;J&(qj+ zhxgVkl($fL^4MPu>5^_^(9fK|BK_PH1|~uGba7<&UtXr4tqt4v9Y$|}d0`>4Xodf2 zD^`{k_x0kP&2-`23A3k>_tiP}A3sIJgg_#K1F^KUAaYeI=H_OkCA`$`fr`yoSeVOa z+gkTRm3dSa?67A>bNbw6GLC%CxEcaw@A@SK z`VW?XbxloNC@8_(!TI<;@q#$#)pY(_RQB`G#jI!z z#T66TC3;~^Z5@V(^eW-w;Y<%p3+d?%jZHZ9vqP`f%fclNxTEnz&mQ=CxKL20mKG(7 zed~Cbx*s%_XcAiVdf76IzdxJl9c{XM{y_-*XfNGA?LG*@uC6sGS&GZ#_)kF@+x^9; ztMp9#e}#>T_*~aOW1_)8T=(ZX6G3)vS)l?dGjsEd{{c?$*iaI{@jw6o002ovPDHLk FV1mKWT-*Qv literal 0 HcmV?d00001 diff --git a/.github/images/house-keeping.png b/.github/images/house-keeping.png new file mode 100644 index 0000000000000000000000000000000000000000..84db93866199b32c6a71dc2f4ef1fd5ce31ed104 GIT binary patch literal 2267 zcmV<12qgE3P)BS}idM??cn)Q+iR5?@tG6&sD|jAxN+dQ0pJ<{y1bM#}*oB1!_Ra2ooqH)1bl0M0NT zJLh-K`If1enAYgn9%(X4BY1_d%UH`M5 zBDRX+B4Mg+K~G0Fz_P<)D@VwO{}?4Knl{+m3_qNY+yUYruSE14OQ8F*04=Al!qIIW zmPkJSmq!7pg;51uNwdXUm7nH(f>w!qj0MBx!c?t6<*s8e*J<6-(ft|X7aIZ9>IHC^tn{42X!aYNkMUn_yjYKKo`2-NE{LF^;<>@KUL`zm%Gr9SCj56cju)TV2Pqst8MFgYA%EAGDa z0W2+gB>sLad{hdwUo8g1;UFM622PU|n$N$X&eop0-cNUgQlw9hL&?_tu(cX6_WjlH z67pfZ*8sn`2ngg7lx{l!!|h5W{B9LQV^q}0o-Q*)vElSDd2g<3c_5qz0%F&9B5GX* zcmaO6yX^psWpzl{vBtf;w{xLhpW#s#xtnsudjDh#*oq5j}`5C^MPr9(b@3d(mJ zhT*$%uny-SQ2GGrC@6(=S^~U$gcJ-CtwGNvBjS~LZsqCo3n7^tkB%FqZgp|}eG$2Q zF075MsN8cL)@D5-UzvxH=cl3e?_a>CGazbx#vnjE`AhOtJQNu-(QxQIba}TZYb5T< zf`42D?!3Nd=zz3eDek9|UdK#E$(#G3$Vh=~Mk0zg??d;!dg`FS>4}J1vyeuM|2P$z zPF!*e2mzNwi(gC_dOD5hEUHHHseBsEk*_`vdD6%;SbgmgOb*I)Xb zAG2vOq%)IH{KkKt(F+W{!@r2j2>SCCRNka&w_V275=hTU{Ih58+GGQ2)_cwB;Al zJ><@$zIEIzL+9-Z8bAXnYhYKZd~H60=k@{;wm22yiKA%%_t8@?qfDX!K4i)oq+kFb z!E>e}=qD3UzViqS1!ZvcI4Bq-BDCkOL6(w?)~~-q(}{0r79{>*9sFX$QIwqnAEkm8 zNzEsDu(q_rZ*(}NLwkD{NE0EM9EXOZdC;A|(aYP3YADjDQ-BHo-aixdQI_V|MXHO~ zL7I-T_YOk#OcFvDKJ8W>nG%mJ3r& z6D^w5QPO~3N_DzW^T8?TzAB(y-2JP+%R2lO2#0(53NiM*l^_vbn4JUCM0k=H^lY-n zcall*6cDbjH#kBb?Ic|`J8BP{hVH^m_(p{E0+M%&28wd^fN;f024b z0TuhvI}utYfD~=Y`R^Gr)KQ7&?@Q^&X|zzINblXZ2vC9`39On{x6`waG6cS=P;}j` zr3IMGBYlf}4)GtW0-=?zlG-Q!Qt&W&p5DoxO{Rd<<(`JAstI1+0@`*DyyH;)L}nPj zxJYysR?z@;S!{HMA(UDAb}kLlht45GRrLS7Zy+H0%SE&OVMZZI>Q?{&002ovPDHLkV1mBvJR$%9 literal 0 HcmV?d00001 diff --git a/.github/images/ledger.png b/.github/images/ledger.png new file mode 100644 index 0000000000000000000000000000000000000000..babf6a3ca797c7d49080abbc2c354b93fb26434f GIT binary patch literal 1270 zcmV+Q)k9P^FrF7$;#UlB{Ydv z3TbUdHw|qIYF;vLAx^v?AUduGjtAkKx4pkvQ|TN%HaG40_j#Z1`+c6@^Zh-~PYRft zVW(B8-j=Q86iLPtBrBd`lc3HBdknqVB)Mu<gdOGKa#`pzyEZz786j9&U%HB0|8Sd*&)%6A(?fT(pZ%Z#pA}MPZ@1{&5 z$lHa})wOs!JK|*D4eezFt3{k^UaUt;oaQ-I>hfSd-Wa)}}=o)HZ!c%`W8pm3rlRyw}WE z-qU#iv7?63*wRj`PA}TTslOT*M|*NU|ADc?hY%I$!_0NNIZ;(3{5k2W1MCBFxaA6`-qJo*8RY2nNAFPS+U-{}Jl4HWq>N*)?vQiIL+z}ICU6C(n#v+XMc+pg=RAY-;kY@;kcY~J*&ywWP$ z{~1!{qDPl%#*02zOi_MTVJXE&en+d*^G@;vK~f>CSk295K`3E$KI2CCiDVU>D3xq% z>%iW&FA1xZHmenJrmz*g-OHm%+hbbyB>!(yPEmY#fHx{tFOF4SqqSXkpYoN&f_+`N zP;*nP6b6G4FK0(Whk8?u_4?gAm)f?hh55qPybsvqqg=1TM z9_Zyl-m;nK^mq8=yI*m2>QCClD3M^sjssk6XnGvj2d~N}w-PU(5yR}5aM4D}9etsu zfrTIK71Q~@nplb5UsZZ&%ie8-WedLNZcX8i%g|Q4#P10mT7UK|sV*zz=rm1M`sPMx}x)sGzIjln6?jpeWiY2rUd&Q>+vb z6vK7Z1wXTuZ4JxgCx(P31E?qj@-+i9Ffe=GheD5QdOV<~bGZMRKi+xH{odE}yMOod zJ~C(LznYnMtaz@HgO(D z_kYiqDLK?ut2!M*#2SAp?$nUI_cV4xtU5nmMsNt*Gn#d=G=*=prX3A()cuLD(G6k1Qa2q=m zji#BH@D%!*o3L=%YmD-60GW(ZWjP)VXT)k1~M6!&nrnwK2GrB$?f?p z2lgfE!$3y5+hbs8K+)AQvG&KyrPw=Ji#qbo6*10h7&b$!Xi#fd7oEX3$1kC2Y-&^O z!yx=BaY=f&N-HrikYO>PFGfa&)ZA5xmvnHJQ&myR&Mn6XdV6wvJLsBqBxgo2)J0A~ zUMX^03;J2KP2SkZbml0080;_*ovuX`vhDAOiQBvoCs$j}{I>vUy~m%N$vbNO;gjOiX)<){*K^ zUMoYZ(J^@FKpIpU76&GAt>EV4A>6I31w z!Yh6Y!pitrc)m28Mg9pwF;Ymo<2%EPq}Y7|!ins2?Ai8ju~X8{ZpsM9(Zz=HvTBNd zy2D_{ffyV2;H{aTJQBhfuVFZkuw{|oy<9%8c@VzZkL-V(=E}ulmd5yVe;rF!PGf4| zQ-+{;$CoM7J&6h5PHs*<%}qKIQ$t0su3MGye-IRZ^Tj`S0x6r0a4_Rr>gyWVk{N-M zi_K#pNCx~zZ&zZ%?&Vs#%8xe!yog`9o9fDXqT**gdk9W0a-u()gETt#q@2WduqED; zMq^@T+-{8bD`D!a7YK>)<#~ zaCqPM>`gsMZMB+tp|1)@@7LcQ5rM$Pu5!_0o`6@JYpnXrGbH+}k^YZPh*sM~gIde#kAuY6iWS!O563C;qtcYHJMEpx?a0Y fE2&ytYvTU^2ouTVSSEnf00000NkvXXu0mjf7G69Y literal 0 HcmV?d00001 diff --git a/.github/images/network-policy.png b/.github/images/network-policy.png new file mode 100644 index 0000000000000000000000000000000000000000..84452a613eb763b3172d790aeb6f98e21c8037c7 GIT binary patch literal 2383 zcmV-V39$BwP)Cd+5a1ku{c%ya zn067(EzJX#>r3e`5$UxLm(ngFzvwR5Hf)?vJ&%~A7}Pa<+!+T1g!2cI(A?S#j}R6r zsw)PpF`o;BQyq5MfX zj`)5Lc`12Vd0C;TtQgLloUvq{E*$-x(8=S$*U1;kGn64PL;xifrC^1!P*7TcsS~GS zuV*;!6&FD5D>byWw<6)^1Xvna_Ao(7K?xiiPrPb+1&>e`%B#wI20%ku18i#+ipq+h zI#U%>{x$_QwKcTn?7P|M;B`P|n)ILMmy?w1VZx2v47gjl;cQAGE~H+-WQob}aoP=% zzrDR3w+nA$*S=j~+p;l9ViKJEm=rJ)!EV7+%ItmYQT(`se)di#sLW77hS2lhn=8@DK0NYJ+~f;3W})X)*<(PF0|%o(TAT*J_U8f zuc0tq0mjUARJWt|9Qy-=El9tWj+meyAt5FK=YZ|-cJQX(y^@gv0RaJMDr=*p@ z3k(?|K${>vRT{ib9&JE&{!KWVJ5ms8UOdB2`<)c@&7PLXyPt>7uGdGHUda|06M5|EiDgVfAx5E(5( z2g+urHL~v9gwRMK+Bf1MPX0`k{hPcd^aDbDLmjpUZpY&%<3ymKq>xUw-asE zJ>l2vU!gNk2f{+au;f@Fr!eO&iQt1k*ue^8qq4dZu9hw^)i*`Jp#V&qG!4dj#{K5+ z3xddKVXV?wg~O*w-KW5P#YKGR2?}=fxoB)$y%AaYS+q~ua~IK}A!j^uIe{{^Ul5Yh zlW{cRC|+`3!o$h~MtVjtcQeN-os}?LW=JQSOjLJwH^j$^W8%1p2tE=5lYgwk)7qyL z1hTOZ3Cg~Ai_(@bN@SEUs-9ILHR~D-ml}W*;f2+@tD&vF2qrG3xLb6WP!vn%FTswj zUO0C(30Zft;O(#rnRl`fc|4Lz9N!a214$%ZNkY&M!E|F`Zghf)z6nHyMd`JK%L&ld z(8kfkqdm=1S5ily%N|_$*Hy?%%0qRgO27I0f}o_J2z5num~1yee(~M6{4X)`EFC%v z_GUP3aDtZVd>A{gqY}%H_sS6|JnpABimr#1`yU`|fY}N&=r7d6i~1MTA9}}u_=B)F zvqx>+^B!Y96LA_N1%)tCd;$s{7JvZ;$hJ{cQ$>N<#InG)_4b%g3S_=6Q16?+(=8-1 zB@tQqHz^3D3C9wT(XERQ0+ApR!-tQc(nSEHgR<0+dKU@8TEd3FBSE-){W7gvOH~WL zOdq6Yr(>q1y)A^wMy+M$bl*Kn{3*Z*) zj%!)hsDBdXlj&#rGa)=m1fd=w=;-L6%YaXm5B~YfPju1wC?+(vG~$r=cNjl*JoX)r zq>^Lt?Iw&D9}h#vweVy5(rfH+Ph{q0VzI_z>KQ~QzumS5k18MGWLP|A$jm_Ku~5Wb zh=c4GvIuewqDJW%?n&z-+ZT~JVw@!SdwO3c@ZS>xoc*z6-V*GM+1n#I{DbmA5EB)H z&jDWu64tD-pmnZsFu+K`ksqADHwa{i$VNCucnl(A_tQ;srS=Ny1HK3S=qw?i=Xzn(CWi+xl%3aT26?eh2;N*21ynP`RpqRZr!i zqPh|Z5oa)I!X(;IVyY)X;-IFeMnTIj%BQ~Kypf6ZE7$i(NNam5T{Tl~q|n0=5R%i9 zaV#;KZen~nij0j!a@r*bj}oTa7x`}A!}38GGkOdJ1qJB}Ojxt$@E#;yIY&+ML-P~Q zV%vBk>1q;U&d1PRSQuD9Y>XHk$kOssIQTl!zr@@4OAGNu@BQ9*^7KjnAiU)+fARs@ zROZZ@gP}tOaQj{k^$wDh1SyEDh>cB+Z>);_J)7J|riMrynV8e~?XzoDen;GDYjNA;P)000KENkl?GZ70FXDP@+o0F$Zvm4a<+S=|d<v6TWV{_~rX8Di8#=?TC#%9*!AK}k)Uc}DIinRxia8-SmtVIhL=j}nt?tLP<{xEww zF@XWB$}M;#+IFSHGdo~3mI{Tq_S)V8?r6GA>eRHTktB)8kv?pgHH`>g9~26>roPK> z4-|?0eo>tF-^c*fV-{Ii$SBV^{5(eMx z?k3DfNvoy@z0rubqXTg}vS{wqus1bP)VoEQ`$WylTe=XXlOw5F`>AQZ^CJhp{Xzu4 znHquRFa^2iFS6yE@Axb+)}&7I?mVukTPa+bLWt6vl50268H`N-#YoQ7)w7|nn1u1; zSUq*30DS7kEvAj~<>PP9vZJh$w(cIb%!?v6XbcJIIT$60?MZP2c(@50vd>ks>EGY7 zEpcwY`Va5lEXY<(H*fAcBqB>*FlwwnaXYdZ>*>zBFU{cil^eptjUAo57d4B;6GAw3 zqmGD?D%R#7Md{?gx*1a#?(9g~*>ikaTEX_DSSlNC_s#ohs(ktSVk8i{;i?h+>a5Bw zq^4QT$MMk=)m$N~vRc5&U6MrT2qg(SbEs-+=0R%bR$XMx3z6(9KW`SKqqQ}!?9Syv zV>3yi!DjVOT>SyP!5~a93o`#g4WFDYN8P32Pjg;mN%(Ulr0*dqG>AoEA+&UL(cYsI zDdy>5&v0iaww0DKe|#Xtm#?C7abb+7JI=N?)ZK08=;f=VgoW@KSKV$;c&G>BXY3@uJqsT7X* z-Hge2IXX~T-^5${4~uePYCN3U3!V!ys}mLI&$5Z3{O#*fc2!g%M@Rm$R|!^nJ_0hk zvYK@>Cv)&ZEn82Oi6D@pe}d0&qCekl5~SRW%-LDl&_u7%_~alvwK_7A=L;|&m7Kz0 zgw<2R@pf_`W_u=nZqM-7s9E?pJM;4PT_REnmM0T3+>7^*oh0o{rD#wCfmEO{tMj~% zlHbjm#?jiV0_4KbAn~ypX2HCj*;LdwQM_ug*yqNg6a0SmG|}ibmz*ZR)1BC$0PL)+ zdHJ&plOX-w-OTEL-*`XU2CR|&rMB#eWs{y~{miMNk;p^tbQ_NxC%f_jdV`Uo*HTcq zI5U4|4%JP~B2uRKsfbC-r2JL`lH5^D3^^i=NW8W0e$<-Nk&i5UQXHVd4l= z)pVOcFAr|Db+CNTK~ZMpG9)`rE-muECMO$fw7tEwb!&07v1V>sCI+K~oazUvYuHv= zj@)SFVNSoJM{6FWX%ip)Ro;+%jJvV!MjFORiS}o4Dw)nU>iSwpL_v8BB-zEpr?>8a`W%bW=^8b!MLyyr0 z@BjOc(Y67}Ll1Tbfm434D_%9&NE;*+selTGUNt;EQmGM0*BK03{tM|EPOJag&^7=7 N002ovPDHLkV1mMLk2wGU literal 0 HcmV?d00001 diff --git a/.github/images/p2p.png b/.github/images/p2p.png new file mode 100644 index 0000000000000000000000000000000000000000..d638bd234240661a6a39c7d7bc01eadaf9c1c3d6 GIT binary patch literal 816 zcmV-01JC@4P)OuUXbqh3n9_ua-=ni%vLK@Yh75Y ztY%`Y%bGfyQqiW1mXaEdoTH;oa~2a${@Q3g??2D?clkcQ=O-u>3R``*G**DM2*?2o zCic9?NReRZ%@tgnJqkfs1K3Wi=CIq1!Y08*uByX`YEp#(0pXnB;;ecMxKFk?Q1<_c zFI=>MLx*EgDqXR(w4|e>i;T1!Zk6BR>(?H!MI3+TR#pe8}pXADu%;oPaL#ofaV&7=BJS%bkaG_aAGFJBo*!hs#gWV6v|p3v2)#Y5#rU*C5k z!#5+5SP~K%#QBn|G&jG+Xf%?Qoy_tT0aRDt#mifTgTwSu+2_xi#EHLdZXqE)owsk^ z5gWgi$jDV>rss0wdc|*j-Lfr;bukfGSXgl3d?~@9L5O6{XI^~v5*II&(b=iR%iDvj z?1NNP)KGY`i1zj`EKtlRL!HPHr7Is=+t|B11t%v*_U+%oSnRL#&5IvBQebkgPN&1q z&zm%L0yWk5Igxvcx%1|bc_azBTt-RJ6$5Gn`8;cA!bUokrp9JblWU;t zB3big@4w*ottxanz1WF0*mIF=*@!PSAkd$KDSOCL=TTWvgMLU)$BJS+?5{8NA1)K7 uHL6D%C;Tw2QO*;-MhUc<)~Ij2IX?jjiM4`pT0tEE0000zjyEF+0SqP_VfIncO?P<%Qbqw z90z-V>p{=$<6}TTR3zfKsC}Dr14Oge^jjt3L}4F8*zGYkM}QM?t3?(rdiemS)eg|d zih!s!YTD50Wrzz`kG=DAkn5~~!Fp!Mx}AcGmt}40ztbmj z7&34avhpsWqO!D2ZNE)p?}Y@mGkq~}q!s44_J5<;+!jY8_4;X?y|lm8>xT>&g>|;E z*t*vZzoZ>*^?GRw2J{&Q|9|em_I;jjw6`|hOcP_$F#EqGL1IV_(r%nV$j%k5#;r?d zMGPG{1{t?5wE1oQkVzm7vt}gF(&*3F{O@1mVLs9d4~z5Rv(*~PimLEhx&uAC>wx1L zaP#hE1jX5*?o};58#o#^Q{B-+O&fJ}HMm!lgTU{WpsM->JEZ>FL$P{(IFuE-p|s)& zO3I3$r}Y`j1Q8x*@Zx0|Ji=!Q2O8+K9}05HSh>l(*&)aHT!f0E8tNPBk$LMPHpbeb zZ!ZI^U9=5dmDJI|H6X7r6B}dgP+9f7+4_FH2gAcQ7T^Bh!uIF6G!Ey}4#CuD3KY7i z;Ld{^*n2z-PV+*cB;OTf6(#VAvPMyH0Za_dVP~-c=Pw<^SmW7{ms3Ph@jV1YFGO+K zLo_9UB+UBs9Mmem6ofSV2}_FO$hjCy9laO|a!M$#EXBsyrMPqdI$FX^9GGS#-~*va zuj=b?^js_wPljV>KpHxCl1EPd71Y*Mv$}f!@ol(;O~t%y79kCe=l>>V+$ zW5-Xh#M>D57J(RVVu9%WUO1DokG)R_Oh>1`$uSa`44woRn+UkFv~_?DH+A zd-2p}H#-0mM$AFzE(fGsJH_TxRv;o0KyLg5=B-*qq?R-mm&*3rvSh!TQL#5Q#*BCXnx!#cT zpDK4}b(wC8^^`T})x974U7?FIQ{F^^5SL?YGv9a&M%|xleU>FaU&llchCgn)f#TAK zjCA2{r=Z$Z6Z6~+;9wODvmsN3Go!*Jq z@BTG`1j7v`NW|>G&ykot(E+mheI5Q(l8FQ{2iD_saw3a^E|#&Oxq$H-kw9GG@+q5c z73l%-k$55;E(;>rPemmK?B?nB9gYT$VE3~y91sC zTXwI)Z|VOPNO1E`s!)nrB7sNvOym__XY(lwP&U|ed^57|qzWV$YdnjUxt1_HpLz)M zr@2E`ztZsk?w}7V(-f1qJ!hM5VPZI`?MSd>NSr$CqfGMLEusS}{ z=qrT8uR!XJ)9hV*K&n6j-{rfZuVakW!ISae$sP7S+MC3ks<1&Ly)WQtw}WX0-QGq_ zh-TkSYecq2#1rcdyq6`gy6w1eJRX-6vT3dhqd+&&HFO#Z9_2K$(^5H*^)Pr%K)3!s zNjrrbM1W%%bvSqFfG~H?q?MRCVFeREG)O#=9=M*HjP2e@tP7w)08s})-9v6cIy@sR1@Xii zql`dZg80WGUTBi4-j?Vgl>~fx}z2S?ZJ23JRxO^8{X4B5je?Io~5(ydQK!-(f;pcAM#nX_1;899JsIpp}E2T19d>g U?0+PWl>h($07*qoM6N<$f*tL9$^ZZW literal 0 HcmV?d00001 diff --git a/.github/images/rpc.png b/.github/images/rpc.png new file mode 100644 index 0000000000000000000000000000000000000000..24b6c3537510ec5f5cbf776f2ad24f2bdccb0024 GIT binary patch literal 799 zcmV+)1K|9LP)&d9s%k=D8?%86{c$k=81wh4^TLf(V>)0uq_v+g?QctLV6P9s4Z~R4!aKo_c#nr z|A#rl<&HLbsnl#v&!MWaf-%7paC4I&ll7&%>>8tjLK!?n#mA5D*qyePM-Pm&wzQ!3 zA4&YCT?7OM)7)(3X+=5vGLxx${p$Bec7*wk7>#aw9;)Gfw6(TU_3Rm!qs zv}QiuYJZll*74@G34KN)b+u-etV$*_dLemxQyHrAVP@2PjvqP5h0`T8Ha4&)_Y|Ik zz0f5r#QgI4-(e5$-lC*X&sgmwV&hUcbG+zRu^{av5_MUW87|@Nqha*8P}VJvrt0Z~ zu6oiQ%kG%B0+Q9e>Rj)P5sLh>fDU@{x03 zhHK|IR(ycZpFXfOPRFd-3&_jfN>E4`Vc`*Erp0sn<`tToEu?3a(0{-nwr^QUjrqmj zZEUZspNEn|`V=IRUPQ;l;-T~;ZgHd|ts7JKqfoeW^l%pTG*63|L&g0va`Y*@tM4ix z{-e%G#Sgbw-q#b1!_!EW8S z=up+o<49wdBW7}V1gjF#C^(RT(QpZ?)zUqdeZ>6J;b~tB+~mRr7hLRX!O$L93+hFL dV!YQKrkRG#rD#Y8iCjdiZnsI@M9IlEX<`PzW@s!859t3 zNSHq?X+`kDqXYwW;|9l0kHwgngw5VgFesB^GSTaF;_-P=6lE+u;|H%;ww#>orBv;$ zAzGthbAA!WPMzS_^S|-e@bLcxoVjo@%d%cUpD>f4EOVyWO2e5(ygn}meG(g9&nMZC zjQ_SD_n@1E_$S#}Qx&H8DWi#k*VZxQ_w&^^hq?LZANL#xw_4Kac<+sOnDoRX99^A+ zHqV$Ii)G(#9Nk^KyUk3p!ANhP6P;FvPOC)-!AGB${|oH)cqq(WkED~-z4p%Q$g(^( z_~p!(Se>&1Ys*=h&RP)yHslp>>1rE^GxaQ4l!3LSnN!x&_-^_5;H?s7nNs+;>a!8> z<=?L`Km9p08jT9=aM(vfL-26Ln#mg8-@Zdt<@Ncn*=;m6Td_MFY$@Ety!2%U`Q(0zZ%9-L}@f}U5G=8!&TE|ONKTKVPv zTCy{sIHIwK$VqwU!aZQ*?KmU{q8TU+k^nTDy&)92^Y~2Zw?c zvhG;p5A?hGF&UHDT2ze3>rw488BH8K@--LRE)%#DV8=Eyb5hgz#8NQ=KGAd%?=2ts zYw`#L0_-`okG`8X{u`X};v(`^t;N>S&hf?u42enPtz66bwoA0zJIGzR21SuMaea(J_zANQ4ZW078QR3bH$6Yl&~Lk00000NkvXXu0mjfa5K!B literal 0 HcmV?d00001 diff --git a/.github/images/solution-design.png b/.github/images/solution-design.png new file mode 100644 index 0000000000000000000000000000000000000000..552c083d0b6598ccb4ccf942d25845a46de2e92a GIT binary patch literal 1420 zcmV;71#|j|P)mNy000G3NklK82%4G@h|+A@g=R|Rjd@8eO`B$EwrQESv|6s!tkxfRi}zR&ahJ{Rd=@*<-~ zr(Ov1R2iZqBwxD6sY0f}?e=~w9Zy}FCreC5#@Ic4Z||inFVyY$XKKI$xp zp3gr*_>_k!o3{zuUsYW)u75C!*j3}G+jokZt%q?p*t+!2eFfp8Q)5hv#c`nqXZ8P( z30+c8q85!p_kbBsivy>n32kf$B`{67%XfkV zF>j5UMxhwFAiI---WK||8o>FE0O!hYU@s)tVeBp-?5 zsd?DWR+F@DhTylo{2J~CJNkZRJPlSVR(?a&!jbrB)L8$#g1)~QMNjAEZx)6X5DJ}Y zzbhjC{fX!j!?6`t;omC|Rghjdrr41DdK(7s|QV72p(H2WpfI!mtFmL5D_zn z6E-=MnjM8$zBq)t-b(U@nHUB}QT*ImG;v{=U(TZGP#INuKjX4A5xHOlA*0i1JXD4$ zJs!)~M+NVd6a7XujR#9{)wU4zdbR+eGH3`IHIVAOpQ!!*Bpz!k$@#M|^pB)?+S)b{ zo<kY%FZ%pqvR07_@) z6FhPt!8s4%uCwB9c8GhwAU%FzCaTx}LQr-Jn#f=QzPYG^ny-#vJ$(snpNKYLE15H- z#~CJ04d}GuL;YAY#^V z0YVcSLcq`@Dwb}i@%J)hmxshpreMlQ;OzAE{~d%eJ&u@VqXkVaeXtipYAhjR(oh9x zh3LFiCkY=;LKSQf^ua3&4f%x_so7ab;N$&iIZ?sY{9n-~_ryFmOH`ER!t)}U3J6E} zHSu35yOu8xi|W(k(Z2ZV{o4t<%b8Hbs0cT7{2+WyS|LtnRlRV!6CVcPPb~8I?RMNIRZzyrNc47NAHgzB?d|5gSDst-xtyPp?g$3spY{6c7M+v=KU+?VL zakqEw^sw+n;XE7f`}$Qz(;|Zq7!Y8Mht@KzV72 zWJxnEQ%w})SDL&bsLrq=x?x#}-pRa$J#_M`kZb{){WmQ-A-L3OY`x-N9=wQy5 z{mSL48e0B|NZ1j%h%v51kR*xk&s`ua?o(8~da*Wm1`iJzgi7kgxw1-DZb_w}xD-Qc z`|xz^Z%53sx#Sm@;_fmSonBAq=47sF>sc4{EaM(@!N^F(nUZo=#HaFeX(dS!!B|_E zv3yf9zm)$fAV$3~6E_zpqSLcjFzInJj^?sA=QJu+uMTy>=XhgcY{aVgR7xtYux-`z zIBN#5aQ#-!Ub;-!%xCZ%=}JiS4)J_*bQlRQ`g-u3*LX1}CeHF z`2xsT*CEt3HZgzQhx~M@qTR{gKgfaD&_D(|*o#x!ot;Z``hEdsgtHSrl~z!rZQ#Ls zHPqBMuwdO*mil?(>F!Fv+wq({Ta4lZ>1#qT7z}Jbki(06_a`Z$dCP>C3!#5-7S*j?XxER?ha~SY8nu z)AmzYeXUJnSaMFX02qntl5iwHc$v-j=7`hjpm4 zEi;?RV;|$+9OBT)0#?tTD&_=5eMCfnH&<%4L?-U0pW3nw!cfP7A{9H+3HE*pS(drmMooTk z8IlA_WGWyW?5qh~n?PYnS-bV`s5%5qegdCyBM9A;Om2NEA<EyOSfQ z3mN8gPa6caxf$M%xpk^D%VRVi?yjiKO?h|cmm+nSO!LG}ZNZPfloA%ZQ<&zh1L_?V#zx%SEGfvrjmdcb0b-`**6Nq)TLg4+Ct~ zObw3~Wi@ThQieJ@@Lp;rJF<>bTi%KrQr=j?$orh|i`+z>;%TztYJZN~ zw#_z{W*7{zFh8XiP@a`j(bhLnP*O&N?s_}1J9$tl#t0WjdiPdws;HQ2^^L-4yE?i{ zM_Knj@$Jx6KwX`G1H%8G(#ev>HzYxlB!3yX=U%GZxL#{oAxn~Sy*9ANT(2QjfSjai bmZE^dqmMNVb3E?!BHFLO7gRR$2m|BTq`$p`a9XzRO;b7i=!qlPs za87eG>lQsNz0Ccb`+cwlK)DS$#2ksHI;n{zS*4IEx1qM)<6%at*)JC#^+3pfA@fdOi-IqkL{!V z-$0TB=>p75&#+0Qz?5m`UDJC)W0l?oNvRnq99}fQ+hqNK09abWfPSoWn}n!M$3GaOKe-sziu^aVs(m7s&Y53 nV&SQBLcCk$SixBY;|5{o$;#_~38ohGazOqN|nAKGFmc^*WMNCd7j_SbDKY$m7|^GoLqn1=lrg7pU?fhzt?r$Kgl-C&FqOr z6Qjc*SVDFN3~7I%Mn;83yFpTfxF$=;lL52#$N3_Wq?5xX(~zF$0q^z>EBGXK>47f* zUT*@hgp~c-fIAs=#J86>W%nzntgFVS=R0D3yXp=at@eNE^IC!Xx_F@aQc3o?BNSXc z$GYGpV!ip8ipu)xmjbVv9FMyCE*S+`FXXmc;QWLv9zAVj&W<>7E6<}v;Qe#AVcJna zWNJLu@0ODpy%kSqH$GF&qU2U7ivyw=_ufdtw#>!cq%#ZsBN^D!3rUi=ey^N}9dQ)h zyo{%lTdNAovdo6i<&5b20mdDSxKwe4h?F?4sIQYfFNL9=z8FXboV`&<__kPX+$;aL z=34OZo~TU>>phs!iBq^=`;hGUDfD)7W1=#g+)KZ3C?=J+EV~f8DH`R}W%TRj!O4EB{*V%8#Xa&9{55#QtM>P^Y*QmX1}@P50WxcWflEXI0`V2%dW?rxQJ9CSRp3#=+8#nDMi5u(D@+-fp(!?j&{gdM=iiustt> z6%!YbQ<%rDf&mx>+tV1Wu*qPhlXl>8Z%yp`*jy+Ix zR4{IJNUOm5{9zux0=Tj1@eAEz?cuHD6rLbwL3-POf0(+Qk9|JE%G8pj``1y^P%Erq zZ(+-YzlsUpzJMU#34HP4=d3-PEL72}l@psT4)8Ky3lnn!eaEr(r!DNv-%o90Jwx0F zFk{4IHXco*u)LVOMf=(Y?C;}8;-rN*SvxR%c_5|gGLFV&(9gw#We3)?EpIpaoH+kT zj$S;8DnC;kAZYLeQT1aJgK5%gNS&SZpFW&hl+VU#E3vb%Wz~-xg(V_Jg<@~ng;6Ue zi5oqYa6pI?m9~UaSI+RXxvBM{(|<8B?!@s$dvUgLVC?D;E>&C=>J94EpOGtrIA2zT zk)aU>=cfq&b}%sHann1$HERxSCjOHsvd-p+!I2b_AlCZA_3!UT?1TtW z%=&27YKYsDNXF@G>Kg0WJUx+s0b{6Ys39O}CYS%d_Hy91%uP=xSByItb4^_)JlWOS z0j;d%VOqMX2jmNtP$QF%Nk0i`1<9Mu!|MNjSC7UnJ=c$SRt(%6|avM{x(Y50a+< O0000 Date: Wed, 21 Aug 2019 05:05:41 +0800 Subject: [PATCH 33/54] Optimize `GetHeader()` and `GetBlock()` (#1039) --- neo/Persistence/Helper.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/neo/Persistence/Helper.cs b/neo/Persistence/Helper.cs index 3cc1b92ca9..d884e0da6b 100644 --- a/neo/Persistence/Helper.cs +++ b/neo/Persistence/Helper.cs @@ -20,6 +20,7 @@ public static bool ContainsTransaction(this IPersistence persistence, UInt256 ha public static Block GetBlock(this IPersistence persistence, uint index) { + if (index == 0) return Blockchain.GenesisBlock; UInt256 hash = Blockchain.Singleton.GetBlockHash(index); if (hash == null) return null; return persistence.GetBlock(hash); @@ -35,6 +36,7 @@ public static Block GetBlock(this IPersistence persistence, UInt256 hash) public static Header GetHeader(this IPersistence persistence, uint index) { + if (index == 0) return Blockchain.GenesisBlock.Header; UInt256 hash = Blockchain.Singleton.GetBlockHash(index); if (hash == null) return null; return persistence.GetHeader(hash); From b1a4d29fa90e2b7ca91596694f8052d2b446f9c4 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 21 Aug 2019 20:38:04 +0200 Subject: [PATCH 34/54] Update policy - Add maximum witness size (in bytes) (#1020) * Max witness size * Add error test * Rename class * allow 10/10 * rounding up to 1024 bytes * Error with 11 * Fix ut --- .../Network/P2P/Payloads/UT_Witness.cs | 122 +++++++++++++++++- neo/Network/P2P/Payloads/Witness.cs | 7 +- 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs index ec3525931e..01a76eeee4 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs @@ -1,13 +1,62 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.IO; using Neo.IO.Json; using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.SmartContract; +using Neo.Wallets; +using Neo.Wallets.NEP6; +using System; +using System.IO; +using System.Linq; namespace Neo.UnitTests.Network.P2P.Payloads { [TestClass] public class UT_Witness { + class DummyVerificable : IVerifiable + { + private UInt160 _hash; + + public Witness[] Witnesses { get; set; } + + public int Size => 1; + + public DummyVerificable(UInt160 hash) + { + _hash = hash; + } + + public void Deserialize(BinaryReader reader) + { + DeserializeUnsigned(reader); + Witnesses = reader.ReadSerializableArray(16); + } + + public void DeserializeUnsigned(BinaryReader reader) + { + reader.ReadByte(); + } + + public UInt160[] GetScriptHashesForVerifying(Snapshot snapshot) + { + return new UInt160[] { _hash }; + } + + public void Serialize(BinaryWriter writer) + { + SerializeUnsigned(writer); + writer.Write(Witnesses); + } + + public void SerializeUnsigned(BinaryWriter writer) + { + writer.Write((byte)1); + } + } + Witness uut; [TestInitialize] @@ -22,6 +71,77 @@ public void InvocationScript_Get() uut.InvocationScript.Should().BeNull(); } + private Witness PrepareDummyWitness(int maxAccounts) + { + var store = TestBlockchain.GetStore(); + var wallet = TestUtils.GenerateTestWallet(); + var snapshot = store.GetSnapshot(); + + // Prepare + + var address = new WalletAccount[maxAccounts]; + var wallets = new NEP6Wallet[maxAccounts]; + var walletsUnlocks = new IDisposable[maxAccounts]; + + for (int x = 0; x < maxAccounts; x++) + { + wallets[x] = TestUtils.GenerateTestWallet(); + walletsUnlocks[x] = wallets[x].Unlock("123"); + address[x] = wallets[x].CreateAccount(); + } + + // Generate multisignature + + var multiSignContract = Contract.CreateMultiSigContract(maxAccounts, address.Select(a => a.GetKey().PublicKey).ToArray()); + + for (int x = 0; x < maxAccounts; x++) + { + wallets[x].CreateAccount(multiSignContract, address[x].GetKey()); + } + + // Sign + + var data = new ContractParametersContext(new DummyVerificable(multiSignContract.ScriptHash)); + + for (int x = 0; x < maxAccounts; x++) + { + Assert.IsTrue(wallets[x].Sign(data)); + } + + Assert.IsTrue(data.Completed); + return data.GetWitnesses()[0]; + } + + [TestMethod] + public void MaxSize_OK() + { + var witness = PrepareDummyWitness(10); + + // Check max size + + witness.Size.Should().Be(1003); + witness.InvocationScript.GetVarSize().Should().Be(653); + witness.VerificationScript.GetVarSize().Should().Be(350); + + Assert.IsTrue(witness.Size <= 1024); + + var copy = witness.ToArray().AsSerializable(); + + CollectionAssert.AreEqual(witness.InvocationScript, copy.InvocationScript); + CollectionAssert.AreEqual(witness.VerificationScript, copy.VerificationScript); + } + + [TestMethod] + public void MaxSize_Error() + { + var witness = PrepareDummyWitness(11); + + // Check max size + + Assert.IsTrue(witness.Size > 1024); + Assert.ThrowsException(() => witness.ToArray().AsSerializable()); + } + [TestMethod] public void InvocationScript_Set() { @@ -73,4 +193,4 @@ public void ToJson() Assert.AreEqual(json["verification"].AsString(), "202020"); } } -} \ No newline at end of file +} diff --git a/neo/Network/P2P/Payloads/Witness.cs b/neo/Network/P2P/Payloads/Witness.cs index d352882e17..52a2186ee8 100644 --- a/neo/Network/P2P/Payloads/Witness.cs +++ b/neo/Network/P2P/Payloads/Witness.cs @@ -28,8 +28,11 @@ public virtual UInt160 ScriptHash void ISerializable.Deserialize(BinaryReader reader) { - InvocationScript = reader.ReadVarBytes(65536); - VerificationScript = reader.ReadVarBytes(65536); + // This is designed to allow a MultiSig 10/10 (around 1003 bytes) ~1024 bytes + // Invocation = 10 * 64 + 10 = 650 ~ 664 (exact is 653) + InvocationScript = reader.ReadVarBytes(664); + // Verification = 10 * 33 + 10 = 340 ~ 360 (exact is 350) + VerificationScript = reader.ReadVarBytes(360); } void ISerializable.Serialize(BinaryWriter writer) From 8960dd8216be0518160d51a0ec938b186769e4da Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 23 Aug 2019 15:05:48 +0200 Subject: [PATCH 35/54] Update VM to last changes (#1048) * Update VM to last changes * Remove hashes --- neo/SmartContract/ApplicationEngine.cs | 27 +++++++++++----------- neo/SmartContract/ExecutionContextState.cs | 10 ++++++++ neo/neo.csproj | 2 +- 3 files changed, 24 insertions(+), 15 deletions(-) create mode 100644 neo/SmartContract/ExecutionContextState.cs diff --git a/neo/SmartContract/ApplicationEngine.cs b/neo/SmartContract/ApplicationEngine.cs index d211d7aac8..45763ed30a 100644 --- a/neo/SmartContract/ApplicationEngine.cs +++ b/neo/SmartContract/ApplicationEngine.cs @@ -15,7 +15,6 @@ public partial class ApplicationEngine : ExecutionEngine public const long GasFree = 0; private readonly long gas_amount; private readonly bool testMode; - private readonly RandomAccessStack hashes = new RandomAccessStack(); private readonly List notifications = new List(); private readonly List disposables = new List(); @@ -23,9 +22,9 @@ public partial class ApplicationEngine : ExecutionEngine public IVerifiable ScriptContainer { get; } public Snapshot Snapshot { get; } public long GasConsumed { get; private set; } = 0; - public UInt160 CurrentScriptHash => hashes.Count > 0 ? hashes.Peek() : null; - public UInt160 CallingScriptHash => hashes.Count > 1 ? hashes.Peek(1) : null; - public UInt160 EntryScriptHash => hashes.Count > 0 ? hashes.Peek(hashes.Count - 1) : null; + public UInt160 CurrentScriptHash => CurrentContext?.GetState().ScriptHash; + public UInt160 CallingScriptHash => InvocationStack.Count > 1 ? InvocationStack.Peek(1).GetState().ScriptHash : null; + public UInt160 EntryScriptHash => EntryContext?.GetState().ScriptHash; public IReadOnlyList Notifications => notifications; internal Dictionary InvocationCounter { get; } = new Dictionary(); @@ -36,8 +35,6 @@ public ApplicationEngine(TriggerType trigger, IVerifiable container, Snapshot sn this.Trigger = trigger; this.ScriptContainer = container; this.Snapshot = snapshot; - ContextLoaded += ApplicationEngine_ContextLoaded; - ContextUnloaded += ApplicationEngine_ContextUnloaded; } internal T AddDisposable(T disposable) where T : IDisposable @@ -52,14 +49,16 @@ private bool AddGas(long gas) return testMode || GasConsumed <= gas_amount; } - private void ApplicationEngine_ContextLoaded(object sender, ExecutionContext e) - { - hashes.Push(((byte[])e.Script).ToScriptHash()); - } - - private void ApplicationEngine_ContextUnloaded(object sender, ExecutionContext e) - { - hashes.Pop(); + protected override void LoadContext(ExecutionContext context) + { + // Set default execution context state + + context.SetState(new ExecutionContextState() + { + ScriptHash = ((byte[])context.Script).ToScriptHash() + }); + + base.LoadContext(context); } public override void Dispose() diff --git a/neo/SmartContract/ExecutionContextState.cs b/neo/SmartContract/ExecutionContextState.cs new file mode 100644 index 0000000000..7895d943a2 --- /dev/null +++ b/neo/SmartContract/ExecutionContextState.cs @@ -0,0 +1,10 @@ +namespace Neo.SmartContract +{ + public class ExecutionContextState + { + /// + /// Script hash + /// + public UInt160 ScriptHash { get; set; } + } +} \ No newline at end of file diff --git a/neo/neo.csproj b/neo/neo.csproj index df29d088f2..66e85016bc 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -29,7 +29,7 @@ - + From 34faf4ed8029203595d767a7840826adc789d71e Mon Sep 17 00:00:00 2001 From: Igor Machado Coelho Date: Sat, 24 Aug 2019 16:33:14 -0300 Subject: [PATCH 36/54] dotnet format (#1054) * dotnet format * fix CRLF --- .../Network/P2P/Payloads/UT_Witness.cs | 2 +- neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs | 3 +- neo/BigDecimal.cs | 2 +- neo/Consensus/ChangeView.cs | 2 +- neo/Consensus/ChangeViewReason.cs | 2 +- neo/Consensus/Commit.cs | 2 +- neo/Consensus/ConsensusContext.cs | 116 ++++---- neo/Consensus/ConsensusMessage.cs | 2 +- neo/Consensus/ConsensusMessageType.cs | 2 +- neo/Consensus/ConsensusService.cs | 2 +- neo/Consensus/PrepareRequest.cs | 2 +- neo/Consensus/PrepareResponse.cs | 2 +- ...ecoveryMessage.ChangeViewPayloadCompact.cs | 2 +- .../RecoveryMessage.CommitPayloadCompact.cs | 2 +- ...coveryMessage.PreparationPayloadCompact.cs | 2 +- neo/Consensus/RecoveryMessage.cs | 2 +- neo/Consensus/RecoveryRequest.cs | 2 +- neo/Cryptography/Base58.cs | 2 +- neo/Cryptography/BloomFilter.cs | 2 +- neo/Cryptography/Crypto.cs | 2 +- neo/Cryptography/ECC/ECCurve.cs | 2 +- neo/Cryptography/ECC/ECDsa.cs | 2 +- neo/Cryptography/ECC/ECFieldElement.cs | 2 +- neo/Cryptography/ECC/ECPoint.cs | 2 +- neo/Cryptography/Helper.cs | 2 +- neo/Cryptography/MerkleTree.cs | 2 +- neo/Cryptography/MerkleTreeNode.cs | 2 +- neo/Cryptography/Murmur3.cs | 2 +- neo/Cryptography/RIPEMD160Managed.cs | 2 +- neo/Cryptography/SCrypt.cs | 2 +- neo/Helper.cs | 2 +- neo/IO/Actors/Idle.cs | 2 +- neo/IO/Actors/PriorityMailbox.cs | 2 +- neo/IO/Actors/PriorityMessageQueue.cs | 2 +- neo/IO/ByteArrayComparer.cs | 2 +- neo/IO/Caching/Cache.cs | 2 +- neo/IO/Caching/CloneCache.cs | 2 +- neo/IO/Caching/CloneMetaCache.cs | 2 +- neo/IO/Caching/DataCache.cs | 2 +- neo/IO/Caching/FIFOCache.cs | 2 +- neo/IO/Caching/FIFOSet.cs | 130 ++++----- neo/IO/Caching/MetaDataCache.cs | 2 +- neo/IO/Caching/OrderedDictionary.cs | 2 +- neo/IO/Caching/ReflectionCache.cs | 2 +- neo/IO/Caching/ReflectionCacheAttribute.cs | 2 +- neo/IO/Caching/RelayCache.cs | 2 +- neo/IO/Caching/TrackState.cs | 2 +- neo/IO/Data/LevelDB/DB.cs | 2 +- neo/IO/Data/LevelDB/Helper.cs | 2 +- neo/IO/Data/LevelDB/Iterator.cs | 2 +- neo/IO/Data/LevelDB/LevelDBException.cs | 2 +- neo/IO/Data/LevelDB/Native.cs | 2 +- neo/IO/Data/LevelDB/Options.cs | 2 +- neo/IO/Data/LevelDB/ReadOptions.cs | 2 +- neo/IO/Data/LevelDB/Slice.cs | 2 +- neo/IO/Data/LevelDB/SliceBuilder.cs | 2 +- neo/IO/Data/LevelDB/Snapshot.cs | 2 +- neo/IO/Data/LevelDB/WriteBatch.cs | 2 +- neo/IO/Data/LevelDB/WriteOptions.cs | 2 +- neo/IO/Helper.cs | 2 +- neo/IO/ICloneable.cs | 2 +- neo/IO/ISerializable.cs | 2 +- neo/IO/Json/JArray.cs | 2 +- neo/IO/Json/JBoolean.cs | 2 +- neo/IO/Json/JNumber.cs | 2 +- neo/IO/Json/JObject.cs | 2 +- neo/IO/Json/JString.cs | 2 +- neo/IO/Wrappers/SerializableWrapper.cs | 2 +- neo/IO/Wrappers/UInt32Wrapper.cs | 2 +- neo/Ledger/Blockchain.ApplicationExecuted.cs | 2 +- neo/Ledger/Blockchain.cs | 2 +- neo/Ledger/ContractState.cs | 2 +- neo/Ledger/HashIndexState.cs | 2 +- neo/Ledger/HeaderHashList.cs | 2 +- neo/Ledger/RelayResultReason.cs | 2 +- neo/Ledger/StorageFlags.cs | 2 +- neo/Ledger/StorageItem.cs | 2 +- neo/Ledger/StorageKey.cs | 2 +- neo/Ledger/TransactionState.cs | 2 +- neo/Ledger/TrimmedBlock.cs | 2 +- neo/NeoSystem.cs | 2 +- .../P2P/Capabilities/FullNodeCapability.cs | 2 +- .../P2P/Capabilities/NodeCapability.cs | 2 +- .../P2P/Capabilities/NodeCapabilityType.cs | 2 +- .../P2P/Capabilities/ServerCapability.cs | 2 +- neo/Network/P2P/ChannelsConfig.cs | 2 +- neo/Network/P2P/Connection.cs | 2 +- neo/Network/P2P/Helper.cs | 2 +- neo/Network/P2P/LocalNode.cs | 2 +- neo/Network/P2P/Message.cs | 2 +- neo/Network/P2P/MessageCommand.cs | 2 +- neo/Network/P2P/MessageFlags.cs | 2 +- neo/Network/P2P/Payloads/AddrPayload.cs | 2 +- neo/Network/P2P/Payloads/Block.cs | 2 +- neo/Network/P2P/Payloads/BlockBase.cs | 2 +- neo/Network/P2P/Payloads/ConsensusData.cs | 2 +- neo/Network/P2P/Payloads/ConsensusPayload.cs | 2 +- neo/Network/P2P/Payloads/Cosigner.cs | 2 +- neo/Network/P2P/Payloads/FilterAddPayload.cs | 2 +- neo/Network/P2P/Payloads/FilterLoadPayload.cs | 2 +- neo/Network/P2P/Payloads/GetBlocksPayload.cs | 2 +- neo/Network/P2P/Payloads/Header.cs | 2 +- neo/Network/P2P/Payloads/HeadersPayload.cs | 2 +- neo/Network/P2P/Payloads/IInventory.cs | 2 +- neo/Network/P2P/Payloads/IVerifiable.cs | 2 +- neo/Network/P2P/Payloads/InvPayload.cs | 2 +- neo/Network/P2P/Payloads/InventoryType.cs | 2 +- .../P2P/Payloads/MerkleBlockPayload.cs | 2 +- .../P2P/Payloads/NetworkAddressWithTime.cs | 2 +- neo/Network/P2P/Payloads/PingPayload.cs | 2 +- .../P2P/Payloads/TransactionAttribute.cs | 2 +- .../P2P/Payloads/TransactionAttributeUsage.cs | 2 +- neo/Network/P2P/Payloads/VersionPayload.cs | 2 +- neo/Network/P2P/Payloads/Witness.cs | 2 +- neo/Network/P2P/Payloads/WitnessScope.cs | 2 +- neo/Network/P2P/Peer.cs | 2 +- neo/Network/P2P/ProtocolHandler.cs | 2 +- neo/Network/P2P/RemoteNode.cs | 2 +- neo/Network/P2P/TaskManager.cs | 2 +- neo/Network/P2P/TaskSession.cs | 2 +- neo/Network/RPC/Models/RpcBlock.cs | 2 +- neo/Network/RPC/Models/RpcBlockHeader.cs | 2 +- neo/Network/RPC/Models/RpcInvokeResult.cs | 2 +- neo/Network/RPC/Models/RpcNep5Balances.cs | 2 +- neo/Network/RPC/Models/RpcPeers.cs | 2 +- neo/Network/RPC/Models/RpcPlugin.cs | 2 +- neo/Network/RPC/Models/RpcRawMemPool.cs | 2 +- neo/Network/RPC/Models/RpcRequest.cs | 2 +- neo/Network/RPC/Models/RpcResponse.cs | 2 +- neo/Network/RPC/Models/RpcTransaction.cs | 2 +- .../RPC/Models/RpcValidateAddressResult.cs | 2 +- neo/Network/RPC/Models/RpcValidator.cs | 2 +- neo/Network/RPC/Models/RpcVersion.cs | 2 +- neo/Network/RPC/RpcClient.cs | 2 +- neo/Network/RPC/RpcException.cs | 2 +- neo/Persistence/CloneSnapshot.cs | 2 +- neo/Persistence/Helper.cs | 2 +- neo/Persistence/IPersistence.cs | 2 +- neo/Persistence/LevelDB/DbCache.cs | 2 +- neo/Persistence/LevelDB/DbMetaDataCache.cs | 2 +- neo/Persistence/LevelDB/DbSnapshot.cs | 2 +- neo/Persistence/LevelDB/LevelDBStore.cs | 2 +- neo/Persistence/LevelDB/Prefixes.cs | 2 +- neo/Persistence/Snapshot.cs | 2 +- neo/Persistence/Store.cs | 2 +- neo/Plugins/ILogPlugin.cs | 2 +- neo/Plugins/IMemoryPoolTxObserverPlugin.cs | 2 +- neo/Plugins/IP2PPlugin.cs | 2 +- neo/Plugins/IPersistencePlugin.cs | 2 +- neo/Plugins/IRpcPlugin.cs | 2 +- neo/Plugins/LogLevel.cs | 2 +- neo/Plugins/MemoryPoolTxRemovalReason.cs | 2 +- neo/Plugins/Plugin.cs | 2 +- neo/ProtocolSettings.cs | 2 +- .../ApplicationEngine.OpCodePrices.cs | 2 +- neo/SmartContract/ApplicationEngine.cs | 20 +- neo/SmartContract/ContainerPlaceholder.cs | 2 +- neo/SmartContract/Contract.cs | 2 +- neo/SmartContract/ContractParameter.cs | 2 +- neo/SmartContract/ContractParameterType.cs | 2 +- .../ContractParametersContext.cs | 12 +- .../Enumerators/ConcatenatedEnumerator.cs | 2 +- neo/SmartContract/Enumerators/IEnumerator.cs | 2 +- .../Enumerators/IteratorKeysWrapper.cs | 2 +- .../Enumerators/IteratorValuesWrapper.cs | 2 +- neo/SmartContract/ExecutionContextState.cs | 18 +- neo/SmartContract/Helper.cs | 2 +- neo/SmartContract/InteropDescriptor.cs | 2 +- neo/SmartContract/InteropService.NEO.cs | 2 +- neo/SmartContract/InteropService.cs | 2 +- neo/SmartContract/Iterators/ArrayWrapper.cs | 2 +- neo/SmartContract/Iterators/IIterator.cs | 2 +- neo/SmartContract/Iterators/MapWrapper.cs | 2 +- .../Iterators/StorageIterator.cs | 2 +- neo/SmartContract/JsonSerializer.cs | 2 +- neo/SmartContract/LogEventArgs.cs | 2 +- neo/SmartContract/Manifest/ContractAbi.cs | 2 +- .../Manifest/ContractEventDescriptor.cs | 2 +- .../Manifest/ContractFeatures.cs | 2 +- neo/SmartContract/Manifest/ContractGroup.cs | 2 +- .../Manifest/ContractManifest.cs | 2 +- .../Manifest/ContractMethodDescriptor.cs | 2 +- .../Manifest/ContractParameterDefinition.cs | 2 +- .../Manifest/ContractPermission.cs | 2 +- .../Manifest/ContractPermissionDescriptor.cs | 2 +- .../Manifest/WildCardContainer.cs | 2 +- .../Native/ContractMethodAttribute.cs | 2 +- .../Native/ContractMethodMetadata.cs | 2 +- neo/SmartContract/Native/NativeContract.cs | 2 +- neo/SmartContract/Native/PolicyContract.cs | 2 +- neo/SmartContract/Native/Tokens/GasToken.cs | 2 +- .../Native/Tokens/Nep5AccountState.cs | 2 +- neo/SmartContract/Native/Tokens/Nep5Token.cs | 2 +- neo/SmartContract/NefFile.cs | 258 +++++++++--------- neo/SmartContract/NotifyEventArgs.cs | 2 +- neo/SmartContract/StackItemType.cs | 2 +- neo/SmartContract/StorageContext.cs | 2 +- neo/SmartContract/WitnessWrapper.cs | 2 +- neo/UInt160.cs | 2 +- neo/UInt256.cs | 2 +- neo/UIntBase.cs | 2 +- neo/VM/Helper.cs | 2 +- neo/Wallets/AssetDescriptor.cs | 2 +- neo/Wallets/Helper.cs | 2 +- neo/Wallets/KeyPair.cs | 2 +- neo/Wallets/NEP6/NEP6Account.cs | 2 +- neo/Wallets/NEP6/NEP6Contract.cs | 2 +- neo/Wallets/NEP6/NEP6Wallet.cs | 2 +- neo/Wallets/NEP6/ScryptParameters.cs | 2 +- neo/Wallets/NEP6/WalletLocker.cs | 2 +- neo/Wallets/SQLite/Account.cs | 2 +- neo/Wallets/SQLite/Address.cs | 2 +- neo/Wallets/SQLite/Contract.cs | 2 +- neo/Wallets/SQLite/Key.cs | 2 +- neo/Wallets/SQLite/UserWallet.cs | 2 +- neo/Wallets/SQLite/UserWalletAccount.cs | 2 +- neo/Wallets/SQLite/VerificationContract.cs | 2 +- neo/Wallets/SQLite/WalletDataContext.cs | 2 +- neo/Wallets/TransferOutput.cs | 2 +- neo/Wallets/Wallet.cs | 2 +- neo/Wallets/WalletAccount.cs | 2 +- neo/neo.csproj | 2 +- 222 files changed, 494 insertions(+), 493 deletions(-) diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs index 01a76eeee4..efb06d93be 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs @@ -122,7 +122,7 @@ public void MaxSize_OK() witness.Size.Should().Be(1003); witness.InvocationScript.GetVarSize().Should().Be(653); witness.VerificationScript.GetVarSize().Should().Be(350); - + Assert.IsTrue(witness.Size <= 1024); var copy = witness.ToArray().AsSerializable(); diff --git a/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs index c531c8c138..ade2472ba8 100644 --- a/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs @@ -18,7 +18,8 @@ public class UT_NEP6Account private static KeyPair keyPair; [ClassInitialize] - public static void ClassSetup(TestContext context) { + public static void ClassSetup(TestContext context) + { byte[] privateKey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; keyPair = new KeyPair(privateKey); diff --git a/neo/BigDecimal.cs b/neo/BigDecimal.cs index 1d65859b0f..aaf541caa9 100644 --- a/neo/BigDecimal.cs +++ b/neo/BigDecimal.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Numerics; namespace Neo diff --git a/neo/Consensus/ChangeView.cs b/neo/Consensus/ChangeView.cs index 4c18b3fb3f..607e44cfd5 100644 --- a/neo/Consensus/ChangeView.cs +++ b/neo/Consensus/ChangeView.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; namespace Neo.Consensus { diff --git a/neo/Consensus/ChangeViewReason.cs b/neo/Consensus/ChangeViewReason.cs index eb06b7494a..066ecc1085 100644 --- a/neo/Consensus/ChangeViewReason.cs +++ b/neo/Consensus/ChangeViewReason.cs @@ -1,4 +1,4 @@ -namespace Neo.Consensus +namespace Neo.Consensus { public enum ChangeViewReason : byte { diff --git a/neo/Consensus/Commit.cs b/neo/Consensus/Commit.cs index f7c17e559a..84585e1ee4 100644 --- a/neo/Consensus/Commit.cs +++ b/neo/Consensus/Commit.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; namespace Neo.Consensus { diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs index a06c6c965b..fbb21d8cd7 100644 --- a/neo/Consensus/ConsensusContext.cs +++ b/neo/Consensus/ConsensusContext.cs @@ -6,7 +6,7 @@ using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; -using Neo.VM; +using Neo.VM; using Neo.Wallets; using System; using System.Collections.Generic; @@ -39,11 +39,11 @@ internal class ConsensusContext : IDisposable, ISerializable public Snapshot Snapshot { get; private set; } private KeyPair keyPair; - private int _witnessSize; + private int _witnessSize; private readonly Wallet wallet; private readonly Store store; private readonly Random random = new Random(); - + public int F => (Validators.Length - 1) / 3; public int M => Validators.Length - F; public bool IsPrimary => MyIndex == Block.ConsensusData.PrimaryIndex; @@ -205,40 +205,40 @@ private void SignPayload(ConsensusPayload payload) return; } payload.Witness = sc.GetWitnesses()[0]; - } - + } + /// /// Return the expected block size /// - internal int GetExpectedBlockSize() - { - return GetExpectedBlockSizeWithoutTransactions(Transactions.Count) + // Base size - Transactions.Values.Sum(u => u.Size); // Sum Txs + internal int GetExpectedBlockSize() + { + return GetExpectedBlockSizeWithoutTransactions(Transactions.Count) + // Base size + Transactions.Values.Sum(u => u.Size); // Sum Txs } - /// - /// Return the expected block size without txs - /// - /// Expected transactions - internal int GetExpectedBlockSizeWithoutTransactions(int expectedTransactions) - { - var blockSize = - // BlockBase - sizeof(uint) + //Version - UInt256.Length + //PrevHash - UInt256.Length + //MerkleRoot - sizeof(ulong) + //Timestamp - sizeof(uint) + //Index - UInt160.Length + //NextConsensus - 1 + // - _witnessSize; //Witness - - blockSize += - // Block - Block.ConsensusData.Size + //ConsensusData - IO.Helper.GetVarSize(expectedTransactions + 1); //Transactions count - - return blockSize; + /// + /// Return the expected block size without txs + /// + /// Expected transactions + internal int GetExpectedBlockSizeWithoutTransactions(int expectedTransactions) + { + var blockSize = + // BlockBase + sizeof(uint) + //Version + UInt256.Length + //PrevHash + UInt256.Length + //MerkleRoot + sizeof(ulong) + //Timestamp + sizeof(uint) + //Index + UInt160.Length + //NextConsensus + 1 + // + _witnessSize; //Witness + + blockSize += + // Block + Block.ConsensusData.Size + //ConsensusData + IO.Helper.GetVarSize(expectedTransactions + 1); //Transactions count + + return blockSize; } /// @@ -247,18 +247,18 @@ internal int GetExpectedBlockSizeWithoutTransactions(int expectedTransactions) /// Ordered transactions internal void EnsureMaxBlockSize(IEnumerable txs) { - uint maxBlockSize = NativeContract.Policy.GetMaxBlockSize(Snapshot); - uint maxTransactionsPerBlock = NativeContract.Policy.GetMaxTransactionsPerBlock(Snapshot); + uint maxBlockSize = NativeContract.Policy.GetMaxBlockSize(Snapshot); + uint maxTransactionsPerBlock = NativeContract.Policy.GetMaxTransactionsPerBlock(Snapshot); // Limit Speaker proposal to the limit `MaxTransactionsPerBlock` or all available transactions of the mempool txs = txs.Take((int)maxTransactionsPerBlock); List hashes = new List(); Transactions = new Dictionary(); - Block.Transactions = new Transaction[0]; - - // We need to know the expected block size - - var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Count()); + Block.Transactions = new Transaction[0]; + + // We need to know the expected block size + + var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Count()); // Iterate transaction until reach the size @@ -271,8 +271,8 @@ internal void EnsureMaxBlockSize(IEnumerable txs) hashes.Add(tx.Hash); Transactions.Add(tx.Hash, tx); } - - TransactionHashes = hashes.ToArray(); + + TransactionHashes = hashes.ToArray(); } public ConsensusPayload MakePrepareRequest() @@ -281,8 +281,8 @@ public ConsensusPayload MakePrepareRequest() random.NextBytes(buffer); Block.ConsensusData.Nonce = BitConverter.ToUInt64(buffer, 0); EnsureMaxBlockSize(Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions()); - Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); - + Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); + return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareRequest { Timestamp = Block.Timestamp, @@ -348,21 +348,21 @@ public void Reset(byte viewNumber) }; var pv = Validators; Validators = NativeContract.NEO.GetNextBlockValidators(Snapshot); - if (_witnessSize == 0 || (pv != null && pv.Length != Validators.Length)) - { - // Compute the expected size of the witness - using (ScriptBuilder sb = new ScriptBuilder()) - { - for (int x = 0; x < M; x++) - { - sb.EmitPush(new byte[64]); - } - _witnessSize = new Witness - { - InvocationScript = sb.ToArray(), - VerificationScript = Contract.CreateMultiSigRedeemScript(M, Validators) - }.Size; - } + if (_witnessSize == 0 || (pv != null && pv.Length != Validators.Length)) + { + // Compute the expected size of the witness + using (ScriptBuilder sb = new ScriptBuilder()) + { + for (int x = 0; x < M; x++) + { + sb.EmitPush(new byte[64]); + } + _witnessSize = new Witness + { + InvocationScript = sb.ToArray(), + VerificationScript = Contract.CreateMultiSigRedeemScript(M, Validators) + }.Size; + } } MyIndex = -1; ChangeViewPayloads = new ConsensusPayload[Validators.Length]; diff --git a/neo/Consensus/ConsensusMessage.cs b/neo/Consensus/ConsensusMessage.cs index 85bf3174e5..af16db03e3 100644 --- a/neo/Consensus/ConsensusMessage.cs +++ b/neo/Consensus/ConsensusMessage.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Caching; using System; using System.IO; diff --git a/neo/Consensus/ConsensusMessageType.cs b/neo/Consensus/ConsensusMessageType.cs index 0aff263595..fe13207db1 100644 --- a/neo/Consensus/ConsensusMessageType.cs +++ b/neo/Consensus/ConsensusMessageType.cs @@ -1,4 +1,4 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; namespace Neo.Consensus { diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index ee5c91d635..cac657c95f 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.Configuration; using Neo.Cryptography; using Neo.IO; diff --git a/neo/Consensus/PrepareRequest.cs b/neo/Consensus/PrepareRequest.cs index 85823fe957..2369b4f9f7 100644 --- a/neo/Consensus/PrepareRequest.cs +++ b/neo/Consensus/PrepareRequest.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Network.P2P.Payloads; using System; using System.IO; diff --git a/neo/Consensus/PrepareResponse.cs b/neo/Consensus/PrepareResponse.cs index 93eb95833a..7c2956ccc2 100644 --- a/neo/Consensus/PrepareResponse.cs +++ b/neo/Consensus/PrepareResponse.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System.IO; namespace Neo.Consensus diff --git a/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs b/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs index 6d4d6a7ae2..dfc46385c0 100644 --- a/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs +++ b/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Network.P2P.Payloads; using System.IO; diff --git a/neo/Consensus/RecoveryMessage.CommitPayloadCompact.cs b/neo/Consensus/RecoveryMessage.CommitPayloadCompact.cs index d9347b71bc..72962f92b3 100644 --- a/neo/Consensus/RecoveryMessage.CommitPayloadCompact.cs +++ b/neo/Consensus/RecoveryMessage.CommitPayloadCompact.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Network.P2P.Payloads; using System.IO; diff --git a/neo/Consensus/RecoveryMessage.PreparationPayloadCompact.cs b/neo/Consensus/RecoveryMessage.PreparationPayloadCompact.cs index 8c0e52f59f..962ae69185 100644 --- a/neo/Consensus/RecoveryMessage.PreparationPayloadCompact.cs +++ b/neo/Consensus/RecoveryMessage.PreparationPayloadCompact.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Network.P2P.Payloads; using System.IO; diff --git a/neo/Consensus/RecoveryMessage.cs b/neo/Consensus/RecoveryMessage.cs index afae45470b..a5e1c09ac6 100644 --- a/neo/Consensus/RecoveryMessage.cs +++ b/neo/Consensus/RecoveryMessage.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.SmartContract; diff --git a/neo/Consensus/RecoveryRequest.cs b/neo/Consensus/RecoveryRequest.cs index c02ceb176c..6ea0d7c2f7 100644 --- a/neo/Consensus/RecoveryRequest.cs +++ b/neo/Consensus/RecoveryRequest.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; namespace Neo.Consensus { diff --git a/neo/Cryptography/Base58.cs b/neo/Cryptography/Base58.cs index fd5bf4d432..b64f12216b 100644 --- a/neo/Cryptography/Base58.cs +++ b/neo/Cryptography/Base58.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Numerics; using System.Text; diff --git a/neo/Cryptography/BloomFilter.cs b/neo/Cryptography/BloomFilter.cs index 637cd9fac5..c4b79d01f2 100644 --- a/neo/Cryptography/BloomFilter.cs +++ b/neo/Cryptography/BloomFilter.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using System.Linq; namespace Neo.Cryptography diff --git a/neo/Cryptography/Crypto.cs b/neo/Cryptography/Crypto.cs index ae1c8cd168..c835e3eebb 100644 --- a/neo/Cryptography/Crypto.cs +++ b/neo/Cryptography/Crypto.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Security.Cryptography; diff --git a/neo/Cryptography/ECC/ECCurve.cs b/neo/Cryptography/ECC/ECCurve.cs index 9d43bcd25f..45d70d31f4 100644 --- a/neo/Cryptography/ECC/ECCurve.cs +++ b/neo/Cryptography/ECC/ECCurve.cs @@ -1,4 +1,4 @@ -using System.Globalization; +using System.Globalization; using System.Numerics; namespace Neo.Cryptography.ECC diff --git a/neo/Cryptography/ECC/ECDsa.cs b/neo/Cryptography/ECC/ECDsa.cs index a254b4248e..07373a7844 100644 --- a/neo/Cryptography/ECC/ECDsa.cs +++ b/neo/Cryptography/ECC/ECDsa.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Numerics; using System.Security.Cryptography; diff --git a/neo/Cryptography/ECC/ECFieldElement.cs b/neo/Cryptography/ECC/ECFieldElement.cs index e33cab4206..331e1e4408 100644 --- a/neo/Cryptography/ECC/ECFieldElement.cs +++ b/neo/Cryptography/ECC/ECFieldElement.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Numerics; diff --git a/neo/Cryptography/ECC/ECPoint.cs b/neo/Cryptography/ECC/ECPoint.cs index dbd556eb50..803aab9987 100644 --- a/neo/Cryptography/ECC/ECPoint.cs +++ b/neo/Cryptography/ECC/ECPoint.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System; using System.IO; using System.Linq; diff --git a/neo/Cryptography/Helper.cs b/neo/Cryptography/Helper.cs index ff1bb8d3d7..07c9ce74e9 100644 --- a/neo/Cryptography/Helper.cs +++ b/neo/Cryptography/Helper.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Network.P2P.Payloads; using System; using System.Collections.Generic; diff --git a/neo/Cryptography/MerkleTree.cs b/neo/Cryptography/MerkleTree.cs index 8d73f56a23..0d8e617f3f 100644 --- a/neo/Cryptography/MerkleTree.cs +++ b/neo/Cryptography/MerkleTree.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/neo/Cryptography/MerkleTreeNode.cs b/neo/Cryptography/MerkleTreeNode.cs index 6bfc75c8d1..73b84b43e9 100644 --- a/neo/Cryptography/MerkleTreeNode.cs +++ b/neo/Cryptography/MerkleTreeNode.cs @@ -1,4 +1,4 @@ -namespace Neo.Cryptography +namespace Neo.Cryptography { internal class MerkleTreeNode { diff --git a/neo/Cryptography/Murmur3.cs b/neo/Cryptography/Murmur3.cs index e54c19ebc1..6296bb20be 100644 --- a/neo/Cryptography/Murmur3.cs +++ b/neo/Cryptography/Murmur3.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.CompilerServices; using System.Security.Cryptography; diff --git a/neo/Cryptography/RIPEMD160Managed.cs b/neo/Cryptography/RIPEMD160Managed.cs index 898780dc47..22ffafb835 100644 --- a/neo/Cryptography/RIPEMD160Managed.cs +++ b/neo/Cryptography/RIPEMD160Managed.cs @@ -1,4 +1,4 @@ -#if !NET47 +#if !NET47 using System; using System.Runtime.InteropServices; using System.Security; diff --git a/neo/Cryptography/SCrypt.cs b/neo/Cryptography/SCrypt.cs index 3022af296c..e40c2c83c5 100644 --- a/neo/Cryptography/SCrypt.cs +++ b/neo/Cryptography/SCrypt.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Security.Cryptography; namespace Neo.Cryptography diff --git a/neo/Helper.cs b/neo/Helper.cs index d8409b64bd..1a513ec79e 100644 --- a/neo/Helper.cs +++ b/neo/Helper.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Neo.Plugins; using System; using System.Collections.Generic; diff --git a/neo/IO/Actors/Idle.cs b/neo/IO/Actors/Idle.cs index 4bb8655bd8..bd4a2d05fa 100644 --- a/neo/IO/Actors/Idle.cs +++ b/neo/IO/Actors/Idle.cs @@ -1,4 +1,4 @@ -namespace Neo.IO.Actors +namespace Neo.IO.Actors { internal sealed class Idle { diff --git a/neo/IO/Actors/PriorityMailbox.cs b/neo/IO/Actors/PriorityMailbox.cs index c6c8a8fbe2..31a50c9a89 100644 --- a/neo/IO/Actors/PriorityMailbox.cs +++ b/neo/IO/Actors/PriorityMailbox.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.Configuration; using Akka.Dispatch; using Akka.Dispatch.MessageQueues; diff --git a/neo/IO/Actors/PriorityMessageQueue.cs b/neo/IO/Actors/PriorityMessageQueue.cs index d22f7626fe..b7820b065a 100644 --- a/neo/IO/Actors/PriorityMessageQueue.cs +++ b/neo/IO/Actors/PriorityMessageQueue.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.Dispatch; using Akka.Dispatch.MessageQueues; using System; diff --git a/neo/IO/ByteArrayComparer.cs b/neo/IO/ByteArrayComparer.cs index 956ab758e6..478c6e3c7d 100644 --- a/neo/IO/ByteArrayComparer.cs +++ b/neo/IO/ByteArrayComparer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Neo.IO diff --git a/neo/IO/Caching/Cache.cs b/neo/IO/Caching/Cache.cs index 5b97d3a223..b5095231f3 100644 --- a/neo/IO/Caching/Cache.cs +++ b/neo/IO/Caching/Cache.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; diff --git a/neo/IO/Caching/CloneCache.cs b/neo/IO/Caching/CloneCache.cs index f13865a41b..0dd030fcb6 100644 --- a/neo/IO/Caching/CloneCache.cs +++ b/neo/IO/Caching/CloneCache.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Neo.IO.Caching diff --git a/neo/IO/Caching/CloneMetaCache.cs b/neo/IO/Caching/CloneMetaCache.cs index 6b354e256e..3cb0d83201 100644 --- a/neo/IO/Caching/CloneMetaCache.cs +++ b/neo/IO/Caching/CloneMetaCache.cs @@ -1,4 +1,4 @@ -namespace Neo.IO.Caching +namespace Neo.IO.Caching { internal class CloneMetaCache : MetaDataCache where T : class, ICloneable, ISerializable, new() diff --git a/neo/IO/Caching/DataCache.cs b/neo/IO/Caching/DataCache.cs index 278c01d650..dc97031d10 100644 --- a/neo/IO/Caching/DataCache.cs +++ b/neo/IO/Caching/DataCache.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; diff --git a/neo/IO/Caching/FIFOCache.cs b/neo/IO/Caching/FIFOCache.cs index 4aa7198b50..c96b11bf6e 100644 --- a/neo/IO/Caching/FIFOCache.cs +++ b/neo/IO/Caching/FIFOCache.cs @@ -1,4 +1,4 @@ -namespace Neo.IO.Caching +namespace Neo.IO.Caching { internal abstract class FIFOCache : Cache { diff --git a/neo/IO/Caching/FIFOSet.cs b/neo/IO/Caching/FIFOSet.cs index aba54463ae..98733ce444 100644 --- a/neo/IO/Caching/FIFOSet.cs +++ b/neo/IO/Caching/FIFOSet.cs @@ -1,65 +1,65 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; - -namespace Neo.IO.Caching -{ - internal class FIFOSet : IEnumerable where T : IEquatable - { - private readonly int maxCapacity; - private readonly int removeCount; - private readonly OrderedDictionary dictionary; - - public FIFOSet(int maxCapacity, decimal batchSize = 0.1m) - { - if (maxCapacity <= 0) throw new ArgumentOutOfRangeException(nameof(maxCapacity)); - if (batchSize <= 0 || batchSize > 1) throw new ArgumentOutOfRangeException(nameof(batchSize)); - - this.maxCapacity = maxCapacity; - this.removeCount = Math.Max((int)(maxCapacity * batchSize), 1); - this.dictionary = new OrderedDictionary(maxCapacity); - } - - public bool Add(T item) - { - if (dictionary.Contains(item)) return false; - if (dictionary.Count >= maxCapacity) - { - if (removeCount == maxCapacity) - { - dictionary.Clear(); - } - else - { - for (int i = 0; i < removeCount; i++) - dictionary.RemoveAt(0); - } - } - dictionary.Add(item, null); - return true; - } - - public bool Contains(T item) - { - return dictionary.Contains(item); - } - - public void ExceptWith(IEnumerable hashes) - { - foreach (var hash in hashes) - { - dictionary.Remove(hash); - } - } - - public IEnumerator GetEnumerator() - { - var entries = dictionary.Keys.Cast().ToArray(); - foreach (var entry in entries) yield return entry; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; + +namespace Neo.IO.Caching +{ + internal class FIFOSet : IEnumerable where T : IEquatable + { + private readonly int maxCapacity; + private readonly int removeCount; + private readonly OrderedDictionary dictionary; + + public FIFOSet(int maxCapacity, decimal batchSize = 0.1m) + { + if (maxCapacity <= 0) throw new ArgumentOutOfRangeException(nameof(maxCapacity)); + if (batchSize <= 0 || batchSize > 1) throw new ArgumentOutOfRangeException(nameof(batchSize)); + + this.maxCapacity = maxCapacity; + this.removeCount = Math.Max((int)(maxCapacity * batchSize), 1); + this.dictionary = new OrderedDictionary(maxCapacity); + } + + public bool Add(T item) + { + if (dictionary.Contains(item)) return false; + if (dictionary.Count >= maxCapacity) + { + if (removeCount == maxCapacity) + { + dictionary.Clear(); + } + else + { + for (int i = 0; i < removeCount; i++) + dictionary.RemoveAt(0); + } + } + dictionary.Add(item, null); + return true; + } + + public bool Contains(T item) + { + return dictionary.Contains(item); + } + + public void ExceptWith(IEnumerable hashes) + { + foreach (var hash in hashes) + { + dictionary.Remove(hash); + } + } + + public IEnumerator GetEnumerator() + { + var entries = dictionary.Keys.Cast().ToArray(); + foreach (var entry in entries) yield return entry; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} diff --git a/neo/IO/Caching/MetaDataCache.cs b/neo/IO/Caching/MetaDataCache.cs index fa3fed6215..f0c40cc59a 100644 --- a/neo/IO/Caching/MetaDataCache.cs +++ b/neo/IO/Caching/MetaDataCache.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Caching { diff --git a/neo/IO/Caching/OrderedDictionary.cs b/neo/IO/Caching/OrderedDictionary.cs index bf12785406..efc85b6305 100644 --- a/neo/IO/Caching/OrderedDictionary.cs +++ b/neo/IO/Caching/OrderedDictionary.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; diff --git a/neo/IO/Caching/ReflectionCache.cs b/neo/IO/Caching/ReflectionCache.cs index 800561c6d9..705366e2fb 100644 --- a/neo/IO/Caching/ReflectionCache.cs +++ b/neo/IO/Caching/ReflectionCache.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/neo/IO/Caching/ReflectionCacheAttribute.cs b/neo/IO/Caching/ReflectionCacheAttribute.cs index e1c1200278..ba5fd4e1bc 100644 --- a/neo/IO/Caching/ReflectionCacheAttribute.cs +++ b/neo/IO/Caching/ReflectionCacheAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Caching { diff --git a/neo/IO/Caching/RelayCache.cs b/neo/IO/Caching/RelayCache.cs index ec6e35bdce..0bc2884eda 100644 --- a/neo/IO/Caching/RelayCache.cs +++ b/neo/IO/Caching/RelayCache.cs @@ -1,4 +1,4 @@ -using Neo.Network.P2P.Payloads; +using Neo.Network.P2P.Payloads; namespace Neo.IO.Caching { diff --git a/neo/IO/Caching/TrackState.cs b/neo/IO/Caching/TrackState.cs index aa144aab34..cba7daec0c 100644 --- a/neo/IO/Caching/TrackState.cs +++ b/neo/IO/Caching/TrackState.cs @@ -1,4 +1,4 @@ -namespace Neo.IO.Caching +namespace Neo.IO.Caching { public enum TrackState : byte { diff --git a/neo/IO/Data/LevelDB/DB.cs b/neo/IO/Data/LevelDB/DB.cs index 559a109594..04e8f50e8f 100644 --- a/neo/IO/Data/LevelDB/DB.cs +++ b/neo/IO/Data/LevelDB/DB.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Data.LevelDB { diff --git a/neo/IO/Data/LevelDB/Helper.cs b/neo/IO/Data/LevelDB/Helper.cs index 2b58690db0..d4c451f574 100644 --- a/neo/IO/Data/LevelDB/Helper.cs +++ b/neo/IO/Data/LevelDB/Helper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; diff --git a/neo/IO/Data/LevelDB/Iterator.cs b/neo/IO/Data/LevelDB/Iterator.cs index 11e72faf63..b3a6a0bfe0 100644 --- a/neo/IO/Data/LevelDB/Iterator.cs +++ b/neo/IO/Data/LevelDB/Iterator.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Data.LevelDB { diff --git a/neo/IO/Data/LevelDB/LevelDBException.cs b/neo/IO/Data/LevelDB/LevelDBException.cs index 0fa0578c56..8804f1f7f2 100644 --- a/neo/IO/Data/LevelDB/LevelDBException.cs +++ b/neo/IO/Data/LevelDB/LevelDBException.cs @@ -1,4 +1,4 @@ -using System.Data.Common; +using System.Data.Common; namespace Neo.IO.Data.LevelDB { diff --git a/neo/IO/Data/LevelDB/Native.cs b/neo/IO/Data/LevelDB/Native.cs index fc3ccd6387..6a19ef4cfe 100644 --- a/neo/IO/Data/LevelDB/Native.cs +++ b/neo/IO/Data/LevelDB/Native.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Runtime.InteropServices; diff --git a/neo/IO/Data/LevelDB/Options.cs b/neo/IO/Data/LevelDB/Options.cs index 676627cb08..53dd6e488b 100644 --- a/neo/IO/Data/LevelDB/Options.cs +++ b/neo/IO/Data/LevelDB/Options.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Data.LevelDB { diff --git a/neo/IO/Data/LevelDB/ReadOptions.cs b/neo/IO/Data/LevelDB/ReadOptions.cs index d27f0d7b59..9c198cfba1 100644 --- a/neo/IO/Data/LevelDB/ReadOptions.cs +++ b/neo/IO/Data/LevelDB/ReadOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Data.LevelDB { diff --git a/neo/IO/Data/LevelDB/Slice.cs b/neo/IO/Data/LevelDB/Slice.cs index 95da8c6a44..1f9d927783 100644 --- a/neo/IO/Data/LevelDB/Slice.cs +++ b/neo/IO/Data/LevelDB/Slice.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using System; using System.Linq; using System.Runtime.InteropServices; diff --git a/neo/IO/Data/LevelDB/SliceBuilder.cs b/neo/IO/Data/LevelDB/SliceBuilder.cs index f00ce20454..d5888c6b5e 100644 --- a/neo/IO/Data/LevelDB/SliceBuilder.cs +++ b/neo/IO/Data/LevelDB/SliceBuilder.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text; diff --git a/neo/IO/Data/LevelDB/Snapshot.cs b/neo/IO/Data/LevelDB/Snapshot.cs index 89a89cb55a..d651098388 100644 --- a/neo/IO/Data/LevelDB/Snapshot.cs +++ b/neo/IO/Data/LevelDB/Snapshot.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Data.LevelDB { diff --git a/neo/IO/Data/LevelDB/WriteBatch.cs b/neo/IO/Data/LevelDB/WriteBatch.cs index eaa3e08bd6..b3a9782108 100644 --- a/neo/IO/Data/LevelDB/WriteBatch.cs +++ b/neo/IO/Data/LevelDB/WriteBatch.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Data.LevelDB { diff --git a/neo/IO/Data/LevelDB/WriteOptions.cs b/neo/IO/Data/LevelDB/WriteOptions.cs index 8a74fb5340..8d120c3997 100644 --- a/neo/IO/Data/LevelDB/WriteOptions.cs +++ b/neo/IO/Data/LevelDB/WriteOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.IO.Data.LevelDB { diff --git a/neo/IO/Helper.cs b/neo/IO/Helper.cs index a306e297d5..c985e676b2 100644 --- a/neo/IO/Helper.cs +++ b/neo/IO/Helper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/neo/IO/ICloneable.cs b/neo/IO/ICloneable.cs index 4df61c84b8..83b4d77725 100644 --- a/neo/IO/ICloneable.cs +++ b/neo/IO/ICloneable.cs @@ -1,4 +1,4 @@ -namespace Neo.IO +namespace Neo.IO { public interface ICloneable { diff --git a/neo/IO/ISerializable.cs b/neo/IO/ISerializable.cs index 28f1ec3e01..d03540deb2 100644 --- a/neo/IO/ISerializable.cs +++ b/neo/IO/ISerializable.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; namespace Neo.IO { diff --git a/neo/IO/Json/JArray.cs b/neo/IO/Json/JArray.cs index 3109b3b61c..6de623d29a 100644 --- a/neo/IO/Json/JArray.cs +++ b/neo/IO/Json/JArray.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.IO; diff --git a/neo/IO/Json/JBoolean.cs b/neo/IO/Json/JBoolean.cs index 83a9111422..6b7c7a34c4 100644 --- a/neo/IO/Json/JBoolean.cs +++ b/neo/IO/Json/JBoolean.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace Neo.IO.Json diff --git a/neo/IO/Json/JNumber.cs b/neo/IO/Json/JNumber.cs index 2a23dc3157..daac440094 100644 --- a/neo/IO/Json/JNumber.cs +++ b/neo/IO/Json/JNumber.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using System.IO; using System.Text; diff --git a/neo/IO/Json/JObject.cs b/neo/IO/Json/JObject.cs index 40aa18f5da..cf6f68cbc7 100644 --- a/neo/IO/Json/JObject.cs +++ b/neo/IO/Json/JObject.cs @@ -1,4 +1,4 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; using System; using System.Collections.Generic; using System.IO; diff --git a/neo/IO/Json/JString.cs b/neo/IO/Json/JString.cs index 065e7b59f9..032470cf4e 100644 --- a/neo/IO/Json/JString.cs +++ b/neo/IO/Json/JString.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using System.IO; using System.Text; diff --git a/neo/IO/Wrappers/SerializableWrapper.cs b/neo/IO/Wrappers/SerializableWrapper.cs index 868c9bcba2..098e4b9c7a 100644 --- a/neo/IO/Wrappers/SerializableWrapper.cs +++ b/neo/IO/Wrappers/SerializableWrapper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace Neo.IO.Wrappers diff --git a/neo/IO/Wrappers/UInt32Wrapper.cs b/neo/IO/Wrappers/UInt32Wrapper.cs index fa8406d50a..6e1fb71da1 100644 --- a/neo/IO/Wrappers/UInt32Wrapper.cs +++ b/neo/IO/Wrappers/UInt32Wrapper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace Neo.IO.Wrappers diff --git a/neo/Ledger/Blockchain.ApplicationExecuted.cs b/neo/Ledger/Blockchain.ApplicationExecuted.cs index 2f5d74fcb8..1bcc65563f 100644 --- a/neo/Ledger/Blockchain.ApplicationExecuted.cs +++ b/neo/Ledger/Blockchain.ApplicationExecuted.cs @@ -1,4 +1,4 @@ -using Neo.Network.P2P.Payloads; +using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.VM; using System.Linq; diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index 7d0b72402d..db879c0732 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.Configuration; using Neo.Cryptography.ECC; using Neo.IO; diff --git a/neo/Ledger/ContractState.cs b/neo/Ledger/ContractState.cs index da02db912f..f6c641d7d5 100644 --- a/neo/Ledger/ContractState.cs +++ b/neo/Ledger/ContractState.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Json; using Neo.SmartContract; using Neo.SmartContract.Manifest; diff --git a/neo/Ledger/HashIndexState.cs b/neo/Ledger/HashIndexState.cs index f83aefd34f..04f7b0bd4a 100644 --- a/neo/Ledger/HashIndexState.cs +++ b/neo/Ledger/HashIndexState.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System.IO; namespace Neo.Ledger diff --git a/neo/Ledger/HeaderHashList.cs b/neo/Ledger/HeaderHashList.cs index c9e9878235..928a26e5d2 100644 --- a/neo/Ledger/HeaderHashList.cs +++ b/neo/Ledger/HeaderHashList.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System.IO; namespace Neo.Ledger diff --git a/neo/Ledger/RelayResultReason.cs b/neo/Ledger/RelayResultReason.cs index e698d0ea34..7bf92afac6 100644 --- a/neo/Ledger/RelayResultReason.cs +++ b/neo/Ledger/RelayResultReason.cs @@ -1,4 +1,4 @@ -namespace Neo.Ledger +namespace Neo.Ledger { public enum RelayResultReason : byte { diff --git a/neo/Ledger/StorageFlags.cs b/neo/Ledger/StorageFlags.cs index a0d7034c1d..cace3c97ef 100644 --- a/neo/Ledger/StorageFlags.cs +++ b/neo/Ledger/StorageFlags.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.Ledger { diff --git a/neo/Ledger/StorageItem.cs b/neo/Ledger/StorageItem.cs index 37a69dba2d..49ea93d8a1 100644 --- a/neo/Ledger/StorageItem.cs +++ b/neo/Ledger/StorageItem.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System.IO; namespace Neo.Ledger diff --git a/neo/Ledger/StorageKey.cs b/neo/Ledger/StorageKey.cs index 187a895aa3..c214260c21 100644 --- a/neo/Ledger/StorageKey.cs +++ b/neo/Ledger/StorageKey.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO; using System; using System.IO; diff --git a/neo/Ledger/TransactionState.cs b/neo/Ledger/TransactionState.cs index c493bd631e..c8a479424a 100644 --- a/neo/Ledger/TransactionState.cs +++ b/neo/Ledger/TransactionState.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.VM; using System.IO; diff --git a/neo/Ledger/TrimmedBlock.cs b/neo/Ledger/TrimmedBlock.cs index 614ee89ac1..2a6f84672b 100644 --- a/neo/Ledger/TrimmedBlock.cs +++ b/neo/Ledger/TrimmedBlock.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Caching; using Neo.IO.Json; using Neo.Network.P2P.Payloads; diff --git a/neo/NeoSystem.cs b/neo/NeoSystem.cs index f53d6efa76..867d4e4201 100644 --- a/neo/NeoSystem.cs +++ b/neo/NeoSystem.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Neo.Consensus; using Neo.Ledger; using Neo.Network.P2P; diff --git a/neo/Network/P2P/Capabilities/FullNodeCapability.cs b/neo/Network/P2P/Capabilities/FullNodeCapability.cs index 7c2ae75845..ccaabbdb5a 100644 --- a/neo/Network/P2P/Capabilities/FullNodeCapability.cs +++ b/neo/Network/P2P/Capabilities/FullNodeCapability.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; namespace Neo.Network.P2P.Capabilities { diff --git a/neo/Network/P2P/Capabilities/NodeCapability.cs b/neo/Network/P2P/Capabilities/NodeCapability.cs index 1160dad912..034afb6be8 100644 --- a/neo/Network/P2P/Capabilities/NodeCapability.cs +++ b/neo/Network/P2P/Capabilities/NodeCapability.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System; using System.IO; diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityType.cs b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs index e8eb71850c..5ea0594d7b 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityType.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs @@ -1,4 +1,4 @@ -namespace Neo.Network.P2P.Capabilities +namespace Neo.Network.P2P.Capabilities { public enum NodeCapabilityType : byte { diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index a27573d438..0ce31e130e 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace Neo.Network.P2P.Capabilities diff --git a/neo/Network/P2P/ChannelsConfig.cs b/neo/Network/P2P/ChannelsConfig.cs index fe09c54996..2882876bd2 100644 --- a/neo/Network/P2P/ChannelsConfig.cs +++ b/neo/Network/P2P/ChannelsConfig.cs @@ -1,4 +1,4 @@ -using System.Net; +using System.Net; namespace Neo.Network.P2P { diff --git a/neo/Network/P2P/Connection.cs b/neo/Network/P2P/Connection.cs index d741f1d0ee..5a00a588ef 100644 --- a/neo/Network/P2P/Connection.cs +++ b/neo/Network/P2P/Connection.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.IO; using System; using System.Net; diff --git a/neo/Network/P2P/Helper.cs b/neo/Network/P2P/Helper.cs index 433725c45b..e3e7cece1b 100644 --- a/neo/Network/P2P/Helper.cs +++ b/neo/Network/P2P/Helper.cs @@ -1,4 +1,4 @@ -using K4os.Compression.LZ4; +using K4os.Compression.LZ4; using Neo.Network.P2P.Payloads; using System; using System.Buffers; diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index 6f30ed50cb..79ad7fb096 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; diff --git a/neo/Network/P2P/Message.cs b/neo/Network/P2P/Message.cs index 5be16b2be0..61ee4493b4 100644 --- a/neo/Network/P2P/Message.cs +++ b/neo/Network/P2P/Message.cs @@ -1,4 +1,4 @@ -using Akka.IO; +using Akka.IO; using Neo.Cryptography; using Neo.IO; using Neo.Network.P2P.Payloads; diff --git a/neo/Network/P2P/MessageCommand.cs b/neo/Network/P2P/MessageCommand.cs index ce0527e136..ed8dc6b96b 100644 --- a/neo/Network/P2P/MessageCommand.cs +++ b/neo/Network/P2P/MessageCommand.cs @@ -1,4 +1,4 @@ -namespace Neo.Network.P2P +namespace Neo.Network.P2P { public enum MessageCommand : byte { diff --git a/neo/Network/P2P/MessageFlags.cs b/neo/Network/P2P/MessageFlags.cs index 9af64e5fbc..4e8a34c1a7 100644 --- a/neo/Network/P2P/MessageFlags.cs +++ b/neo/Network/P2P/MessageFlags.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.Network.P2P { diff --git a/neo/Network/P2P/Payloads/AddrPayload.cs b/neo/Network/P2P/Payloads/AddrPayload.cs index 65337f0869..0a8f09c71e 100644 --- a/neo/Network/P2P/Payloads/AddrPayload.cs +++ b/neo/Network/P2P/Payloads/AddrPayload.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System; using System.IO; diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index 75e5d7c424..d339b536a0 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO; using Neo.IO.Json; using Neo.Ledger; diff --git a/neo/Network/P2P/Payloads/BlockBase.cs b/neo/Network/P2P/Payloads/BlockBase.cs index 20a0c98211..90b1531cd0 100644 --- a/neo/Network/P2P/Payloads/BlockBase.cs +++ b/neo/Network/P2P/Payloads/BlockBase.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO; using Neo.IO.Json; using Neo.Persistence; diff --git a/neo/Network/P2P/Payloads/ConsensusData.cs b/neo/Network/P2P/Payloads/ConsensusData.cs index 622c42e464..48d3d14ac8 100644 --- a/neo/Network/P2P/Payloads/ConsensusData.cs +++ b/neo/Network/P2P/Payloads/ConsensusData.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO; using Neo.IO.Json; using Neo.Ledger; diff --git a/neo/Network/P2P/Payloads/ConsensusPayload.cs b/neo/Network/P2P/Payloads/ConsensusPayload.cs index a4c6e86ee6..062e5d9830 100644 --- a/neo/Network/P2P/Payloads/ConsensusPayload.cs +++ b/neo/Network/P2P/Payloads/ConsensusPayload.cs @@ -1,4 +1,4 @@ -using Neo.Consensus; +using Neo.Consensus; using Neo.Cryptography; using Neo.Cryptography.ECC; using Neo.IO; diff --git a/neo/Network/P2P/Payloads/Cosigner.cs b/neo/Network/P2P/Payloads/Cosigner.cs index 2d1f42039c..99672ecf4d 100644 --- a/neo/Network/P2P/Payloads/Cosigner.cs +++ b/neo/Network/P2P/Payloads/Cosigner.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography.ECC; +using Neo.Cryptography.ECC; using Neo.IO; using Neo.IO.Json; using System; diff --git a/neo/Network/P2P/Payloads/FilterAddPayload.cs b/neo/Network/P2P/Payloads/FilterAddPayload.cs index 71bddea5dc..3a7a4a9e6f 100644 --- a/neo/Network/P2P/Payloads/FilterAddPayload.cs +++ b/neo/Network/P2P/Payloads/FilterAddPayload.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System.IO; namespace Neo.Network.P2P.Payloads diff --git a/neo/Network/P2P/Payloads/FilterLoadPayload.cs b/neo/Network/P2P/Payloads/FilterLoadPayload.cs index 5d337c8dac..dfba728fc0 100644 --- a/neo/Network/P2P/Payloads/FilterLoadPayload.cs +++ b/neo/Network/P2P/Payloads/FilterLoadPayload.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO; using System; using System.IO; diff --git a/neo/Network/P2P/Payloads/GetBlocksPayload.cs b/neo/Network/P2P/Payloads/GetBlocksPayload.cs index f7e39927f1..eccd66ed19 100644 --- a/neo/Network/P2P/Payloads/GetBlocksPayload.cs +++ b/neo/Network/P2P/Payloads/GetBlocksPayload.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System; using System.IO; diff --git a/neo/Network/P2P/Payloads/Header.cs b/neo/Network/P2P/Payloads/Header.cs index abd7fbd370..eaef0dc160 100644 --- a/neo/Network/P2P/Payloads/Header.cs +++ b/neo/Network/P2P/Payloads/Header.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Neo.Ledger; using Neo.Wallets; using System; diff --git a/neo/Network/P2P/Payloads/HeadersPayload.cs b/neo/Network/P2P/Payloads/HeadersPayload.cs index 54948a142d..3b13405d24 100644 --- a/neo/Network/P2P/Payloads/HeadersPayload.cs +++ b/neo/Network/P2P/Payloads/HeadersPayload.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/neo/Network/P2P/Payloads/IInventory.cs b/neo/Network/P2P/Payloads/IInventory.cs index dcf3114a8b..26b62346d9 100644 --- a/neo/Network/P2P/Payloads/IInventory.cs +++ b/neo/Network/P2P/Payloads/IInventory.cs @@ -1,4 +1,4 @@ -using Neo.Persistence; +using Neo.Persistence; namespace Neo.Network.P2P.Payloads { diff --git a/neo/Network/P2P/Payloads/IVerifiable.cs b/neo/Network/P2P/Payloads/IVerifiable.cs index 50651ad9ff..8540d8a626 100644 --- a/neo/Network/P2P/Payloads/IVerifiable.cs +++ b/neo/Network/P2P/Payloads/IVerifiable.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Persistence; using System.IO; diff --git a/neo/Network/P2P/Payloads/InvPayload.cs b/neo/Network/P2P/Payloads/InvPayload.cs index a3bc82a4d9..613d280234 100644 --- a/neo/Network/P2P/Payloads/InvPayload.cs +++ b/neo/Network/P2P/Payloads/InvPayload.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System; using System.Collections.Generic; using System.IO; diff --git a/neo/Network/P2P/Payloads/InventoryType.cs b/neo/Network/P2P/Payloads/InventoryType.cs index 58ad12471b..775eed958f 100644 --- a/neo/Network/P2P/Payloads/InventoryType.cs +++ b/neo/Network/P2P/Payloads/InventoryType.cs @@ -1,4 +1,4 @@ -namespace Neo.Network.P2P.Payloads +namespace Neo.Network.P2P.Payloads { public enum InventoryType : byte { diff --git a/neo/Network/P2P/Payloads/MerkleBlockPayload.cs b/neo/Network/P2P/Payloads/MerkleBlockPayload.cs index 11b9fb3a6e..0d00434cd4 100644 --- a/neo/Network/P2P/Payloads/MerkleBlockPayload.cs +++ b/neo/Network/P2P/Payloads/MerkleBlockPayload.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO; using System.Collections; using System.IO; diff --git a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index 01508524a5..6fcda2f809 100644 --- a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Network.P2P.Capabilities; using System; using System.IO; diff --git a/neo/Network/P2P/Payloads/PingPayload.cs b/neo/Network/P2P/Payloads/PingPayload.cs index 107dd501d5..680de9dd0a 100644 --- a/neo/Network/P2P/Payloads/PingPayload.cs +++ b/neo/Network/P2P/Payloads/PingPayload.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System; using System.IO; diff --git a/neo/Network/P2P/Payloads/TransactionAttribute.cs b/neo/Network/P2P/Payloads/TransactionAttribute.cs index 99d1671ebd..5adc34db8e 100644 --- a/neo/Network/P2P/Payloads/TransactionAttribute.cs +++ b/neo/Network/P2P/Payloads/TransactionAttribute.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Json; using System; using System.IO; diff --git a/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs b/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs index 89c1a1cec2..9bf5cc204c 100644 --- a/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs +++ b/neo/Network/P2P/Payloads/TransactionAttributeUsage.cs @@ -1,4 +1,4 @@ -namespace Neo.Network.P2P.Payloads +namespace Neo.Network.P2P.Payloads { public enum TransactionAttributeUsage : byte { diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 754000e062..16c401b7db 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.Network.P2P.Capabilities; using System; using System.IO; diff --git a/neo/Network/P2P/Payloads/Witness.cs b/neo/Network/P2P/Payloads/Witness.cs index 52a2186ee8..227d810a39 100644 --- a/neo/Network/P2P/Payloads/Witness.cs +++ b/neo/Network/P2P/Payloads/Witness.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Json; using Neo.SmartContract; using Neo.VM; diff --git a/neo/Network/P2P/Payloads/WitnessScope.cs b/neo/Network/P2P/Payloads/WitnessScope.cs index e67706cbbf..f35e550a34 100644 --- a/neo/Network/P2P/Payloads/WitnessScope.cs +++ b/neo/Network/P2P/Payloads/WitnessScope.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.Network.P2P.Payloads { diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index eb21095685..0cbd6cbaff 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index 63ecbe3318..aa7f0e06f2 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.Configuration; using Neo.Cryptography; using Neo.IO; diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 7700c896b2..ec2a16e047 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.Configuration; using Akka.IO; using Neo.Cryptography; diff --git a/neo/Network/P2P/TaskManager.cs b/neo/Network/P2P/TaskManager.cs index cd96547df8..2c0f7ae07b 100644 --- a/neo/Network/P2P/TaskManager.cs +++ b/neo/Network/P2P/TaskManager.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Akka.Configuration; using Neo.IO.Actors; using Neo.IO.Caching; diff --git a/neo/Network/P2P/TaskSession.cs b/neo/Network/P2P/TaskSession.cs index 5617e0efa1..a1cf8a0ffc 100644 --- a/neo/Network/P2P/TaskSession.cs +++ b/neo/Network/P2P/TaskSession.cs @@ -1,4 +1,4 @@ -using Akka.Actor; +using Akka.Actor; using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; using System; diff --git a/neo/Network/RPC/Models/RpcBlock.cs b/neo/Network/RPC/Models/RpcBlock.cs index 0d49b3b53a..f71af51168 100644 --- a/neo/Network/RPC/Models/RpcBlock.cs +++ b/neo/Network/RPC/Models/RpcBlock.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Neo.Network.P2P.Payloads; namespace Neo.Network.RPC.Models diff --git a/neo/Network/RPC/Models/RpcBlockHeader.cs b/neo/Network/RPC/Models/RpcBlockHeader.cs index 250acfd818..2b9293ecaf 100644 --- a/neo/Network/RPC/Models/RpcBlockHeader.cs +++ b/neo/Network/RPC/Models/RpcBlockHeader.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Neo.Network.P2P.Payloads; namespace Neo.Network.RPC.Models diff --git a/neo/Network/RPC/Models/RpcInvokeResult.cs b/neo/Network/RPC/Models/RpcInvokeResult.cs index 9df9492e2b..73f2c6a2af 100644 --- a/neo/Network/RPC/Models/RpcInvokeResult.cs +++ b/neo/Network/RPC/Models/RpcInvokeResult.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Newtonsoft.Json; using System.Linq; diff --git a/neo/Network/RPC/Models/RpcNep5Balances.cs b/neo/Network/RPC/Models/RpcNep5Balances.cs index f29f0c5564..b471ab4545 100644 --- a/neo/Network/RPC/Models/RpcNep5Balances.cs +++ b/neo/Network/RPC/Models/RpcNep5Balances.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System.Linq; using System.Numerics; diff --git a/neo/Network/RPC/Models/RpcPeers.cs b/neo/Network/RPC/Models/RpcPeers.cs index 5caa99a66a..fac73842de 100644 --- a/neo/Network/RPC/Models/RpcPeers.cs +++ b/neo/Network/RPC/Models/RpcPeers.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System.Linq; namespace Neo.Network.RPC.Models diff --git a/neo/Network/RPC/Models/RpcPlugin.cs b/neo/Network/RPC/Models/RpcPlugin.cs index ae778ee87a..db03f70eb3 100644 --- a/neo/Network/RPC/Models/RpcPlugin.cs +++ b/neo/Network/RPC/Models/RpcPlugin.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System.Linq; namespace Neo.Network.RPC.Models diff --git a/neo/Network/RPC/Models/RpcRawMemPool.cs b/neo/Network/RPC/Models/RpcRawMemPool.cs index df439bf3a6..c5ebd63419 100644 --- a/neo/Network/RPC/Models/RpcRawMemPool.cs +++ b/neo/Network/RPC/Models/RpcRawMemPool.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System.Linq; namespace Neo.Network.RPC.Models diff --git a/neo/Network/RPC/Models/RpcRequest.cs b/neo/Network/RPC/Models/RpcRequest.cs index 010e3037b8..1970adedbf 100644 --- a/neo/Network/RPC/Models/RpcRequest.cs +++ b/neo/Network/RPC/Models/RpcRequest.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System.Linq; namespace Neo.Network.RPC.Models diff --git a/neo/Network/RPC/Models/RpcResponse.cs b/neo/Network/RPC/Models/RpcResponse.cs index ff20200519..e4ebcaed1b 100644 --- a/neo/Network/RPC/Models/RpcResponse.cs +++ b/neo/Network/RPC/Models/RpcResponse.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; namespace Neo.Network.RPC.Models { diff --git a/neo/Network/RPC/Models/RpcTransaction.cs b/neo/Network/RPC/Models/RpcTransaction.cs index 3e45830ae6..f41c04710a 100644 --- a/neo/Network/RPC/Models/RpcTransaction.cs +++ b/neo/Network/RPC/Models/RpcTransaction.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Neo.Network.P2P.Payloads; namespace Neo.Network.RPC.Models diff --git a/neo/Network/RPC/Models/RpcValidateAddressResult.cs b/neo/Network/RPC/Models/RpcValidateAddressResult.cs index f33467356e..5e0a704797 100644 --- a/neo/Network/RPC/Models/RpcValidateAddressResult.cs +++ b/neo/Network/RPC/Models/RpcValidateAddressResult.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; namespace Neo.Network.RPC.Models { diff --git a/neo/Network/RPC/Models/RpcValidator.cs b/neo/Network/RPC/Models/RpcValidator.cs index b694a6dfcd..f3116ed2e4 100644 --- a/neo/Network/RPC/Models/RpcValidator.cs +++ b/neo/Network/RPC/Models/RpcValidator.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System.Numerics; namespace Neo.Network.RPC.Models diff --git a/neo/Network/RPC/Models/RpcVersion.cs b/neo/Network/RPC/Models/RpcVersion.cs index 02f4dc3407..8163875b64 100644 --- a/neo/Network/RPC/Models/RpcVersion.cs +++ b/neo/Network/RPC/Models/RpcVersion.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; namespace Neo.Network.RPC.Models { diff --git a/neo/Network/RPC/RpcClient.cs b/neo/Network/RPC/RpcClient.cs index 4b968163c7..69352b8cfd 100644 --- a/neo/Network/RPC/RpcClient.cs +++ b/neo/Network/RPC/RpcClient.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Neo.Ledger; using Neo.Network.RPC.Models; using System; diff --git a/neo/Network/RPC/RpcException.cs b/neo/Network/RPC/RpcException.cs index 5a2120f083..b5030750ca 100644 --- a/neo/Network/RPC/RpcException.cs +++ b/neo/Network/RPC/RpcException.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.Network.RPC { diff --git a/neo/Persistence/CloneSnapshot.cs b/neo/Persistence/CloneSnapshot.cs index 9f86f2a1bf..0b79bd2739 100644 --- a/neo/Persistence/CloneSnapshot.cs +++ b/neo/Persistence/CloneSnapshot.cs @@ -1,4 +1,4 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; using Neo.IO.Wrappers; using Neo.Ledger; diff --git a/neo/Persistence/Helper.cs b/neo/Persistence/Helper.cs index d884e0da6b..7f412e47d3 100644 --- a/neo/Persistence/Helper.cs +++ b/neo/Persistence/Helper.cs @@ -1,4 +1,4 @@ -using Neo.Ledger; +using Neo.Ledger; using Neo.Network.P2P.Payloads; namespace Neo.Persistence diff --git a/neo/Persistence/IPersistence.cs b/neo/Persistence/IPersistence.cs index 34f1169f9b..0632b5d0fa 100644 --- a/neo/Persistence/IPersistence.cs +++ b/neo/Persistence/IPersistence.cs @@ -1,4 +1,4 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; using Neo.IO.Wrappers; using Neo.Ledger; diff --git a/neo/Persistence/LevelDB/DbCache.cs b/neo/Persistence/LevelDB/DbCache.cs index 86ff7a39ea..ae55b31326 100644 --- a/neo/Persistence/LevelDB/DbCache.cs +++ b/neo/Persistence/LevelDB/DbCache.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Caching; using Neo.IO.Data.LevelDB; using System; diff --git a/neo/Persistence/LevelDB/DbMetaDataCache.cs b/neo/Persistence/LevelDB/DbMetaDataCache.cs index e2c03ca2fd..0163d84e39 100644 --- a/neo/Persistence/LevelDB/DbMetaDataCache.cs +++ b/neo/Persistence/LevelDB/DbMetaDataCache.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Caching; using Neo.IO.Data.LevelDB; using System; diff --git a/neo/Persistence/LevelDB/DbSnapshot.cs b/neo/Persistence/LevelDB/DbSnapshot.cs index f7ade52ad8..365584fa7c 100644 --- a/neo/Persistence/LevelDB/DbSnapshot.cs +++ b/neo/Persistence/LevelDB/DbSnapshot.cs @@ -1,4 +1,4 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; using Neo.IO.Data.LevelDB; using Neo.IO.Wrappers; using Neo.Ledger; diff --git a/neo/Persistence/LevelDB/LevelDBStore.cs b/neo/Persistence/LevelDB/LevelDBStore.cs index 189f0cfbb5..bb6ac26698 100644 --- a/neo/Persistence/LevelDB/LevelDBStore.cs +++ b/neo/Persistence/LevelDB/LevelDBStore.cs @@ -1,4 +1,4 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; using Neo.IO.Data.LevelDB; using Neo.IO.Wrappers; using Neo.Ledger; diff --git a/neo/Persistence/LevelDB/Prefixes.cs b/neo/Persistence/LevelDB/Prefixes.cs index 605e9f1451..f40359a55a 100644 --- a/neo/Persistence/LevelDB/Prefixes.cs +++ b/neo/Persistence/LevelDB/Prefixes.cs @@ -1,4 +1,4 @@ -namespace Neo.Persistence.LevelDB +namespace Neo.Persistence.LevelDB { internal static class Prefixes { diff --git a/neo/Persistence/Snapshot.cs b/neo/Persistence/Snapshot.cs index f058562200..1e900800b0 100644 --- a/neo/Persistence/Snapshot.cs +++ b/neo/Persistence/Snapshot.cs @@ -1,4 +1,4 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; using Neo.IO.Wrappers; using Neo.Ledger; using Neo.Network.P2P.Payloads; diff --git a/neo/Persistence/Store.cs b/neo/Persistence/Store.cs index 7b5b3b6435..3dc7127f3a 100644 --- a/neo/Persistence/Store.cs +++ b/neo/Persistence/Store.cs @@ -1,4 +1,4 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; using Neo.IO.Wrappers; using Neo.Ledger; diff --git a/neo/Plugins/ILogPlugin.cs b/neo/Plugins/ILogPlugin.cs index ff1052be2e..c0733f9143 100644 --- a/neo/Plugins/ILogPlugin.cs +++ b/neo/Plugins/ILogPlugin.cs @@ -1,4 +1,4 @@ -namespace Neo.Plugins +namespace Neo.Plugins { public interface ILogPlugin { diff --git a/neo/Plugins/IMemoryPoolTxObserverPlugin.cs b/neo/Plugins/IMemoryPoolTxObserverPlugin.cs index e596b9a7b5..3dd1cb3ef2 100644 --- a/neo/Plugins/IMemoryPoolTxObserverPlugin.cs +++ b/neo/Plugins/IMemoryPoolTxObserverPlugin.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Neo.Network.P2P.Payloads; namespace Neo.Plugins diff --git a/neo/Plugins/IP2PPlugin.cs b/neo/Plugins/IP2PPlugin.cs index 3029aaf849..e2043104fc 100644 --- a/neo/Plugins/IP2PPlugin.cs +++ b/neo/Plugins/IP2PPlugin.cs @@ -1,4 +1,4 @@ -using Neo.Network.P2P; +using Neo.Network.P2P; using Neo.Network.P2P.Payloads; namespace Neo.Plugins diff --git a/neo/Plugins/IPersistencePlugin.cs b/neo/Plugins/IPersistencePlugin.cs index af3cbe05b8..0f06ae51eb 100644 --- a/neo/Plugins/IPersistencePlugin.cs +++ b/neo/Plugins/IPersistencePlugin.cs @@ -1,4 +1,4 @@ -using System; +using System; using Neo.Persistence; using System.Collections.Generic; using static Neo.Ledger.Blockchain; diff --git a/neo/Plugins/IRpcPlugin.cs b/neo/Plugins/IRpcPlugin.cs index 19e5b71808..92e7a0fa48 100644 --- a/neo/Plugins/IRpcPlugin.cs +++ b/neo/Plugins/IRpcPlugin.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http; using Neo.IO.Json; namespace Neo.Plugins diff --git a/neo/Plugins/LogLevel.cs b/neo/Plugins/LogLevel.cs index 72158c8aad..8f6e0b9df7 100644 --- a/neo/Plugins/LogLevel.cs +++ b/neo/Plugins/LogLevel.cs @@ -1,4 +1,4 @@ -namespace Neo.Plugins +namespace Neo.Plugins { public enum LogLevel : byte { diff --git a/neo/Plugins/MemoryPoolTxRemovalReason.cs b/neo/Plugins/MemoryPoolTxRemovalReason.cs index f7320dc60e..d08a37eba2 100644 --- a/neo/Plugins/MemoryPoolTxRemovalReason.cs +++ b/neo/Plugins/MemoryPoolTxRemovalReason.cs @@ -1,4 +1,4 @@ -namespace Neo.Plugins +namespace Neo.Plugins { public enum MemoryPoolTxRemovalReason : byte { diff --git a/neo/Plugins/Plugin.cs b/neo/Plugins/Plugin.cs index 72c7ce3b14..aa04b0778d 100644 --- a/neo/Plugins/Plugin.cs +++ b/neo/Plugins/Plugin.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.IO; diff --git a/neo/ProtocolSettings.cs b/neo/ProtocolSettings.cs index 381e56c8a7..18c915d614 100644 --- a/neo/ProtocolSettings.cs +++ b/neo/ProtocolSettings.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using System; using System.Linq; using System.Threading; diff --git a/neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/neo/SmartContract/ApplicationEngine.OpCodePrices.cs index 9da0f6c75d..271a76f935 100644 --- a/neo/SmartContract/ApplicationEngine.OpCodePrices.cs +++ b/neo/SmartContract/ApplicationEngine.OpCodePrices.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; using System.Collections.Generic; namespace Neo.SmartContract diff --git a/neo/SmartContract/ApplicationEngine.cs b/neo/SmartContract/ApplicationEngine.cs index 45763ed30a..2eeeef52e0 100644 --- a/neo/SmartContract/ApplicationEngine.cs +++ b/neo/SmartContract/ApplicationEngine.cs @@ -49,16 +49,16 @@ private bool AddGas(long gas) return testMode || GasConsumed <= gas_amount; } - protected override void LoadContext(ExecutionContext context) - { - // Set default execution context state - - context.SetState(new ExecutionContextState() - { - ScriptHash = ((byte[])context.Script).ToScriptHash() - }); - - base.LoadContext(context); + protected override void LoadContext(ExecutionContext context) + { + // Set default execution context state + + context.SetState(new ExecutionContextState() + { + ScriptHash = ((byte[])context.Script).ToScriptHash() + }); + + base.LoadContext(context); } public override void Dispose() diff --git a/neo/SmartContract/ContainerPlaceholder.cs b/neo/SmartContract/ContainerPlaceholder.cs index 14e97ae848..a379ddd9d3 100644 --- a/neo/SmartContract/ContainerPlaceholder.cs +++ b/neo/SmartContract/ContainerPlaceholder.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; using System; namespace Neo.SmartContract diff --git a/neo/SmartContract/Contract.cs b/neo/SmartContract/Contract.cs index 8d23997006..19fcceb7ca 100644 --- a/neo/SmartContract/Contract.cs +++ b/neo/SmartContract/Contract.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography.ECC; +using Neo.Cryptography.ECC; using Neo.VM; using Neo.Wallets; using System; diff --git a/neo/SmartContract/ContractParameter.cs b/neo/SmartContract/ContractParameter.cs index 5e78005e13..cae59229b8 100644 --- a/neo/SmartContract/ContractParameter.cs +++ b/neo/SmartContract/ContractParameter.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography.ECC; +using Neo.Cryptography.ECC; using Neo.IO.Json; using System; using System.Collections.Generic; diff --git a/neo/SmartContract/ContractParameterType.cs b/neo/SmartContract/ContractParameterType.cs index 67191852fa..748ff86654 100644 --- a/neo/SmartContract/ContractParameterType.cs +++ b/neo/SmartContract/ContractParameterType.cs @@ -1,4 +1,4 @@ -namespace Neo.SmartContract +namespace Neo.SmartContract { public enum ContractParameterType : byte { diff --git a/neo/SmartContract/ContractParametersContext.cs b/neo/SmartContract/ContractParametersContext.cs index 35a2c36898..8a91c936b8 100644 --- a/neo/SmartContract/ContractParametersContext.cs +++ b/neo/SmartContract/ContractParametersContext.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography.ECC; +using Neo.Cryptography.ECC; using Neo.IO.Json; using Neo.Ledger; using Neo.Network.P2P.Payloads; @@ -72,14 +72,14 @@ public bool Completed } } - /// - /// Cache for public ScriptHashes field + /// + /// Cache for public ScriptHashes field /// private UInt160[] _ScriptHashes = null; - /// - /// ScriptHashes are the verifiable ScriptHashes from Verifiable element - /// Equivalent to: Verifiable.GetScriptHashesForVerifying(Blockchain.Singleton.GetSnapshot()) + /// + /// ScriptHashes are the verifiable ScriptHashes from Verifiable element + /// Equivalent to: Verifiable.GetScriptHashesForVerifying(Blockchain.Singleton.GetSnapshot()) /// public IReadOnlyList ScriptHashes { diff --git a/neo/SmartContract/Enumerators/ConcatenatedEnumerator.cs b/neo/SmartContract/Enumerators/ConcatenatedEnumerator.cs index 36e8c4fe97..2b75b1d46b 100644 --- a/neo/SmartContract/Enumerators/ConcatenatedEnumerator.cs +++ b/neo/SmartContract/Enumerators/ConcatenatedEnumerator.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; namespace Neo.SmartContract.Enumerators { diff --git a/neo/SmartContract/Enumerators/IEnumerator.cs b/neo/SmartContract/Enumerators/IEnumerator.cs index 27e30b5e18..4d1f11fe65 100644 --- a/neo/SmartContract/Enumerators/IEnumerator.cs +++ b/neo/SmartContract/Enumerators/IEnumerator.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; using System; namespace Neo.SmartContract.Enumerators diff --git a/neo/SmartContract/Enumerators/IteratorKeysWrapper.cs b/neo/SmartContract/Enumerators/IteratorKeysWrapper.cs index ef2e49d49f..d134eb884c 100644 --- a/neo/SmartContract/Enumerators/IteratorKeysWrapper.cs +++ b/neo/SmartContract/Enumerators/IteratorKeysWrapper.cs @@ -1,4 +1,4 @@ -using Neo.SmartContract.Iterators; +using Neo.SmartContract.Iterators; using Neo.VM; namespace Neo.SmartContract.Enumerators diff --git a/neo/SmartContract/Enumerators/IteratorValuesWrapper.cs b/neo/SmartContract/Enumerators/IteratorValuesWrapper.cs index fb69070d40..15e06f2223 100644 --- a/neo/SmartContract/Enumerators/IteratorValuesWrapper.cs +++ b/neo/SmartContract/Enumerators/IteratorValuesWrapper.cs @@ -1,4 +1,4 @@ -using Neo.SmartContract.Iterators; +using Neo.SmartContract.Iterators; using Neo.VM; namespace Neo.SmartContract.Enumerators diff --git a/neo/SmartContract/ExecutionContextState.cs b/neo/SmartContract/ExecutionContextState.cs index 7895d943a2..11e6f88a00 100644 --- a/neo/SmartContract/ExecutionContextState.cs +++ b/neo/SmartContract/ExecutionContextState.cs @@ -1,10 +1,10 @@ -namespace Neo.SmartContract -{ - public class ExecutionContextState - { - /// - /// Script hash - /// - public UInt160 ScriptHash { get; set; } - } +namespace Neo.SmartContract +{ + public class ExecutionContextState + { + /// + /// Script hash + /// + public UInt160 ScriptHash { get; set; } + } } \ No newline at end of file diff --git a/neo/SmartContract/Helper.cs b/neo/SmartContract/Helper.cs index 259e997b09..6a22249cd7 100644 --- a/neo/SmartContract/Helper.cs +++ b/neo/SmartContract/Helper.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.Persistence; diff --git a/neo/SmartContract/InteropDescriptor.cs b/neo/SmartContract/InteropDescriptor.cs index c283e474de..6db599ea64 100644 --- a/neo/SmartContract/InteropDescriptor.cs +++ b/neo/SmartContract/InteropDescriptor.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; using System; namespace Neo.SmartContract diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index 91b941649f..7f0d857fe9 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO.Json; using Neo.Ledger; using Neo.Network.P2P; diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 9fbb5c6675..b4121d7a24 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.Cryptography.ECC; using Neo.IO; using Neo.Ledger; diff --git a/neo/SmartContract/Iterators/ArrayWrapper.cs b/neo/SmartContract/Iterators/ArrayWrapper.cs index 3284f1317f..883327bee0 100644 --- a/neo/SmartContract/Iterators/ArrayWrapper.cs +++ b/neo/SmartContract/Iterators/ArrayWrapper.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; using System; using System.Collections.Generic; diff --git a/neo/SmartContract/Iterators/IIterator.cs b/neo/SmartContract/Iterators/IIterator.cs index ca67ae0331..3438286615 100644 --- a/neo/SmartContract/Iterators/IIterator.cs +++ b/neo/SmartContract/Iterators/IIterator.cs @@ -1,4 +1,4 @@ -using Neo.SmartContract.Enumerators; +using Neo.SmartContract.Enumerators; using Neo.VM; namespace Neo.SmartContract.Iterators diff --git a/neo/SmartContract/Iterators/MapWrapper.cs b/neo/SmartContract/Iterators/MapWrapper.cs index d42f940fac..343b946982 100644 --- a/neo/SmartContract/Iterators/MapWrapper.cs +++ b/neo/SmartContract/Iterators/MapWrapper.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; using System.Collections.Generic; namespace Neo.SmartContract.Iterators diff --git a/neo/SmartContract/Iterators/StorageIterator.cs b/neo/SmartContract/Iterators/StorageIterator.cs index 2dd604d5d8..45c9d21ebd 100644 --- a/neo/SmartContract/Iterators/StorageIterator.cs +++ b/neo/SmartContract/Iterators/StorageIterator.cs @@ -1,4 +1,4 @@ -using Neo.Ledger; +using Neo.Ledger; using Neo.VM; using System.Collections.Generic; diff --git a/neo/SmartContract/JsonSerializer.cs b/neo/SmartContract/JsonSerializer.cs index d635c6c7b8..a4853fc39a 100644 --- a/neo/SmartContract/JsonSerializer.cs +++ b/neo/SmartContract/JsonSerializer.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Neo.VM; using Neo.VM.Types; using System; diff --git a/neo/SmartContract/LogEventArgs.cs b/neo/SmartContract/LogEventArgs.cs index d124b6f9ab..8c007fe101 100644 --- a/neo/SmartContract/LogEventArgs.cs +++ b/neo/SmartContract/LogEventArgs.cs @@ -1,4 +1,4 @@ -using Neo.Network.P2P.Payloads; +using Neo.Network.P2P.Payloads; using System; namespace Neo.SmartContract diff --git a/neo/SmartContract/Manifest/ContractAbi.cs b/neo/SmartContract/Manifest/ContractAbi.cs index 033306f8e6..1d27ae4f1b 100644 --- a/neo/SmartContract/Manifest/ContractAbi.cs +++ b/neo/SmartContract/Manifest/ContractAbi.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System.Linq; namespace Neo.SmartContract.Manifest diff --git a/neo/SmartContract/Manifest/ContractEventDescriptor.cs b/neo/SmartContract/Manifest/ContractEventDescriptor.cs index b06b64f341..00748f9b09 100644 --- a/neo/SmartContract/Manifest/ContractEventDescriptor.cs +++ b/neo/SmartContract/Manifest/ContractEventDescriptor.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System.Linq; namespace Neo.SmartContract.Manifest diff --git a/neo/SmartContract/Manifest/ContractFeatures.cs b/neo/SmartContract/Manifest/ContractFeatures.cs index dd8336f695..9f94a9d3f1 100644 --- a/neo/SmartContract/Manifest/ContractFeatures.cs +++ b/neo/SmartContract/Manifest/ContractFeatures.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.SmartContract.Manifest { diff --git a/neo/SmartContract/Manifest/ContractGroup.cs b/neo/SmartContract/Manifest/ContractGroup.cs index fd73787a09..75359e782a 100644 --- a/neo/SmartContract/Manifest/ContractGroup.cs +++ b/neo/SmartContract/Manifest/ContractGroup.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.Cryptography.ECC; using Neo.IO.Json; diff --git a/neo/SmartContract/Manifest/ContractManifest.cs b/neo/SmartContract/Manifest/ContractManifest.cs index 967a10e856..ebbcd61f2c 100644 --- a/neo/SmartContract/Manifest/ContractManifest.cs +++ b/neo/SmartContract/Manifest/ContractManifest.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Json; using System.IO; using System.Linq; diff --git a/neo/SmartContract/Manifest/ContractMethodDescriptor.cs b/neo/SmartContract/Manifest/ContractMethodDescriptor.cs index c631aa0450..476ec546a6 100644 --- a/neo/SmartContract/Manifest/ContractMethodDescriptor.cs +++ b/neo/SmartContract/Manifest/ContractMethodDescriptor.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System; using System.Linq; diff --git a/neo/SmartContract/Manifest/ContractParameterDefinition.cs b/neo/SmartContract/Manifest/ContractParameterDefinition.cs index af07315a3a..3f184d6ba8 100644 --- a/neo/SmartContract/Manifest/ContractParameterDefinition.cs +++ b/neo/SmartContract/Manifest/ContractParameterDefinition.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System; namespace Neo.SmartContract.Manifest diff --git a/neo/SmartContract/Manifest/ContractPermission.cs b/neo/SmartContract/Manifest/ContractPermission.cs index b7d1d54bb9..890de9d200 100644 --- a/neo/SmartContract/Manifest/ContractPermission.cs +++ b/neo/SmartContract/Manifest/ContractPermission.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System; using System.Linq; diff --git a/neo/SmartContract/Manifest/ContractPermissionDescriptor.cs b/neo/SmartContract/Manifest/ContractPermissionDescriptor.cs index 7b64a66935..909ae27e42 100644 --- a/neo/SmartContract/Manifest/ContractPermissionDescriptor.cs +++ b/neo/SmartContract/Manifest/ContractPermissionDescriptor.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography.ECC; +using Neo.Cryptography.ECC; using Neo.IO.Json; using System; diff --git a/neo/SmartContract/Manifest/WildCardContainer.cs b/neo/SmartContract/Manifest/WildCardContainer.cs index aab6ba838e..12dbac60fe 100644 --- a/neo/SmartContract/Manifest/WildCardContainer.cs +++ b/neo/SmartContract/Manifest/WildCardContainer.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System; using System.Collections; using System.Collections.Generic; diff --git a/neo/SmartContract/Native/ContractMethodAttribute.cs b/neo/SmartContract/Native/ContractMethodAttribute.cs index 393737d92e..42b414eed6 100644 --- a/neo/SmartContract/Native/ContractMethodAttribute.cs +++ b/neo/SmartContract/Native/ContractMethodAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.SmartContract.Native { diff --git a/neo/SmartContract/Native/ContractMethodMetadata.cs b/neo/SmartContract/Native/ContractMethodMetadata.cs index f63344eec9..9267bb7db9 100644 --- a/neo/SmartContract/Native/ContractMethodMetadata.cs +++ b/neo/SmartContract/Native/ContractMethodMetadata.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; using System; using VMArray = Neo.VM.Types.Array; diff --git a/neo/SmartContract/Native/NativeContract.cs b/neo/SmartContract/Native/NativeContract.cs index 08971dcf6b..546743fc49 100644 --- a/neo/SmartContract/Native/NativeContract.cs +++ b/neo/SmartContract/Native/NativeContract.cs @@ -1,4 +1,4 @@ -#pragma warning disable IDE0060 +#pragma warning disable IDE0060 using Neo.IO; using Neo.Ledger; diff --git a/neo/SmartContract/Native/PolicyContract.cs b/neo/SmartContract/Native/PolicyContract.cs index c5820cfd15..3ffe8199e5 100644 --- a/neo/SmartContract/Native/PolicyContract.cs +++ b/neo/SmartContract/Native/PolicyContract.cs @@ -1,4 +1,4 @@ -#pragma warning disable IDE0051 +#pragma warning disable IDE0051 #pragma warning disable IDE0060 using Neo.IO; diff --git a/neo/SmartContract/Native/Tokens/GasToken.cs b/neo/SmartContract/Native/Tokens/GasToken.cs index fd39979670..7ef522dab7 100644 --- a/neo/SmartContract/Native/Tokens/GasToken.cs +++ b/neo/SmartContract/Native/Tokens/GasToken.cs @@ -1,4 +1,4 @@ -#pragma warning disable IDE0051 +#pragma warning disable IDE0051 using Neo.Cryptography.ECC; using Neo.Ledger; diff --git a/neo/SmartContract/Native/Tokens/Nep5AccountState.cs b/neo/SmartContract/Native/Tokens/Nep5AccountState.cs index c775f044ec..aa62cf4bec 100644 --- a/neo/SmartContract/Native/Tokens/Nep5AccountState.cs +++ b/neo/SmartContract/Native/Tokens/Nep5AccountState.cs @@ -1,4 +1,4 @@ -using Neo.VM; +using Neo.VM; using Neo.VM.Types; using System.Numerics; diff --git a/neo/SmartContract/Native/Tokens/Nep5Token.cs b/neo/SmartContract/Native/Tokens/Nep5Token.cs index 6a2e1c78b3..a95885a665 100644 --- a/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -1,4 +1,4 @@ -#pragma warning disable IDE0060 +#pragma warning disable IDE0060 using Neo.Ledger; using Neo.Persistence; diff --git a/neo/SmartContract/NefFile.cs b/neo/SmartContract/NefFile.cs index 52507eda08..e0068b7213 100644 --- a/neo/SmartContract/NefFile.cs +++ b/neo/SmartContract/NefFile.cs @@ -1,129 +1,129 @@ -using Neo.Cryptography; -using Neo.IO; -using System; -using System.IO; - -namespace Neo.SmartContract -{ - /// - /// +------------+-----------+------------------------------------------------------------+ - /// | Field | Length | Comment | - /// +------------+-----------+------------------------------------------------------------+ - /// | Magic | 4 bytes | Magic header | - /// | Compiler | 32 bytes | Compiler used | - /// | Version | 16 bytes | Compiler version (Mayor, Minor, Build, Version) | - /// | ScriptHash | 20 bytes | ScriptHash for the script | - /// +------------+-----------+------------------------------------------------------------+ - /// | Checksum | 4 bytes | Sha256 of the header (CRC) | - /// +------------+-----------+------------------------------------------------------------+ - /// | Script | Var bytes | Var bytes for the payload | - /// +------------+-----------+------------------------------------------------------------+ - /// - public class NefFile : ISerializable - { - /// - /// NEO Executable Format 3 (NEF3) - /// - private const uint Magic = 0x3346454E; - - /// - /// Compiler - /// - public string Compiler { get; set; } - - /// - /// Version - /// - public Version Version { get; set; } - - /// - /// Script Hash - /// - public UInt160 ScriptHash { get; set; } - - /// - /// Checksum - /// - public uint CheckSum { get; set; } - - /// - /// Script - /// - public byte[] Script { get; set; } - - private const int HeaderSize = - sizeof(uint) + // Magic - 32 + // Compiler - (sizeof(int) * 4) + // Version - UInt160.Length + // ScriptHash - sizeof(uint); // Checksum - - public int Size => - HeaderSize + // Header - Script.GetVarSize(); // Script - - public void Serialize(BinaryWriter writer) - { - writer.Write(Magic); - writer.WriteFixedString(Compiler, 32); - - // Version - writer.Write(Version.Major); - writer.Write(Version.Minor); - writer.Write(Version.Build); - writer.Write(Version.Revision); - - writer.Write(ScriptHash); - writer.Write(CheckSum); - writer.WriteVarBytes(Script ?? new byte[0]); - } - - public void Deserialize(BinaryReader reader) - { - if (reader.ReadUInt32() != Magic) - { - throw new FormatException("Wrong magic"); - } - - Compiler = reader.ReadFixedString(32); - Version = new Version(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32()); - ScriptHash = reader.ReadSerializable(); - CheckSum = reader.ReadUInt32(); - - if (CheckSum != ComputeChecksum(this)) - { - throw new FormatException("CRC verification fail"); - } - - Script = reader.ReadVarBytes(1024 * 1024); - - if (Script.ToScriptHash() != ScriptHash) - { - throw new FormatException("ScriptHash is different"); - } - } - - /// - /// Compute checksum for a file - /// - /// File - /// Return checksum - public static uint ComputeChecksum(NefFile file) - { - using (var ms = new MemoryStream()) - using (var wr = new BinaryWriter(ms)) - { - file.Serialize(wr); - wr.Flush(); - - // Read header without CRC - - var buffer = new byte[HeaderSize - sizeof(uint)]; - ms.Seek(0, SeekOrigin.Begin); - ms.Read(buffer, 0, buffer.Length); - - return BitConverter.ToUInt32(buffer.Sha256(), 0); - } - } - } -} +using Neo.Cryptography; +using Neo.IO; +using System; +using System.IO; + +namespace Neo.SmartContract +{ + /// + /// +------------+-----------+------------------------------------------------------------+ + /// | Field | Length | Comment | + /// +------------+-----------+------------------------------------------------------------+ + /// | Magic | 4 bytes | Magic header | + /// | Compiler | 32 bytes | Compiler used | + /// | Version | 16 bytes | Compiler version (Mayor, Minor, Build, Version) | + /// | ScriptHash | 20 bytes | ScriptHash for the script | + /// +------------+-----------+------------------------------------------------------------+ + /// | Checksum | 4 bytes | Sha256 of the header (CRC) | + /// +------------+-----------+------------------------------------------------------------+ + /// | Script | Var bytes | Var bytes for the payload | + /// +------------+-----------+------------------------------------------------------------+ + /// + public class NefFile : ISerializable + { + /// + /// NEO Executable Format 3 (NEF3) + /// + private const uint Magic = 0x3346454E; + + /// + /// Compiler + /// + public string Compiler { get; set; } + + /// + /// Version + /// + public Version Version { get; set; } + + /// + /// Script Hash + /// + public UInt160 ScriptHash { get; set; } + + /// + /// Checksum + /// + public uint CheckSum { get; set; } + + /// + /// Script + /// + public byte[] Script { get; set; } + + private const int HeaderSize = + sizeof(uint) + // Magic + 32 + // Compiler + (sizeof(int) * 4) + // Version + UInt160.Length + // ScriptHash + sizeof(uint); // Checksum + + public int Size => + HeaderSize + // Header + Script.GetVarSize(); // Script + + public void Serialize(BinaryWriter writer) + { + writer.Write(Magic); + writer.WriteFixedString(Compiler, 32); + + // Version + writer.Write(Version.Major); + writer.Write(Version.Minor); + writer.Write(Version.Build); + writer.Write(Version.Revision); + + writer.Write(ScriptHash); + writer.Write(CheckSum); + writer.WriteVarBytes(Script ?? new byte[0]); + } + + public void Deserialize(BinaryReader reader) + { + if (reader.ReadUInt32() != Magic) + { + throw new FormatException("Wrong magic"); + } + + Compiler = reader.ReadFixedString(32); + Version = new Version(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32()); + ScriptHash = reader.ReadSerializable(); + CheckSum = reader.ReadUInt32(); + + if (CheckSum != ComputeChecksum(this)) + { + throw new FormatException("CRC verification fail"); + } + + Script = reader.ReadVarBytes(1024 * 1024); + + if (Script.ToScriptHash() != ScriptHash) + { + throw new FormatException("ScriptHash is different"); + } + } + + /// + /// Compute checksum for a file + /// + /// File + /// Return checksum + public static uint ComputeChecksum(NefFile file) + { + using (var ms = new MemoryStream()) + using (var wr = new BinaryWriter(ms)) + { + file.Serialize(wr); + wr.Flush(); + + // Read header without CRC + + var buffer = new byte[HeaderSize - sizeof(uint)]; + ms.Seek(0, SeekOrigin.Begin); + ms.Read(buffer, 0, buffer.Length); + + return BitConverter.ToUInt32(buffer.Sha256(), 0); + } + } + } +} diff --git a/neo/SmartContract/NotifyEventArgs.cs b/neo/SmartContract/NotifyEventArgs.cs index f4e4e169b8..8fab961408 100644 --- a/neo/SmartContract/NotifyEventArgs.cs +++ b/neo/SmartContract/NotifyEventArgs.cs @@ -1,4 +1,4 @@ -using Neo.Network.P2P.Payloads; +using Neo.Network.P2P.Payloads; using Neo.VM; using System; diff --git a/neo/SmartContract/StackItemType.cs b/neo/SmartContract/StackItemType.cs index 94ee4f23ba..b47999e157 100644 --- a/neo/SmartContract/StackItemType.cs +++ b/neo/SmartContract/StackItemType.cs @@ -1,4 +1,4 @@ -namespace Neo.SmartContract +namespace Neo.SmartContract { internal enum StackItemType : byte { diff --git a/neo/SmartContract/StorageContext.cs b/neo/SmartContract/StorageContext.cs index 1c3336c9ac..abea2e343d 100644 --- a/neo/SmartContract/StorageContext.cs +++ b/neo/SmartContract/StorageContext.cs @@ -1,4 +1,4 @@ -namespace Neo.SmartContract +namespace Neo.SmartContract { internal class StorageContext { diff --git a/neo/SmartContract/WitnessWrapper.cs b/neo/SmartContract/WitnessWrapper.cs index f67690cad5..28019be0c2 100644 --- a/neo/SmartContract/WitnessWrapper.cs +++ b/neo/SmartContract/WitnessWrapper.cs @@ -1,4 +1,4 @@ -using Neo.Network.P2P.Payloads; +using Neo.Network.P2P.Payloads; using Neo.Persistence; using System.Linq; diff --git a/neo/UInt160.cs b/neo/UInt160.cs index 0c6bea4b5a..0052d45569 100644 --- a/neo/UInt160.cs +++ b/neo/UInt160.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using System.Linq; diff --git a/neo/UInt256.cs b/neo/UInt256.cs index ec79ae21ea..72719f0e90 100644 --- a/neo/UInt256.cs +++ b/neo/UInt256.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using System.Linq; diff --git a/neo/UIntBase.cs b/neo/UIntBase.cs index 22431c4cae..af26e36d0a 100644 --- a/neo/UIntBase.cs +++ b/neo/UIntBase.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using System; using System.IO; using System.Linq; diff --git a/neo/VM/Helper.cs b/neo/VM/Helper.cs index 6a7a37d7d5..e996463e3f 100644 --- a/neo/VM/Helper.cs +++ b/neo/VM/Helper.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography.ECC; +using Neo.Cryptography.ECC; using Neo.IO; using Neo.SmartContract; using Neo.VM.Types; diff --git a/neo/Wallets/AssetDescriptor.cs b/neo/Wallets/AssetDescriptor.cs index 49144834bb..dca0b10b25 100644 --- a/neo/Wallets/AssetDescriptor.cs +++ b/neo/Wallets/AssetDescriptor.cs @@ -1,4 +1,4 @@ -using Neo.SmartContract; +using Neo.SmartContract; using Neo.VM; using System; diff --git a/neo/Wallets/Helper.cs b/neo/Wallets/Helper.cs index 4b26982db1..5960876fe2 100644 --- a/neo/Wallets/Helper.cs +++ b/neo/Wallets/Helper.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; using System; diff --git a/neo/Wallets/KeyPair.cs b/neo/Wallets/KeyPair.cs index 0125d10f99..afea8e822a 100644 --- a/neo/Wallets/KeyPair.cs +++ b/neo/Wallets/KeyPair.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.SmartContract; using System; using System.Linq; diff --git a/neo/Wallets/NEP6/NEP6Account.cs b/neo/Wallets/NEP6/NEP6Account.cs index ddeace2523..990612d542 100644 --- a/neo/Wallets/NEP6/NEP6Account.cs +++ b/neo/Wallets/NEP6/NEP6Account.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using System; namespace Neo.Wallets.NEP6 diff --git a/neo/Wallets/NEP6/NEP6Contract.cs b/neo/Wallets/NEP6/NEP6Contract.cs index a3dd36f414..45f0b5e157 100644 --- a/neo/Wallets/NEP6/NEP6Contract.cs +++ b/neo/Wallets/NEP6/NEP6Contract.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Neo.SmartContract; using System.Linq; diff --git a/neo/Wallets/NEP6/NEP6Wallet.cs b/neo/Wallets/NEP6/NEP6Wallet.cs index 9f0d0a1315..f76640e886 100644 --- a/neo/Wallets/NEP6/NEP6Wallet.cs +++ b/neo/Wallets/NEP6/NEP6Wallet.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; using Neo.SmartContract; using System; using System.Collections.Generic; diff --git a/neo/Wallets/NEP6/ScryptParameters.cs b/neo/Wallets/NEP6/ScryptParameters.cs index 018f0bfd46..a987159ad6 100644 --- a/neo/Wallets/NEP6/ScryptParameters.cs +++ b/neo/Wallets/NEP6/ScryptParameters.cs @@ -1,4 +1,4 @@ -using Neo.IO.Json; +using Neo.IO.Json; namespace Neo.Wallets.NEP6 { diff --git a/neo/Wallets/NEP6/WalletLocker.cs b/neo/Wallets/NEP6/WalletLocker.cs index 6f28779361..45574b5cfe 100644 --- a/neo/Wallets/NEP6/WalletLocker.cs +++ b/neo/Wallets/NEP6/WalletLocker.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Neo.Wallets.NEP6 { diff --git a/neo/Wallets/SQLite/Account.cs b/neo/Wallets/SQLite/Account.cs index 5c91556fb2..ce8ed1e01e 100644 --- a/neo/Wallets/SQLite/Account.cs +++ b/neo/Wallets/SQLite/Account.cs @@ -1,4 +1,4 @@ -namespace Neo.Wallets.SQLite +namespace Neo.Wallets.SQLite { internal class Account { diff --git a/neo/Wallets/SQLite/Address.cs b/neo/Wallets/SQLite/Address.cs index 79ef9e1031..a5abe4dcfc 100644 --- a/neo/Wallets/SQLite/Address.cs +++ b/neo/Wallets/SQLite/Address.cs @@ -1,4 +1,4 @@ -namespace Neo.Wallets.SQLite +namespace Neo.Wallets.SQLite { internal class Address { diff --git a/neo/Wallets/SQLite/Contract.cs b/neo/Wallets/SQLite/Contract.cs index a69c0f0968..96ba3c51a6 100644 --- a/neo/Wallets/SQLite/Contract.cs +++ b/neo/Wallets/SQLite/Contract.cs @@ -1,4 +1,4 @@ -namespace Neo.Wallets.SQLite +namespace Neo.Wallets.SQLite { internal class Contract { diff --git a/neo/Wallets/SQLite/Key.cs b/neo/Wallets/SQLite/Key.cs index 97c063a3f2..f493b7310d 100644 --- a/neo/Wallets/SQLite/Key.cs +++ b/neo/Wallets/SQLite/Key.cs @@ -1,4 +1,4 @@ -namespace Neo.Wallets.SQLite +namespace Neo.Wallets.SQLite { internal class Key { diff --git a/neo/Wallets/SQLite/UserWallet.cs b/neo/Wallets/SQLite/UserWallet.cs index df4cccfe08..efb477a61a 100644 --- a/neo/Wallets/SQLite/UserWallet.cs +++ b/neo/Wallets/SQLite/UserWallet.cs @@ -1,4 +1,4 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Neo.Cryptography; using Neo.IO; using Neo.SmartContract; diff --git a/neo/Wallets/SQLite/UserWalletAccount.cs b/neo/Wallets/SQLite/UserWalletAccount.cs index 2d3ac74836..d586f59d36 100644 --- a/neo/Wallets/SQLite/UserWalletAccount.cs +++ b/neo/Wallets/SQLite/UserWalletAccount.cs @@ -1,4 +1,4 @@ -namespace Neo.Wallets.SQLite +namespace Neo.Wallets.SQLite { internal class UserWalletAccount : WalletAccount { diff --git a/neo/Wallets/SQLite/VerificationContract.cs b/neo/Wallets/SQLite/VerificationContract.cs index 41f8d44055..587a0fe468 100644 --- a/neo/Wallets/SQLite/VerificationContract.cs +++ b/neo/Wallets/SQLite/VerificationContract.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.SmartContract; using Neo.VM; using System; diff --git a/neo/Wallets/SQLite/WalletDataContext.cs b/neo/Wallets/SQLite/WalletDataContext.cs index cba60cb00d..6d1ec957a8 100644 --- a/neo/Wallets/SQLite/WalletDataContext.cs +++ b/neo/Wallets/SQLite/WalletDataContext.cs @@ -1,4 +1,4 @@ -using Microsoft.Data.Sqlite; +using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; namespace Neo.Wallets.SQLite diff --git a/neo/Wallets/TransferOutput.cs b/neo/Wallets/TransferOutput.cs index 6e45baa04b..9431f5616d 100644 --- a/neo/Wallets/TransferOutput.cs +++ b/neo/Wallets/TransferOutput.cs @@ -1,4 +1,4 @@ -namespace Neo.Wallets +namespace Neo.Wallets { public class TransferOutput { diff --git a/neo/Wallets/Wallet.cs b/neo/Wallets/Wallet.cs index d22c8ff128..eb816c7a0a 100644 --- a/neo/Wallets/Wallet.cs +++ b/neo/Wallets/Wallet.cs @@ -1,4 +1,4 @@ -using Neo.Cryptography; +using Neo.Cryptography; using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; diff --git a/neo/Wallets/WalletAccount.cs b/neo/Wallets/WalletAccount.cs index a427a9e50b..5e2408a1d0 100644 --- a/neo/Wallets/WalletAccount.cs +++ b/neo/Wallets/WalletAccount.cs @@ -1,4 +1,4 @@ -using Neo.SmartContract; +using Neo.SmartContract; namespace Neo.Wallets { diff --git a/neo/neo.csproj b/neo/neo.csproj index 66e85016bc..54ba724da9 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -1,4 +1,4 @@ - + 2015-2019 The Neo Project From 98173cf14a29072d6219274a3df691b7c856dae1 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 25 Aug 2019 11:40:46 +0200 Subject: [PATCH 37/54] Fix consensus problem for proposed blocks with zero transactions (#1053) * Fix consensus (CRLF) * Removing unnecessary lines changes - Cleaning PR * Reverting all changes on CC * Modifying ConsensusContext with proposed changes --- neo/Consensus/ConsensusContext.cs | 5 +---- neo/Consensus/ConsensusService.cs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs index fbb21d8cd7..4574d70f7e 100644 --- a/neo/Consensus/ConsensusContext.cs +++ b/neo/Consensus/ConsensusContext.cs @@ -254,14 +254,11 @@ internal void EnsureMaxBlockSize(IEnumerable txs) txs = txs.Take((int)maxTransactionsPerBlock); List hashes = new List(); Transactions = new Dictionary(); - Block.Transactions = new Transaction[0]; - - // We need to know the expected block size + // Expected block size var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Count()); // Iterate transaction until reach the size - foreach (Transaction tx in txs) { // Check if maximum block size has been already exceeded with the current selected set diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index cac657c95f..4d8b70a333 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -74,6 +74,11 @@ private bool AddTransaction(Transaction tx, bool verify) return false; } context.Transactions[tx.Hash] = tx; + return CheckPrepareResponse(); + } + + private bool CheckPrepareResponse() + { if (context.TransactionHashes.Length == context.Transactions.Count) { // if we are the primary for this view, but acting as a backup because we recovered our own @@ -428,6 +433,14 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m if (context.CommitPayloads[i]?.ConsensusMessage.ViewNumber == context.ViewNumber) if (!Crypto.Default.VerifySignature(hashData, context.CommitPayloads[i].GetDeserializedMessage().Signature, context.Validators[i].EncodePoint(false))) context.CommitPayloads[i] = null; + + if (context.TransactionHashes.Length == 0) + { + // There are no tx so we should act like if all the transactions were filled + CheckPrepareResponse(); + return; + } + Dictionary mempoolVerified = Blockchain.Singleton.MemPool.GetVerifiedTransactions().ToDictionary(p => p.Hash); List unverified = new List(); foreach (UInt256 hash in context.TransactionHashes) From 25666baa1720997f708cc8ce2ac28d95f20446a3 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 26 Aug 2019 22:12:34 +0200 Subject: [PATCH 38/54] Small OnPersist optimization (#1058) * Small update * Cache native persist script --- neo/Ledger/Blockchain.cs | 24 +++++++++++++----------- neo/Ledger/HashIndexState.cs | 7 +++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index db879c0732..a74bfa981c 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -53,6 +53,7 @@ public class FillCompleted { } Transactions = new[] { DeployNativeContracts() } }; + private readonly static byte[] onPersistNativeContractScript; private const int MaxTxToReverifyPerIdle = 10; private static readonly object lockObj = new object(); private readonly NeoSystem system; @@ -83,6 +84,15 @@ public static Blockchain Singleton static Blockchain() { GenesisBlock.RebuildMerkleRoot(); + + NativeContract[] contracts = { NativeContract.GAS, NativeContract.NEO }; + using (ScriptBuilder sb = new ScriptBuilder()) + { + foreach (NativeContract contract in contracts) + sb.EmitAppCall(contract.Hash, "onPersist"); + + onPersistNativeContractScript = sb.ToArray(); + } } public Blockchain(NeoSystem system, Store store) @@ -416,15 +426,9 @@ private void Persist(Block block) snapshot.PersistingBlock = block; if (block.Index > 0) { - NativeContract[] contracts = { NativeContract.GAS, NativeContract.NEO }; using (ApplicationEngine engine = new ApplicationEngine(TriggerType.System, null, snapshot, 0, true)) { - using (ScriptBuilder sb = new ScriptBuilder()) - { - foreach (NativeContract contract in contracts) - sb.EmitAppCall(contract.Hash, "onPersist"); - engine.LoadScript(sb.ToArray()); - } + engine.LoadScript(onPersistNativeContractScript); if (engine.Execute() != VMState.HALT) throw new InvalidOperationException(); ApplicationExecuted application_executed = new ApplicationExecuted(engine); Context.System.EventStream.Publish(application_executed); @@ -455,13 +459,11 @@ private void Persist(Block block) all_application_executed.Add(application_executed); } } - snapshot.BlockHashIndex.GetAndChange().Hash = block.Hash; - snapshot.BlockHashIndex.GetAndChange().Index = block.Index; + snapshot.BlockHashIndex.GetAndChange().Set(block); if (block.Index == header_index.Count) { header_index.Add(block.Hash); - snapshot.HeaderHashIndex.GetAndChange().Hash = block.Hash; - snapshot.HeaderHashIndex.GetAndChange().Index = block.Index; + snapshot.HeaderHashIndex.GetAndChange().Set(block); } foreach (IPersistencePlugin plugin in Plugin.PersistencePlugins) plugin.OnPersist(snapshot, all_application_executed); diff --git a/neo/Ledger/HashIndexState.cs b/neo/Ledger/HashIndexState.cs index 04f7b0bd4a..fb7439a252 100644 --- a/neo/Ledger/HashIndexState.cs +++ b/neo/Ledger/HashIndexState.cs @@ -1,4 +1,5 @@ using Neo.IO; +using Neo.Network.P2P.Payloads; using System.IO; namespace Neo.Ledger @@ -36,5 +37,11 @@ void ISerializable.Serialize(BinaryWriter writer) writer.Write(Hash); writer.Write(Index); } + + internal void Set(BlockBase block) + { + Hash = block.Hash; + Index = block.Index; + } } } From 5995f327c42b2dce17e270c9fc6ba5a5be1251d5 Mon Sep 17 00:00:00 2001 From: Igor Machado Coelho Date: Tue, 27 Aug 2019 14:47:55 +0800 Subject: [PATCH 39/54] fix crlf on neo.UnitTests and set all files to not use BOM (byte order mark) (#1057) * Check dotnet format in travis * Try to find the path * Update .travis.yml * Update .travis.yml * Update .travis.yml * Format travis * test and source * test and source * Move to before the script * testing if CRLF format is respected * fix crlf on unit tests * testing for crlf on unit tests too * all utf-8 * neo/ on utf8 too * looks like sudo is needed by travis * download dos2unix 7.4.0 * temporaly remove | test * back to | test * explicit test zero * no bom * more non-boom to boom * ensuring no_bom at all files * Printing files with bom prefix * Check both folders in one command * Add verbosity * Create .editorconfig * Ensure the path of .editorconfig file * Update .editorconfig * Update .editorconfig * Update .editorconfig * use only dotnet-format Is confirmed that .editorconfig works, so we should configure only this file * basic formatting (just 5 files affected) * dotnet version * new lines on end * update travis * advice on auto crlf * Update .travis.yml * Update .travis.yml * enforcing lf * Fix dotnet format version * removed dos2unix --- .editorconfig | 18 ++ .travis.yml | 16 +- NuGet.Config | 2 +- .../Consensus/UT_ConsensusContext.cs | 306 +++++++++--------- .../Consensus/UT_ConsensusServiceMailbox.cs | 2 +- neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs | 4 +- .../Cryptography/ECC/UT_ECFieldElement.cs | 2 +- neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs | 4 +- neo.UnitTests/Cryptography/UT_Base58.cs | 4 +- neo.UnitTests/Cryptography/UT_BloomFilter.cs | 4 +- neo.UnitTests/Cryptography/UT_Crypto.cs | 4 +- .../Cryptography/UT_Cryptography_Helper.cs | 4 +- neo.UnitTests/Cryptography/UT_MerkleTree.cs | 4 +- .../Cryptography/UT_MerkleTreeNode.cs | 4 +- neo.UnitTests/Cryptography/UT_Murmur3.cs | 4 +- neo.UnitTests/Cryptography/UT_SCrypt.cs | 4 +- .../Extensions/NativeContractExtensions.cs | 4 +- .../Nep5NativeContractExtensions.cs | 8 +- neo.UnitTests/IO/Caching/UT_Cache.cs | 2 +- neo.UnitTests/IO/Caching/UT_CloneCache.cs | 4 +- neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs | 4 +- neo.UnitTests/IO/Caching/UT_DataCache.cs | 4 +- neo.UnitTests/IO/Caching/UT_FIFOSet.cs | 4 +- neo.UnitTests/IO/Caching/UT_MetaDataCache.cs | 4 +- .../IO/Caching/UT_OrderedDictionary.cs | 4 +- .../IO/Caching/UT_ReflectionCache.cs | 4 +- neo.UnitTests/IO/Caching/UT_RelayCache.cs | 4 +- neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs | 2 +- neo.UnitTests/IO/Json/UT_JArray.cs | 4 +- neo.UnitTests/IO/Json/UT_JBoolean.cs | 4 +- neo.UnitTests/IO/Json/UT_JNumber.cs | 4 +- neo.UnitTests/IO/Json/UT_JObject.cs | 4 +- neo.UnitTests/IO/Json/UT_JString.cs | 4 +- neo.UnitTests/IO/UT_IOHelper.cs | 2 +- .../IO/Wrappers/UT_SerializableWrapper.cs | 4 +- neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs | 4 +- neo.UnitTests/Ledger/UT_MemoryPool.cs | 2 +- neo.UnitTests/Ledger/UT_PoolItem.cs | 2 +- neo.UnitTests/Ledger/UT_StorageKey.cs | 2 +- .../Network/P2P/Payloads/UT_Cosigner.cs | 2 +- .../Network/P2P/Payloads/UT_Header.cs | 2 +- .../Network/P2P/Payloads/UT_Transaction.cs | 2 +- .../Network/P2P/Payloads/UT_Witness.cs | 2 +- neo.UnitTests/Network/P2P/UT_Message.cs | 2 +- .../Network/P2P/UT_ProtocolHandler.cs | 2 +- .../Network/P2P/UT_ProtocolHandlerMailbox.cs | 2 +- neo.UnitTests/Network/P2P/UT_RemoteNode.cs | 2 +- .../Network/P2P/UT_RemoteNodeMailbox.cs | 2 +- .../Network/P2P/UT_TaskManagerMailbox.cs | 2 +- neo.UnitTests/Network/RPC/UT_RpcClient.cs | 2 +- .../Iterators/UT_ConcatenatedIterator.cs | 2 +- .../Manifest/UT_ContractManifest.cs | 2 +- .../Native/Tokens/UT_GasToken.cs | 4 +- .../Native/Tokens/UT_NeoToken.cs | 2 +- .../SmartContract/Native/UT_PolicyContract.cs | 2 +- .../SmartContract/UT_InteropService.cs | 2 +- .../SmartContract/UT_JsonSerializer.cs | 2 +- .../SmartContract/UT_OpCodePrices.cs | 2 +- neo.UnitTests/SmartContract/UT_Syscalls.cs | 4 +- neo.UnitTests/TestBlockchain.cs | 4 +- neo.UnitTests/TestDataCache.cs | 2 +- neo.UnitTests/TestMetaDataCache.cs | 2 +- neo.UnitTests/TestUtils.cs | 4 +- neo.UnitTests/TestVerifiable.cs | 2 +- neo.UnitTests/TestWalletAccount.cs | 2 +- neo.UnitTests/UT_BigDecimal.cs | 4 +- neo.UnitTests/UT_Culture.cs | 2 +- neo.UnitTests/UT_DataCache.cs | 2 +- neo.UnitTests/UT_Helper.cs | 2 +- neo.UnitTests/UT_NefFile.cs | 150 ++++----- neo.UnitTests/UT_ProtocolSettings.cs | 4 +- neo.UnitTests/VM/UT_Helper.cs | 4 +- neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs | 2 +- neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs | 2 +- neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs | 2 +- .../Wallets/NEP6/UT_ScryptParameters.cs | 2 +- neo.UnitTests/Wallets/SQLite/UT_Account.cs | 4 +- neo.UnitTests/Wallets/SQLite/UT_Address.cs | 4 +- neo.UnitTests/Wallets/SQLite/UT_Contract.cs | 4 +- neo.UnitTests/Wallets/SQLite/UT_Key.cs | 4 +- neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs | 2 +- .../Wallets/SQLite/UT_UserWalletAccount.cs | 2 +- .../Wallets/SQLite/UT_VerificationContract.cs | 2 +- neo.UnitTests/Wallets/UT_AssetDescriptor.cs | 4 +- neo.UnitTests/Wallets/UT_KeyPair.cs | 2 +- neo.UnitTests/Wallets/UT_Wallet.cs | 4 +- neo.UnitTests/Wallets/UT_WalletAccount.cs | 2 +- neo.UnitTests/Wallets/UT_Wallets_Helper.cs | 2 +- neo.UnitTests/neo.UnitTests.csproj | 2 +- neo.sln | 2 +- neo/Consensus/ChangeViewReason.cs | 2 +- neo/IO/Caching/ReflectionCache.cs | 2 +- neo/IO/Caching/ReflectionCacheAttribute.cs | 2 +- neo/Plugins/MemoryPoolTxRemovalReason.cs | 2 +- neo/SmartContract/ExecutionContextState.cs | 2 +- 95 files changed, 390 insertions(+), 366 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..2cbe224983 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +############################### +# Core EditorConfig Options # +############################### + +# dotnet-format requires version 3.1.37601 +# dotnet tool update -g dotnet-format +# remember to have: git config --global core.autocrlf false #(which is usually default) + +root = true + +# Every file + +[*] +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 +end_of_line = lf +#indent_style = tab # TODO diff --git a/.travis.yml b/.travis.yml index aaf9dd660d..f08f8110bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,18 +11,24 @@ mono: none dotnet: 2.2.300 env: -- TEST_SUITE="without-cultures" -- TEST_SUITE="cultures" + - TEST_SUITE="without-cultures" + - TEST_SUITE="cultures" before_install: - - cd neo.UnitTests - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ulimit -n 2048; fi +install: + - dotnet tool install -g dotnet-format --version 4.0.40103 --add-source https://dotnet.myget.org/F/format/api/v3/index.json + - export PATH="$PATH:$HOME/.dotnet/tools" + - dotnet-format --version +before_script: + - echo "Checking format..." + - dotnet format --check --dry-run -w . -v diagnostic # check C# formatting for neo.sln + - cd neo.UnitTests script: | + dotnet restore if [[ "$TEST_SUITE" == cultures ]]; then - dotnet restore dotnet test else - dotnet restore find * -name *.csproj | xargs -I % dotnet add % package coverlet.msbuild dotnet test -v n --filter FullyQualifiedName!=Neo.UnitTests.UT_Culture.All_Tests_Cultures /p:CollectCoverage=true /p:CoverletOutputFormat=opencover fi diff --git a/NuGet.Config b/NuGet.Config index 640fd0fe31..c06788942f 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -1,4 +1,4 @@ - + diff --git a/neo.UnitTests/Consensus/UT_ConsensusContext.cs b/neo.UnitTests/Consensus/UT_ConsensusContext.cs index 696d6aaa0a..9a0dd39ba7 100644 --- a/neo.UnitTests/Consensus/UT_ConsensusContext.cs +++ b/neo.UnitTests/Consensus/UT_ConsensusContext.cs @@ -1,134 +1,134 @@ -using Akka.TestKit.Xunit2; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using Neo.Consensus; -using Neo.IO; -using Neo.Network.P2P.Payloads; -using Neo.SmartContract; -using Neo.SmartContract.Native; -using Neo.Wallets; -using System; -using System.Linq; - -namespace Neo.UnitTests.Consensus -{ - - [TestClass] - public class UT_ConsensusContext : TestKit - { - ConsensusContext _context; - KeyPair[] _validatorKeys; - - [TestInitialize] - public void TestSetup() - { - TestBlockchain.InitializeMockNeoSystem(); - - var rand = new Random(); - var mockWallet = new Mock(); - mockWallet.Setup(p => p.GetAccount(It.IsAny())).Returns(p => new TestWalletAccount(p)); - - // Create dummy validators - - _validatorKeys = new KeyPair[7]; - for (int x = 0; x < _validatorKeys.Length; x++) - { - var pk = new byte[32]; - rand.NextBytes(pk); - - _validatorKeys[x] = new KeyPair(pk); - } - - _context = new ConsensusContext(mockWallet.Object, TestBlockchain.GetStore()) - { - Validators = _validatorKeys.Select(u => u.PublicKey).ToArray() - }; - _context.Reset(0); - } - - [TestCleanup] - public void Cleanup() - { - Shutdown(); - } - - [TestMethod] - public void TestMaxBlockSize_Good() - { - // Only one tx, is included - - var tx1 = CreateTransactionWithSize(200); - _context.EnsureMaxBlockSize(new Transaction[] { tx1 }); - EnsureContext(_context, tx1); - - // All txs included - - var max = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(_context.Snapshot); - var txs = new Transaction[max]; - - for (int x = 0; x < max; x++) txs[x] = CreateTransactionWithSize(100); - - _context.EnsureMaxBlockSize(txs); - EnsureContext(_context, txs); - } - - [TestMethod] - public void TestMaxBlockSize_Exceed() - { - // Two tx, the last one exceed the size rule, only the first will be included - - var tx1 = CreateTransactionWithSize(200); - var tx2 = CreateTransactionWithSize(256 * 1024); - _context.EnsureMaxBlockSize(new Transaction[] { tx1, tx2 }); - EnsureContext(_context, tx1); - - // Exceed txs number, just MaxTransactionsPerBlock included - - var max = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(_context.Snapshot); - var txs = new Transaction[max + 1]; - - for (int x = 0; x < max; x++) txs[x] = CreateTransactionWithSize(100); - - _context.EnsureMaxBlockSize(txs); - EnsureContext(_context, txs.Take(max).ToArray()); - } - - private Transaction CreateTransactionWithSize(int v) - { - var r = new Random(); - var tx = new Transaction() - { - Cosigners = new Cosigner[0], - Attributes = new TransactionAttribute[0], - NetworkFee = 0, - Nonce = (uint)Environment.TickCount, - Script = new byte[0], - Sender = UInt160.Zero, - SystemFee = 0, - ValidUntilBlock = (uint)r.Next(), - Version = 0, - Witnesses = new Witness[0], - }; - - // Could be higher (few bytes) if varSize grows - tx.Script = new byte[v - tx.Size]; - return tx; - } - - private Block SignBlock(ConsensusContext context) - { - context.Block.MerkleRoot = null; - - for (int x = 0; x < _validatorKeys.Length; x++) - { - _context.MyIndex = x; - - var com = _context.MakeCommit(); - _context.CommitPayloads[_context.MyIndex] = com; - } - - // Manual block sign - +using Akka.TestKit.Xunit2; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Neo.Consensus; +using Neo.IO; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.Wallets; +using System; +using System.Linq; + +namespace Neo.UnitTests.Consensus +{ + + [TestClass] + public class UT_ConsensusContext : TestKit + { + ConsensusContext _context; + KeyPair[] _validatorKeys; + + [TestInitialize] + public void TestSetup() + { + TestBlockchain.InitializeMockNeoSystem(); + + var rand = new Random(); + var mockWallet = new Mock(); + mockWallet.Setup(p => p.GetAccount(It.IsAny())).Returns(p => new TestWalletAccount(p)); + + // Create dummy validators + + _validatorKeys = new KeyPair[7]; + for (int x = 0; x < _validatorKeys.Length; x++) + { + var pk = new byte[32]; + rand.NextBytes(pk); + + _validatorKeys[x] = new KeyPair(pk); + } + + _context = new ConsensusContext(mockWallet.Object, TestBlockchain.GetStore()) + { + Validators = _validatorKeys.Select(u => u.PublicKey).ToArray() + }; + _context.Reset(0); + } + + [TestCleanup] + public void Cleanup() + { + Shutdown(); + } + + [TestMethod] + public void TestMaxBlockSize_Good() + { + // Only one tx, is included + + var tx1 = CreateTransactionWithSize(200); + _context.EnsureMaxBlockSize(new Transaction[] { tx1 }); + EnsureContext(_context, tx1); + + // All txs included + + var max = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(_context.Snapshot); + var txs = new Transaction[max]; + + for (int x = 0; x < max; x++) txs[x] = CreateTransactionWithSize(100); + + _context.EnsureMaxBlockSize(txs); + EnsureContext(_context, txs); + } + + [TestMethod] + public void TestMaxBlockSize_Exceed() + { + // Two tx, the last one exceed the size rule, only the first will be included + + var tx1 = CreateTransactionWithSize(200); + var tx2 = CreateTransactionWithSize(256 * 1024); + _context.EnsureMaxBlockSize(new Transaction[] { tx1, tx2 }); + EnsureContext(_context, tx1); + + // Exceed txs number, just MaxTransactionsPerBlock included + + var max = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(_context.Snapshot); + var txs = new Transaction[max + 1]; + + for (int x = 0; x < max; x++) txs[x] = CreateTransactionWithSize(100); + + _context.EnsureMaxBlockSize(txs); + EnsureContext(_context, txs.Take(max).ToArray()); + } + + private Transaction CreateTransactionWithSize(int v) + { + var r = new Random(); + var tx = new Transaction() + { + Cosigners = new Cosigner[0], + Attributes = new TransactionAttribute[0], + NetworkFee = 0, + Nonce = (uint)Environment.TickCount, + Script = new byte[0], + Sender = UInt160.Zero, + SystemFee = 0, + ValidUntilBlock = (uint)r.Next(), + Version = 0, + Witnesses = new Witness[0], + }; + + // Could be higher (few bytes) if varSize grows + tx.Script = new byte[v - tx.Size]; + return tx; + } + + private Block SignBlock(ConsensusContext context) + { + context.Block.MerkleRoot = null; + + for (int x = 0; x < _validatorKeys.Length; x++) + { + _context.MyIndex = x; + + var com = _context.MakeCommit(); + _context.CommitPayloads[_context.MyIndex] = com; + } + + // Manual block sign + Contract contract = Contract.CreateMultiSigContract(context.M, context.Validators); ContractParametersContext sc = new ContractParametersContext(context.Block); for (int i = 0, j = 0; i < context.Validators.Length && j < context.M; i++) @@ -139,25 +139,25 @@ private Block SignBlock(ConsensusContext context) } context.Block.Witness = sc.GetWitnesses()[0]; context.Block.Transactions = context.TransactionHashes.Select(p => context.Transactions[p]).ToArray(); - return context.Block; - } - - private void EnsureContext(ConsensusContext context, params Transaction[] expected) - { - // Check all tx - - Assert.AreEqual(expected.Length, context.Transactions.Count); - Assert.IsTrue(expected.All(tx => context.Transactions.ContainsKey(tx.Hash))); - - Assert.AreEqual(expected.Length, context.TransactionHashes.Length); - Assert.IsTrue(expected.All(tx => context.TransactionHashes.Count(t => t == tx.Hash) == 1)); - - // Ensure length - - var block = SignBlock(context); - - Assert.AreEqual(context.GetExpectedBlockSize(), block.Size); - Assert.IsTrue(block.Size < NativeContract.Policy.GetMaxBlockSize(context.Snapshot)); - } - } -} + return context.Block; + } + + private void EnsureContext(ConsensusContext context, params Transaction[] expected) + { + // Check all tx + + Assert.AreEqual(expected.Length, context.Transactions.Count); + Assert.IsTrue(expected.All(tx => context.Transactions.ContainsKey(tx.Hash))); + + Assert.AreEqual(expected.Length, context.TransactionHashes.Length); + Assert.IsTrue(expected.All(tx => context.TransactionHashes.Count(t => t == tx.Hash) == 1)); + + // Ensure length + + var block = SignBlock(context); + + Assert.AreEqual(context.GetExpectedBlockSize(), block.Size); + Assert.IsTrue(block.Size < NativeContract.Policy.GetMaxBlockSize(context.Snapshot)); + } + } +} diff --git a/neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs b/neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs index fec1ee6bc9..3c58c53473 100644 --- a/neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs +++ b/neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs @@ -1,4 +1,4 @@ -using Akka.TestKit; +using Akka.TestKit; using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs b/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs index dcd394fa4f..6c24fcb922 100644 --- a/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs +++ b/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Wallets; using System; @@ -52,4 +52,4 @@ public void TestVerifySignature() sa.VerifySignature(message, new BigInteger(-100), result[1]).Should().BeFalse(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs b/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs index 035e4dc469..90a31b495d 100644 --- a/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs +++ b/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs @@ -66,4 +66,4 @@ public void TestToByteArray() new ECFieldElement(BigInteger.Pow(new BigInteger(10), 77), ECCurve.Secp256k1).ToByteArray().Should().BeEquivalentTo(result3); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs index cc6fa87d5a..26d71cc3e6 100644 --- a/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs +++ b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography.ECC; using Neo.IO; @@ -349,4 +349,4 @@ public void TestTwice() ECCurve.Secp256k1)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/UT_Base58.cs b/neo.UnitTests/Cryptography/UT_Base58.cs index 21cc63dda2..1a539cc42c 100644 --- a/neo.UnitTests/Cryptography/UT_Base58.cs +++ b/neo.UnitTests/Cryptography/UT_Base58.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using System; @@ -28,4 +28,4 @@ public void TestDecode() action.ShouldThrow(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/UT_BloomFilter.cs b/neo.UnitTests/Cryptography/UT_BloomFilter.cs index d611e0965d..5deabe1b8e 100644 --- a/neo.UnitTests/Cryptography/UT_BloomFilter.cs +++ b/neo.UnitTests/Cryptography/UT_BloomFilter.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using System; @@ -66,4 +66,4 @@ public void TestGetBits() value.Should().Be(0); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/UT_Crypto.cs b/neo.UnitTests/Cryptography/UT_Crypto.cs index ec0d95add6..c46f25aa69 100644 --- a/neo.UnitTests/Cryptography/UT_Crypto.cs +++ b/neo.UnitTests/Cryptography/UT_Crypto.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using Neo.Wallets; @@ -61,4 +61,4 @@ public void TestVerifySignature() action.ShouldThrow(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index d7a3e65136..67ed2a920d 100644 --- a/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using Neo.Network.P2P.Payloads; @@ -223,4 +223,4 @@ public void TestToArray() result.Should().Equal(byteArray); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/UT_MerkleTree.cs b/neo.UnitTests/Cryptography/UT_MerkleTree.cs index 75ab2330b2..4b56380957 100644 --- a/neo.UnitTests/Cryptography/UT_MerkleTree.cs +++ b/neo.UnitTests/Cryptography/UT_MerkleTree.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using System; @@ -77,4 +77,4 @@ public void TestTrim() hashArray[0].Should().Be(result); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs b/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs index 48fd05745d..78274c2d18 100644 --- a/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs +++ b/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using System.Text; @@ -48,4 +48,4 @@ public void TestGetIsRoot() node.IsRoot.Should().BeTrue(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/UT_Murmur3.cs b/neo.UnitTests/Cryptography/UT_Murmur3.cs index c59a53645a..3ed3ab22fa 100644 --- a/neo.UnitTests/Cryptography/UT_Murmur3.cs +++ b/neo.UnitTests/Cryptography/UT_Murmur3.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; @@ -21,4 +21,4 @@ public void TestHashCore() array.Murmur32(10u).Should().Be(378574820u); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Cryptography/UT_SCrypt.cs b/neo.UnitTests/Cryptography/UT_SCrypt.cs index afe41bf475..612a8307c6 100644 --- a/neo.UnitTests/Cryptography/UT_SCrypt.cs +++ b/neo.UnitTests/Cryptography/UT_SCrypt.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; namespace Neo.UnitTests.Cryptography @@ -15,4 +15,4 @@ public void DeriveKeyTest() Assert.AreEqual("b6274d3a81892c24335ab46a08ec16d040ac00c5943b212099a44b76a9b8102631ab988fa07fb35357cee7b0e3910098c0774c0e97399997676d890b2bf2bb25", derivedkey); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Extensions/NativeContractExtensions.cs b/neo.UnitTests/Extensions/NativeContractExtensions.cs index 6a641c2387..4d3f7bcb95 100644 --- a/neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -1,4 +1,4 @@ -using Neo.Network.P2P.Payloads; +using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; @@ -37,4 +37,4 @@ public static StackItem Call(this NativeContract contract, Neo.Persistence.Snaps return engine.ResultStack.Pop(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs b/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs index a9aa8a7777..a531591d34 100644 --- a/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs +++ b/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.SmartContract.Native; @@ -12,9 +12,9 @@ namespace Neo.UnitTests.Extensions { public static class Nep5NativeContractExtensions - { + { internal class ManualWitness : IVerifiable - { + { private readonly UInt160[] _hashForVerify; public Witness[] Witnesses @@ -191,4 +191,4 @@ public static string Name(this NativeContract contract) return Encoding.UTF8.GetString((result as VM.Types.ByteArray).GetByteArray()); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Caching/UT_Cache.cs b/neo.UnitTests/IO/Caching/UT_Cache.cs index 1376863e1a..930547f314 100644 --- a/neo.UnitTests/IO/Caching/UT_Cache.cs +++ b/neo.UnitTests/IO/Caching/UT_Cache.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; using System; diff --git a/neo.UnitTests/IO/Caching/UT_CloneCache.cs b/neo.UnitTests/IO/Caching/UT_CloneCache.cs index 52c665a95d..afa550e45c 100644 --- a/neo.UnitTests/IO/Caching/UT_CloneCache.cs +++ b/neo.UnitTests/IO/Caching/UT_CloneCache.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using Neo.IO.Caching; @@ -124,4 +124,4 @@ public void TestUpdateInternal() myDataCache[new MyKey("key2")].Should().Be(new MyValue("value_new_2")); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs b/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs index 812cbc26ba..591ea8ea05 100644 --- a/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs +++ b/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; @@ -45,4 +45,4 @@ public void TestUpdateInternal() value.Value.Should().Be("value2"); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Caching/UT_DataCache.cs b/neo.UnitTests/IO/Caching/UT_DataCache.cs index d93316022d..f21624814d 100644 --- a/neo.UnitTests/IO/Caching/UT_DataCache.cs +++ b/neo.UnitTests/IO/Caching/UT_DataCache.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using Neo.IO.Caching; @@ -344,4 +344,4 @@ public void TestTryGet() myDataCache.TryGet(new MyKey("key3")).Should().BeNull(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Caching/UT_FIFOSet.cs b/neo.UnitTests/IO/Caching/UT_FIFOSet.cs index f36984b89f..9b781858ee 100644 --- a/neo.UnitTests/IO/Caching/UT_FIFOSet.cs +++ b/neo.UnitTests/IO/Caching/UT_FIFOSet.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; using System; @@ -146,4 +146,4 @@ public void TestExceptWith() CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a }); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs b/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs index 368e866f54..1ed84a5a0e 100644 --- a/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs +++ b/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using Neo.IO.Caching; @@ -73,4 +73,4 @@ public void TestCreateSnapshot() myMetaCache.CreateSnapshot().Should().NotBeNull(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs b/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs index 262528cd88..66b1dd0e7c 100644 --- a/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs +++ b/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; using System.Collections; @@ -126,4 +126,4 @@ public void TestGetEnumerator() collection.GetEnumerator().MoveNext().Should().BeTrue(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Caching/UT_ReflectionCache.cs b/neo.UnitTests/IO/Caching/UT_ReflectionCache.cs index e7de68f3c1..e51f6f81d6 100644 --- a/neo.UnitTests/IO/Caching/UT_ReflectionCache.cs +++ b/neo.UnitTests/IO/Caching/UT_ReflectionCache.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; using System; @@ -77,4 +77,4 @@ public void TestCreateInstance2() (item1 is TestItem1).Should().BeTrue(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Caching/UT_RelayCache.cs b/neo.UnitTests/IO/Caching/UT_RelayCache.cs index ed41c1128a..4608dd0e14 100644 --- a/neo.UnitTests/IO/Caching/UT_RelayCache.cs +++ b/neo.UnitTests/IO/Caching/UT_RelayCache.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; using Neo.Network.P2P.Payloads; @@ -39,4 +39,4 @@ public void TestGetKeyForItem() (tmp is Transaction).Should().BeTrue(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs b/neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs index 21dea9f1d1..d9ad5af951 100644 --- a/neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs +++ b/neo.UnitTests/IO/Data/LevelDb/UT_Slice.cs @@ -405,4 +405,4 @@ public void TestUnequal() Assert.AreEqual(false, result); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Json/UT_JArray.cs b/neo.UnitTests/IO/Json/UT_JArray.cs index 1bb165f224..5b7a30c9ae 100644 --- a/neo.UnitTests/IO/Json/UT_JArray.cs +++ b/neo.UnitTests/IO/Json/UT_JArray.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using System; @@ -249,4 +249,4 @@ public void TestAsString() Assert.AreEqual(s, "{\"name\":\"alice\",\"age\":30,\"score\":100.001,\"gender\":\"female\",\"isMarried\":true,\"pet\":{\"name\":\"Tom\",\"type\":\"cat\"}},{\"name\":\"bob\",\"age\":100000,\"score\":0.001,\"gender\":\"male\",\"isMarried\":false,\"pet\":{\"name\":\"Paul\",\"type\":\"dog\"}}"); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Json/UT_JBoolean.cs b/neo.UnitTests/IO/Json/UT_JBoolean.cs index cb44570e45..8e5f4acdd6 100644 --- a/neo.UnitTests/IO/Json/UT_JBoolean.cs +++ b/neo.UnitTests/IO/Json/UT_JBoolean.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using System; @@ -74,4 +74,4 @@ public void TestParseTrue() ret3.AsBoolean().Should().BeTrue(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Json/UT_JNumber.cs b/neo.UnitTests/IO/Json/UT_JNumber.cs index 7232e8b969..16adbe9d80 100644 --- a/neo.UnitTests/IO/Json/UT_JNumber.cs +++ b/neo.UnitTests/IO/Json/UT_JNumber.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using System; @@ -64,4 +64,4 @@ public void TestParse() action2.ShouldThrow(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Json/UT_JObject.cs b/neo.UnitTests/IO/Json/UT_JObject.cs index 3c8dff0b46..990363bcb1 100644 --- a/neo.UnitTests/IO/Json/UT_JObject.cs +++ b/neo.UnitTests/IO/Json/UT_JObject.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using System; @@ -115,4 +115,4 @@ public void TestGetNull() JObject.Null.Should().BeNull(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Json/UT_JString.cs b/neo.UnitTests/IO/Json/UT_JString.cs index 07f231674f..5d20b30fa0 100644 --- a/neo.UnitTests/IO/Json/UT_JString.cs +++ b/neo.UnitTests/IO/Json/UT_JString.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using Neo.SmartContract; using System; @@ -70,4 +70,4 @@ public void TestTryGetEnum() Assert.AreEqual(ContractParameterType.Void, cp); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/UT_IOHelper.cs b/neo.UnitTests/IO/UT_IOHelper.cs index b0593c02ec..350cc31425 100644 --- a/neo.UnitTests/IO/UT_IOHelper.cs +++ b/neo.UnitTests/IO/UT_IOHelper.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using System; diff --git a/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs b/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs index 3f4f0c6d06..aa6c0cfbc8 100644 --- a/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs +++ b/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Wrappers; using System.IO; @@ -47,4 +47,4 @@ public void TestEqualsOtherSerializableWrapper() Assert.AreEqual(true, temp.Equals(temp2)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs b/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs index 7762c56b7c..766ed8e694 100644 --- a/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs +++ b/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Wrappers; using System.IO; using System.Text; @@ -94,4 +94,4 @@ public void TestOperatorUInt32Wrapper() Assert.AreEqual(true, temp.Equals(1)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Ledger/UT_MemoryPool.cs b/neo.UnitTests/Ledger/UT_MemoryPool.cs index 96b0e99a19..ea797d7c03 100644 --- a/neo.UnitTests/Ledger/UT_MemoryPool.cs +++ b/neo.UnitTests/Ledger/UT_MemoryPool.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Neo.Ledger; diff --git a/neo.UnitTests/Ledger/UT_PoolItem.cs b/neo.UnitTests/Ledger/UT_PoolItem.cs index e87aad3ffe..10a57ecc90 100644 --- a/neo.UnitTests/Ledger/UT_PoolItem.cs +++ b/neo.UnitTests/Ledger/UT_PoolItem.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Neo.Ledger; diff --git a/neo.UnitTests/Ledger/UT_StorageKey.cs b/neo.UnitTests/Ledger/UT_StorageKey.cs index 7e2ec9bdb2..6e2223cdcb 100644 --- a/neo.UnitTests/Ledger/UT_StorageKey.cs +++ b/neo.UnitTests/Ledger/UT_StorageKey.cs @@ -128,4 +128,4 @@ public void GetHashCode_Get() uut.GetHashCode().Should().Be(806209853); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Cosigner.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Cosigner.cs index ef6124b3a8..e21f468575 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Cosigner.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Cosigner.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography.ECC; using Neo.IO; diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs index b367a3efbd..3eabd054b6 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using Neo.Network.P2P.Payloads; diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index c357541d7e..91510e0ec9 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography.ECC; using Neo.IO; diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs index efb06d93be..5114d524b2 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using Neo.IO.Json; diff --git a/neo.UnitTests/Network/P2P/UT_Message.cs b/neo.UnitTests/Network/P2P/UT_Message.cs index 4bb37a8166..6f194ea862 100644 --- a/neo.UnitTests/Network/P2P/UT_Message.cs +++ b/neo.UnitTests/Network/P2P/UT_Message.cs @@ -112,4 +112,4 @@ public void Compression() ((ServerCapability)payloadCopy.Capabilities[0]).Port.Should().Be(25); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs b/neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs index 4ea998ef40..f8b932c4f2 100644 --- a/neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs +++ b/neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs @@ -1,4 +1,4 @@ -using Akka.TestKit.Xunit2; +using Akka.TestKit.Xunit2; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Network.P2P; using Neo.Network.P2P.Capabilities; diff --git a/neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs b/neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs index 91caf65297..cb9c4586a8 100644 --- a/neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs +++ b/neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs @@ -1,4 +1,4 @@ -using Akka.TestKit.Xunit2; +using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; diff --git a/neo.UnitTests/Network/P2P/UT_RemoteNode.cs b/neo.UnitTests/Network/P2P/UT_RemoteNode.cs index 03da2a3db8..570cc904da 100644 --- a/neo.UnitTests/Network/P2P/UT_RemoteNode.cs +++ b/neo.UnitTests/Network/P2P/UT_RemoteNode.cs @@ -8,7 +8,7 @@ namespace Neo.UnitTests.Network.P2P { - [TestClass] + [TestClass] [NotReRunnable] public class UT_RemoteNode : TestKit { diff --git a/neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs b/neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs index 860012a31e..b57e9e93a7 100644 --- a/neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs +++ b/neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs @@ -1,4 +1,4 @@ -using Akka.IO; +using Akka.IO; using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs b/neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs index 6d014cd9c7..fca280d1eb 100644 --- a/neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs +++ b/neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs @@ -1,4 +1,4 @@ -using Akka.TestKit.Xunit2; +using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Network.P2P; diff --git a/neo.UnitTests/Network/RPC/UT_RpcClient.cs b/neo.UnitTests/Network/RPC/UT_RpcClient.cs index 955c481248..76cf7556bf 100644 --- a/neo.UnitTests/Network/RPC/UT_RpcClient.cs +++ b/neo.UnitTests/Network/RPC/UT_RpcClient.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Moq.Protected; using Neo.IO; diff --git a/neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs b/neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs index 51db50ea31..5fad01c94b 100644 --- a/neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs +++ b/neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs @@ -66,4 +66,4 @@ private Integer MakeIntegerStackItem(int val) return new Integer(new BigInteger(val)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs b/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs index bbb613c2be..a96c3ff4c5 100644 --- a/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs +++ b/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography.ECC; using Neo.SmartContract.Manifest; diff --git a/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index 0ad69a7198..0202e9d6d0 100644 --- a/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs +++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Ledger; using Neo.Network.P2P.Payloads; @@ -141,4 +141,4 @@ public void Check_BadScript() NativeContract.GAS.Invoke(engine).Should().BeFalse(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index f7b216544c..38befbe790 100644 --- a/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using Neo.Cryptography.ECC; diff --git a/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs index b53932dbf8..8442904f5b 100644 --- a/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs +++ b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Network.P2P.Payloads; using Neo.Persistence; diff --git a/neo.UnitTests/SmartContract/UT_InteropService.cs b/neo.UnitTests/SmartContract/UT_InteropService.cs index 023ba4c8e5..39687fd720 100644 --- a/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -189,4 +189,4 @@ private void AssertNotification(StackItem stackItem, UInt160 scriptHash, int not Assert.AreEqual(notification, array[1].GetBigInteger()); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/SmartContract/UT_JsonSerializer.cs b/neo.UnitTests/SmartContract/UT_JsonSerializer.cs index adfbea8760..e7fdf30667 100644 --- a/neo.UnitTests/SmartContract/UT_JsonSerializer.cs +++ b/neo.UnitTests/SmartContract/UT_JsonSerializer.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using Neo.SmartContract; using Neo.VM; diff --git a/neo.UnitTests/SmartContract/UT_OpCodePrices.cs b/neo.UnitTests/SmartContract/UT_OpCodePrices.cs index 3174d8494b..cb04990e31 100644 --- a/neo.UnitTests/SmartContract/UT_OpCodePrices.cs +++ b/neo.UnitTests/SmartContract/UT_OpCodePrices.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; using Neo.VM; using System; diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index c80899b8f8..65066b9079 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Ledger; using Neo.SmartContract; using Neo.VM; @@ -63,4 +63,4 @@ public void System_Runtime_GetInvocationCounter() ); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/TestBlockchain.cs b/neo.UnitTests/TestBlockchain.cs index 3037e9e3dc..5276dc2e4c 100644 --- a/neo.UnitTests/TestBlockchain.cs +++ b/neo.UnitTests/TestBlockchain.cs @@ -1,4 +1,4 @@ -using Moq; +using Moq; using Neo.IO.Wrappers; using Neo.Ledger; using Neo.Persistence; @@ -59,4 +59,4 @@ public static NeoSystem InitializeMockNeoSystem() return TheNeoSystem; } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/TestDataCache.cs b/neo.UnitTests/TestDataCache.cs index 68f3b07da7..44d86141b5 100644 --- a/neo.UnitTests/TestDataCache.cs +++ b/neo.UnitTests/TestDataCache.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Caching; using System; using System.Collections.Generic; diff --git a/neo.UnitTests/TestMetaDataCache.cs b/neo.UnitTests/TestMetaDataCache.cs index 55dca734f4..0cb5646928 100644 --- a/neo.UnitTests/TestMetaDataCache.cs +++ b/neo.UnitTests/TestMetaDataCache.cs @@ -1,4 +1,4 @@ -using Neo.IO; +using Neo.IO; using Neo.IO.Caching; namespace Neo.UnitTests diff --git a/neo.UnitTests/TestUtils.cs b/neo.UnitTests/TestUtils.cs index 086098a8ec..554b492d4b 100644 --- a/neo.UnitTests/TestUtils.cs +++ b/neo.UnitTests/TestUtils.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Neo.IO; using Neo.IO.Json; using Neo.Ledger; @@ -144,4 +144,4 @@ public static void DeleteFile(string file) } } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/TestVerifiable.cs b/neo.UnitTests/TestVerifiable.cs index dfe21c2d0f..c0920df480 100644 --- a/neo.UnitTests/TestVerifiable.cs +++ b/neo.UnitTests/TestVerifiable.cs @@ -42,4 +42,4 @@ public void SerializeUnsigned(BinaryWriter writer) writer.Write((string)testStr); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/TestWalletAccount.cs b/neo.UnitTests/TestWalletAccount.cs index 5b07045d1e..b8a242c578 100644 --- a/neo.UnitTests/TestWalletAccount.cs +++ b/neo.UnitTests/TestWalletAccount.cs @@ -1,4 +1,4 @@ -using Moq; +using Moq; using Neo.SmartContract; using Neo.Wallets; using System; diff --git a/neo.UnitTests/UT_BigDecimal.cs b/neo.UnitTests/UT_BigDecimal.cs index 3975d5503e..2d359da891 100644 --- a/neo.UnitTests/UT_BigDecimal.cs +++ b/neo.UnitTests/UT_BigDecimal.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Numerics; @@ -188,4 +188,4 @@ public void TestTryParse() result.Should().Be(default(BigDecimal)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/UT_Culture.cs b/neo.UnitTests/UT_Culture.cs index 807e67990c..37a44b24ef 100644 --- a/neo.UnitTests/UT_Culture.cs +++ b/neo.UnitTests/UT_Culture.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; diff --git a/neo.UnitTests/UT_DataCache.cs b/neo.UnitTests/UT_DataCache.cs index 85df272db5..a428e72d8d 100644 --- a/neo.UnitTests/UT_DataCache.cs +++ b/neo.UnitTests/UT_DataCache.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Caching; using Neo.Ledger; using System.Linq; diff --git a/neo.UnitTests/UT_Helper.cs b/neo.UnitTests/UT_Helper.cs index d64d9c9173..aaad993bb1 100644 --- a/neo.UnitTests/UT_Helper.cs +++ b/neo.UnitTests/UT_Helper.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Network.P2P; using Neo.SmartContract; diff --git a/neo.UnitTests/UT_NefFile.cs b/neo.UnitTests/UT_NefFile.cs index ba14496a27..056333163d 100644 --- a/neo.UnitTests/UT_NefFile.cs +++ b/neo.UnitTests/UT_NefFile.cs @@ -1,75 +1,75 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.Cryptography; -using Neo.IO; -using Neo.SmartContract; -using System; - -namespace Neo.UnitTests -{ - [TestClass] - public class UT_NefFile - { - [TestMethod] - public void ParseTest() - { - var file = new NefFile() - { - Compiler = "".PadLeft(32, ' '), - Version = new Version(1, 2, 3, 4), - Script = new byte[] { 0x01, 0x02, 0x03 } - }; - - file.ScriptHash = file.Script.ToScriptHash(); - file.CheckSum = NefFile.ComputeChecksum(file); - - var data = file.ToArray(); - file = data.AsSerializable(); - - Assert.AreEqual("".PadLeft(32, ' '), file.Compiler); - Assert.AreEqual(new Version(1, 2, 3, 4), file.Version); - Assert.AreEqual(file.Script.ToScriptHash(), file.ScriptHash); - CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }, file.Script); - } - - [TestMethod] - public void LimitTest() - { - var file = new NefFile() - { - Compiler = "".PadLeft(byte.MaxValue, ' '), - Version = new Version(1, 2, 3, 4), - Script = new byte[1024 * 1024], - ScriptHash = new byte[1024 * 1024].ToScriptHash(), - CheckSum = 0 - }; - - // Wrong compiler - - Assert.ThrowsException(() => file.ToArray()); - - // Wrong script - - file.Compiler = ""; - file.Script = new byte[(1024 * 1024) + 1]; - file.ScriptHash = file.Script.ToScriptHash(); - var data = file.ToArray(); - - Assert.ThrowsException(() => data.AsSerializable()); - - // Wrong script hash - - file.Script = new byte[1024 * 1024]; - data = file.ToArray(); - - Assert.ThrowsException(() => data.AsSerializable()); - - // Wrong checksum - - file.Script = new byte[1024]; - data = file.ToArray(); - file.CheckSum = NefFile.ComputeChecksum(file) + 1; - - Assert.ThrowsException(() => data.AsSerializable()); - } - } -} \ No newline at end of file +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.IO; +using Neo.SmartContract; +using System; + +namespace Neo.UnitTests +{ + [TestClass] + public class UT_NefFile + { + [TestMethod] + public void ParseTest() + { + var file = new NefFile() + { + Compiler = "".PadLeft(32, ' '), + Version = new Version(1, 2, 3, 4), + Script = new byte[] { 0x01, 0x02, 0x03 } + }; + + file.ScriptHash = file.Script.ToScriptHash(); + file.CheckSum = NefFile.ComputeChecksum(file); + + var data = file.ToArray(); + file = data.AsSerializable(); + + Assert.AreEqual("".PadLeft(32, ' '), file.Compiler); + Assert.AreEqual(new Version(1, 2, 3, 4), file.Version); + Assert.AreEqual(file.Script.ToScriptHash(), file.ScriptHash); + CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }, file.Script); + } + + [TestMethod] + public void LimitTest() + { + var file = new NefFile() + { + Compiler = "".PadLeft(byte.MaxValue, ' '), + Version = new Version(1, 2, 3, 4), + Script = new byte[1024 * 1024], + ScriptHash = new byte[1024 * 1024].ToScriptHash(), + CheckSum = 0 + }; + + // Wrong compiler + + Assert.ThrowsException(() => file.ToArray()); + + // Wrong script + + file.Compiler = ""; + file.Script = new byte[(1024 * 1024) + 1]; + file.ScriptHash = file.Script.ToScriptHash(); + var data = file.ToArray(); + + Assert.ThrowsException(() => data.AsSerializable()); + + // Wrong script hash + + file.Script = new byte[1024 * 1024]; + data = file.ToArray(); + + Assert.ThrowsException(() => data.AsSerializable()); + + // Wrong checksum + + file.Script = new byte[1024]; + data = file.ToArray(); + file.CheckSum = NefFile.ComputeChecksum(file) + 1; + + Assert.ThrowsException(() => data.AsSerializable()); + } + } +} diff --git a/neo.UnitTests/UT_ProtocolSettings.cs b/neo.UnitTests/UT_ProtocolSettings.cs index 053c5d7e37..a5fa189231 100644 --- a/neo.UnitTests/UT_ProtocolSettings.cs +++ b/neo.UnitTests/UT_ProtocolSettings.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.Extensions.Configuration; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; @@ -93,4 +93,4 @@ public void Cant_initialize_ProtocolSettings_twice() ProtocolSettings.Default.Magic.Should().Be(expectedMagic); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/VM/UT_Helper.cs b/neo.UnitTests/VM/UT_Helper.cs index b57ca02a7c..e9ccc539bb 100644 --- a/neo.UnitTests/VM/UT_Helper.cs +++ b/neo.UnitTests/VM/UT_Helper.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; using Neo.VM; using System; @@ -79,4 +79,4 @@ public void TestEmitAppCall3() Assert.AreEqual(Encoding.Default.GetString(tempArray), Encoding.Default.GetString(resultArray)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs index ade2472ba8..e2f4ca13f4 100644 --- a/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Account.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using Neo.IO.Json; diff --git a/neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs index 6dc7f714d5..3f4e7b3a63 100644 --- a/neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Contract.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using Neo.SmartContract; diff --git a/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs index 89499e7c57..294afd91cd 100644 --- a/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using Neo.Wallets; diff --git a/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs b/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs index adac8a13a2..65d29e9fce 100644 --- a/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs +++ b/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO.Json; using Neo.Wallets.NEP6; diff --git a/neo.UnitTests/Wallets/SQLite/UT_Account.cs b/neo.UnitTests/Wallets/SQLite/UT_Account.cs index c60e90fd10..0fabb80b1e 100644 --- a/neo.UnitTests/Wallets/SQLite/UT_Account.cs +++ b/neo.UnitTests/Wallets/SQLite/UT_Account.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Wallets.SQLite; using System.Text; @@ -34,4 +34,4 @@ public void TestSetAndGetPublicKeyHash() Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(account.PublicKeyHash)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Wallets/SQLite/UT_Address.cs b/neo.UnitTests/Wallets/SQLite/UT_Address.cs index 4d3e2d6717..6157d26fe7 100644 --- a/neo.UnitTests/Wallets/SQLite/UT_Address.cs +++ b/neo.UnitTests/Wallets/SQLite/UT_Address.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Wallets.SQLite; using System.Text; @@ -24,4 +24,4 @@ public void TestSetAndGetScriptHash() Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(address.ScriptHash)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Wallets/SQLite/UT_Contract.cs b/neo.UnitTests/Wallets/SQLite/UT_Contract.cs index 52c197a778..262c74ce08 100644 --- a/neo.UnitTests/Wallets/SQLite/UT_Contract.cs +++ b/neo.UnitTests/Wallets/SQLite/UT_Contract.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Wallets.SQLite; using System.Text; @@ -62,4 +62,4 @@ public void TestSetAndGetAddress() Assert.AreEqual(address, contract.Address); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Wallets/SQLite/UT_Key.cs b/neo.UnitTests/Wallets/SQLite/UT_Key.cs index e09896b72c..f4876cee11 100644 --- a/neo.UnitTests/Wallets/SQLite/UT_Key.cs +++ b/neo.UnitTests/Wallets/SQLite/UT_Key.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Wallets.SQLite; using System.Text; @@ -34,4 +34,4 @@ public void TestSetAndGetValue() Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(key.Value)); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs b/neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs index 70f3a649cf..dcba52bc11 100644 --- a/neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs +++ b/neo.UnitTests/Wallets/SQLite/UT_UserWallet.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; using Neo.Wallets; diff --git a/neo.UnitTests/Wallets/SQLite/UT_UserWalletAccount.cs b/neo.UnitTests/Wallets/SQLite/UT_UserWalletAccount.cs index 2a0dfd3f1d..0a1fde1321 100644 --- a/neo.UnitTests/Wallets/SQLite/UT_UserWalletAccount.cs +++ b/neo.UnitTests/Wallets/SQLite/UT_UserWalletAccount.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Wallets.SQLite; using System.Text; diff --git a/neo.UnitTests/Wallets/SQLite/UT_VerificationContract.cs b/neo.UnitTests/Wallets/SQLite/UT_VerificationContract.cs index d590640fe5..8f111f2112 100644 --- a/neo.UnitTests/Wallets/SQLite/UT_VerificationContract.cs +++ b/neo.UnitTests/Wallets/SQLite/UT_VerificationContract.cs @@ -1,4 +1,4 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; using Neo.Wallets; using Neo.Wallets.SQLite; diff --git a/neo.UnitTests/Wallets/UT_AssetDescriptor.cs b/neo.UnitTests/Wallets/UT_AssetDescriptor.cs index ca80f27b28..14eb6766b1 100644 --- a/neo.UnitTests/Wallets/UT_AssetDescriptor.cs +++ b/neo.UnitTests/Wallets/UT_AssetDescriptor.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Persistence; using Neo.SmartContract.Native; @@ -48,4 +48,4 @@ public void Check_NEO() descriptor.Decimals.Should().Be(0); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Wallets/UT_KeyPair.cs b/neo.UnitTests/Wallets/UT_KeyPair.cs index dc67599111..57f06bb5a9 100644 --- a/neo.UnitTests/Wallets/UT_KeyPair.cs +++ b/neo.UnitTests/Wallets/UT_KeyPair.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using Neo.Cryptography.ECC; diff --git a/neo.UnitTests/Wallets/UT_Wallet.cs b/neo.UnitTests/Wallets/UT_Wallet.cs index 59289ae548..c09f8e26c2 100644 --- a/neo.UnitTests/Wallets/UT_Wallet.cs +++ b/neo.UnitTests/Wallets/UT_Wallet.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography.ECC; using Neo.Ledger; @@ -433,4 +433,4 @@ public void TestVerifyPassword() action.ShouldNotThrow(); } } -} \ No newline at end of file +} diff --git a/neo.UnitTests/Wallets/UT_WalletAccount.cs b/neo.UnitTests/Wallets/UT_WalletAccount.cs index 15e2bd1974..413caf6880 100644 --- a/neo.UnitTests/Wallets/UT_WalletAccount.cs +++ b/neo.UnitTests/Wallets/UT_WalletAccount.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.SmartContract; using Neo.Wallets; diff --git a/neo.UnitTests/Wallets/UT_Wallets_Helper.cs b/neo.UnitTests/Wallets/UT_Wallets_Helper.cs index 01f47fea16..4abf10d9ed 100644 --- a/neo.UnitTests/Wallets/UT_Wallets_Helper.cs +++ b/neo.UnitTests/Wallets/UT_Wallets_Helper.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography; using Neo.Wallets; diff --git a/neo.UnitTests/neo.UnitTests.csproj b/neo.UnitTests/neo.UnitTests.csproj index 5d967c0845..4cbc7f4164 100644 --- a/neo.UnitTests/neo.UnitTests.csproj +++ b/neo.UnitTests/neo.UnitTests.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/neo.sln b/neo.sln index 9d4c436c0e..fd72762fc2 100644 --- a/neo.sln +++ b/neo.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26430.15 diff --git a/neo/Consensus/ChangeViewReason.cs b/neo/Consensus/ChangeViewReason.cs index 066ecc1085..87c88c74c2 100644 --- a/neo/Consensus/ChangeViewReason.cs +++ b/neo/Consensus/ChangeViewReason.cs @@ -9,4 +9,4 @@ public enum ChangeViewReason : byte TxInvalid = 0x4, BlockRejectedByPolicy = 0x5 } -} \ No newline at end of file +} diff --git a/neo/IO/Caching/ReflectionCache.cs b/neo/IO/Caching/ReflectionCache.cs index 705366e2fb..452856698c 100644 --- a/neo/IO/Caching/ReflectionCache.cs +++ b/neo/IO/Caching/ReflectionCache.cs @@ -77,4 +77,4 @@ public K CreateInstance(T key, K def = default(K)) return def; } } -} \ No newline at end of file +} diff --git a/neo/IO/Caching/ReflectionCacheAttribute.cs b/neo/IO/Caching/ReflectionCacheAttribute.cs index ba5fd4e1bc..b2ac3c3054 100644 --- a/neo/IO/Caching/ReflectionCacheAttribute.cs +++ b/neo/IO/Caching/ReflectionCacheAttribute.cs @@ -18,4 +18,4 @@ public ReflectionCacheAttribute(Type type) Type = type; } } -} \ No newline at end of file +} diff --git a/neo/Plugins/MemoryPoolTxRemovalReason.cs b/neo/Plugins/MemoryPoolTxRemovalReason.cs index d08a37eba2..ddc7e10981 100644 --- a/neo/Plugins/MemoryPoolTxRemovalReason.cs +++ b/neo/Plugins/MemoryPoolTxRemovalReason.cs @@ -11,4 +11,4 @@ public enum MemoryPoolTxRemovalReason : byte /// NoLongerValid, } -} \ No newline at end of file +} diff --git a/neo/SmartContract/ExecutionContextState.cs b/neo/SmartContract/ExecutionContextState.cs index 11e6f88a00..d26641f7dd 100644 --- a/neo/SmartContract/ExecutionContextState.cs +++ b/neo/SmartContract/ExecutionContextState.cs @@ -7,4 +7,4 @@ public class ExecutionContextState /// public UInt160 ScriptHash { get; set; } } -} \ No newline at end of file +} From 68a3a3c3a22b69f40b93add25133623fa1ce91b8 Mon Sep 17 00:00:00 2001 From: Ricardo Prado <38396062+lock9@users.noreply.github.com> Date: Tue, 27 Aug 2019 04:58:24 -0300 Subject: [PATCH 40/54] Exposing supported methods used by InteropService (#1060) * Supported methods names * dotnet format * Simplify --- neo/SmartContract/InteropService.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index b4121d7a24..8651dfbc3d 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -77,6 +77,11 @@ public static long GetPrice(uint hash, RandomAccessStack stack) return methods[hash].GetPrice(stack); } + public static Dictionary SupportedMethods() + { + return methods.ToDictionary(p => p.Key, p => p.Value.Method); + } + private static long GetStoragePrice(RandomAccessStack stack) { return (stack.Peek(1).GetByteLength() + stack.Peek(2).GetByteLength()) * GasPerByte; From b9d55115c3969f02b9defae800657180c1c92b29 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 27 Aug 2019 14:25:39 +0200 Subject: [PATCH 41/54] Remove lines of code (#1062) It's not working --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 77e2a2e566..ac251a7a77 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,6 @@ Current Coverage Status. - - Current total lines. - License. From 9a0c3f9d4dae355d1cd6b0ad2d7ac56a7853a044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?= Date: Wed, 28 Aug 2019 17:30:43 +0800 Subject: [PATCH 42/54] Cleaning .editorconfig file (#1067) --- .editorconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 2cbe224983..5acd074d26 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,4 +15,3 @@ insert_final_newline = true trim_trailing_whitespace = true charset = utf-8 end_of_line = lf -#indent_style = tab # TODO From 22ed3eba81efdb7daaf610a773b299000bad8557 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Wed, 28 Aug 2019 21:05:24 +0800 Subject: [PATCH 43/54] Hide the prefix in the store (#1070) --- neo/Consensus/ConsensusContext.cs | 8 ++++---- neo/Persistence/LevelDB/LevelDBStore.cs | 12 ++++++------ neo/Persistence/Store.cs | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs index 4574d70f7e..f96409318a 100644 --- a/neo/Consensus/ConsensusContext.cs +++ b/neo/Consensus/ConsensusContext.cs @@ -19,9 +19,9 @@ namespace Neo.Consensus internal class ConsensusContext : IDisposable, ISerializable { /// - /// Prefix for saving consensus state. + /// Key for saving consensus state. /// - public const byte CN_Context = 0xf4; + private static readonly byte[] ConsensusStateKey = { 0xf4 }; public Block Block; public byte ViewNumber; @@ -143,7 +143,7 @@ public uint GetPrimaryIndex(byte viewNumber) public bool Load() { - byte[] data = store.Get(CN_Context, new byte[0]); + byte[] data = store.Get(ConsensusStateKey); if (data is null || data.Length == 0) return false; using (MemoryStream ms = new MemoryStream(data, false)) using (BinaryReader reader = new BinaryReader(ms)) @@ -401,7 +401,7 @@ public void Reset(byte viewNumber) public void Save() { - store.PutSync(CN_Context, new byte[0], this.ToArray()); + store.PutSync(ConsensusStateKey, this.ToArray()); } public void Serialize(BinaryWriter writer) diff --git a/neo/Persistence/LevelDB/LevelDBStore.cs b/neo/Persistence/LevelDB/LevelDBStore.cs index bb6ac26698..805c1fe915 100644 --- a/neo/Persistence/LevelDB/LevelDBStore.cs +++ b/neo/Persistence/LevelDB/LevelDBStore.cs @@ -34,9 +34,9 @@ public void Dispose() db.Dispose(); } - public override byte[] Get(byte prefix, byte[] key) + public override byte[] Get(byte[] key) { - if (!db.TryGet(ReadOptions.Default, SliceBuilder.Begin(prefix).Add(key), out Slice slice)) + if (!db.TryGet(ReadOptions.Default, key, out Slice slice)) return null; return slice.ToArray(); } @@ -81,14 +81,14 @@ public override MetaDataCache GetHeaderHashIndex() return new DbMetaDataCache(db, null, null, Prefixes.IX_CurrentHeader); } - public override void Put(byte prefix, byte[] key, byte[] value) + public override void Put(byte[] key, byte[] value) { - db.Put(WriteOptions.Default, SliceBuilder.Begin(prefix).Add(key), value); + db.Put(WriteOptions.Default, key, value); } - public override void PutSync(byte prefix, byte[] key, byte[] value) + public override void PutSync(byte[] key, byte[] value) { - db.Put(new WriteOptions { Sync = true }, SliceBuilder.Begin(prefix).Add(key), value); + db.Put(new WriteOptions { Sync = true }, key, value); } } } diff --git a/neo/Persistence/Store.cs b/neo/Persistence/Store.cs index 3dc7127f3a..eab5c182b9 100644 --- a/neo/Persistence/Store.cs +++ b/neo/Persistence/Store.cs @@ -14,7 +14,7 @@ public abstract class Store : IPersistence MetaDataCache IPersistence.BlockHashIndex => GetBlockHashIndex(); MetaDataCache IPersistence.HeaderHashIndex => GetHeaderHashIndex(); - public abstract byte[] Get(byte prefix, byte[] key); + public abstract byte[] Get(byte[] key); public abstract DataCache GetBlocks(); public abstract DataCache GetTransactions(); public abstract DataCache GetContracts(); @@ -22,8 +22,8 @@ public abstract class Store : IPersistence public abstract DataCache GetHeaderHashList(); public abstract MetaDataCache GetBlockHashIndex(); public abstract MetaDataCache GetHeaderHashIndex(); - public abstract void Put(byte prefix, byte[] key, byte[] value); - public abstract void PutSync(byte prefix, byte[] key, byte[] value); + public abstract void Put(byte[] key, byte[] value); + public abstract void PutSync(byte[] key, byte[] value); public abstract Snapshot GetSnapshot(); } From c04ee5d277f522eb42bc8fc6a792b0aedf6ab0fc Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Thu, 29 Aug 2019 04:34:30 +0800 Subject: [PATCH 44/54] Fixes `Transaction.ToJson()` (#1071) * Fixes `Transaction.ToJson()` * Fix tests --- neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs | 2 +- neo/Network/P2P/Payloads/Transaction.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index 91510e0ec9..fc32744b96 100644 --- a/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -1067,7 +1067,7 @@ public void ToJson() ((JArray)jObj["cosigners"]).Count.Should().Be(0); jObj["net_fee"].AsString().Should().Be("0"); jObj["script"].AsString().Should().Be("4220202020202020202020202020202020202020202020202020202020202020"); - jObj["sys_fee"].AsNumber().Should().Be(42); + jObj["sys_fee"].AsString().Should().Be("4200000000"); } } } diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs index b83cbd977d..a2586e6da2 100644 --- a/neo/Network/P2P/Payloads/Transaction.cs +++ b/neo/Network/P2P/Payloads/Transaction.cs @@ -175,8 +175,8 @@ public JObject ToJson() json["version"] = Version; json["nonce"] = Nonce; json["sender"] = Sender.ToAddress(); - json["sys_fee"] = new BigDecimal(SystemFee, NativeContract.GAS.Decimals).ToString(); - json["net_fee"] = new BigDecimal(NetworkFee, NativeContract.GAS.Decimals).ToString(); + json["sys_fee"] = SystemFee.ToString(); + json["net_fee"] = NetworkFee.ToString(); json["valid_until_block"] = ValidUntilBlock; json["attributes"] = Attributes.Select(p => p.ToJson()).ToArray(); json["cosigners"] = Cosigners.Select(p => p.ToJson()).ToArray(); From 0bd198e6f6fb78b42026eec3cd4cf940a5899e35 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 29 Aug 2019 06:19:28 +0200 Subject: [PATCH 45/54] Optimize mempool message (#1068) * Optimization * Prevent relay * Change comment * Optimizations --- neo/Ledger/Blockchain.cs | 14 ++++++++++---- neo/Ledger/MemoryPool.cs | 7 ++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs index a74bfa981c..50393d4c8e 100644 --- a/neo/Ledger/Blockchain.cs +++ b/neo/Ledger/Blockchain.cs @@ -364,7 +364,7 @@ private void OnNewHeaders(Header[] headers) system.TaskManager.Tell(new TaskManager.HeaderTaskCompleted(), Sender); } - private RelayResultReason OnNewTransaction(Transaction transaction) + private RelayResultReason OnNewTransaction(Transaction transaction, bool relay) { if (ContainsTransaction(transaction.Hash)) return RelayResultReason.AlreadyExists; @@ -377,8 +377,8 @@ private RelayResultReason OnNewTransaction(Transaction transaction) if (!MemPool.TryAdd(transaction.Hash, transaction)) return RelayResultReason.OutOfMemory; - - system.LocalNode.Tell(new LocalNode.RelayDirectly { Inventory = transaction }); + if (relay) + system.LocalNode.Tell(new LocalNode.RelayDirectly { Inventory = transaction }); return RelayResultReason.Succeed; } @@ -405,8 +405,14 @@ protected override void OnReceive(object message) case Block block: Sender.Tell(OnNewBlock(block)); break; + case Transaction[] transactions: + { + // This message comes from a mempool's revalidation, already relayed + foreach (var tx in transactions) OnNewTransaction(tx, false); + break; + } case Transaction transaction: - Sender.Tell(OnNewTransaction(transaction)); + Sender.Tell(OnNewTransaction(transaction, true)); break; case ConsensusPayload payload: Sender.Tell(OnNewConsensus(payload)); diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs index 739085f5b6..a6af9fc721 100644 --- a/neo/Ledger/MemoryPool.cs +++ b/neo/Ledger/MemoryPool.cs @@ -360,9 +360,14 @@ internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot) if (policyChanged) { + var tx = new List(); foreach (PoolItem item in _unverifiedSortedTransactions.Reverse()) if (item.Tx.FeePerByte >= _feePerByte) - _system.Blockchain.Tell(item.Tx, ActorRefs.NoSender); + tx.Add(item.Tx); + + if (tx.Count > 0) + _system.Blockchain.Tell(tx.ToArray(), ActorRefs.NoSender); + _unverifiedTransactions.Clear(); _unverifiedSortedTransactions.Clear(); } From 919cc804de99b299c1f79f9c4cb14d3411e588c0 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 29 Aug 2019 09:00:21 +0200 Subject: [PATCH 46/54] Fix Runtime_GetNotifications (#1073) --- neo/SmartContract/InteropService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 8651dfbc3d..6868da1886 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -238,13 +238,13 @@ private static bool Runtime_GetNotifications(ApplicationEngine engine) { var data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); if (data.Length != UInt160.Length) return false; - if (!engine.CheckArraySize(engine.Notifications.Count)) return false; var hash = new UInt160(data); IEnumerable notifications = engine.Notifications; if (!hash.Equals(UInt160.Zero)) notifications = notifications.Where(p => p.ScriptHash == hash); + if (!engine.CheckArraySize(notifications.Count())) return false; engine.CurrentContext.EvaluationStack.Push(notifications.Select(u => new VM.Types.Array(new StackItem[] { u.ScriptHash.ToArray(), u.State })).ToArray()); return true; } From 93d1d6a7c07dbece1ae9dc70ad8f5a08098ca1aa Mon Sep 17 00:00:00 2001 From: Igor Machado Coelho Date: Fri, 30 Aug 2019 22:27:16 +0800 Subject: [PATCH 47/54] empty scripthash, all notifications (#1074) * empty scripthash, all notifications * || to && * Fix ut --- neo.UnitTests/SmartContract/UT_InteropService.cs | 2 +- neo/SmartContract/InteropService.cs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_InteropService.cs b/neo.UnitTests/SmartContract/UT_InteropService.cs index 39687fd720..6a33a32abc 100644 --- a/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -85,7 +85,7 @@ public void Runtime_GetNotifications_Test() // Receive all notifications - script.EmitPush(UInt160.Zero.ToArray()); + script.EmitPush(new byte[0]); script.EmitSysCall(InteropService.System_Runtime_GetNotifications); // Execute diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 6868da1886..7aa7fd7284 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -236,13 +236,15 @@ private static bool Runtime_Serialize(ApplicationEngine engine) private static bool Runtime_GetNotifications(ApplicationEngine engine) { - var data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); - if (data.Length != UInt160.Length) return false; + byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); + if ((data.Length != 0) && (data.Length != UInt160.Length)) return false; - var hash = new UInt160(data); IEnumerable notifications = engine.Notifications; - if (!hash.Equals(UInt160.Zero)) + if (data.Length == UInt160.Length) // must filter by scriptHash + { + var hash = new UInt160(data); notifications = notifications.Where(p => p.ScriptHash == hash); + } if (!engine.CheckArraySize(notifications.Count())) return false; engine.CurrentContext.EvaluationStack.Push(notifications.Select(u => new VM.Types.Array(new StackItem[] { u.ScriptHash.ToArray(), u.State })).ToArray()); From 2da4fb16b0e15b988e75cea072ae7e7bcad129b3 Mon Sep 17 00:00:00 2001 From: Ricardo Prado <38396062+lock9@users.noreply.github.com> Date: Sun, 1 Sep 2019 00:45:31 -0300 Subject: [PATCH 48/54] Issues templates for Bug report and Feature Request (#1034) --- .github/ISSUE_TEMPLATE/bug_report.md | 31 +++++++++++++++++++ .../feature-or-enhancement-request.md | 26 ++++++++++++++++ .github/ISSUE_TEMPLATE/questions.md | 9 ++++++ 3 files changed, 66 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature-or-enhancement-request.md create mode 100644 .github/ISSUE_TEMPLATE/questions.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..f69eccca73 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,31 @@ +--- +name: Bug report +about: Create a report to detail an error or unexpected behavior +title: '' +labels: '' +assignees: '' +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Open the project, run '...' +2. Type '...' or do '...' +3. ... + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Platform:** + - OS: [e.g. Windows 10 x64] + - Version [e.g. neo-cli 2.10.2] + +**(Optional) Additional context** +Add any other context about the problem here. + +However, if your issue does not fit these aforementioned criteria, or it can be understood in another manner, feel free to open it in a different format. diff --git a/.github/ISSUE_TEMPLATE/feature-or-enhancement-request.md b/.github/ISSUE_TEMPLATE/feature-or-enhancement-request.md new file mode 100644 index 0000000000..30077088b9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-or-enhancement-request.md @@ -0,0 +1,26 @@ +--- +name: Feature or enhancement request +about: Suggest an idea for Neo +title: '' +labels: discussion +assignees: '' +--- + +**Summary** +A summary of the problem you want to solve or metric you want to improve + +**Do you have any solution you want to propose?** +A clear and concise description of what you expect with this change. + +**Where in software does this update applies to?** +- [ ] Compiler +- [ ] Consensus +- [ ] CLI +- [ ] Plugins +- [ ] Ledger +- [ ] Network Policy +- [ ] P2P (TCP) +- [ ] RPC (HTTP) +- [ ] SDK +- [ ] VM +- [ ] Other: diff --git a/.github/ISSUE_TEMPLATE/questions.md b/.github/ISSUE_TEMPLATE/questions.md new file mode 100644 index 0000000000..4d97925f89 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/questions.md @@ -0,0 +1,9 @@ +--- +name: Questions +about: Questions about Neo Platform +title: '' +labels: question +assignees: '' +--- + +**Delete this: We would like to use GitHub for bug reports and feature requests only however if you are unable to get support from our team in: our [Discord](https://discord.io/neo) server or in our [offical documentation](https://docs.neo.org/docs/en-us/index.html), feel encouraged to create an issue here on GitHub.** From 1a392037f23a767a943c7f05adb0ce0d6916297f Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 2 Sep 2019 23:45:39 +0800 Subject: [PATCH 49/54] Update NuGets (#1080) * Update NuGets * Clean BOM * Update Neo.VM --- neo/neo.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/neo/neo.csproj b/neo/neo.csproj index 54ba724da9..d6d8f7cb4d 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -21,15 +21,15 @@ - - + + - - + + - + From 197a6ec216fe9ef2d17ac20f8ec6d95ed01fb1c3 Mon Sep 17 00:00:00 2001 From: cloud8little <34291844+cloud8little@users.noreply.github.com> Date: Wed, 11 Sep 2019 02:19:18 +0800 Subject: [PATCH 50/54] Downgrade Sqlite to 2.1.4 (#1086) --- neo/neo.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neo/neo.csproj b/neo/neo.csproj index d6d8f7cb4d..556487c280 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -27,7 +27,8 @@ - + + From 4e40b12b8fd1929d53f6b7a2d604c26f2f81e35a Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Thu, 12 Sep 2019 15:56:27 +0800 Subject: [PATCH 51/54] Fix consensus (#1083) --- neo/Consensus/ConsensusContext.cs | 14 ++++++++------ neo/Consensus/ConsensusService.cs | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs index f96409318a..0d9edbb3dc 100644 --- a/neo/Consensus/ConsensusContext.cs +++ b/neo/Consensus/ConsensusContext.cs @@ -103,10 +103,7 @@ public void Deserialize(BinaryReader reader) Block.ConsensusData = reader.ReadSerializable(); ViewNumber = reader.ReadByte(); TransactionHashes = reader.ReadSerializableArray(); - if (TransactionHashes.Length == 0) - TransactionHashes = null; Transaction[] transactions = reader.ReadSerializableArray(Block.MaxTransactionsPerBlock); - Transactions = transactions.Length == 0 ? null : transactions.ToDictionary(p => p.Hash); PreparationPayloads = new ConsensusPayload[reader.ReadVarInt(Blockchain.MaxValidators)]; for (int i = 0; i < PreparationPayloads.Length; i++) PreparationPayloads[i] = reader.ReadBoolean() ? reader.ReadSerializable() : null; @@ -119,6 +116,9 @@ public void Deserialize(BinaryReader reader) LastChangeViewPayloads = new ConsensusPayload[reader.ReadVarInt(Blockchain.MaxValidators)]; for (int i = 0; i < LastChangeViewPayloads.Length; i++) LastChangeViewPayloads[i] = reader.ReadBoolean() ? reader.ReadSerializable() : null; + if (TransactionHashes.Length == 0 && !RequestSentOrReceived) + TransactionHashes = null; + Transactions = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash); } public void Dispose() @@ -340,8 +340,7 @@ public void Reset(byte viewNumber) { PrevHash = Snapshot.CurrentBlockHash, Index = Snapshot.Height + 1, - NextConsensus = Blockchain.GetConsensusAddress(NativeContract.NEO.GetValidators(Snapshot).ToArray()), - ConsensusData = new ConsensusData() + NextConsensus = Blockchain.GetConsensusAddress(NativeContract.NEO.GetValidators(Snapshot).ToArray()) }; var pv = Validators; Validators = NativeContract.NEO.GetNextBlockValidators(Snapshot); @@ -390,7 +389,10 @@ public void Reset(byte viewNumber) LastChangeViewPayloads[i] = null; } ViewNumber = viewNumber; - Block.ConsensusData.PrimaryIndex = GetPrimaryIndex(viewNumber); + Block.ConsensusData = new ConsensusData + { + PrimaryIndex = GetPrimaryIndex(viewNumber) + }; Block.MerkleRoot = null; Block.Timestamp = 0; Block.Transactions = null; diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index 4d8b70a333..a65916b5aa 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -202,7 +202,7 @@ private void OnChangeViewReceived(ConsensusPayload payload, ChangeView message) if (message.NewViewNumber <= expectedView) return; - Log($"{nameof(OnChangeViewReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} nv={message.NewViewNumber}"); + Log($"{nameof(OnChangeViewReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} nv={message.NewViewNumber} reason={message.Reason}"); context.ChangeViewPayloads[payload.ValidatorIndex] = payload; CheckExpectedView(message.NewViewNumber); } From e1fdde307153879f0a7ae64bd3e11d042284896e Mon Sep 17 00:00:00 2001 From: erikzhang Date: Mon, 16 Sep 2019 18:02:40 +0800 Subject: [PATCH 52/54] v3.0.0-preview1 --- neo/neo.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo/neo.csproj b/neo/neo.csproj index 556487c280..724090c004 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -3,7 +3,7 @@ 2015-2019 The Neo Project Neo - 2.10.1 + 3.0.0-preview1 The Neo Project netstandard2.0;net47 true @@ -30,7 +30,7 @@ - + From 4ceae9ed0dc0f6d75785e189a48dff90b06ac16f Mon Sep 17 00:00:00 2001 From: Krain Chen Date: Fri, 20 Sep 2019 20:54:42 +0800 Subject: [PATCH 53/54] C# SDK Add Transaction Manager and Smart Contract APIs (#1026) * Add NEO SDK based on RPC client * add rpc interface methods for neo3 * update unit test * add unit test * Update TransactionHelper.cs Changed for neo 3.0, not final yet. * implement sdk rpc client methods * backup files * change class name * remove uncompleted modules for pull request * change json deserialize method with Neo JObject * modified JSON implementation, added FromJson() * more RPC change * PR correction * RPC module fix, remove newton.json * fix * fix getblock issue * PR correction * PR Correction * PR Correction: rename RPC models * PR Correction * resolve conflicts * Clean code * Clean code * Clean code * Clean code * Update RpcValidateAddressResult.cs * Clean code * PR correction * Move test file to the right place * Added SDK Transaction module. * Add SDK SmartContract module * height = count - 1 * Add sign function for TxManager * Add Deploy Contract * Add unit tests * Add Network Fee calculate for TxManager, add unit tests * adjust cosigners change * PR Correction * Remove empty line * Rename TxManager to TransactionManager * PR correction * PR correction * change namespace * Reorder methods * Remove TransactionContext * fix unit test * Remove `virtual` * Remove virtuals * Remove ScriptHash from KeyPair * Add comments * Add comments * Adjust to Neo_Contract_Create parameter * use default mainfest * fix unit test * Fix typo * use manifest as parameter * add cosigner for nep5 transfer * code clean * Update neo.UnitTests/Network/RPC/UT_RpcClient.cs Co-Authored-By: Shargon * move MakeScript to VM.Helper * Add unit test for InteropInterface * PR Correction * Add unit test --- .../Network/RPC/UT_ContractClient.cs | 68 ++++++ neo.UnitTests/Network/RPC/UT_Nep5API.cs | 89 +++++++ neo.UnitTests/Network/RPC/UT_PolicyAPI.cs | 69 ++++++ neo.UnitTests/Network/RPC/UT_RpcClient.cs | 24 +- .../Network/RPC/UT_TransactionManager.cs | 194 +++++++++++++++ neo.UnitTests/VM/UT_Helper.cs | 60 +++++ neo/Network/RPC/ContractClient.cs | 65 ++++++ neo/Network/RPC/Models/RpcInvokeResult.cs | 11 +- neo/Network/RPC/Nep5API.cs | 97 ++++++++ neo/Network/RPC/PolicyAPI.cs | 57 +++++ neo/Network/RPC/RpcClient.cs | 43 ++-- neo/Network/RPC/TransactionManager.cs | 220 ++++++++++++++++++ neo/SmartContract/Contract.cs | 14 ++ .../ContractParametersContext.cs | 27 +++ neo/VM/Helper.cs | 81 +++++++ neo/Wallets/Wallet.cs | 51 ++-- 16 files changed, 1112 insertions(+), 58 deletions(-) create mode 100644 neo.UnitTests/Network/RPC/UT_ContractClient.cs create mode 100644 neo.UnitTests/Network/RPC/UT_Nep5API.cs create mode 100644 neo.UnitTests/Network/RPC/UT_PolicyAPI.cs create mode 100644 neo.UnitTests/Network/RPC/UT_TransactionManager.cs create mode 100644 neo/Network/RPC/ContractClient.cs create mode 100644 neo/Network/RPC/Nep5API.cs create mode 100644 neo/Network/RPC/PolicyAPI.cs create mode 100644 neo/Network/RPC/TransactionManager.cs diff --git a/neo.UnitTests/Network/RPC/UT_ContractClient.cs b/neo.UnitTests/Network/RPC/UT_ContractClient.cs new file mode 100644 index 0000000000..fde8a7747d --- /dev/null +++ b/neo.UnitTests/Network/RPC/UT_ContractClient.cs @@ -0,0 +1,68 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Neo.Network.RPC; +using Neo.SmartContract; +using Neo.SmartContract.Manifest; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; + +namespace Neo.UnitTests.Network.RPC +{ + [TestClass] + public class UT_ContractClient + { + Mock rpcClientMock; + KeyPair keyPair1; + UInt160 sender; + + [TestInitialize] + public void TestSetup() + { + keyPair1 = new KeyPair(Wallet.GetPrivateKeyFromWIF("KyXwTh1hB76RRMquSvnxZrJzQx7h9nQP2PCRL38v6VDb5ip3nf1p")); + sender = Contract.CreateSignatureRedeemScript(keyPair1.PublicKey).ToScriptHash(); + rpcClientMock = UT_TransactionManager.MockRpcClient(sender, new byte[0]); + } + + [TestMethod] + public void TestMakeScript() + { + byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); + + Assert.AreEqual("14000000000000000000000000000000000000000051c10962616c616e63654f66142582d1b275e86c8f0e93a9b2facd5fdb760976a168627d5b52", + testScript.ToHexString()); + } + + [TestMethod] + public void TestInvoke() + { + byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.ByteArray, Value = "00e057eb481b".HexToBytes() }); + + ContractClient contractClient = new ContractClient(rpcClientMock.Object); + var result = contractClient.TestInvoke(NativeContract.GAS.Hash, "balanceOf", UInt160.Zero); + + Assert.AreEqual(30000000000000L, (long)result.Stack[0].ToStackItem().GetBigInteger()); + } + + [TestMethod] + public void TestDeployContract() + { + byte[] script; + var manifest = ContractManifest.CreateDefault(new byte[1].ToScriptHash()); + manifest.Features = ContractFeatures.HasStorage | ContractFeatures.Payable; + using (ScriptBuilder sb = new ScriptBuilder()) + { + sb.EmitSysCall(InteropService.Neo_Contract_Create, new byte[1], manifest.ToString()); + script = sb.ToArray(); + } + + UT_TransactionManager.MockInvokeScript(rpcClientMock, script, new ContractParameter()); + + ContractClient contractClient = new ContractClient(rpcClientMock.Object); + var result = contractClient.DeployContract(new byte[1], manifest, keyPair1); + + Assert.IsNotNull(result); + } + } +} diff --git a/neo.UnitTests/Network/RPC/UT_Nep5API.cs b/neo.UnitTests/Network/RPC/UT_Nep5API.cs new file mode 100644 index 0000000000..72e0c29487 --- /dev/null +++ b/neo.UnitTests/Network/RPC/UT_Nep5API.cs @@ -0,0 +1,89 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Neo.Network.RPC; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; +using System.Numerics; + +namespace Neo.UnitTests.Network.RPC +{ + [TestClass] + public class UT_Nep5API + { + Mock rpcClientMock; + KeyPair keyPair1; + UInt160 sender; + Nep5API nep5API; + + [TestInitialize] + public void TestSetup() + { + keyPair1 = new KeyPair(Wallet.GetPrivateKeyFromWIF("KyXwTh1hB76RRMquSvnxZrJzQx7h9nQP2PCRL38v6VDb5ip3nf1p")); + sender = Contract.CreateSignatureRedeemScript(keyPair1.PublicKey).ToScriptHash(); + rpcClientMock = UT_TransactionManager.MockRpcClient(sender, new byte[0]); + nep5API = new Nep5API(rpcClientMock.Object); + } + + [TestMethod] + public void TestBalanceOf() + { + byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(10000) }); + + var balance = nep5API.BalanceOf(NativeContract.GAS.Hash, UInt160.Zero); + Assert.AreEqual(10000, (int)balance); + } + + [TestMethod] + public void TestGetName() + { + byte[] testScript = NativeContract.GAS.Hash.MakeScript("name"); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.GAS.Name }); + + var result = nep5API.Name(NativeContract.GAS.Hash); + Assert.AreEqual(NativeContract.GAS.Name, result); + } + + [TestMethod] + public void TestGetSymbol() + { + byte[] testScript = NativeContract.GAS.Hash.MakeScript("symbol"); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.GAS.Symbol }); + + var result = nep5API.Symbol(NativeContract.GAS.Hash); + Assert.AreEqual(NativeContract.GAS.Symbol, result); + } + + [TestMethod] + public void TestGetDecimals() + { + byte[] testScript = NativeContract.GAS.Hash.MakeScript("decimals"); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(NativeContract.GAS.Decimals) }); + + var result = nep5API.Decimals(NativeContract.GAS.Hash); + Assert.AreEqual(NativeContract.GAS.Decimals, (byte)result); + } + + [TestMethod] + public void TestGetTotalSupply() + { + byte[] testScript = NativeContract.GAS.Hash.MakeScript("totalSupply"); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_00000000) }); + + var result = nep5API.TotalSupply(NativeContract.GAS.Hash); + Assert.AreEqual(1_00000000, (int)result); + } + + [TestMethod] + public void TestTransfer() + { + byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, new BigInteger(1_00000000)); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter()); + + var result = nep5API.Transfer(NativeContract.GAS.Hash, keyPair1, UInt160.Zero, new BigInteger(1_00000000)); + Assert.IsNotNull(result); + } + } +} diff --git a/neo.UnitTests/Network/RPC/UT_PolicyAPI.cs b/neo.UnitTests/Network/RPC/UT_PolicyAPI.cs new file mode 100644 index 0000000000..6b6c449111 --- /dev/null +++ b/neo.UnitTests/Network/RPC/UT_PolicyAPI.cs @@ -0,0 +1,69 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Neo.Network.RPC; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; +using System.Numerics; + +namespace Neo.UnitTests.Network.RPC +{ + [TestClass] + public class UT_PolicyAPI + { + Mock rpcClientMock; + KeyPair keyPair1; + UInt160 sender; + PolicyAPI policyAPI; + + [TestInitialize] + public void TestSetup() + { + keyPair1 = new KeyPair(Wallet.GetPrivateKeyFromWIF("KyXwTh1hB76RRMquSvnxZrJzQx7h9nQP2PCRL38v6VDb5ip3nf1p")); + sender = Contract.CreateSignatureRedeemScript(keyPair1.PublicKey).ToScriptHash(); + rpcClientMock = UT_TransactionManager.MockRpcClient(sender, new byte[0]); + policyAPI = new PolicyAPI(rpcClientMock.Object); + } + + [TestMethod] + public void TestGetMaxTransactionsPerBlock() + { + byte[] testScript = NativeContract.Policy.Hash.MakeScript("getMaxTransactionsPerBlock"); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(512) }); + + var result = policyAPI.GetMaxTransactionsPerBlock(); + Assert.AreEqual(512u, result); + } + + [TestMethod] + public void TestGetMaxBlockSize() + { + byte[] testScript = NativeContract.Policy.Hash.MakeScript("getMaxBlockSize"); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1024u * 256u) }); + + var result = policyAPI.GetMaxBlockSize(); + Assert.AreEqual(1024u * 256u, result); + } + + [TestMethod] + public void TestGetFeePerByte() + { + byte[] testScript = NativeContract.Policy.Hash.MakeScript("getFeePerByte"); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1000) }); + + var result = policyAPI.GetFeePerByte(); + Assert.AreEqual(1000L, result); + } + + [TestMethod] + public void TestGetBlockedAccounts() + { + byte[] testScript = NativeContract.Policy.Hash.MakeScript("getBlockedAccounts"); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Array, Value = new[] { new ContractParameter { Type = ContractParameterType.Hash160, Value = UInt160.Zero } } }); + + var result = policyAPI.GetBlockedAccounts(); + Assert.AreEqual(UInt160.Zero, result[0]); + } + } +} diff --git a/neo.UnitTests/Network/RPC/UT_RpcClient.cs b/neo.UnitTests/Network/RPC/UT_RpcClient.cs index 76cf7556bf..0875a5a793 100644 --- a/neo.UnitTests/Network/RPC/UT_RpcClient.cs +++ b/neo.UnitTests/Network/RPC/UT_RpcClient.cs @@ -119,7 +119,7 @@ public void TestGetBlock() { // create block var block = new Block(); - TestUtils.SetupBlockWithValues(block, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, 0); + TestUtils.SetupBlockWithValues(block, UInt256.Zero, out _, out UInt160 _, out ulong _, out uint _, out Witness _, out Transaction[] _, 0); block.Transactions = new[] { @@ -158,7 +158,7 @@ public void TestGetBlockCount() MockResponse(response.ToString()); var result = rpc.GetBlockCount(); - Assert.AreEqual(100, result); + Assert.AreEqual(100u, result); } [TestMethod] @@ -187,7 +187,7 @@ public void TestGetBlockHeaderHex() public void TestGetBlockHeader() { Header header = new Header(); - TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal); + TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 _, out UInt160 _, out ulong _, out uint _, out Witness _); JObject json = header.ToJson(); JObject response = CreateResponse(1); @@ -231,12 +231,16 @@ public void TestGetConnectionCount() [TestMethod] public void TestGetContractState() { - var sb = new ScriptBuilder(); - sb.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); + byte[] script; + using (var sb = new ScriptBuilder()) + { + sb.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); + script = sb.ToArray(); + } ContractState state = new ContractState { - Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(sb.ToArray()).ToArray(), + Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(script).ToArray(), Manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")) }; @@ -316,7 +320,7 @@ public void TestGetRawMempoolBoth() MockResponse(response.ToString()); var result = rpc.GetRawMempoolBoth(); - Assert.AreEqual((uint)65535, result.Height); + Assert.AreEqual(65535u, result.Height); Assert.AreEqual("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e", result.Verified[0]); Assert.AreEqual("0xf86f6f2c08fbf766ebe59dc84bc3b8829f1053f0a01deb26bf7960d99fa86cd6", result.UnVerified[1]); } @@ -476,7 +480,7 @@ public void TestInvokeScript() response["result"] = json; MockResponse(response.ToString()); - var result = rpc.InvokeScript("00046e616d656724058e5e1b6008847cd662728549088a9ee82191"); + var result = rpc.InvokeScript("00046e616d656724058e5e1b6008847cd662728549088a9ee82191".HexToBytes()); Assert.AreEqual(json.ToString(), result.ToJson().ToString()); } @@ -507,7 +511,7 @@ public void TestSendRawTransaction() response["result"] = json; MockResponse(response.ToString()); - var result = rpc.SendRawTransaction("80000001195876cb34364dc38b730077156c6bc3a7fc570044a66fbfeeea56f71327e8ab0000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500c65eaf440000000f9a23e06f74cf86b8827a9108ec2e0f89ad956c9b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50092e14b5e00000030aab52ad93f6ce17ca07fa88fc191828c58cb71014140915467ecd359684b2dc358024ca750609591aa731a0b309c7fb3cab5cd0836ad3992aa0a24da431f43b68883ea5651d548feb6bd3c8e16376e6e426f91f84c58232103322f35c7819267e721335948d385fae5be66e7ba8c748ac15467dcca0693692dac"); + var result = rpc.SendRawTransaction("80000001195876cb34364dc38b730077156c6bc3a7fc570044a66fbfeeea56f71327e8ab0000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500c65eaf440000000f9a23e06f74cf86b8827a9108ec2e0f89ad956c9b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50092e14b5e00000030aab52ad93f6ce17ca07fa88fc191828c58cb71014140915467ecd359684b2dc358024ca750609591aa731a0b309c7fb3cab5cd0836ad3992aa0a24da431f43b68883ea5651d548feb6bd3c8e16376e6e426f91f84c58232103322f35c7819267e721335948d385fae5be66e7ba8c748ac15467dcca0693692dac".HexToBytes()); Assert.AreEqual(json.ToString(), ((JObject)result).ToString()); } @@ -519,7 +523,7 @@ public void TestSubmitBlock() response["result"] = json; MockResponse(response.ToString()); - var result = rpc.SubmitBlock("03febccf81ac85e3d795bc5cbd4e84e907812aa3"); + var result = rpc.SubmitBlock("03febccf81ac85e3d795bc5cbd4e84e907812aa3".HexToBytes()); Assert.AreEqual(json.ToString(), ((JObject)result).ToString()); } diff --git a/neo.UnitTests/Network/RPC/UT_TransactionManager.cs b/neo.UnitTests/Network/RPC/UT_TransactionManager.cs new file mode 100644 index 0000000000..ee55f81bb9 --- /dev/null +++ b/neo.UnitTests/Network/RPC/UT_TransactionManager.cs @@ -0,0 +1,194 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Neo.Cryptography; +using Neo.IO; +using Neo.IO.Json; +using Neo.Network.P2P; +using Neo.Network.P2P.Payloads; +using Neo.Network.RPC; +using Neo.Network.RPC.Models; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; +using System; +using System.Linq; +using System.Numerics; + +namespace Neo.UnitTests.Network.RPC +{ + [TestClass] + public class UT_TransactionManager + { + TransactionManager txManager; + Mock rpcClientMock; + KeyPair keyPair1; + KeyPair keyPair2; + UInt160 sender; + + [TestInitialize] + public void TestSetup() + { + keyPair1 = new KeyPair(Wallet.GetPrivateKeyFromWIF("KyXwTh1hB76RRMquSvnxZrJzQx7h9nQP2PCRL38v6VDb5ip3nf1p")); + keyPair2 = new KeyPair(Wallet.GetPrivateKeyFromWIF("L2LGkrwiNmUAnWYb1XGd5mv7v2eDf6P4F3gHyXSrNJJR4ArmBp7Q")); + sender = Contract.CreateSignatureRedeemScript(keyPair1.PublicKey).ToScriptHash(); + rpcClientMock = MockRpcClient(sender, new byte[1]); + } + + public static Mock MockRpcClient(UInt160 sender, byte[] script) + { + var mockRpc = new Mock(MockBehavior.Strict, "http://seed1.neo.org:10331"); + + // MockHeight + mockRpc.Setup(p => p.RpcSend("getblockcount")).Returns(100).Verifiable(); + + // MockGasBalance + byte[] balanceScript = NativeContract.GAS.Hash.MakeScript("balanceOf", sender); + var balanceResult = new ContractParameter() { Type = ContractParameterType.Integer, Value = BigInteger.Parse("10000000000000000") }; + + MockInvokeScript(mockRpc, balanceScript, balanceResult); + + // MockFeePerByte + byte[] policyScript = NativeContract.Policy.Hash.MakeScript("getFeePerByte"); + var policyResult = new ContractParameter() { Type = ContractParameterType.Integer, Value = BigInteger.Parse("1000") }; + + MockInvokeScript(mockRpc, policyScript, policyResult); + + // MockGasConsumed + var result = new ContractParameter(); + MockInvokeScript(mockRpc, script, result); + + return mockRpc; + } + + public static void MockInvokeScript(Mock mockClient, byte[] script, params ContractParameter[] parameters) + { + var result = new RpcInvokeResult() + { + Stack = parameters, + GasConsumed = "100", + Script = script.ToHexString(), + State = "", + Tx = "" + }; + + mockClient.Setup(p => p.RpcSend("invokescript", It.Is(j => j.AsString() == script.ToHexString()))) + .Returns(result.ToJson()) + .Verifiable(); + } + + [TestMethod] + public void TestMakeTransaction() + { + txManager = new TransactionManager(rpcClientMock.Object, sender); + + TransactionAttribute[] attributes = new TransactionAttribute[1] + { + new TransactionAttribute + { + Usage = TransactionAttributeUsage.Url, + Data = "53616d706c6555726c".HexToBytes() // "SampleUrl" + } + }; + + byte[] script = new byte[1]; + txManager.MakeTransaction(script, attributes, null, 60000); + + var tx = txManager.Tx; + Assert.AreEqual("53616d706c6555726c", tx.Attributes[0].Data.ToHexString()); + Assert.AreEqual(0, tx.SystemFee % (long)NativeContract.GAS.Factor); + Assert.AreEqual(60000, tx.NetworkFee); + } + + [TestMethod] + public void TestSign() + { + txManager = new TransactionManager(rpcClientMock.Object, sender); + + TransactionAttribute[] attributes = new TransactionAttribute[1] + { + new TransactionAttribute + { + Usage = TransactionAttributeUsage.Url, + Data = "53616d706c6555726c".HexToBytes() // "SampleUrl" + } + }; + + byte[] script = new byte[1]; + txManager.MakeTransaction(script, attributes) + .AddSignature(keyPair1) + .Sign(); + + // get signature from Witnesses + var tx = txManager.Tx; + byte[] signature = tx.Witnesses[0].InvocationScript.Skip(1).ToArray(); + + Assert.IsTrue(Crypto.Default.VerifySignature(tx.GetHashData(), signature, keyPair1.PublicKey.EncodePoint(false).Skip(1).ToArray())); + + // duplicate sign should not add new witness + txManager.AddSignature(keyPair1).Sign(); + Assert.AreEqual(1, txManager.Tx.Witnesses.Length); + + // throw exception when the KeyPair is wrong + Assert.ThrowsException(() => txManager.AddSignature(keyPair2)); + } + + [TestMethod] + public void TestSignMulti() + { + txManager = new TransactionManager(rpcClientMock.Object, sender); + + var multiContract = Contract.CreateMultiSigContract(2, keyPair1.PublicKey, keyPair2.PublicKey); + + // Cosigner needs multi signature + Cosigner[] cosigners = new Cosigner[1] + { + new Cosigner + { + Account = multiContract.ScriptHash, + Scopes = WitnessScope.Global + } + }; + + byte[] script = new byte[1]; + txManager.MakeTransaction(script, null, cosigners, 0_10000000) + .AddMultiSig(keyPair1, 2, keyPair1.PublicKey, keyPair2.PublicKey) + .AddMultiSig(keyPair2, 2, keyPair1.PublicKey, keyPair2.PublicKey) + .AddSignature(keyPair1) + .Sign(); + + var store = TestBlockchain.GetStore(); + var snapshot = store.GetSnapshot(); + + var tx = txManager.Tx; + Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); + } + + [TestMethod] + public void TestAddWitness() + { + txManager = new TransactionManager(rpcClientMock.Object, sender); + + // Cosigner as contract scripthash + Cosigner[] cosigners = new Cosigner[1] + { + new Cosigner + { + Account = UInt160.Zero, + Scopes = WitnessScope.Global + } + }; + + byte[] script = new byte[1]; + txManager.MakeTransaction(script, null, cosigners, 0_10000000); + txManager.AddWitness(UInt160.Zero); + txManager.AddSignature(keyPair1); + txManager.Sign(); + + var tx = txManager.Tx; + Assert.AreEqual(2, tx.Witnesses.Length); + Assert.AreEqual(0, tx.Witnesses[0].VerificationScript.Length); + Assert.AreEqual(0, tx.Witnesses[0].InvocationScript.Length); + } + } +} diff --git a/neo.UnitTests/VM/UT_Helper.cs b/neo.UnitTests/VM/UT_Helper.cs index e9ccc539bb..cf5ad0bff5 100644 --- a/neo.UnitTests/VM/UT_Helper.cs +++ b/neo.UnitTests/VM/UT_Helper.cs @@ -1,7 +1,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.ECC; using Neo.SmartContract; using Neo.VM; using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; using System.Text; namespace Neo.UnitTests.IO @@ -78,5 +82,61 @@ public void TestEmitAppCall3() byte[] resultArray = sb.ToArray(); Assert.AreEqual(Encoding.Default.GetString(tempArray), Encoding.Default.GetString(resultArray)); } + + [TestMethod] + public void TestToParameter() + { + StackItem byteItem = "00e057eb481b".HexToBytes(); + Assert.AreEqual(30000000000000L, (long)new BigInteger(byteItem.ToParameter().Value as byte[])); + + StackItem boolItem = false; + Assert.AreEqual(false, (bool)boolItem.ToParameter().Value); + + StackItem intItem = new BigInteger(1000); + Assert.AreEqual(1000, (BigInteger)intItem.ToParameter().Value); + + StackItem interopItem = new VM.Types.InteropInterface("test"); + Assert.AreEqual(null, interopItem.ToParameter().Value); + + StackItem arrayItem = new VM.Types.Array(new[] { byteItem, boolItem, intItem, interopItem }); + Assert.AreEqual(1000, (BigInteger)(arrayItem.ToParameter().Value as List)[2].Value); + + StackItem mapItem = new VM.Types.Map(new Dictionary(new[] { new KeyValuePair(byteItem, intItem) })); + Assert.AreEqual(1000, (BigInteger)(mapItem.ToParameter().Value as List>)[0].Value.Value); + } + + [TestMethod] + public void TestToStackItem() + { + ContractParameter byteParameter = new ContractParameter { Type = ContractParameterType.ByteArray, Value = "00e057eb481b".HexToBytes() }; + Assert.AreEqual(30000000000000L, (long)byteParameter.ToStackItem().GetBigInteger()); + + ContractParameter boolParameter = new ContractParameter { Type = ContractParameterType.Boolean, Value = false }; + Assert.AreEqual(false, boolParameter.ToStackItem().GetBoolean()); + + ContractParameter intParameter = new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1000) }; + Assert.AreEqual(1000, intParameter.ToStackItem().GetBigInteger()); + + ContractParameter h160Parameter = new ContractParameter { Type = ContractParameterType.Hash160, Value = UInt160.Zero }; + Assert.AreEqual(0, h160Parameter.ToStackItem().GetBigInteger()); + + ContractParameter h256Parameter = new ContractParameter { Type = ContractParameterType.Hash256, Value = UInt256.Zero }; + Assert.AreEqual(0, h256Parameter.ToStackItem().GetBigInteger()); + + ContractParameter pkParameter = new ContractParameter { Type = ContractParameterType.PublicKey, Value = ECPoint.Parse("02f9ec1fd0a98796cf75b586772a4ddd41a0af07a1dbdf86a7238f74fb72503575", ECCurve.Secp256r1) }; + Assert.AreEqual("02f9ec1fd0a98796cf75b586772a4ddd41a0af07a1dbdf86a7238f74fb72503575", pkParameter.ToStackItem().GetByteArray().ToHexString()); + + ContractParameter strParameter = new ContractParameter { Type = ContractParameterType.String, Value = "test😂👍" }; + Assert.AreEqual("test😂👍", Encoding.UTF8.GetString(strParameter.ToStackItem().GetByteArray())); + + ContractParameter interopParameter = new ContractParameter { Type = ContractParameterType.InteropInterface }; + Assert.AreEqual(null, interopParameter.ToStackItem()); + + ContractParameter arrayParameter = new ContractParameter { Type = ContractParameterType.Array, Value = new[] { byteParameter, boolParameter, intParameter, h160Parameter, h256Parameter, pkParameter, strParameter, interopParameter }.ToList() }; + Assert.AreEqual(1000, ((VM.Types.Array)arrayParameter.ToStackItem())[2].GetBigInteger()); + + ContractParameter mapParameter = new ContractParameter { Type = ContractParameterType.Map, Value = new[] { new KeyValuePair(byteParameter, pkParameter) } }; + Assert.AreEqual(30000000000000L, (long)((VM.Types.Map)mapParameter.ToStackItem()).Keys.First().GetBigInteger()); + } } } diff --git a/neo/Network/RPC/ContractClient.cs b/neo/Network/RPC/ContractClient.cs new file mode 100644 index 0000000000..a329e07674 --- /dev/null +++ b/neo/Network/RPC/ContractClient.cs @@ -0,0 +1,65 @@ +using Neo.Network.P2P.Payloads; +using Neo.Network.RPC.Models; +using Neo.SmartContract; +using Neo.SmartContract.Manifest; +using Neo.VM; +using Neo.Wallets; + +namespace Neo.Network.RPC +{ + /// + /// Contract related operations through RPC API + /// + public class ContractClient + { + protected readonly RpcClient rpcClient; + + /// + /// ContractClient Constructor + /// + /// the RPC client to call NEO RPC methods + public ContractClient(RpcClient rpc) + { + rpcClient = rpc; + } + + /// + /// Use RPC method to test invoke operation. + /// + /// contract script hash + /// contract operation + /// operation arguments + /// + public RpcInvokeResult TestInvoke(UInt160 scriptHash, string operation, params object[] args) + { + byte[] script = scriptHash.MakeScript(operation, args); + return rpcClient.InvokeScript(script); + } + + /// + /// Deploy Contract, return signed transaction + /// + /// contract script + /// contract manifest + /// sender KeyPair + /// transaction NetworkFee, set to be 0 if you don't need higher priority + /// + public Transaction DeployContract(byte[] contractScript, ContractManifest manifest, KeyPair key, long networkFee = 0) + { + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + sb.EmitSysCall(InteropService.Neo_Contract_Create, contractScript, manifest.ToString()); + script = sb.ToArray(); + } + + Transaction tx = new TransactionManager(rpcClient, Contract.CreateSignatureRedeemScript(key.PublicKey).ToScriptHash()) + .MakeTransaction(script, null, null, networkFee) + .AddSignature(key) + .Sign() + .Tx; + + return tx; + } + } +} diff --git a/neo/Network/RPC/Models/RpcInvokeResult.cs b/neo/Network/RPC/Models/RpcInvokeResult.cs index 73f2c6a2af..c56307950a 100644 --- a/neo/Network/RPC/Models/RpcInvokeResult.cs +++ b/neo/Network/RPC/Models/RpcInvokeResult.cs @@ -1,24 +1,19 @@ using Neo.IO.Json; -using Newtonsoft.Json; +using Neo.SmartContract; using System.Linq; namespace Neo.Network.RPC.Models { public class RpcInvokeResult { - [JsonProperty(PropertyName = "script")] public string Script { get; set; } - [JsonProperty(PropertyName = "state")] public string State { get; set; } - [JsonProperty(PropertyName = "gas_consumed")] public string GasConsumed { get; set; } - [JsonProperty(PropertyName = "stack")] - public RpcStack[] Stack { get; set; } + public ContractParameter[] Stack { get; set; } - [JsonProperty(PropertyName = "tx")] public string Tx { get; set; } public JObject ToJson() @@ -39,7 +34,7 @@ public static RpcInvokeResult FromJson(JObject json) invokeScriptResult.State = json["state"].AsString(); invokeScriptResult.GasConsumed = json["gas_consumed"].AsString(); invokeScriptResult.Tx = json["tx"].AsString(); - invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => RpcStack.FromJson(p)).ToArray(); + invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => ContractParameter.FromJson(p)).ToArray(); return invokeScriptResult; } } diff --git a/neo/Network/RPC/Nep5API.cs b/neo/Network/RPC/Nep5API.cs new file mode 100644 index 0000000000..abfad6c9ed --- /dev/null +++ b/neo/Network/RPC/Nep5API.cs @@ -0,0 +1,97 @@ +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.VM; +using Neo.Wallets; +using System.Linq; +using System.Numerics; + +namespace Neo.Network.RPC +{ + /// + /// Call NEP5 methods with RPC API + /// + public class Nep5API : ContractClient + { + /// + /// Nep5API Constructor + /// + /// the RPC client to call NEO RPC methods + public Nep5API(RpcClient rpcClient) : base(rpcClient) { } + + /// + /// Get balance of NEP5 token + /// + /// contract script hash + /// account script hash + /// + public BigInteger BalanceOf(UInt160 scriptHash, UInt160 account) + { + BigInteger balance = TestInvoke(scriptHash, "balanceOf", account).Stack.Single().ToStackItem().GetBigInteger(); + return balance; + } + + /// + /// Get name of NEP5 token + /// + /// contract script hash + /// + public string Name(UInt160 scriptHash) + { + return TestInvoke(scriptHash, "name").Stack.Single().ToStackItem().GetString(); + } + + /// + /// Get symbol of NEP5 token + /// + /// contract script hash + /// + public string Symbol(UInt160 scriptHash) + { + return TestInvoke(scriptHash, "symbol").Stack.Single().ToStackItem().GetString(); + } + + /// + /// Get decimals of NEP5 token + /// + /// contract script hash + /// + public uint Decimals(UInt160 scriptHash) + { + return (uint)TestInvoke(scriptHash, "decimals").Stack.Single().ToStackItem().GetBigInteger(); + } + + /// + /// Get total supply of NEP5 token + /// + /// contract script hash + /// + public BigInteger TotalSupply(UInt160 scriptHash) + { + return TestInvoke(scriptHash, "totalSupply").Stack.Single().ToStackItem().GetBigInteger(); + } + + /// + /// Get name of NEP5 token + /// + /// contract script hash + /// from KeyPair + /// to account script hash + /// transfer amount + /// netwotk fee, set to be 0 if you don't need higher priority + /// + public Transaction Transfer(UInt160 scriptHash, KeyPair fromKey, UInt160 to, BigInteger amount, long networkFee = 0) + { + var sender = Contract.CreateSignatureRedeemScript(fromKey.PublicKey).ToScriptHash(); + Cosigner[] cosigners = new[] { new Cosigner { Scopes = WitnessScope.CalledByEntry, Account = sender } }; + + byte[] script = scriptHash.MakeScript("transfer", sender, to, amount); + Transaction tx = new TransactionManager(rpcClient, sender) + .MakeTransaction(script, null, cosigners, networkFee) + .AddSignature(fromKey) + .Sign() + .Tx; + + return tx; + } + } +} diff --git a/neo/Network/RPC/PolicyAPI.cs b/neo/Network/RPC/PolicyAPI.cs new file mode 100644 index 0000000000..969c1c22f1 --- /dev/null +++ b/neo/Network/RPC/PolicyAPI.cs @@ -0,0 +1,57 @@ +using Neo.SmartContract.Native; +using Neo.VM; +using System.Linq; + +namespace Neo.Network.RPC +{ + /// + /// Get Policy info by RPC API + /// + public class PolicyAPI : ContractClient + { + readonly UInt160 scriptHash = NativeContract.Policy.Hash; + + /// + /// PolicyAPI Constructor + /// + /// the RPC client to call NEO RPC methods + public PolicyAPI(RpcClient rpcClient) : base(rpcClient) { } + + /// + /// Get Max Transactions Count Per Block + /// + /// + public uint GetMaxTransactionsPerBlock() + { + return (uint)TestInvoke(scriptHash, "getMaxTransactionsPerBlock").Stack.Single().ToStackItem().GetBigInteger(); + } + + /// + /// Get Max Block Size + /// + /// + public uint GetMaxBlockSize() + { + return (uint)TestInvoke(scriptHash, "getMaxBlockSize").Stack.Single().ToStackItem().GetBigInteger(); + } + + /// + /// Get Network Fee Per Byte + /// + /// + public long GetFeePerByte() + { + return (long)TestInvoke(scriptHash, "getFeePerByte").Stack.Single().ToStackItem().GetBigInteger(); + } + + /// + /// Get Ploicy Blocked Accounts + /// + /// + public UInt160[] GetBlockedAccounts() + { + var result = (VM.Types.Array)TestInvoke(scriptHash, "getBlockedAccounts").Stack.Single().ToStackItem(); + return result.Select(p => new UInt160(p.GetByteArray())).ToArray(); + } + } +} diff --git a/neo/Network/RPC/RpcClient.cs b/neo/Network/RPC/RpcClient.cs index 69352b8cfd..cd0578953e 100644 --- a/neo/Network/RPC/RpcClient.cs +++ b/neo/Network/RPC/RpcClient.cs @@ -9,6 +9,9 @@ namespace Neo.Network.RPC { + /// + /// The RPC client to call NEO RPC methods + /// public class RpcClient : IDisposable { private readonly HttpClient httpClient; @@ -31,17 +34,19 @@ public void Dispose() public async Task SendAsync(RpcRequest request) { var requestJson = request.ToJson().ToString(); - var result = await httpClient.PostAsync(httpClient.BaseAddress, new StringContent(requestJson, Encoding.UTF8)); - var content = await result.Content.ReadAsStringAsync(); - var response = RpcResponse.FromJson(JObject.Parse(content)); - response.RawResponse = content; - - if (response.Error != null) + using (var result = await httpClient.PostAsync(httpClient.BaseAddress, new StringContent(requestJson, Encoding.UTF8))) { - throw new RpcException(response.Error.Code, response.Error.Message); - } + var content = await result.Content.ReadAsStringAsync(); + var response = RpcResponse.FromJson(JObject.Parse(content)); + response.RawResponse = content; - return response; + if (response.Error != null) + { + throw new RpcException(response.Error.Code, response.Error.Message); + } + + return response; + } } public RpcResponse Send(RpcRequest request) @@ -56,7 +61,7 @@ public RpcResponse Send(RpcRequest request) } } - private JObject RpcSend(string method, params JObject[] paraArgs) + public virtual JObject RpcSend(string method, params JObject[] paraArgs) { var request = new RpcRequest { @@ -104,9 +109,9 @@ public RpcBlock GetBlock(string hashOrIndex) /// /// Gets the number of blocks in the main chain. /// - public int GetBlockCount() + public uint GetBlockCount() { - return (int)RpcSend("getblockcount").AsNumber(); + return (uint)RpcSend("getblockcount").AsNumber(); } /// @@ -187,7 +192,7 @@ public string[] GetRawMempool() /// public RpcRawMemPool GetRawMempoolBoth() { - return RpcRawMemPool.FromJson(RpcSend("getrawmempool")); + return RpcRawMemPool.FromJson(RpcSend("getrawmempool", true)); } /// @@ -252,9 +257,9 @@ public RpcInvokeResult InvokeFunction(string address, string function, RpcStack[ /// Returns the result after passing a script through the VM. /// This RPC call does not affect the blockchain in any way. /// - public RpcInvokeResult InvokeScript(string script) + public RpcInvokeResult InvokeScript(byte[] script) { - return RpcInvokeResult.FromJson(RpcSend("invokescript", script)); + return RpcInvokeResult.FromJson(RpcSend("invokescript", script.ToHexString())); } /// @@ -268,17 +273,17 @@ public RpcPlugin[] ListPlugins() /// /// Broadcasts a transaction over the NEO network. /// - public bool SendRawTransaction(string rawTransaction) + public bool SendRawTransaction(byte[] rawTransaction) { - return RpcSend("sendrawtransaction", rawTransaction).AsBoolean(); + return RpcSend("sendrawtransaction", rawTransaction.ToHexString()).AsBoolean(); } /// /// Broadcasts a raw block over the NEO network. /// - public bool SubmitBlock(string block) + public bool SubmitBlock(byte[] block) { - return RpcSend("submitblock", block).AsBoolean(); + return RpcSend("submitblock", block.ToHexString()).AsBoolean(); } /// diff --git a/neo/Network/RPC/TransactionManager.cs b/neo/Network/RPC/TransactionManager.cs new file mode 100644 index 0000000000..7b4db697ab --- /dev/null +++ b/neo/Network/RPC/TransactionManager.cs @@ -0,0 +1,220 @@ +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.Network.P2P.Payloads; +using Neo.Network.RPC.Models; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; +using System; + +namespace Neo.Network.RPC +{ + /// + /// This class helps to create transaction with RPC API. + /// + public class TransactionManager + { + private static readonly Random rand = new Random(); + private readonly RpcClient rpcClient; + private readonly UInt160 sender; + + /// + /// The Transaction context to manage the witnesses + /// + private ContractParametersContext context; + + /// + /// The Transaction managed by this class + /// + public Transaction Tx { get; private set; } + + /// + /// TransactionManager Constructor + /// + /// the RPC client to call NEO RPC API + /// the account script hash of sender + public TransactionManager(RpcClient rpc, UInt160 sender) + { + rpcClient = rpc; + this.sender = sender; + } + + /// + /// Create an unsigned Transaction object with given parameters. + /// + /// Transaction Script + /// Transaction Attributes + /// Transaction Cosigners + /// Transaction NetworkFee, will set to estimate value(with only basic signatures) when networkFee is 0 + /// + public TransactionManager MakeTransaction(byte[] script, TransactionAttribute[] attributes = null, Cosigner[] cosigners = null, long networkFee = 0) + { + uint height = rpcClient.GetBlockCount() - 1; + Tx = new Transaction + { + Version = 0, + Nonce = (uint)rand.Next(), + Script = script, + Sender = sender, + ValidUntilBlock = height + Transaction.MaxValidUntilBlockIncrement, + Attributes = attributes ?? new TransactionAttribute[0], + Cosigners = cosigners ?? new Cosigner[0], + Witnesses = new Witness[0] + }; + + RpcInvokeResult result = rpcClient.InvokeScript(script); + Tx.SystemFee = Math.Max(long.Parse(result.GasConsumed) - ApplicationEngine.GasFree, 0); + if (Tx.SystemFee > 0) + { + long d = (long)NativeContract.GAS.Factor; + long remainder = Tx.SystemFee % d; + if (remainder > 0) + Tx.SystemFee += d - remainder; + else if (remainder < 0) + Tx.SystemFee -= remainder; + } + + context = new ContractParametersContext(Tx); + + // set networkfee to estimate value when networkFee is 0 + Tx.NetworkFee = networkFee == 0 ? EstimateNetworkFee() : networkFee; + + var gasBalance = new Nep5API(rpcClient).BalanceOf(NativeContract.GAS.Hash, sender); + if (gasBalance >= Tx.SystemFee + Tx.NetworkFee) return this; + throw new InvalidOperationException($"Insufficient GAS in address: {sender.ToAddress()}"); + } + + /// + /// Estimate NetworkFee, assuming the witnesses are basic Signature Contract + /// + private long EstimateNetworkFee() + { + long networkFee = 0; + UInt160[] hashes = Tx.GetScriptHashesForVerifying(null); + int size = Transaction.HeaderSize + Tx.Attributes.GetVarSize() + Tx.Script.GetVarSize() + IO.Helper.GetVarSize(hashes.Length); + + // assume the hashes are single Signature + foreach (var hash in hashes) + { + size += 166; + networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES64] + ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES33] + InteropService.GetPrice(InteropService.Neo_Crypto_CheckSig, null); + } + + networkFee += size * new PolicyAPI(rpcClient).GetFeePerByte(); + return networkFee; + } + + /// + /// Calculate NetworkFee with context items + /// + private long CalculateNetworkFee() + { + long networkFee = 0; + UInt160[] hashes = Tx.GetScriptHashesForVerifying(null); + int size = Transaction.HeaderSize + Tx.Attributes.GetVarSize() + Tx.Script.GetVarSize() + IO.Helper.GetVarSize(hashes.Length); + foreach (UInt160 hash in hashes) + { + byte[] witness_script = context.GetScript(hash); + if (witness_script is null || witness_script.Length == 0) + { + try + { + witness_script = rpcClient.GetContractState(hash.ToString())?.Script; + } + catch { } + } + + if (witness_script is null) continue; + + networkFee += Wallet.CalculateNetWorkFee(witness_script, ref size); + } + networkFee += size * new PolicyAPI(rpcClient).GetFeePerByte(); + return networkFee; + } + + /// + /// Add Signature + /// + /// The KeyPair to sign transction + /// + public TransactionManager AddSignature(KeyPair key) + { + var contract = Contract.CreateSignatureContract(key.PublicKey); + + byte[] signature = Tx.Sign(key); + if (!context.AddSignature(contract, key.PublicKey, signature)) + { + throw new Exception("AddSignature failed!"); + } + + return this; + } + + /// + /// Add Multi-Signature + /// + /// The KeyPair to sign transction + /// The least count of signatures needed for multiple signature contract + /// The Public Keys construct the multiple signature contract + public TransactionManager AddMultiSig(KeyPair key, int m, params ECPoint[] publicKeys) + { + Contract contract = Contract.CreateMultiSigContract(m, publicKeys); + + byte[] signature = Tx.Sign(key); + if (!context.AddSignature(contract, key.PublicKey, signature)) + { + throw new Exception("AddMultiSig failed!"); + } + + return this; + } + + /// + /// Add Witness with contract + /// + /// The witness verification contract + /// The witness invocation parameters + public TransactionManager AddWitness(Contract contract, params object[] parameters) + { + if (!context.Add(contract, parameters)) + { + throw new Exception("AddWitness failed!"); + }; + return this; + } + + /// + /// Add Witness with scriptHash + /// + /// The witness verification contract hash + /// The witness invocation parameters + public TransactionManager AddWitness(UInt160 scriptHash, params object[] parameters) + { + var contract = Contract.Create(scriptHash); + return AddWitness(contract, parameters); + } + + /// + /// Verify Witness count and add witnesses + /// + public TransactionManager Sign() + { + // Verify witness count + if (!context.Completed) + { + throw new Exception($"Please add signature or witness first!"); + } + + // Calculate NetworkFee + long leastNetworkFee = CalculateNetworkFee(); + if (Tx.NetworkFee < leastNetworkFee) + { + throw new InvalidOperationException("Insufficient NetworkFee"); + } + + Tx.Witnesses = context.GetWitnesses(); + return this; + } + } +} diff --git a/neo/SmartContract/Contract.cs b/neo/SmartContract/Contract.cs index 19fcceb7ca..58e32768d7 100644 --- a/neo/SmartContract/Contract.cs +++ b/neo/SmartContract/Contract.cs @@ -46,6 +46,20 @@ public static Contract Create(ContractParameterType[] parameterList, byte[] rede }; } + /// + /// Construct special Contract with empty Script, will get the Script with scriptHash from blockchain when doing the Verify + /// verification = snapshot.Contracts.TryGet(hashes[i])?.Script; + /// + public static Contract Create(UInt160 scriptHash, params ContractParameterType[] parameterList) + { + return new Contract + { + Script = new byte[0], + _scriptHash = scriptHash, + ParameterList = parameterList + }; + } + public static Contract CreateMultiSigContract(int m, params ECPoint[] publicKeys) { return new Contract diff --git a/neo/SmartContract/ContractParametersContext.cs b/neo/SmartContract/ContractParametersContext.cs index 8a91c936b8..0388df342c 100644 --- a/neo/SmartContract/ContractParametersContext.cs +++ b/neo/SmartContract/ContractParametersContext.cs @@ -86,10 +86,19 @@ public IReadOnlyList ScriptHashes get { if (_ScriptHashes == null) + { + // snapshot is not necessary for Transaction + if (Verifiable is Transaction) + { + _ScriptHashes = Verifiable.GetScriptHashesForVerifying(null); + return _ScriptHashes; + } + using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) { _ScriptHashes = Verifiable.GetScriptHashesForVerifying(snapshot); } + } return _ScriptHashes; } } @@ -108,6 +117,17 @@ public bool Add(Contract contract, int index, object parameter) return true; } + public bool Add(Contract contract, params object[] parameters) + { + ContextItem item = CreateItem(contract); + if (item == null) return false; + for (int index = 0; index < parameters.Length; index++) + { + item.Parameters[index].Value = parameters[index]; + } + return true; + } + public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) { if (contract.Script.IsMultiSigContract(out _, out _)) @@ -220,6 +240,13 @@ public IReadOnlyList GetParameters(UInt160 scriptHash) return item.Parameters; } + public byte[] GetScript(UInt160 scriptHash) + { + if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + return null; + return item.Script; + } + public Witness[] GetWitnesses() { if (!Completed) throw new InvalidOperationException(); diff --git a/neo/VM/Helper.cs b/neo/VM/Helper.cs index e996463e3f..d63bebb89a 100644 --- a/neo/VM/Helper.cs +++ b/neo/VM/Helper.cs @@ -162,6 +162,25 @@ public static ScriptBuilder EmitSysCall(this ScriptBuilder sb, uint method, para return sb.EmitSysCall(method); } + /// + /// Generate scripts to call a specific method from a specific contract. + /// + /// contract script hash + /// contract operation + /// operation arguments + /// + public static byte[] MakeScript(this UInt160 scriptHash, string operation, params object[] args) + { + using (ScriptBuilder sb = new ScriptBuilder()) + { + if (args.Length > 0) + sb.EmitAppCall(scriptHash, operation, args); + else + sb.EmitAppCall(scriptHash, operation); + return sb.ToArray(); + } + } + public static ContractParameter ToParameter(this StackItem item) { return ToParameter(item, null); @@ -228,5 +247,67 @@ private static ContractParameter ToParameter(StackItem item, List> context) + { + StackItem stackItem = null; + switch (parameter.Type) + { + case ContractParameterType.Array: + if (context is null) + context = new List>(); + else + stackItem = context.FirstOrDefault(p => ReferenceEquals(p.Item2, parameter))?.Item1; + if (stackItem is null) + { + stackItem = ((IList)parameter.Value).Select(p => ToStackItem(p, context)).ToList(); + context.Add(new Tuple(stackItem, parameter)); + } + break; + case ContractParameterType.Map: + if (context is null) + context = new List>(); + else + stackItem = context.FirstOrDefault(p => ReferenceEquals(p.Item2, parameter))?.Item1; + if (stackItem is null) + { + stackItem = new Map(((IList>)parameter.Value).ToDictionary(p => ToStackItem(p.Key, context), p => ToStackItem(p.Value, context))); + context.Add(new Tuple(stackItem, parameter)); + } + break; + case ContractParameterType.Boolean: + stackItem = (bool)parameter.Value; + break; + case ContractParameterType.ByteArray: + case ContractParameterType.Signature: + stackItem = (byte[])parameter.Value; + break; + case ContractParameterType.Integer: + stackItem = (BigInteger)parameter.Value; + break; + case ContractParameterType.Hash160: + stackItem = ((UInt160)parameter.Value).ToArray(); + break; + case ContractParameterType.Hash256: + stackItem = ((UInt256)parameter.Value).ToArray(); + break; + case ContractParameterType.PublicKey: + stackItem = ((ECPoint)parameter.Value).EncodePoint(true); + break; + case ContractParameterType.String: + stackItem = (string)parameter.Value; + break; + case ContractParameterType.InteropInterface: + break; + default: + throw new ArgumentException($"ContractParameterType({parameter.Type}) is not supported to StackItem."); + } + return stackItem; + } } } diff --git a/neo/Wallets/Wallet.cs b/neo/Wallets/Wallet.cs index eb816c7a0a..5149c2b2fe 100644 --- a/neo/Wallets/Wallet.cs +++ b/neo/Wallets/Wallet.cs @@ -338,27 +338,7 @@ private Transaction MakeTransaction(Snapshot snapshot, byte[] script, Transactio { byte[] witness_script = GetAccount(hash)?.Contract?.Script ?? snapshot.Contracts.TryGet(hash)?.Script; if (witness_script is null) continue; - if (witness_script.IsSignatureContract()) - { - size += 66 + witness_script.GetVarSize(); - tx.NetworkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES64] + ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES33] + InteropService.GetPrice(InteropService.Neo_Crypto_CheckSig, null); - } - else if (witness_script.IsMultiSigContract(out int m, out int n)) - { - int size_inv = 65 * m; - size += IO.Helper.GetVarSize(size_inv) + size_inv + witness_script.GetVarSize(); - tx.NetworkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES64] * m; - using (ScriptBuilder sb = new ScriptBuilder()) - tx.NetworkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(m).ToArray()[0]]; - tx.NetworkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES33] * n; - using (ScriptBuilder sb = new ScriptBuilder()) - tx.NetworkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(n).ToArray()[0]]; - tx.NetworkFee += InteropService.GetPrice(InteropService.Neo_Crypto_CheckSig, null) * n; - } - else - { - //We can support more contract types in the future. - } + tx.NetworkFee += CalculateNetWorkFee(witness_script, ref size); } tx.NetworkFee += size * NativeContract.Policy.GetFeePerByte(snapshot); if (value >= tx.SystemFee + tx.NetworkFee) return tx; @@ -366,6 +346,35 @@ private Transaction MakeTransaction(Snapshot snapshot, byte[] script, Transactio throw new InvalidOperationException("Insufficient GAS"); } + public static long CalculateNetWorkFee(byte[] witness_script, ref int size) + { + long networkFee = 0; + + if (witness_script.IsSignatureContract()) + { + size += 66 + witness_script.GetVarSize(); + networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES64] + ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES33] + InteropService.GetPrice(InteropService.Neo_Crypto_CheckSig, null); + } + else if (witness_script.IsMultiSigContract(out int m, out int n)) + { + int size_inv = 65 * m; + size += IO.Helper.GetVarSize(size_inv) + size_inv + witness_script.GetVarSize(); + networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES64] * m; + using (ScriptBuilder sb = new ScriptBuilder()) + networkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(m).ToArray()[0]]; + networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHBYTES33] * n; + using (ScriptBuilder sb = new ScriptBuilder()) + networkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(n).ToArray()[0]]; + networkFee += InteropService.GetPrice(InteropService.Neo_Crypto_CheckSig, null) * n; + } + else + { + //We can support more contract types in the future. + } + + return networkFee; + } + public bool Sign(ContractParametersContext context) { bool fSuccess = false; From f7e03624f6e132a642e9fb50f0d0ee6c68ea0cb9 Mon Sep 17 00:00:00 2001 From: Ricardo Prado <38396062+lock9@users.noreply.github.com> Date: Sat, 21 Sep 2019 23:53:17 -0300 Subject: [PATCH 54/54] Template fix (#1107) * Fixing template * Fix --- .../feature-or-enhancement-request.md | 25 +++++++------- CONTRIBUTING.md | 34 +++++++++---------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature-or-enhancement-request.md b/.github/ISSUE_TEMPLATE/feature-or-enhancement-request.md index 30077088b9..a2ddf9047c 100644 --- a/.github/ISSUE_TEMPLATE/feature-or-enhancement-request.md +++ b/.github/ISSUE_TEMPLATE/feature-or-enhancement-request.md @@ -12,15 +12,16 @@ A summary of the problem you want to solve or metric you want to improve **Do you have any solution you want to propose?** A clear and concise description of what you expect with this change. -**Where in software does this update applies to?** -- [ ] Compiler -- [ ] Consensus -- [ ] CLI -- [ ] Plugins -- [ ] Ledger -- [ ] Network Policy -- [ ] P2P (TCP) -- [ ] RPC (HTTP) -- [ ] SDK -- [ ] VM -- [ ] Other: +**Where in the software does this update applies to?** +- Compiler +- Consensus +- CLI +- Plugins +- Ledger +- Network Policy +- P2P (TCP) +- RPC (HTTP) +- SDK +- VM +- Other: + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 655dcda27a..5fd0592924 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,45 +37,45 @@ If you are looking to start contributing to NEO, we suggest you start working on ### Tags for Issues States -![](./.github/images/discussion.png) Whenever someone posts a new feature request, the tag discussion is added. This means that there is no consensus if the feature should be implemented or not. Avoid creating PR to solve issues in this state since it may be completely discarded. +![Discussion](./.github/images/discussion.png) Whenever someone posts a new feature request, the tag discussion is added. This means that there is no consensus if the feature should be implemented or not. Avoid creating PR to solve issues in this state since it may be completely discarded. -![](./.github/images/solution-design.png) When a feature request is accepted by the team, but there is no consensus about the implementation, the issue is tagged with design. We recommend the team to agree in the solution design before anyone attempts to implement it, using text or UML. It is not recommended, but developers can also present their solution using code. +![Design](./.github/images/solution-design.png) When a feature request is accepted by the team, but there is no consensus about the implementation, the issue is tagged with design. We recommend the team to agree in the solution design before anyone attempts to implement it, using text or UML. It is not recommended, but developers can also present their solution using code. Note that PRs for issues in this state may also be discarded if the team disagree with the proposed solution. -![](./.github/images/ready-to-implement.png) Once the team has agreed on feature and the proposed solution, the issue is tagged with ready-to-implement. When implementing it, please follow the solution accepted by the team. +![Ready-to-implement](./.github/images/ready-to-implement.png) Once the team has agreed on feature and the proposed solution, the issue is tagged with ready-to-implement. When implementing it, please follow the solution accepted by the team. ### Tags for Issue Types -![](./.github/images/cosmetic.png) Issues with the cosmetic tag are usually changes in code or documentation that improve user experience without affecting current functionality. These issues are recommended for beginners because they require little to no knowledge about Neo platform. +![Cosmetic](./.github/images/cosmetic.png) Issues with the cosmetic tag are usually changes in code or documentation that improve user experience without affecting current functionality. These issues are recommended for beginners because they require little to no knowledge about Neo platform. -![](./.github/images/enhancement.png) Enhancements are platform changes that may affect performance, usability or add new features to existing modules. It is recommended that developers have previous knowledge in the platform to work in these improvements, specially in more complicated modules like the compiler, ledger and consensus. +![Enhancement](./.github/images/enhancement.png) Enhancements are platform changes that may affect performance, usability or add new features to existing modules. It is recommended that developers have previous knowledge in the platform to work in these improvements, specially in more complicated modules like the compiler, ledger and consensus. -![](./.github/images/new-feature.png) New features may include large changes in the code base. Some are complex, but some are not. So, a few issues with new-feature may be recommended for starters, specially those related to the rpc and the sdk module. +![Feature](./.github/images/new-feature.png) New features may include large changes in the code base. Some are complex, but some are not. So, a few issues with new-feature may be recommended for starters, specially those related to the rpc and the sdk module. -![](./.github/images/migration.png) Issues related to the migration from Neo 2 to Neo 3 are tagged with migration. These issues are usually the most complicated ones since they require a deep knowledge in both versions. +![Migration](./.github/images/migration.png) Issues related to the migration from Neo 2 to Neo 3 are tagged with migration. These issues are usually the most complicated ones since they require a deep knowledge in both versions. ### Tags for Project Modules These tags do not necessarily represent each module at code level. Modules consensus and compiler are not recommended for beginners. -![](./.github/images/compiler.png) Issues that are related or influence the behavior of our C# compiler. Note that the compiler itself is hosted in the [neo-devpack-dotnet](https://github.com/neo-project/neo-devpack-dotnet) repository. +![Compiler](./.github/images/compiler.png) Issues that are related or influence the behavior of our C# compiler. Note that the compiler itself is hosted in the [neo-devpack-dotnet](https://github.com/neo-project/neo-devpack-dotnet) repository. -![](./.github/images/consensus.png) Changes to consensus are usually harder to make and test. Avoid implementing issues in this module that are not yet decided. +![Consensus](./.github/images/consensus.png) Changes to consensus are usually harder to make and test. Avoid implementing issues in this module that are not yet decided. -![](./.github/images/ledger.png) The ledger is our 'database', any changes in the way we store information or the data-structures have this tag. +![Ledger](./.github/images/ledger.png) The ledger is our 'database', any changes in the way we store information or the data-structures have this tag. -![](./.github/images/house-keeping.png) 'Small' enhancements that need to be done in order to keep the project organised and ensure overall quality. These changes may be applied in any place in code, as long as they are small or do not alter current behavior. +![House-keeping](./.github/images/house-keeping.png) 'Small' enhancements that need to be done in order to keep the project organised and ensure overall quality. These changes may be applied in any place in code, as long as they are small or do not alter current behavior. -![](./.github/images/network-policy.png) Identify issues that affect the network-policy like fees, access list or other related issues. Voting may also be related to the network policy module. +![Network-policy](./.github/images/network-policy.png) Identify issues that affect the network-policy like fees, access list or other related issues. Voting may also be related to the network policy module. -![](./.github/images/p2p.png) This module includes peer-to-peer message exchange and network optimisations, at TCP or UDP level (not HTTP). +![P2P](./.github/images/p2p.png) This module includes peer-to-peer message exchange and network optimisations, at TCP or UDP level (not HTTP). -![](./.github/images/rpc.png) All HTTP communication is handled by the RPC module. This module usually provides support methods since the main communication protocol takes place at the p2p module. +![RPC](./.github/images/rpc.png) All HTTP communication is handled by the RPC module. This module usually provides support methods since the main communication protocol takes place at the p2p module. -![](./.github/images/vm.png) New features that affect the Neo Virtual Machine or the Interop layer have this tag. +![VM](./.github/images/vm.png) New features that affect the Neo Virtual Machine or the Interop layer. -![](./.github/images/sdk.png) Neo provides an SDK to help developers to interact with the blockchain. Changes in this module must not impact other parts of the software. +![SDK](./.github/images/sdk.png) Neo provides an SDK to help developers to interact with the blockchain. Changes in this module must not impact other parts of the software. -![](./.github/images/wallet.png) Wallets are used to track funds and interact with the blockchain. Note that this module depends on a full node implementation (data stored on local disk). +![Wallet](./.github/images/wallet.png) Wallets are used to track funds and interact with the blockchain. Note that this module depends on a full node implementation (data stored on local disk).