From 4dcef17cc4110677eca3e9724c78f53ce80b0205 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 18:05:36 +0200 Subject: [PATCH 01/32] Update syscalls for neo3 --- src/Neo.SmartContract.Framework/Helper.cs | 4 +- .../Services/Neo/Block.cs | 11 +---- .../Services/Neo/Blockchain.cs | 11 ++--- .../Services/Neo/Contract.cs | 8 +++- .../Services/Neo/Crypto.cs | 20 ++++++++ .../Services/Neo/Header.cs | 47 ------------------- .../Services/Neo/Json.cs | 11 +++++ .../Services/Neo/Runtime.cs | 8 +++- .../Services/Neo/Storage.cs | 9 ++++ .../Services/Neo/StorageContext.cs | 8 ++++ .../Services/Neo/Transaction.cs | 17 ++----- .../Services/Neo/TransactionAttribute.cs | 17 ------- .../Services/Neo/TriggerType.cs | 2 + .../SmartContract.cs | 15 +----- 14 files changed, 77 insertions(+), 111 deletions(-) create mode 100644 src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs delete mode 100644 src/Neo.SmartContract.Framework/Services/Neo/Header.cs create mode 100644 src/Neo.SmartContract.Framework/Services/Neo/Json.cs delete mode 100644 src/Neo.SmartContract.Framework/Services/Neo/TransactionAttribute.cs diff --git a/src/Neo.SmartContract.Framework/Helper.cs b/src/Neo.SmartContract.Framework/Helper.cs index 4258c63e7..e4d9bd57d 100644 --- a/src/Neo.SmartContract.Framework/Helper.cs +++ b/src/Neo.SmartContract.Framework/Helper.cs @@ -238,10 +238,10 @@ public static byte[] Reverse(this byte[] source) [NonemitWithConvert(ConvertMethod.ToBigInteger)] public extern static BigInteger ToBigInteger(this string text); - [Syscall("Neo.Runtime.Serialize")] + [Syscall("System.Runtime.Serialize")] public extern static byte[] Serialize(this object source); - [Syscall("Neo.Runtime.Deserialize")] + [Syscall("System.Runtime.Deserialize")] public extern static object Deserialize(this byte[] source); } } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Block.cs b/src/Neo.SmartContract.Framework/Services/Neo/Block.cs index 009233712..b2d1b00fb 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Block.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Block.cs @@ -1,14 +1,7 @@ namespace Neo.SmartContract.Framework.Services.Neo { - public class Block : Header + public class Block { - [Syscall("Neo.Block.GetTransactionCount")] - public extern int GetTransactionCount(); - - [Syscall("Neo.Block.GetTransactions")] - public extern Transaction[] GetTransactions(); - - [Syscall("Neo.Block.GetTransaction")] - public extern Transaction GetTransaction(int index); + public readonly byte[] Hash; } } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs b/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs index 11b5c6296..f12ae1a8d 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs @@ -1,3 +1,5 @@ +using System.Numerics; + namespace Neo.SmartContract.Framework.Services.Neo { public static class Blockchain @@ -5,12 +7,6 @@ public static class Blockchain [Syscall("Neo.Blockchain.GetHeight")] public static extern uint GetHeight(); - [Syscall("Neo.Blockchain.GetHeader")] - public static extern Header GetHeader(uint height); - - [Syscall("Neo.Blockchain.GetHeader")] - public static extern Header GetHeader(byte[] hash); - [Syscall("Neo.Blockchain.GetBlock")] public static extern Block GetBlock(uint height); @@ -20,6 +16,9 @@ public static class Blockchain [Syscall("Neo.Blockchain.GetTransaction")] public static extern Transaction GetTransaction(byte[] hash); + [Syscall("System.Blockchain.GetTransactionHeight")] + public static extern BigInteger GetTransactionHeight(byte[] hash); + [Syscall("Neo.Blockchain.GetContract")] public static extern Contract GetContract(byte[] script_hash); } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs b/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs index 41f3e22b1..6cf156c15 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs @@ -14,8 +14,14 @@ public class Contract get; } + [Syscall("Neo.Contract.Call")] + public static extern Contract Call(byte[] scriptHash, string method, object[] arguments); + [Syscall("Neo.Contract.Create")] - public static extern Contract Create(byte[] script, ContractPropertyState contract_property_state); + public static extern Contract Create(byte[] script, string manifest); + + [Syscall("Neo.Contract.Update")] + public static extern Contract Update(byte[] script, string manifest); [Syscall("Neo.Contract.Migrate")] public static extern Contract Migrate(byte[] script, ContractPropertyState contract_property_state); diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs b/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs new file mode 100644 index 000000000..f1778ece5 --- /dev/null +++ b/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs @@ -0,0 +1,20 @@ +namespace Neo.SmartContract.Framework.Services.Neo +{ + public static class Cryto + { + [Syscall("Neo.Crypto.Hash160")] + public extern static byte[] Hash160(byte[] data); + + [Syscall("Neo.Crypto.Hash256")] + public extern static byte[] Hash256(byte[] data); + + [Syscall("Neo.Crypto.CheckSig")] + public extern static bool VerifySignature(byte[] signature, byte[] pubkey); + + [Syscall("System.Crypto.Verify")] + public extern static bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey); + + [Syscall("Neo.Crypto.CheckMultiSig")] + public extern static bool VerifySignatures(byte[][] signature, byte[][] pubkey); + } +} diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Header.cs b/src/Neo.SmartContract.Framework/Services/Neo/Header.cs deleted file mode 100644 index 4b60f6ce8..000000000 --- a/src/Neo.SmartContract.Framework/Services/Neo/Header.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace Neo.SmartContract.Framework.Services.Neo -{ - public class Header : IScriptContainer - { - public extern byte[] Hash - { - [Syscall("System.Header.GetHash")] - get; - } - - public extern uint Version - { - [Syscall("Neo.Header.GetVersion")] - get; - } - - public extern byte[] PrevHash - { - [Syscall("System.Header.GetPrevHash")] - get; - } - - public extern byte[] MerkleRoot - { - [Syscall("Neo.Header.GetMerkleRoot")] - get; - } - - public extern uint Timestamp - { - [Syscall("System.Header.GetTimestamp")] - get; - } - - public extern uint Index - { - [Syscall("System.Header.GetIndex")] - get; - } - - public extern byte[] NextConsensus - { - [Syscall("Neo.Header.GetNextConsensus")] - get; - } - } -} diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Json.cs b/src/Neo.SmartContract.Framework/Services/Neo/Json.cs new file mode 100644 index 000000000..5a4cb2b3f --- /dev/null +++ b/src/Neo.SmartContract.Framework/Services/Neo/Json.cs @@ -0,0 +1,11 @@ +namespace Neo.SmartContract.Framework.Services.Neo +{ + public static class Json + { + [Syscall("Neo.Json.Serialize")] + public extern static string Serialize(object obj); + + [Syscall("Neo.Json.Deserialize")] + public extern static object Deserialize(string json); + } +} diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Runtime.cs b/src/Neo.SmartContract.Framework/Services/Neo/Runtime.cs index 96bb9c415..979b381a5 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Runtime.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Runtime.cs @@ -8,7 +8,13 @@ public static class Runtime get; } - public static extern uint Time + public static extern string Platform + { + [Syscall("System.Runtime.Platform")] + get; + } + + public static extern ulong Time { [Syscall("System.Runtime.GetTime")] get; diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Storage.cs b/src/Neo.SmartContract.Framework/Services/Neo/Storage.cs index 8d516e8a5..7a12a8845 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Storage.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Storage.cs @@ -13,6 +13,15 @@ public static class Storage get; } + /// + /// Returns current read only StorageContext + /// + public static extern StorageContext CurrentReadOnlyContext + { + [Syscall("System.Storage.GetReadOnlyContext")] + get; + } + /// /// Returns the byte[] value corresponding to given byte[] key for Storage context (faster: generates opcode directly) /// diff --git a/src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs b/src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs index 9ab00f506..be9af013d 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs @@ -2,5 +2,13 @@ namespace Neo.SmartContract.Framework.Services.Neo { public class StorageContext { + /// + /// Returns current StorageContext as ReadOnly + /// + public static extern StorageContext AsReadOnly + { + [Syscall("System.StorageContext.AsReadOnly")] + get; + } } } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs b/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs index 05f5dd1bb..66cf1f9f8 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs @@ -1,20 +1,9 @@ namespace Neo.SmartContract.Framework.Services.Neo { - public class Transaction : IScriptContainer + public class Transaction { - public extern byte[] Hash - { - [Syscall("System.Transaction.GetHash")] - get; - } + public readonly byte[] Hash; - public extern byte[] Script - { - [Syscall("Neo.Transaction.GetScript")] - get; - } - - [Syscall("Neo.Transaction.GetAttributes")] - public extern TransactionAttribute[] GetAttributes(); + // TODO: Wait for merge https://github.com/neo-project/neo/pull/1081 } } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/TransactionAttribute.cs b/src/Neo.SmartContract.Framework/Services/Neo/TransactionAttribute.cs deleted file mode 100644 index 4ea7a2a34..000000000 --- a/src/Neo.SmartContract.Framework/Services/Neo/TransactionAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Neo.SmartContract.Framework.Services.Neo -{ - public class TransactionAttribute : IApiInterface - { - public extern byte Usage - { - [Syscall("Neo.Attribute.GetUsage")] - get; - } - - public extern byte[] Data - { - [Syscall("Neo.Attribute.GetData")] - get; - } - } -} diff --git a/src/Neo.SmartContract.Framework/Services/Neo/TriggerType.cs b/src/Neo.SmartContract.Framework/Services/Neo/TriggerType.cs index 7bf1579ab..4625cb582 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/TriggerType.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/TriggerType.cs @@ -2,7 +2,9 @@ namespace Neo.SmartContract.Framework.Services.Neo { public enum TriggerType : byte { + System = 0x01, Verification = 0x20, Application = 0x40, + All = System | Verification | Application } } diff --git a/src/Neo.SmartContract.Framework/SmartContract.cs b/src/Neo.SmartContract.Framework/SmartContract.cs index e59f7efc5..631ea7e8d 100644 --- a/src/Neo.SmartContract.Framework/SmartContract.cs +++ b/src/Neo.SmartContract.Framework/SmartContract.cs @@ -2,19 +2,6 @@ namespace Neo.SmartContract.Framework { public class SmartContract { - [Syscall("Neo.Crypto.Hash160")] - protected extern static byte[] Hash160(byte[] data); - - [Syscall("Neo.Crypto.Hash256")] - protected extern static byte[] Hash256(byte[] data); - - [Syscall("Neo.Crypto.CheckSig")] - protected extern static bool VerifySignature(byte[] signature, byte[] pubkey); - - [Syscall("System.Crypto.Verify")] - protected extern static bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey); - - [Syscall("Neo.Crypto.CheckMultiSig")] - protected extern static bool VerifySignatures(byte[][] signature, byte[][] pubkey); + } } From c6c98605ff06ba167fbf7f7ecc0b54f845a9f0fc Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 18:07:25 +0200 Subject: [PATCH 02/32] Update block --- src/Neo.SmartContract.Framework/Services/Neo/Block.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Block.cs b/src/Neo.SmartContract.Framework/Services/Neo/Block.cs index b2d1b00fb..2f7691ea8 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Block.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Block.cs @@ -3,5 +3,7 @@ namespace Neo.SmartContract.Framework.Services.Neo public class Block { public readonly byte[] Hash; + + // TODO: Wait for merge https://github.com/neo-project/neo/pull/1081 } } From 7c53c7df3c957541bc7eb14f509c34275895e27d Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 18:11:39 +0200 Subject: [PATCH 03/32] Fix --- src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs b/src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs index be9af013d..a87ed4e45 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/StorageContext.cs @@ -5,7 +5,7 @@ public class StorageContext /// /// Returns current StorageContext as ReadOnly /// - public static extern StorageContext AsReadOnly + public extern StorageContext AsReadOnly { [Syscall("System.StorageContext.AsReadOnly")] get; From 301e56f8692102b2cb949d0ccdbd30b781624dae Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 12 Sep 2019 08:01:03 +0200 Subject: [PATCH 04/32] UT for test all syscalls --- .../Services/Neo/Blockchain.cs | 10 ++-- .../UT_SyscallTest.cs | 59 +++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs b/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs index f12ae1a8d..7336dece6 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs @@ -4,22 +4,22 @@ namespace Neo.SmartContract.Framework.Services.Neo { public static class Blockchain { - [Syscall("Neo.Blockchain.GetHeight")] + [Syscall("System.Blockchain.GetHeight")] public static extern uint GetHeight(); - [Syscall("Neo.Blockchain.GetBlock")] + [Syscall("System.Blockchain.GetBlock")] public static extern Block GetBlock(uint height); - [Syscall("Neo.Blockchain.GetBlock")] + [Syscall("System.Blockchain.GetBlock")] public static extern Block GetBlock(byte[] hash); - [Syscall("Neo.Blockchain.GetTransaction")] + [Syscall("System.Blockchain.GetTransaction")] public static extern Transaction GetTransaction(byte[] hash); [Syscall("System.Blockchain.GetTransactionHeight")] public static extern BigInteger GetTransactionHeight(byte[] hash); - [Syscall("Neo.Blockchain.GetContract")] + [Syscall("System.Blockchain.GetContract")] public static extern Contract GetContract(byte[] script_hash); } } diff --git a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs new file mode 100644 index 000000000..bc8e15e88 --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs @@ -0,0 +1,59 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using FrameworkOpCode = Neo.SmartContract.Framework.OpCode; +using VMOpCode = Neo.VM.OpCode; + +namespace Neo.SmartContract.Framework.UnitTests +{ + [TestClass] + public class UT_SyscallTest + { + [TestMethod] + public void TestAllSyscalls() + { + // Current syscalls + + var list = new List(); + + using (var stream = File.OpenRead(typeof(SmartContract).Assembly.Location)) + { + var module = Mono.Cecil.ModuleDefinition.ReadModule(stream); + + if (module.HasTypes) + { + foreach (var type in module.Types) + { + foreach (var method in type.Methods) + { + foreach (var attr in method.CustomAttributes) + { + if (attr.AttributeType.FullName == "Neo.SmartContract.Framework.SyscallAttribute") + { + var syscall = attr.ConstructorArguments[0].Value.ToString(); + if (!list.Contains(syscall)) list.Add(syscall); + } + } + } + } + } + } + + // Neo syscalls + + foreach (var syscall in InteropService.SupportedMethods().Values) + { + if (list.Remove(syscall)) continue; + + Assert.Fail($"Not implemented the '{syscall}'"); + } + + if (list.Count > 0) + { + Assert.Fail($"Unknown syscalls: {string.Join(",", list)}"); + } + } + } +} From 27d4966ae668f6327dea7066bdfdd481268afac5 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 12 Sep 2019 08:03:05 +0200 Subject: [PATCH 05/32] Clean ut --- .../UT_SyscallTest.cs | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs index bc8e15e88..da461e0af 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs @@ -1,10 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using FrameworkOpCode = Neo.SmartContract.Framework.OpCode; -using VMOpCode = Neo.VM.OpCode; namespace Neo.SmartContract.Framework.UnitTests { @@ -22,23 +18,16 @@ public void TestAllSyscalls() { var module = Mono.Cecil.ModuleDefinition.ReadModule(stream); - if (module.HasTypes) - { - foreach (var type in module.Types) - { - foreach (var method in type.Methods) + foreach (var type in module.Types) + foreach (var method in type.Methods) + foreach (var attr in method.CustomAttributes) { - foreach (var attr in method.CustomAttributes) + if (attr.AttributeType.FullName == "Neo.SmartContract.Framework.SyscallAttribute") { - if (attr.AttributeType.FullName == "Neo.SmartContract.Framework.SyscallAttribute") - { - var syscall = attr.ConstructorArguments[0].Value.ToString(); - if (!list.Contains(syscall)) list.Add(syscall); - } + var syscall = attr.ConstructorArguments[0].Value.ToString(); + if (!list.Contains(syscall)) list.Add(syscall); } } - } - } } // Neo syscalls From 7f2f83bb751762d754f77fdd840a62768bddcef6 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 19 Sep 2019 14:23:40 +0200 Subject: [PATCH 06/32] Update values --- src/Neo.SmartContract.Framework/Services/Neo/Block.cs | 7 +++++++ .../Services/Neo/Transaction.cs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Block.cs b/src/Neo.SmartContract.Framework/Services/Neo/Block.cs index 2f7691ea8..3b563fb60 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Block.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Block.cs @@ -3,6 +3,13 @@ namespace Neo.SmartContract.Framework.Services.Neo public class Block { public readonly byte[] Hash; + public readonly uint Version; + public readonly byte[] PrevHash; + public readonly byte[] MerkleRoot; + public readonly ulong Timestamp; + public readonly uint Index; + public readonly byte[] NextConsensus; + public readonly int TransactionsCount; // TODO: Wait for merge https://github.com/neo-project/neo/pull/1081 } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs b/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs index 66cf1f9f8..6f703eed1 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs @@ -3,6 +3,13 @@ namespace Neo.SmartContract.Framework.Services.Neo public class Transaction { public readonly byte[] Hash; + public readonly byte Version; + public readonly uint Nonce; + public readonly byte[] Sender; + public readonly long SystemFee; + public readonly long NetworkFee; + public readonly uint ValidUntilBlock; + public readonly byte[] Script; // TODO: Wait for merge https://github.com/neo-project/neo/pull/1081 } From d999c8e4a32aaa6039f244a8fd8268b76e0a7a0b Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 16 Oct 2019 10:37:31 +0200 Subject: [PATCH 07/32] Update opcodes --- .../Neo.Compiler.MSIL.csproj | 2 +- src/Neo.SmartContract.Framework/OpCode.cs | 28 +++++++++++++------ .../Services/Neo/Block.cs | 4 +-- .../Services/Neo/Contract.cs | 23 ++++++++------- .../Services/Neo/Transaction.cs | 2 -- .../Services/Neo/TriggerType.cs | 2 +- .../SmartContract.cs | 2 +- .../UT_SyscallTest.cs | 7 ++++- 8 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj index c9d69fa61..27b686a59 100644 --- a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj +++ b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj @@ -23,7 +23,7 @@ - + diff --git a/src/Neo.SmartContract.Framework/OpCode.cs b/src/Neo.SmartContract.Framework/OpCode.cs index 308d1ba15..395301f8f 100644 --- a/src/Neo.SmartContract.Framework/OpCode.cs +++ b/src/Neo.SmartContract.Framework/OpCode.cs @@ -327,6 +327,10 @@ public enum OpCode : byte /// PUSHM1 = 0x4F, /// + /// The item null is pushed onto the stack. + /// + PUSHNULL = 0x50, + /// /// The number 1 is pushed onto the stack. /// PUSH1 = 0x51, @@ -425,14 +429,6 @@ public enum OpCode : byte // Stack /// - /// Copies the bottom of alt stack and put it on top of main stack. - /// - DUPFROMALTSTACKBOTTOM = 0x69, - /// - /// Duplicates the item on top of alt stack and put it on top of main stack. - /// - DUPFROMALTSTACK = 0x6A, - /// /// Puts the input onto the top of the alt stack. Removes it from the main stack. /// TOALTSTACK = 0x6B, @@ -441,9 +437,21 @@ public enum OpCode : byte /// FROMALTSTACK = 0x6C, /// + /// Duplicates the item on top of alt stack and put it on top of main stack. + /// + DUPFROMALTSTACK = 0x6D, + /// + /// Copies the bottom of alt stack and put it on top of main stack. + /// + DUPFROMALTSTACKBOTTOM = 0x6E, + /// + /// Returns true if the input is null. Returns false otherwise. + /// + ISNULL = 0x70, + /// /// The item n back in the main stack is removed. /// - XDROP = 0x6D, + XDROP = 0x71, /// /// The item n back in the main stack in swapped with top stack item. /// @@ -668,10 +676,12 @@ public enum OpCode : byte SETITEM = 0xC4, /// /// A value n is taken from top of main stack. A zero-filled array type with size n is put on top of the main stack. + /// OR a struct is taken from top of main stack and is converted to an array. /// NEWARRAY = 0xC5, /// /// A value n is taken from top of main stack. A zero-filled struct type with size n is put on top of the main stack. + /// OR an array is taken from top of main stack and is converted to a struct. /// NEWSTRUCT = 0xC6, /// diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Block.cs b/src/Neo.SmartContract.Framework/Services/Neo/Block.cs index 3b563fb60..bfeefd873 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Block.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Block.cs @@ -1,6 +1,6 @@ namespace Neo.SmartContract.Framework.Services.Neo { - public class Block + public class Block { public readonly byte[] Hash; public readonly uint Version; @@ -10,7 +10,5 @@ public class Block public readonly uint Index; public readonly byte[] NextConsensus; public readonly int TransactionsCount; - - // TODO: Wait for merge https://github.com/neo-project/neo/pull/1081 } } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs b/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs index 6cf156c15..e9dd958a5 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs @@ -2,17 +2,20 @@ namespace Neo.SmartContract.Framework.Services.Neo { public class Contract { - public extern byte[] Script - { - [Syscall("Neo.Contract.GetScript")] - get; - } + /// + /// Script + /// + public readonly byte[] Script; - public extern bool IsPayable - { - [Syscall("Neo.Contract.IsPayable")] - get; - } + /// + /// Has storage + /// + public readonly bool HasStorage; + + /// + /// Is payable + /// + public readonly bool IsPayable; [Syscall("Neo.Contract.Call")] public static extern Contract Call(byte[] scriptHash, string method, object[] arguments); diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs b/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs index 6f703eed1..7bde5847f 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Transaction.cs @@ -10,7 +10,5 @@ public class Transaction public readonly long NetworkFee; public readonly uint ValidUntilBlock; public readonly byte[] Script; - - // TODO: Wait for merge https://github.com/neo-project/neo/pull/1081 } } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/TriggerType.cs b/src/Neo.SmartContract.Framework/Services/Neo/TriggerType.cs index 4625cb582..fd2a878de 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/TriggerType.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/TriggerType.cs @@ -2,7 +2,7 @@ namespace Neo.SmartContract.Framework.Services.Neo { public enum TriggerType : byte { - System = 0x01, + System = 0x01, Verification = 0x20, Application = 0x40, All = System | Verification | Application diff --git a/src/Neo.SmartContract.Framework/SmartContract.cs b/src/Neo.SmartContract.Framework/SmartContract.cs index 631ea7e8d..0443671da 100644 --- a/src/Neo.SmartContract.Framework/SmartContract.cs +++ b/src/Neo.SmartContract.Framework/SmartContract.cs @@ -2,6 +2,6 @@ namespace Neo.SmartContract.Framework { public class SmartContract { - + } } diff --git a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs index da461e0af..28f64e091 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs @@ -16,18 +16,23 @@ public void TestAllSyscalls() using (var stream = File.OpenRead(typeof(SmartContract).Assembly.Location)) { + var expectedType = typeof(SyscallAttribute).FullName; var module = Mono.Cecil.ModuleDefinition.ReadModule(stream); foreach (var type in module.Types) + { foreach (var method in type.Methods) + { foreach (var attr in method.CustomAttributes) { - if (attr.AttributeType.FullName == "Neo.SmartContract.Framework.SyscallAttribute") + if (attr.AttributeType.FullName == expectedType) { var syscall = attr.ConstructorArguments[0].Value.ToString(); if (!list.Contains(syscall)) list.Add(syscall); } } + } + } } // Neo syscalls From f0f70c7d78d842ee12ac49cfaf7c809082b67e11 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 18 Oct 2019 19:32:34 +0200 Subject: [PATCH 08/32] More Syscalls --- src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj | 4 ++-- .../Services/Neo/Blockchain.cs | 6 ++++++ .../Services/Neo/Contract.cs | 5 +---- .../Services/Neo/Crypto.cs | 6 ------ .../Services/Neo/Native.cs | 14 ++++++++++++++ .../UT_SyscallTest.cs | 12 ++++++++++-- 6 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 src/Neo.SmartContract.Framework/Services/Neo/Native.cs diff --git a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj index 27b686a59..8467f998b 100644 --- a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj +++ b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj @@ -1,4 +1,4 @@ - + 2015-2019 The Neo Project @@ -23,7 +23,7 @@ - + diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs b/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs index 7336dece6..05218acc0 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Blockchain.cs @@ -16,6 +16,12 @@ public static class Blockchain [Syscall("System.Blockchain.GetTransaction")] public static extern Transaction GetTransaction(byte[] hash); + [Syscall("System.Blockchain.GetTransactionFromBlock")] + public static extern Transaction GetTransactionFromBlock(byte[] blockHash, int txIndex); + + [Syscall("System.Blockchain.GetTransactionFromBlock")] + public static extern Transaction GetTransactionFromBlock(uint blockIndex, int txIndex); + [Syscall("System.Blockchain.GetTransactionHeight")] public static extern BigInteger GetTransactionHeight(byte[] hash); diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs b/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs index e9dd958a5..fc4d1dcb1 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs @@ -17,7 +17,7 @@ public class Contract /// public readonly bool IsPayable; - [Syscall("Neo.Contract.Call")] + [Syscall("System.Contract.Call")] public static extern Contract Call(byte[] scriptHash, string method, object[] arguments); [Syscall("Neo.Contract.Create")] @@ -26,9 +26,6 @@ public class Contract [Syscall("Neo.Contract.Update")] public static extern Contract Update(byte[] script, string manifest); - [Syscall("Neo.Contract.Migrate")] - public static extern Contract Migrate(byte[] script, ContractPropertyState contract_property_state); - [Syscall("System.Contract.Destroy")] public static extern void Destroy(); } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs b/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs index f1778ece5..6ba58b38a 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs @@ -2,12 +2,6 @@ namespace Neo.SmartContract.Framework.Services.Neo { public static class Cryto { - [Syscall("Neo.Crypto.Hash160")] - public extern static byte[] Hash160(byte[] data); - - [Syscall("Neo.Crypto.Hash256")] - public extern static byte[] Hash256(byte[] data); - [Syscall("Neo.Crypto.CheckSig")] public extern static bool VerifySignature(byte[] signature, byte[] pubkey); diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Native.cs b/src/Neo.SmartContract.Framework/Services/Neo/Native.cs new file mode 100644 index 000000000..bf95e2060 --- /dev/null +++ b/src/Neo.SmartContract.Framework/Services/Neo/Native.cs @@ -0,0 +1,14 @@ +namespace Neo.SmartContract.Framework.Services.Neo +{ + public class Native + { + [Syscall("Neo.Native.Tokens.NEO")] + public static extern Contract NEO(string method, object[] arguments); + + [Syscall("Neo.Native.Tokens.GAS")] + public static extern Contract GAS(string method, object[] arguments); + + [Syscall("Neo.Native.Policy")] + public static extern Contract Policy(string method, object[] arguments); + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs index 28f64e091..bceaf0344 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs @@ -37,16 +37,24 @@ public void TestAllSyscalls() // Neo syscalls + var notFound = new List(); + foreach (var syscall in InteropService.SupportedMethods().Values) { + if (syscall == "Neo.Native.Deploy") continue; if (list.Remove(syscall)) continue; - Assert.Fail($"Not implemented the '{syscall}'"); + notFound.Add(syscall); } if (list.Count > 0) { - Assert.Fail($"Unknown syscalls: {string.Join(",", list)}"); + Assert.Fail($"Unknown syscalls:{string.Join("\n-", list)}"); + } + + if (notFound.Count > 0) + { + Assert.Fail($"Not implemented syscalls:{string.Join("\n-", notFound)}"); } } } From 449973688956cfe0ee145cb9572b261f770c1992 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 18 Oct 2019 19:48:42 +0200 Subject: [PATCH 09/32] All ut --- .../Services/Neo/Enumerator.cs | 22 ++++++++++ .../Services/Neo/Iterator.cs | 23 ++++++++++ .../Services/Neo/Storage.cs | 42 +++++++++++++++++++ .../Services/Neo/StorageFlags.cs | 11 +++++ .../UT_SyscallTest.cs | 4 +- 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/Neo.SmartContract.Framework/Services/Neo/Enumerator.cs create mode 100644 src/Neo.SmartContract.Framework/Services/Neo/StorageFlags.cs diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Enumerator.cs b/src/Neo.SmartContract.Framework/Services/Neo/Enumerator.cs new file mode 100644 index 000000000..6f6d50507 --- /dev/null +++ b/src/Neo.SmartContract.Framework/Services/Neo/Enumerator.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Neo.SmartContract.Framework.Services.Neo +{ + public class Enumerator + { + [Syscall("Neo.Enumerator.Create")] + public static extern Enumerator Create(IEnumerable entry); + + [Syscall("Neo.Enumerator.Concat")] + public extern Enumerator Concat(Enumerator value); + + [Syscall("Neo.Enumerator.Next")] + public extern bool Next(); + + public extern TValue Value + { + [Syscall("Neo.Enumerator.Value")] + get; + } + } +} diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Iterator.cs b/src/Neo.SmartContract.Framework/Services/Neo/Iterator.cs index 0725e47fa..bc03f4f6e 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Iterator.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Iterator.cs @@ -1,7 +1,18 @@ +using System.Collections.Generic; + namespace Neo.SmartContract.Framework.Services.Neo { public class Iterator { + [Syscall("Neo.Iterator.Create")] + public static extern Iterator Create(IDictionary entry); + + [Syscall("Neo.Iterator.Create")] + public static extern Iterator Create(IEnumerable entry); + + [Syscall("Neo.Iterator.Concat")] + public extern Iterator Concat(Iterator value); + [Syscall("Neo.Enumerator.Next")] public extern bool Next(); @@ -16,5 +27,17 @@ public class Iterator [Syscall("Neo.Enumerator.Value")] get; } + + public extern Enumerator Keys + { + [Syscall("Neo.Iterator.Keys")] + get; + } + + public extern Enumerator Values + { + [Syscall("Neo.Iterator.Values")] + get; + } } } diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Storage.cs b/src/Neo.SmartContract.Framework/Services/Neo/Storage.cs index 7a12a8845..e41023bb7 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Storage.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Storage.cs @@ -115,6 +115,13 @@ public static class Storage [Syscall("System.Storage.Put")] public static extern void Put(byte[] key, byte[] value); + /// + /// Writes BigInteger value on string key for current Storage context + /// + [Syscall("System.Storage.GetContext")] + [Syscall("System.Storage.PutEx")] + public static extern void PutEx(byte[] key, byte[] value, StorageFlags flags); + /// /// Writes BigInteger value on byte[] key for current Storage context /// @@ -122,6 +129,13 @@ public static class Storage [Syscall("System.Storage.Put")] public static extern void Put(byte[] key, BigInteger value); + /// + /// Writes BigInteger value on string key for current Storage context + /// + [Syscall("System.Storage.GetContext")] + [Syscall("System.Storage.PutEx")] + public static extern void PutEx(byte[] key, BigInteger value, StorageFlags flags); + /// /// Writes string value on byte[] key for current Storage context /// @@ -129,6 +143,13 @@ public static class Storage [Syscall("System.Storage.Put")] public static extern void Put(byte[] key, string value); + /// + /// Writes BigInteger value on string key for current Storage context + /// + [Syscall("System.Storage.GetContext")] + [Syscall("System.Storage.PutEx")] + public static extern void PutEx(byte[] key, string value, StorageFlags flags); + /// /// Writes byte[] value on string key for current Storage context /// @@ -136,6 +157,13 @@ public static class Storage [Syscall("System.Storage.Put")] public static extern void Put(string key, byte[] value); + /// + /// Writes BigInteger value on string key for current Storage context + /// + [Syscall("System.Storage.GetContext")] + [Syscall("System.Storage.PutEx")] + public static extern void PutEx(string key, byte[] value, StorageFlags flags); + /// /// Writes BigInteger value on string key for current Storage context /// @@ -143,6 +171,13 @@ public static class Storage [Syscall("System.Storage.Put")] public static extern void Put(string key, BigInteger value); + /// + /// Writes BigInteger value on string key for current Storage context + /// + [Syscall("System.Storage.GetContext")] + [Syscall("System.Storage.PutEx")] + public static extern void PutEx(string key, BigInteger value, StorageFlags flags); + /// /// Writes string value on string key for current Storage context /// @@ -150,6 +185,13 @@ public static class Storage [Syscall("System.Storage.Put")] public static extern void Put(string key, string value); + /// + /// Writes string value on string key for current Storage context + /// + [Syscall("System.Storage.GetContext")] + [Syscall("System.Storage.PutEx")] + public static extern void PutEx(string key, string value, StorageFlags flags); + /// /// Deletes byte[] key from current Storage context /// diff --git a/src/Neo.SmartContract.Framework/Services/Neo/StorageFlags.cs b/src/Neo.SmartContract.Framework/Services/Neo/StorageFlags.cs new file mode 100644 index 000000000..1e46f1ac2 --- /dev/null +++ b/src/Neo.SmartContract.Framework/Services/Neo/StorageFlags.cs @@ -0,0 +1,11 @@ +using System; + +namespace Neo.SmartContract.Framework.Services.Neo +{ + [Flags] + public enum StorageFlags : byte + { + None = 0x00, + Constant = 0x01 + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs index bceaf0344..e46ff30ce 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs @@ -49,12 +49,12 @@ public void TestAllSyscalls() if (list.Count > 0) { - Assert.Fail($"Unknown syscalls:{string.Join("\n-", list)}"); + Assert.Fail($"Unknown syscalls: {string.Join("\n-", list)}"); } if (notFound.Count > 0) { - Assert.Fail($"Not implemented syscalls:{string.Join("\n-", notFound)}"); + Assert.Fail($"Not implemented syscalls: {string.Join("\n-", notFound)}"); } } } From b61191ef7196f5f1f949207ba51d694f153a118f Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 18 Oct 2019 20:02:41 +0200 Subject: [PATCH 10/32] Remove CRLF --- .../Services/Neo/StorageFlags.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Neo.SmartContract.Framework/Services/Neo/StorageFlags.cs b/src/Neo.SmartContract.Framework/Services/Neo/StorageFlags.cs index 1e46f1ac2..d90f38ce7 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/StorageFlags.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/StorageFlags.cs @@ -2,10 +2,10 @@ namespace Neo.SmartContract.Framework.Services.Neo { - [Flags] - public enum StorageFlags : byte - { - None = 0x00, - Constant = 0x01 + [Flags] + public enum StorageFlags : byte + { + None = 0x00, + Constant = 0x01 } } From ff4001de0bef7e077b6c91aacabfd1256c740cd8 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 13:25:50 +0200 Subject: [PATCH 11/32] Test Account --- .../Services/Neo/AccountTest.cs | 55 +++++++++++++++++++ .../TestClasses/Contract_Account.cs | 12 ++++ .../Utils/TestEngine.cs | 14 ++++- 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Account.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs new file mode 100644 index 000000000..75d356a4f --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs @@ -0,0 +1,55 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.VM.Types; + +namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +{ + [TestClass] + public class AccountTest + { + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(); + _engine.AddEntryScript("./TestClasses/Contract_Account.cs"); + } + + [TestMethod] + public void Test_AccountIsStandard() + { + // Empty + + var result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[0])); + Assert.AreEqual(VM.VMState.FAULT, _engine.State); + Assert.AreEqual(0, result.Count); + _engine.InvocationStack.Clear(); + + // No standard + + result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[20])); + Assert.AreEqual(VM.VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Boolean)); + Assert.AreEqual(false, item.GetBoolean()); + _engine.InvocationStack.Clear(); + + // Standard + + result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[20] + { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF + })); + Assert.AreEqual(VM.VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Boolean)); + Assert.AreEqual(true, item.GetBoolean()); + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Account.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Account.cs new file mode 100644 index 000000000..93daa9da3 --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Account.cs @@ -0,0 +1,12 @@ +using Neo.SmartContract.Framework.Services.Neo; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_Account : SmartContract.Framework.SmartContract + { + public static bool AccountIsStandard(byte[] scripthash) + { + return Account.IsStandard(scripthash); + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 78173e66d..da4d55074 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -170,8 +170,20 @@ protected override bool OnSysCall(uint method) { return Runtime_GetNotifications(); } + else if (method == InteropService.Neo_Account_IsStandard) + { + return Account_IsStandard(); + } + + Console.WriteLine($"Syscall not found: {method.ToString("X2")}"); + throw new NotImplementedException(method.ToString("X2")); + } - return base.OnSysCall(method); + private bool Account_IsStandard() + { + UInt160 hash = new UInt160(CurrentContext.EvaluationStack.Pop().GetByteArray()); + CurrentContext.EvaluationStack.Push(hash.Equals(UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))); + return true; } private bool Runtime_GetNotifications() From a260f0a20502aefe359edb7b93a86c57fbf479ce Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 13:36:58 +0200 Subject: [PATCH 12/32] Json Test --- .../Services/Neo/JsonTest.cs | 71 +++++++++++++++++++ .../TestClasses/Contract_Json.cs | 17 +++++ .../Utils/TestEngine.cs | 28 ++++++++ 3 files changed, 116 insertions(+) create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Json.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs new file mode 100644 index 000000000..2df4b0c19 --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs @@ -0,0 +1,71 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.VM; +using Neo.VM.Types; +using System.Text; + +namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +{ + [TestClass] + public class JsonTest + { + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(); + _engine.AddEntryScript("./TestClasses/Contract_Json.cs"); + } + + [TestMethod] + public void Test_SerializeDeserialize() + { + // Empty Serialize + + var result = _engine.ExecuteTestCaseStandard("Serialize"); + Assert.AreEqual(VMState.FAULT, _engine.State); + Assert.AreEqual(0, result.Count); + _engine.InvocationStack.Clear(); + + // Empty Serialize + + result = _engine.ExecuteTestCaseStandard("Deserialize"); + Assert.AreEqual(VMState.FAULT, _engine.State); + Assert.AreEqual(0, result.Count); + _engine.InvocationStack.Clear(); + + // Serialize + + result = _engine.ExecuteTestCaseStandard("Serialize", new Array(new StackItem[]{ + StackItem.Null, new Boolean(true), new ByteArray(Encoding.ASCII.GetBytes("asd")) + })); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual("[null,true,\"asd\"]", item.GetString()); + _engine.InvocationStack.Clear(); + + // Deserialize + + result = _engine.ExecuteTestCaseStandard("Deserialize", new ByteArray(Encoding.ASCII.GetBytes("[null,true,\"asd\"]"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Array)); + + var entry = ((Array)item)[0]; + Assert.IsInstanceOfType(entry, typeof(Null)); + entry = ((Array)item)[1]; + Assert.IsInstanceOfType(entry, typeof(Boolean)); + Assert.AreEqual(true, entry.GetBoolean()); + entry = ((Array)item)[2]; + Assert.IsInstanceOfType(entry, typeof(ByteArray)); + Assert.AreEqual("asd", entry.GetString()); + _engine.InvocationStack.Clear(); + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Json.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Json.cs new file mode 100644 index 000000000..23bd5a8a0 --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Json.cs @@ -0,0 +1,17 @@ +using Neo.SmartContract.Framework.Services.Neo; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_Json : SmartContract.Framework.SmartContract + { + public static string Serialize(object obj) + { + return Json.Serialize(obj); + } + + public static object Deserialize(string json) + { + return Json.Deserialize(json); + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index da4d55074..a26ae8ddc 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -1,3 +1,4 @@ +using Neo.IO.Json; using Neo.Ledger; using Neo.SmartContract; using Neo.VM; @@ -174,6 +175,14 @@ protected override bool OnSysCall(uint method) { return Account_IsStandard(); } + else if (method == InteropService.Neo_Json_Deserialize) + { + return Json_Deserialize(); + } + else if (method == InteropService.Neo_Json_Serialize) + { + return Json_Serialize(); + } Console.WriteLine($"Syscall not found: {method.ToString("X2")}"); throw new NotImplementedException(method.ToString("X2")); @@ -186,6 +195,25 @@ private bool Account_IsStandard() return true; } + private bool Json_Deserialize() + { + var json = CurrentContext.EvaluationStack.Pop().GetString(); + var obj = JObject.Parse(json, 10); + var item = JsonSerializer.Deserialize(obj); + + CurrentContext.EvaluationStack.Push(item); + return true; + } + + private bool Json_Serialize() + { + var item = CurrentContext.EvaluationStack.Pop(); + var json = JsonSerializer.Serialize(item); + + CurrentContext.EvaluationStack.Push(json.ToString()); + return true; + } + private bool Runtime_GetNotifications() { byte[] data = CurrentContext.EvaluationStack.Pop().GetByteArray(); From b27d1599eb76370c56d37e1ad47da774e7d09134 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 16:31:23 +0200 Subject: [PATCH 13/32] Update --- .../Services/Neo/AccountTest.cs | 4 +- .../Services/Neo/JsonTest.cs | 7 +- .../Services/Neo/StorageTest.cs} | 57 ++++- ...ract_StorageMap.cs => Contract_Storage.cs} | 16 +- .../UnitTest_Syscalls.cs | 2 + .../Utils/NeonTestTool.cs | 4 +- .../Utils/TestDataCache.cs | 52 +++++ .../Utils/TestEngine.cs | 211 +++--------------- .../Utils/TestMetaDataCache.cs | 26 +++ .../Utils/TestSnapshot.cs | 32 +++ 10 files changed, 211 insertions(+), 200 deletions(-) rename tests/Neo.Compiler.MSIL.UnitTests/{UnitTest_StorageMap.cs => SmartContractFramework/Services/Neo/StorageTest.cs} (66%) rename tests/Neo.Compiler.MSIL.UnitTests/TestClasses/{Contract_StorageMap.cs => Contract_Storage.cs} (88%) create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs index 75d356a4f..1b26123de 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs @@ -24,10 +24,10 @@ public void Test_AccountIsStandard() var result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[0])); Assert.AreEqual(VM.VMState.FAULT, _engine.State); Assert.AreEqual(0, result.Count); - _engine.InvocationStack.Clear(); // No standard + _engine.Reset(); result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[20])); Assert.AreEqual(VM.VMState.HALT, _engine.State); Assert.AreEqual(1, result.Count); @@ -35,10 +35,10 @@ public void Test_AccountIsStandard() var item = result.Pop(); Assert.IsInstanceOfType(item, typeof(Boolean)); Assert.AreEqual(false, item.GetBoolean()); - _engine.InvocationStack.Clear(); // Standard + _engine.Reset(); result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[20] { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs index 2df4b0c19..49b7063ee 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs @@ -26,17 +26,17 @@ public void Test_SerializeDeserialize() var result = _engine.ExecuteTestCaseStandard("Serialize"); Assert.AreEqual(VMState.FAULT, _engine.State); Assert.AreEqual(0, result.Count); - _engine.InvocationStack.Clear(); // Empty Serialize + _engine.Reset(); result = _engine.ExecuteTestCaseStandard("Deserialize"); Assert.AreEqual(VMState.FAULT, _engine.State); Assert.AreEqual(0, result.Count); - _engine.InvocationStack.Clear(); // Serialize + _engine.Reset(); result = _engine.ExecuteTestCaseStandard("Serialize", new Array(new StackItem[]{ StackItem.Null, new Boolean(true), new ByteArray(Encoding.ASCII.GetBytes("asd")) })); @@ -46,10 +46,10 @@ public void Test_SerializeDeserialize() var item = result.Pop(); Assert.IsInstanceOfType(item, typeof(ByteArray)); Assert.AreEqual("[null,true,\"asd\"]", item.GetString()); - _engine.InvocationStack.Clear(); // Deserialize + _engine.Reset(); result = _engine.ExecuteTestCaseStandard("Deserialize", new ByteArray(Encoding.ASCII.GetBytes("[null,true,\"asd\"]"))); Assert.AreEqual(VMState.HALT, _engine.State); Assert.AreEqual(1, result.Count); @@ -65,7 +65,6 @@ public void Test_SerializeDeserialize() entry = ((Array)item)[2]; Assert.IsInstanceOfType(entry, typeof(ByteArray)); Assert.AreEqual("asd", entry.GetString()); - _engine.InvocationStack.Clear(); } } } diff --git a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_StorageMap.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs similarity index 66% rename from tests/Neo.Compiler.MSIL.UnitTests/UnitTest_StorageMap.cs rename to tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs index 47a8f79be..d623cbb66 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_StorageMap.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs @@ -3,23 +3,24 @@ using Neo.VM.Types; using System.Linq; -namespace Neo.Compiler.MSIL +namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo { [TestClass] - public class UnitTest_StorageMap + public class StorageTest { private void Put(TestEngine testengine, string method, byte[] prefix, byte[] key, byte[] value) { var result = testengine.ExecuteTestCaseStandard(method, new ByteArray(key), new ByteArray(value)); var rItem = result.Pop(); + Assert.IsInstanceOfType(rItem, typeof(Integer)); Assert.AreEqual(1, rItem.GetBigInteger()); Assert.AreEqual(1, - testengine.Storages + testengine.Snapshot.Storages.GetChangeSet() .Count(a => a.Key.Key.SequenceEqual(prefix.Concat(key)) && - a.Value.Value.SequenceEqual(value) && - !a.Value.IsConstant + a.Item.Value.SequenceEqual(value) && + !a.Item.IsConstant )); } @@ -29,7 +30,7 @@ private byte[] Get(TestEngine testengine, string method, byte[] prefix, byte[] k Assert.AreEqual(1, result.Count); var rItem = result.Pop(); Assert.IsInstanceOfType(rItem, typeof(ByteArray)); - Assert.AreEqual(1, testengine.Storages.Count(a => a.Key.Key.SequenceEqual(prefix.Concat(key)))); + Assert.AreEqual(1, testengine.Snapshot.Storages.GetChangeSet().Count(a => a.Key.Key.SequenceEqual(prefix.Concat(key)))); return rItem.GetByteArray(); } @@ -39,7 +40,7 @@ private bool Delete(TestEngine testengine, string method, byte[] prefix, byte[] Assert.AreEqual(1, result.Count); var rItem = result.Pop(); Assert.IsInstanceOfType(rItem, typeof(Boolean)); - Assert.AreEqual(0, testengine.Storages.Count(a => a.Key.Key.SequenceEqual(prefix.Concat(key)))); + Assert.AreEqual(0, testengine.Snapshot.Storages.GetChangeSet().Count(a => a.Key.Key.SequenceEqual(prefix.Concat(key)))); return rItem.GetBoolean(); } @@ -47,7 +48,15 @@ private bool Delete(TestEngine testengine, string method, byte[] prefix, byte[] public void Test_Byte() { var testengine = new TestEngine(); - testengine.AddEntryScript("./TestClasses/Contract_StorageMap.cs"); + testengine.AddEntryScript("./TestClasses/Contract_Storage.cs"); + testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() + { + Script = testengine.EntryContext.Script, + Manifest = new SmartContract.Manifest.ContractManifest() + { + Features = SmartContract.Manifest.ContractFeatures.HasStorage + } + }); var prefix = new byte[] { 0xAA }; var key = new byte[] { 0x01, 0x02, 0x03 }; @@ -59,13 +68,17 @@ public void Test_Byte() // Get + testengine.Reset(); var getVal = Get(testengine, "TestGetByte", prefix, key); CollectionAssert.AreEqual(value, getVal); // Delete + testengine.Reset(); var del = Delete(testengine, "TestDeleteByte", prefix, key); Assert.IsTrue(del); + + testengine.Reset(); del = Delete(testengine, "TestDeleteByte", prefix, key); Assert.IsFalse(del); } @@ -74,7 +87,15 @@ public void Test_Byte() public void Test_ByteArray() { var testengine = new TestEngine(); - testengine.AddEntryScript("./TestClasses/Contract_StorageMap.cs"); + testengine.AddEntryScript("./TestClasses/Contract_Storage.cs"); + testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() + { + Script = testengine.EntryContext.Script, + Manifest = new SmartContract.Manifest.ContractManifest() + { + Features = SmartContract.Manifest.ContractFeatures.HasStorage + } + }); var prefix = new byte[] { 0x00, 0xFF }; var key = new byte[] { 0x01, 0x02, 0x03 }; @@ -86,13 +107,17 @@ public void Test_ByteArray() // Get + testengine.Reset(); var getVal = Get(testengine, "TestGetByteArray", prefix, key); CollectionAssert.AreEqual(value, getVal); // Delete + testengine.Reset(); var del = Delete(testengine, "TestDeleteByteArray", prefix, key); Assert.IsTrue(del); + + testengine.Reset(); del = Delete(testengine, "TestDeleteByteArray", prefix, key); Assert.IsFalse(del); } @@ -101,7 +126,15 @@ public void Test_ByteArray() public void Test_String() { var testengine = new TestEngine(); - testengine.AddEntryScript("./TestClasses/Contract_StorageMap.cs"); + testengine.AddEntryScript("./TestClasses/Contract_Storage.cs"); + testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() + { + Script = testengine.EntryContext.Script, + Manifest = new SmartContract.Manifest.ContractManifest() + { + Features = SmartContract.Manifest.ContractFeatures.HasStorage + } + }); var prefix = new byte[] { 0x61, 0x61 }; var key = new byte[] { 0x01, 0x02, 0x03 }; @@ -113,13 +146,17 @@ public void Test_String() // Get + testengine.Reset(); var getVal = Get(testengine, "TestGetString", prefix, key); CollectionAssert.AreEqual(value, getVal); // Delete + testengine.Reset(); var del = Delete(testengine, "TestDeleteString", prefix, key); Assert.IsTrue(del); + + testengine.Reset(); del = Delete(testengine, "TestDeleteString", prefix, key); Assert.IsFalse(del); } diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_StorageMap.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs similarity index 88% rename from tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_StorageMap.cs rename to tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs index 37903ac11..d404dfd75 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_StorageMap.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs @@ -1,8 +1,8 @@ -using Neo.SmartContract.Framework.Services.Neo; +using Neo.SmartContract.Framework.Services.Neo; namespace Neo.Compiler.MSIL.TestClasses { - class Contract_StorageMap : SmartContract.Framework.SmartContract + class Contract_Storage : SmartContract.Framework.SmartContract { // There is no main here, it can be auto generation. @@ -19,9 +19,9 @@ public static bool TestDeleteByte(byte[] key) { var storage = Storage.CurrentContext.CreateMap(0xAA); var value = storage.Get(key); - var exists = value.Length > 0; + if (value == null) return false; storage.Delete(key); - return exists; + return true; } public static byte[] TestGetByte(byte[] key) @@ -48,9 +48,9 @@ public static bool TestDeleteString(byte[] key) var prefix = "aa"; var storage = Storage.CurrentContext.CreateMap(prefix); var value = storage.Get(key); - var exists = value.Length > 0; + if (value == null) return false; storage.Delete(key); - return exists; + return true; } public static byte[] TestGetString(byte[] key) @@ -78,9 +78,9 @@ public static bool TestDeleteByteArray(byte[] key) var prefix = new byte[] { 0x00, 0xFF }; var storage = Storage.CurrentContext.CreateMap(prefix); var value = storage.Get(key); - var exists = value.Length > 0; + if (value == null) return false; storage.Delete(key); - return exists; + return true; } public static byte[] TestGetByteArray(byte[] key) diff --git a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Syscalls.cs b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Syscalls.cs index 0d0f87645..9bebc9f50 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Syscalls.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Syscalls.cs @@ -38,6 +38,7 @@ public void Test_GetNotificationsCount() Assert.IsInstanceOfType(item, typeof(Integer)); Assert.AreEqual(0x01, item.GetBigInteger()); + _engine.Reset(); result = _engine.ExecuteTestCaseStandard("GetNotificationsCount", new ByteArray(new byte[0])); Assert.AreEqual(1, result.Count); @@ -56,6 +57,7 @@ public void Test_GetNotifications() Assert.IsInstanceOfType(item, typeof(Integer)); Assert.AreEqual(0x02, item.GetBigInteger()); + _engine.Reset(); result = _engine.ExecuteTestCaseStandard("GetNotifications", new ByteArray(new byte[0])); Assert.AreEqual(1, result.Count); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/NeonTestTool.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/NeonTestTool.cs index 6d54e3f60..6289d144d 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/NeonTestTool.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/NeonTestTool.cs @@ -51,8 +51,8 @@ public static BuildScript BuildScript(string filename) var coreDir = Path.GetDirectoryName(typeof(object).Assembly.Location); var srccode = File.ReadAllText(filename); var tree = CSharpSyntaxTree.ParseText(srccode); - var op = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); - var comp = CSharpCompilation.Create("aaa.dll", new[] { tree }, new[] + var op = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Release); + var comp = CSharpCompilation.Create("TestContract", new[] { tree }, new[] { MetadataReference.CreateFromFile(Path.Combine(coreDir, "mscorlib.dll")), MetadataReference.CreateFromFile(Path.Combine(coreDir, "System.Runtime.dll")), diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs new file mode 100644 index 000000000..e2db4d57b --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs @@ -0,0 +1,52 @@ +using Neo.IO; +using Neo.IO.Caching; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Neo.Compiler.MSIL.Utils +{ + public class TestDataCache : DataCache + where TKey : IEquatable, ISerializable + where TValue : class, ICloneable, ISerializable, new() + { + private readonly Dictionary dic = new Dictionary(); + + public TestDataCache() { } + + public TestDataCache(TKey key, TValue value) + { + dic.Add(key, value); + } + public override void DeleteInternal(TKey key) + { + dic.Remove(key); + } + + protected override void AddInternal(TKey key, TValue value) + { + dic.Add(key, value); + } + + protected override IEnumerable> FindInternal(byte[] key_prefix) + { + return dic.ToList(); + } + + protected override TValue GetInternal(TKey key) + { + if (dic[key] == null) throw new NotImplementedException(); + return dic[key]; + } + + protected override TValue TryGetInternal(TKey key) + { + return dic.TryGetValue(key, out TValue value) ? value : null; + } + + protected override void UpdateInternal(TKey key, TValue value) + { + dic[key] = value; + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index a26ae8ddc..64ba05f9d 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -1,5 +1,4 @@ -using Neo.IO.Json; -using Neo.Ledger; +using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.VM; using Neo.VM.Types; @@ -9,7 +8,7 @@ namespace Neo.Compiler.MSIL.Utils { - class TestEngine : ExecutionEngine + class TestEngine : ApplicationEngine { public const int MaxStorageKeySize = 64; public const int MaxStorageValueSize = ushort.MaxValue; @@ -18,18 +17,12 @@ class TestEngine : ExecutionEngine public readonly IDictionary Scripts; - public readonly IDictionary Storages; + public BuildScript ScriptEntry { get; private set; } - public BuildScript ScriptEntry - { - get; - private set; - } - - public TestEngine() + public TestEngine(TriggerType trigger = TriggerType.Application, IVerifiable verificable = null) + : base(trigger, verificable, new TestSnapshot(), 0, true) { Scripts = new Dictionary(); - Storages = new Dictionary(); } public void AddAppcallScript(string filename, string specScriptID) @@ -54,17 +47,27 @@ public void AddEntryScript(string filename) } ScriptEntry = scriptsAll[filename]; + Reset(); + } + + public void Reset() + { + this.State = VMState.BREAK; // Required for allow to reuse the same TestEngine + this.InvocationStack.Clear(); + this.LoadScript(ScriptEntry.finalNEF); } public class ContractMethod { - TestEngine engine; - string methodname; + readonly TestEngine engine; + readonly string methodname; + public ContractMethod(TestEngine engine, string methodname) { this.engine = engine; this.methodname = methodname; } + public StackItem Run(params StackItem[] _params) { return this.engine.ExecuteTestCaseStandard(methodname, _params).Pop(); @@ -76,13 +79,11 @@ public ContractMethod GetMethod(string methodname) return new ContractMethod(this, methodname); } - public RandomAccessStack ExecuteTestCaseStandard(string methodname, params StackItem[] _params) + public RandomAccessStack ExecuteTestCaseStandard(string methodname, params StackItem[] args) { //var engine = new ExecutionEngine(); - this.State = VMState.BREAK; // Required for allow to reuse the same TestEngine - this.LoadScript(ScriptEntry.finalNEF); this.InvocationStack.Peek().InstructionPointer = 0; - this.CurrentContext.EvaluationStack.Push(_params); + this.CurrentContext.EvaluationStack.Push(args); this.CurrentContext.EvaluationStack.Push(methodname); while (true) { @@ -99,16 +100,15 @@ public RandomAccessStack ExecuteTestCaseStandard(string methodname, p return this.ResultStack; } - public RandomAccessStack ExecuteTestCase(StackItem[] _params) + public RandomAccessStack ExecuteTestCase(params StackItem[] args) { //var engine = new ExecutionEngine(); - this.LoadScript(ScriptEntry.finalNEF); this.InvocationStack.Peek().InstructionPointer = 0; - if (_params != null) + if (args != null) { - for (var i = _params.Length - 1; i >= 0; i--) + for (var i = args.Length - 1; i >= 0; i--) { - this.CurrentContext.EvaluationStack.Push(_params[i]); + this.CurrentContext.EvaluationStack.Push(args[i]); } } while (true) @@ -143,25 +143,14 @@ protected override bool OnSysCall(uint method) return Contract_Log(); } // Storages - else if (method == InteropService.System_Storage_GetContext) - { - return Contract_Storage_GetContext(); - } - else if (method == InteropService.System_Storage_GetReadOnlyContext) - { - return Contract_Storage_GetReadOnlyContext(); - } - else if (method == InteropService.System_Storage_Get) - { - return Contract_Storage_Get(); - } - else if (method == InteropService.System_Storage_Delete) - { - return Contract_Storage_Delete(); - } - else if (method == InteropService.System_Storage_Put) - { - return Contract_Storage_Put(); + else if ( + method == InteropService.System_Storage_GetContext || + method == InteropService.System_Storage_GetReadOnlyContext || + method == InteropService.System_Storage_Get || + method == InteropService.System_Storage_Delete || + method == InteropService.System_Storage_Put) + { + return base.OnSysCall(method); } else if (method == InteropService.System_Runtime_GetInvocationCounter) { @@ -175,17 +164,15 @@ protected override bool OnSysCall(uint method) { return Account_IsStandard(); } - else if (method == InteropService.Neo_Json_Deserialize) - { - return Json_Deserialize(); - } - else if (method == InteropService.Neo_Json_Serialize) + else if ( + method == InteropService.Neo_Json_Deserialize || + method == InteropService.Neo_Json_Serialize) { - return Json_Serialize(); + return base.OnSysCall(method); } - Console.WriteLine($"Syscall not found: {method.ToString("X2")}"); - throw new NotImplementedException(method.ToString("X2")); + Console.WriteLine($"Syscall not found: {method.ToString("X2")} (using base call)"); + return base.OnSysCall(method); } private bool Account_IsStandard() @@ -195,25 +182,6 @@ private bool Account_IsStandard() return true; } - private bool Json_Deserialize() - { - var json = CurrentContext.EvaluationStack.Pop().GetString(); - var obj = JObject.Parse(json, 10); - var item = JsonSerializer.Deserialize(obj); - - CurrentContext.EvaluationStack.Push(item); - return true; - } - - private bool Json_Serialize() - { - var item = CurrentContext.EvaluationStack.Pop(); - var json = JsonSerializer.Serialize(item); - - CurrentContext.EvaluationStack.Push(json.ToString()); - return true; - } - private bool Runtime_GetNotifications() { byte[] data = CurrentContext.EvaluationStack.Pop().GetByteArray(); @@ -241,111 +209,6 @@ private bool Runtime_GetInvocationCounter() return true; } - #region Storage - - private bool Contract_Storage_GetContext() - { - CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new TestStorageContext - { - ScriptHash = CurrentContext.ScriptHash(), - IsReadOnly = false - })); - return true; - } - - private bool Contract_Storage_GetReadOnlyContext() - { - CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new TestStorageContext - { - ScriptHash = CurrentContext.ScriptHash(), - IsReadOnly = true - })); - return true; - } - - private bool Contract_Storage_Delete() - { - if (CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - TestStorageContext context = _interface.GetInterface(); - if (context.IsReadOnly) return false; - - StorageKey key = new StorageKey - { - ScriptHash = context.ScriptHash, - Key = CurrentContext.EvaluationStack.Pop().GetByteArray() - }; - if (Storages.TryGetValue(key, out var item) && item.IsConstant == true) return false; - Storages.Remove(key); - return true; - } - return false; - } - - private bool Contract_Storage_Get() - { - if (CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - TestStorageContext context = _interface.GetInterface(); - byte[] key = CurrentContext.EvaluationStack.Pop().GetByteArray(); - - if (Storages.TryGetValue(new StorageKey - { - ScriptHash = context.ScriptHash, - Key = key - }, out var item)) - { - CurrentContext.EvaluationStack.Push(item.Value); - } - else - { - CurrentContext.EvaluationStack.Push(new byte[0]); - } - return true; - } - return false; - } - - private bool Contract_Storage_Put() - { - if (!(CurrentContext.EvaluationStack.Pop() is InteropInterface _interface)) - return false; - TestStorageContext context = _interface.GetInterface(); - byte[] key = CurrentContext.EvaluationStack.Pop().GetByteArray(); - byte[] value = CurrentContext.EvaluationStack.Pop().GetByteArray(); - return PutEx(context, key, value, StorageFlags.None); - } - - private bool PutEx(TestStorageContext context, byte[] key, byte[] value, StorageFlags flags) - { - if (key.Length > MaxStorageKeySize) return false; - if (value.Length > MaxStorageValueSize) return false; - if (context.IsReadOnly) return false; - - StorageKey skey = new StorageKey - { - ScriptHash = context.ScriptHash, - Key = key - }; - - if (Storages.TryGetValue(skey, out var item) && item.IsConstant == true) return false; - - if (value.Length == 0 && !flags.HasFlag(StorageFlags.Constant)) - { - // If put 'value' is empty (and non-const), we remove it (implicit `Storage.Delete`) - Storages.Remove(skey); - } - else - { - item = Storages[skey] = new StorageItem(); - item.Value = value; - item.IsConstant = flags.HasFlag(StorageFlags.Constant); - } - return true; - } - - #endregion - private bool Contract_Call() { StackItem item0 = this.CurrentContext.EvaluationStack.Pop(); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs new file mode 100644 index 000000000..318e902cb --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs @@ -0,0 +1,26 @@ +using Neo.IO; +using Neo.IO.Caching; + +namespace Neo.Compiler.MSIL.Utils +{ + public class TestMetaDataCache : MetaDataCache where T : class, ICloneable, ISerializable, new() + { + public TestMetaDataCache() + : base(null) + { + } + + protected override void AddInternal(T item) + { + } + + protected override T TryGetInternal() + { + return null; + } + + protected override void UpdateInternal(T item) + { + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs new file mode 100644 index 000000000..9f68e4400 --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs @@ -0,0 +1,32 @@ +using Neo.IO.Caching; +using Neo.IO.Wrappers; +using Neo.Ledger; +using Neo.Persistence; + +namespace Neo.Compiler.MSIL.Utils +{ + public class TestSnapshot : Snapshot + { + private DataCache _Blocks = new TestDataCache(); + private DataCache _Transactions = new TestDataCache(); + private DataCache _Contracts = new TestDataCache(); + private DataCache _Storages = new TestDataCache(); + private DataCache _HeaderHashList = new TestDataCache(); + private MetaDataCache _BlockHashIndex = new TestMetaDataCache(); + private MetaDataCache _HeaderHashIndex = new TestMetaDataCache(); + + public override DataCache Blocks => _Blocks; + + public override DataCache Transactions => _Transactions; + + public override DataCache Contracts => _Contracts; + + public override DataCache Storages => _Storages; + + public override DataCache HeaderHashList => _HeaderHashList; + + public override MetaDataCache BlockHashIndex => _BlockHashIndex; + + public override MetaDataCache HeaderHashIndex => _HeaderHashIndex; + } +} From e8ec727b6070fe9004ef73d0e69a1c523f59e2e5 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 18:16:06 +0200 Subject: [PATCH 14/32] More tests --- .../Services/Neo/AccountTest.cs | 26 ++- .../Services/Neo/RuntimeTest.cs | 177 ++++++++++++++++++ .../Services/Neo/StorageTest.cs | 26 +-- .../Services/System/ExecutionEngineTest.cs | 103 ++++++++++ .../TestClasses/Contract_ExecutionEngine.cs | 27 +++ ...ntract_Syscalls.cs => Contract_Runtime.cs} | 35 +++- .../TestClasses/Contract_Storage.cs | 15 +- .../TestClasses/Contract_appcall.cs | 4 +- .../UnitTest_Appcall.cs | 10 +- .../UnitTest_Syscalls.cs | 69 ------- .../Utils/TestEngine.cs | 99 +++------- 11 files changed, 393 insertions(+), 198 deletions(-) create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_ExecutionEngine.cs rename tests/Neo.Compiler.MSIL.UnitTests/TestClasses/{Contract_Syscalls.cs => Contract_Runtime.cs} (52%) delete mode 100644 tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Syscalls.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs index 1b26123de..86737f32f 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs @@ -1,5 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Compiler.MSIL.Utils; +using Neo.Ledger; using Neo.VM.Types; namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo @@ -19,13 +20,24 @@ public void Init() [TestMethod] public void Test_AccountIsStandard() { + var noStandard = new byte[20] + { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF + }; + + _engine.Snapshot.Contracts.Add(new UInt160(noStandard), new ContractState() + { + Script = new byte[0] { } + }); + // Empty var result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[0])); Assert.AreEqual(VM.VMState.FAULT, _engine.State); Assert.AreEqual(0, result.Count); - // No standard + // Standard _engine.Reset(); result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[20])); @@ -34,22 +46,18 @@ public void Test_AccountIsStandard() var item = result.Pop(); Assert.IsInstanceOfType(item, typeof(Boolean)); - Assert.AreEqual(false, item.GetBoolean()); + Assert.AreEqual(true, item.GetBoolean()); - // Standard + // No standard _engine.Reset(); - result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(new byte[20] - { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF - })); + result = _engine.ExecuteTestCaseStandard("AccountIsStandard", new ByteArray(noStandard)); Assert.AreEqual(VM.VMState.HALT, _engine.State); Assert.AreEqual(1, result.Count); item = result.Pop(); Assert.IsInstanceOfType(item, typeof(Boolean)); - Assert.AreEqual(true, item.GetBoolean()); + Assert.AreEqual(false, item.GetBoolean()); } } } diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs new file mode 100644 index 000000000..965c69d69 --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs @@ -0,0 +1,177 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +{ + [TestClass] + public class RuntimeTest + { + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(TriggerType.Application); + _engine.AddEntryScript("./TestClasses/Contract_Runtime.cs"); + } + + [TestMethod] + public void Test_InvocationCounter() + { + // Build script + + _engine.Reset(); + + var contract = _engine.EntryScriptHash; + _engine.Snapshot.Contracts.Add(contract, new Ledger.ContractState() + { + Script = _engine.InvocationStack.Peek(0).Script, + Manifest = new SmartContract.Manifest.ContractManifest() + { + } + }); + + _engine.InvocationStack.Clear(); + + using (ScriptBuilder sb = new ScriptBuilder()) + { + // First + sb.EmitAppCall(contract, "GetInvocationCounter"); + // Second + sb.EmitAppCall(contract, "GetInvocationCounter"); + + _engine.LoadScript(sb.ToArray()); + } + + // Check + + Assert.AreEqual(VMState.HALT, _engine.Execute()); + Assert.AreEqual(2, _engine.ResultStack.Count); + + var item = _engine.ResultStack.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(0x02, item.GetBigInteger()); + + item = _engine.ResultStack.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(0x01, item.GetBigInteger()); + } + + [TestMethod] + public void Test_Time() + { + _engine.Snapshot.GetType().GetProperty("PersistingBlock").SetValue(_engine.Snapshot, new Block() + { + Timestamp = 123 + }); + + var result = _engine.ExecuteTestCaseStandard("GetTime"); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(123, item.GetBigInteger()); + } + + [TestMethod] + public void Test_Platform() + { + var result = _engine.ExecuteTestCaseStandard("GetPlatform"); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual("NEO", item.GetString()); + } + + [TestMethod] + public void Test_Trigger() + { + var result = _engine.ExecuteTestCaseStandard("GetTrigger"); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual((byte)TriggerType.Application, item.GetBigInteger()); + } + + [TestMethod] + public void Test_Log() + { + var list = new List(); + var method = new EventHandler((s, e) => list.Add(e)); + + ApplicationEngine.Log += method; + var result = _engine.ExecuteTestCaseStandard("Log", new ByteArray(Encoding.UTF8.GetBytes("LogTest"))); + ApplicationEngine.Log -= method; + + Assert.AreEqual(1, list.Count); + + var item = list[0]; + Assert.AreEqual("LogTest", item.Message); + } + + [TestMethod] + public void Test_Notify() + { + var list = new List(); + var method = new EventHandler((s, e) => list.Add(e)); + + ApplicationEngine.Notify += method; + var result = _engine.ExecuteTestCaseStandard("Notify", new ByteArray(Encoding.UTF8.GetBytes("NotifyTest"))); + ApplicationEngine.Notify -= method; + + Assert.AreEqual(1, list.Count); + + var item = list[0]; + var array = item.State; + Assert.IsInstanceOfType(array, typeof(VM.Types.Array)); + Assert.AreEqual("NotifyTest", ((VM.Types.Array)array)[0].GetString()); + } + + [TestMethod] + public void Test_GetNotificationsCount() + { + var result = _engine.ExecuteTestCaseStandard("GetNotificationsCount", new ByteArray(UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").ToArray())); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(0x01, item.GetBigInteger()); + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("GetNotificationsCount", new ByteArray(new byte[0])); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(0x02, item.GetBigInteger()); + } + + [TestMethod] + public void Test_GetNotifications() + { + var result = _engine.ExecuteTestCaseStandard("GetNotifications", new ByteArray(UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").ToArray())); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(0x02, item.GetBigInteger()); + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("GetNotifications", new ByteArray(new byte[0])); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(0x03, item.GetBigInteger()); + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs index d623cbb66..a61293e59 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs @@ -34,14 +34,13 @@ private byte[] Get(TestEngine testengine, string method, byte[] prefix, byte[] k return rItem.GetByteArray(); } - private bool Delete(TestEngine testengine, string method, byte[] prefix, byte[] key) + private void Delete(TestEngine testengine, string method, byte[] prefix, byte[] key) { var result = testengine.ExecuteTestCaseStandard(method, new ByteArray(key)); Assert.AreEqual(1, result.Count); var rItem = result.Pop(); - Assert.IsInstanceOfType(rItem, typeof(Boolean)); + Assert.IsInstanceOfType(rItem, typeof(ByteArray)); Assert.AreEqual(0, testengine.Snapshot.Storages.GetChangeSet().Count(a => a.Key.Key.SequenceEqual(prefix.Concat(key)))); - return rItem.GetBoolean(); } [TestMethod] @@ -75,12 +74,7 @@ public void Test_Byte() // Delete testengine.Reset(); - var del = Delete(testengine, "TestDeleteByte", prefix, key); - Assert.IsTrue(del); - - testengine.Reset(); - del = Delete(testengine, "TestDeleteByte", prefix, key); - Assert.IsFalse(del); + Delete(testengine, "TestDeleteByte", prefix, key); } [TestMethod] @@ -114,12 +108,7 @@ public void Test_ByteArray() // Delete testengine.Reset(); - var del = Delete(testengine, "TestDeleteByteArray", prefix, key); - Assert.IsTrue(del); - - testengine.Reset(); - del = Delete(testengine, "TestDeleteByteArray", prefix, key); - Assert.IsFalse(del); + Delete(testengine, "TestDeleteByteArray", prefix, key); } [TestMethod] @@ -153,12 +142,7 @@ public void Test_String() // Delete testengine.Reset(); - var del = Delete(testengine, "TestDeleteString", prefix, key); - Assert.IsTrue(del); - - testengine.Reset(); - del = Delete(testengine, "TestDeleteString", prefix, key); - Assert.IsFalse(del); + Delete(testengine, "TestDeleteString", prefix, key); } } } diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs new file mode 100644 index 000000000..dad3f2a35 --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs @@ -0,0 +1,103 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.VM; +using Neo.VM.Types; +using System.IO; + +namespace Neo.Compiler.MSIL.SmartContractFramework.Services.System +{ + [TestClass] + public class ExecutionEngineTest + { + class DummyVerificable : IVerifiable + { + public Witness[] Witnesses { get; set; } + + public int Size => 0; + + public void Deserialize(BinaryReader reader) + { + } + + public void DeserializeUnsigned(BinaryReader reader) + { + } + + public UInt160[] GetScriptHashesForVerifying(Snapshot snapshot) + { + throw new global::System.NotImplementedException(); + } + + public void Serialize(BinaryWriter writer) + { + } + + public void SerializeUnsigned(BinaryWriter writer) + { + } + } + + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(SmartContract.TriggerType.Application, new DummyVerificable()); + _engine.AddEntryScript("./TestClasses/Contract_ExecutionEngine.cs"); + } + + [TestMethod] + public void CallingScriptHashTest() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("CallingScriptHash"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual("3632c01ec5cc1961ba49d8033798e469f6a6f697", item.GetByteArray().ToHexString()); + } + + [TestMethod] + public void EntryScriptHashTest() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("EntryScriptHash"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual("3632c01ec5cc1961ba49d8033798e469f6a6f697", item.GetByteArray().ToHexString()); + } + + [TestMethod] + public void ExecutingScriptHashTest() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("ExecutingScriptHash"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual("3632c01ec5cc1961ba49d8033798e469f6a6f697", item.GetByteArray().ToHexString()); + } + + [TestMethod] + public void ScriptContainerTest() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("ScriptContainer"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(InteropInterface)); + Assert.AreEqual(_engine.ScriptContainer, ((InteropInterface)item).GetInterface()); + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_ExecutionEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_ExecutionEngine.cs new file mode 100644 index 000000000..b21025ca9 --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_ExecutionEngine.cs @@ -0,0 +1,27 @@ +using Neo.SmartContract.Framework.Services.System; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_ExecutionEngine : SmartContract.Framework.SmartContract + { + public static byte[] CallingScriptHash() + { + return ExecutionEngine.CallingScriptHash; + } + + public static byte[] EntryScriptHash() + { + return ExecutionEngine.EntryScriptHash; + } + + public static byte[] ExecutingScriptHash() + { + return ExecutionEngine.ExecutingScriptHash; + } + + public static object ScriptContainer() + { + return ExecutionEngine.ScriptContainer; + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Syscalls.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs similarity index 52% rename from tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Syscalls.cs rename to tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs index c96c0d4c6..f2ca38328 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Syscalls.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs @@ -1,22 +1,49 @@ +using Neo.SmartContract.Framework.Services.Neo; + namespace Neo.Compiler.MSIL.TestClasses { - public class Contract_Syscalls : SmartContract.Framework.SmartContract + public class Contract_Runtime : SmartContract.Framework.SmartContract { public static uint GetInvocationCounter() { - return SmartContract.Framework.Services.Neo.Runtime.InvocationCounter; + return Runtime.InvocationCounter; + } + + public static ulong GetTime() + { + return Runtime.Time; + } + + public static string GetPlatform() + { + return Runtime.Platform; + } + + public static TriggerType GetTrigger() + { + return Runtime.Trigger; + } + + public static void Log(string message) + { + Runtime.Log(message); + } + + public static void Notify(string message) + { + Runtime.Notify(message); } public static int GetNotificationsCount(byte[] hash) { - var notifications = SmartContract.Framework.Services.Neo.Runtime.GetNotifications(hash); + var notifications = Runtime.GetNotifications(hash); return notifications.Length; } public static int GetNotifications(byte[] hash) { int sum = 0; - var notifications = SmartContract.Framework.Services.Neo.Runtime.GetNotifications(hash); + var notifications = Runtime.GetNotifications(hash); for (int x = 0; x < notifications.Length; x++) { diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs index d404dfd75..0eb58a3e3 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs @@ -15,13 +15,10 @@ public static bool TestPutByte(byte[] key, byte[] value) return true; } - public static bool TestDeleteByte(byte[] key) + public static void TestDeleteByte(byte[] key) { var storage = Storage.CurrentContext.CreateMap(0xAA); - var value = storage.Get(key); - if (value == null) return false; storage.Delete(key); - return true; } public static byte[] TestGetByte(byte[] key) @@ -43,14 +40,11 @@ public static bool TestPutString(byte[] key, byte[] value) return true; } - public static bool TestDeleteString(byte[] key) + public static void TestDeleteString(byte[] key) { var prefix = "aa"; var storage = Storage.CurrentContext.CreateMap(prefix); - var value = storage.Get(key); - if (value == null) return false; storage.Delete(key); - return true; } public static byte[] TestGetString(byte[] key) @@ -73,14 +67,11 @@ public static bool TestPutByteArray(byte[] key, byte[] value) return true; } - public static bool TestDeleteByteArray(byte[] key) + public static void TestDeleteByteArray(byte[] key) { var prefix = new byte[] { 0x00, 0xFF }; var storage = Storage.CurrentContext.CreateMap(prefix); - var value = storage.Get(key); - if (value == null) return false; storage.Delete(key); - return true; } public static byte[] TestGetByteArray(byte[] key) diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_appcall.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_appcall.cs index 68c673729..fa2b9323c 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_appcall.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_appcall.cs @@ -1,7 +1,4 @@ using Neo.SmartContract.Framework; -using System; -using System.Collections.Generic; -using System.Text; namespace Neo.Compiler.MSIL.TestClasses { @@ -10,6 +7,7 @@ class Contract_syscall : SmartContract.Framework.SmartContract //这个appcall的地址,在testcase中可以配置 [Appcall("0102030405060708090A0102030405060708090A")] static extern object unittest001(string method, object[] arr); + public static object Main(string method, object[] args) { return unittest001(method, args); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Appcall.cs b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Appcall.cs index 080de1338..53e455229 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Appcall.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Appcall.cs @@ -1,7 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Compiler.MSIL.Utils; using Neo.VM; -using System; namespace Neo.Compiler.MSIL { @@ -11,8 +10,15 @@ public class UnitTest_AppCall [TestMethod] public void Test_Appcall() { + var hash = UInt160.Parse("0102030405060708090A0102030405060708090A"); var testengine = new TestEngine(); - testengine.AddAppcallScript("./TestClasses/Contract1.cs", "0102030405060708090A0102030405060708090A"); + + testengine.Snapshot.Contracts.Add(hash, new Ledger.ContractState() + { + Manifest = new SmartContract.Manifest.ContractManifest(), + Script = testengine.Build("./TestClasses/Contract1.cs").finalNEF + }); + //will appcall 0102030405060708090A0102030405060708090A testengine.AddEntryScript("./TestClasses/Contract_appcall.cs"); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Syscalls.cs b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Syscalls.cs deleted file mode 100644 index 9bebc9f50..000000000 --- a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_Syscalls.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.Compiler.MSIL.Utils; -using Neo.VM; -using Neo.VM.Types; - -namespace Neo.Compiler.MSIL -{ - [TestClass] - public class UnitTest_Syscalls - { - private TestEngine _engine; - - [TestInitialize] - public void Init() - { - _engine = new TestEngine(); - _engine.AddEntryScript("./TestClasses/Contract_Syscalls.cs"); - } - - [TestMethod] - public void Test_InvocationCounter() - { - var result = _engine.ExecuteTestCaseStandard("GetInvocationCounter"); - Assert.AreEqual(1, result.Count); - - var item = result.Pop(); - Assert.IsInstanceOfType(item, typeof(Integer)); - Assert.AreEqual(0x01, item.GetBigInteger()); - } - - [TestMethod] - public void Test_GetNotificationsCount() - { - var result = _engine.ExecuteTestCaseStandard("GetNotificationsCount", new ByteArray(UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").ToArray())); - Assert.AreEqual(1, result.Count); - - var item = result.Pop(); - Assert.IsInstanceOfType(item, typeof(Integer)); - Assert.AreEqual(0x01, item.GetBigInteger()); - - _engine.Reset(); - result = _engine.ExecuteTestCaseStandard("GetNotificationsCount", new ByteArray(new byte[0])); - Assert.AreEqual(1, result.Count); - - item = result.Pop(); - Assert.IsInstanceOfType(item, typeof(Integer)); - Assert.AreEqual(0x02, item.GetBigInteger()); - } - - [TestMethod] - public void Test_GetNotifications() - { - var result = _engine.ExecuteTestCaseStandard("GetNotifications", new ByteArray(UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").ToArray())); - Assert.AreEqual(1, result.Count); - - var item = result.Pop(); - Assert.IsInstanceOfType(item, typeof(Integer)); - Assert.AreEqual(0x02, item.GetBigInteger()); - - _engine.Reset(); - result = _engine.ExecuteTestCaseStandard("GetNotifications", new ByteArray(new byte[0])); - Assert.AreEqual(1, result.Count); - - item = result.Pop(); - Assert.IsInstanceOfType(item, typeof(Integer)); - Assert.AreEqual(0x03, item.GetBigInteger()); - } - } -} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 64ba05f9d..e96eb6005 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -25,28 +25,19 @@ public TestEngine(TriggerType trigger = TriggerType.Application, IVerifiable ver Scripts = new Dictionary(); } - public void AddAppcallScript(string filename, string specScriptID) + public BuildScript Build(string filename) { - byte[] hex = NeonTestTool.HexString2Bytes(specScriptID); - if (hex.Length != 20) - throw new Exception("fail Script ID"); - if (scriptsAll.ContainsKey(filename) == false) { scriptsAll[filename] = NeonTestTool.BuildScript(filename); } - Scripts[specScriptID.ToLower()] = scriptsAll[filename]; + return scriptsAll[filename]; } public void AddEntryScript(string filename) { - if (scriptsAll.ContainsKey(filename) == false) - { - scriptsAll[filename] = NeonTestTool.BuildScript(filename); - } - - ScriptEntry = scriptsAll[filename]; + ScriptEntry = Build(filename); Reset(); } @@ -129,44 +120,32 @@ public RandomAccessStack ExecuteTestCase(params StackItem[] args) protected override bool OnSysCall(uint method) { - if (method == InteropService.System_Contract_Call) - { - //a appcall - return Contract_Call(); - } - else if (method == InteropService.System_Runtime_Log) - { - return Contract_Log(); - } - else if (method == InteropService.System_Runtime_Notify) + if (method == InteropService.System_Runtime_GetNotifications) { - return Contract_Log(); + return Runtime_GetNotifications(); } - // Storages else if ( + // Account + method == InteropService.Neo_Account_IsStandard || + // Storages method == InteropService.System_Storage_GetContext || method == InteropService.System_Storage_GetReadOnlyContext || method == InteropService.System_Storage_Get || method == InteropService.System_Storage_Delete || - method == InteropService.System_Storage_Put) - { - return base.OnSysCall(method); - } - else if (method == InteropService.System_Runtime_GetInvocationCounter) - { - return Runtime_GetInvocationCounter(); - } - else if (method == InteropService.System_Runtime_GetNotifications) - { - return Runtime_GetNotifications(); - } - else if (method == InteropService.Neo_Account_IsStandard) - { - return Account_IsStandard(); - } - else if ( + method == InteropService.System_Storage_Put || + // Runtime + method == InteropService.System_Runtime_GetInvocationCounter || + method == InteropService.System_Runtime_GetTrigger || + method == InteropService.System_Runtime_GetTime || + method == InteropService.System_Runtime_Platform || + method == InteropService.System_Runtime_Log || + method == InteropService.System_Runtime_Notify || + // Json method == InteropService.Neo_Json_Deserialize || - method == InteropService.Neo_Json_Serialize) + method == InteropService.Neo_Json_Serialize || + // Contract + method == InteropService.System_Contract_Call + ) { return base.OnSysCall(method); } @@ -175,13 +154,6 @@ protected override bool OnSysCall(uint method) return base.OnSysCall(method); } - private bool Account_IsStandard() - { - UInt160 hash = new UInt160(CurrentContext.EvaluationStack.Pop().GetByteArray()); - CurrentContext.EvaluationStack.Push(hash.Equals(UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))); - return true; - } - private bool Runtime_GetNotifications() { byte[] data = CurrentContext.EvaluationStack.Pop().GetByteArray(); @@ -203,35 +175,6 @@ private bool Runtime_GetNotifications() return true; } - private bool Runtime_GetInvocationCounter() - { - CurrentContext.EvaluationStack.Push(0x01); - return true; - } - - private bool Contract_Call() - { - StackItem item0 = this.CurrentContext.EvaluationStack.Pop(); - var contractid = item0.GetByteArray(); - var contractkey = NeonTestTool.Bytes2HexString(contractid.Reverse().ToArray()).ToLower(); - var contract = Scripts[contractkey]; - - if (contract is null) return false; - StackItem item1 = this.CurrentContext.EvaluationStack.Pop(); - StackItem item2 = this.CurrentContext.EvaluationStack.Pop(); - ExecutionContext context_new = this.LoadScript(contract.finalNEF, 1); - context_new.EvaluationStack.Push(item2); - context_new.EvaluationStack.Push(item1); - return true; - } - - private bool Contract_Log() - { - StackItem item0 = this.CurrentContext.EvaluationStack.Pop(); - DumpItem(item0); - return true; - } - public bool CheckAsciiChar(string s) { for (int i = 0; i < s.Length; i++) From b52fb369696769feafdfd0dc47d423cb94433cfa Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 18:18:10 +0200 Subject: [PATCH 15/32] Ensure checks --- tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index e96eb6005..14e9ed3c4 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -133,6 +133,11 @@ protected override bool OnSysCall(uint method) method == InteropService.System_Storage_Get || method == InteropService.System_Storage_Delete || method == InteropService.System_Storage_Put || + // ExecutionEngine + method == InteropService.System_ExecutionEngine_GetCallingScriptHash || + method == InteropService.System_ExecutionEngine_GetEntryScriptHash || + method == InteropService.System_ExecutionEngine_GetExecutingScriptHash || + method == InteropService.System_ExecutionEngine_GetScriptContainer || // Runtime method == InteropService.System_Runtime_GetInvocationCounter || method == InteropService.System_Runtime_GetTrigger || @@ -150,8 +155,7 @@ protected override bool OnSysCall(uint method) return base.OnSysCall(method); } - Console.WriteLine($"Syscall not found: {method.ToString("X2")} (using base call)"); - return base.OnSysCall(method); + throw new Exception($"Syscall not found: {method.ToString("X2")} (using base call)"); } private bool Runtime_GetNotifications() From b9d0e7137c3f0dceb373ec1f862d98a7cd64236e Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 18:40:17 +0200 Subject: [PATCH 16/32] Runtime done --- src/Neo.Compiler.MSIL/MSIL/Converter.cs | 2 +- .../Services/Neo/RuntimeTest.cs | 70 +++++++++++++++- .../TestClasses/Contract_Runtime.cs | 30 +++++-- .../Utils/TestEngine.cs | 83 +++++++------------ 4 files changed, 120 insertions(+), 65 deletions(-) diff --git a/src/Neo.Compiler.MSIL/MSIL/Converter.cs b/src/Neo.Compiler.MSIL/MSIL/Converter.cs index 383eeddc3..220b0b077 100644 --- a/src/Neo.Compiler.MSIL/MSIL/Converter.cs +++ b/src/Neo.Compiler.MSIL/MSIL/Converter.cs @@ -535,7 +535,7 @@ private int ConvertCode(ILMethod method, OpCode src, NeoMethod to) break; case CodeEx.Ldnull: - _ConvertPush(new byte[0], src, to); + _Convert1by1(VM.OpCode.PUSHNULL, src, to); break; case CodeEx.Ldc_I4: diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs index 965c69d69..feb2fff6e 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs @@ -1,11 +1,13 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Compiler.MSIL.Utils; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; using Neo.VM; using Neo.VM.Types; using System; using System.Collections.Generic; +using System.IO; using System.Text; namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo @@ -13,12 +15,35 @@ namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo [TestClass] public class RuntimeTest { + class DummyVerificable : IVerifiable + { + public Witness[] Witnesses { get; set; } + + public int Size => 0; + + public void Deserialize(BinaryReader reader) { } + + public void DeserializeUnsigned(BinaryReader reader) { } + + public UInt160[] GetScriptHashesForVerifying(Snapshot snapshot) + { + return new UInt160[] + { + UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") + }; + } + + public void Serialize(BinaryWriter writer) { } + + public void SerializeUnsigned(BinaryWriter writer) { } + } + private TestEngine _engine; [TestInitialize] public void Init() { - _engine = new TestEngine(TriggerType.Application); + _engine = new TestEngine(TriggerType.Application, new DummyVerificable()); _engine.AddEntryScript("./TestClasses/Contract_Runtime.cs"); } @@ -118,6 +143,29 @@ public void Test_Log() Assert.AreEqual("LogTest", item.Message); } + [TestMethod] + public void Test_CheckWitness() + { + // True + + var result = _engine.ExecuteTestCaseStandard("CheckWitness", new ByteArray("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".HexToBytes())); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(VM.Types.Boolean)); + Assert.IsTrue(item.GetBoolean()); + + // False + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("CheckWitness", new ByteArray("AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".HexToBytes())); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(VM.Types.Boolean)); + Assert.IsFalse(item.GetBoolean()); + } + [TestMethod] public void Test_Notify() { @@ -139,6 +187,14 @@ public void Test_Notify() [TestMethod] public void Test_GetNotificationsCount() { + var notifications = ((List)_engine.Notifications); + notifications.Clear(); + notifications.AddRange(new NotifyEventArgs[] + { + new NotifyEventArgs(null, UInt160.Zero, new Integer(0x01)), + new NotifyEventArgs(null, UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), new Integer(0x02)) + }); + var result = _engine.ExecuteTestCaseStandard("GetNotificationsCount", new ByteArray(UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").ToArray())); Assert.AreEqual(1, result.Count); @@ -147,7 +203,7 @@ public void Test_GetNotificationsCount() Assert.AreEqual(0x01, item.GetBigInteger()); _engine.Reset(); - result = _engine.ExecuteTestCaseStandard("GetNotificationsCount", new ByteArray(new byte[0])); + result = _engine.ExecuteTestCaseStandard("GetNotificationsCount", StackItem.Null); Assert.AreEqual(1, result.Count); item = result.Pop(); @@ -158,6 +214,14 @@ public void Test_GetNotificationsCount() [TestMethod] public void Test_GetNotifications() { + var notifications = ((List)_engine.Notifications); + notifications.Clear(); + notifications.AddRange(new NotifyEventArgs[] + { + new NotifyEventArgs(null, UInt160.Zero, new Integer(0x01)), + new NotifyEventArgs(null, UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), new Integer(0x02)) + }); + var result = _engine.ExecuteTestCaseStandard("GetNotifications", new ByteArray(UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").ToArray())); Assert.AreEqual(1, result.Count); @@ -166,7 +230,7 @@ public void Test_GetNotifications() Assert.AreEqual(0x02, item.GetBigInteger()); _engine.Reset(); - result = _engine.ExecuteTestCaseStandard("GetNotifications", new ByteArray(new byte[0])); + result = _engine.ExecuteTestCaseStandard("GetAllNotifications"); Assert.AreEqual(1, result.Count); item = result.Pop(); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs index f2ca38328..459bb3121 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs @@ -34,12 +34,31 @@ public static void Notify(string message) Runtime.Notify(message); } + public static bool CheckWitness(byte[] hashOrPubkey) + { + return Runtime.CheckWitness(hashOrPubkey); + } + public static int GetNotificationsCount(byte[] hash) { var notifications = Runtime.GetNotifications(hash); return notifications.Length; } + public static int GetAllNotifications() + { + int sum = 0; + var notifications = Runtime.GetNotifications(); + + for (int x = 0; x < notifications.Length; x++) + { + var notify = notifications[x]; + sum += (int)notify.State; + } + + return sum; + } + public static int GetNotifications(byte[] hash) { int sum = 0; @@ -49,14 +68,11 @@ public static int GetNotifications(byte[] hash) { var notify = notifications[x]; - if (hash.Length != 0) - { - // Check that the hash is working well + // Check that the hash is working well - for (int y = 0; y < notify.ScriptHash.Length; y++) - { - if (notify.ScriptHash[y] != hash[y]) return int.MinValue; - } + for (int y = 0; y < notify.ScriptHash.Length; y++) + { + if (notify.ScriptHash[y] != hash[y]) return int.MinValue; } sum += (int)notify.State; diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 14e9ed3c4..4a0fc9192 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -1,10 +1,8 @@ using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.VM; -using Neo.VM.Types; using System; using System.Collections.Generic; -using System.Linq; namespace Neo.Compiler.MSIL.Utils { @@ -120,37 +118,35 @@ public RandomAccessStack ExecuteTestCase(params StackItem[] args) protected override bool OnSysCall(uint method) { - if (method == InteropService.System_Runtime_GetNotifications) - { - return Runtime_GetNotifications(); - } - else if ( - // Account - method == InteropService.Neo_Account_IsStandard || - // Storages - method == InteropService.System_Storage_GetContext || - method == InteropService.System_Storage_GetReadOnlyContext || - method == InteropService.System_Storage_Get || - method == InteropService.System_Storage_Delete || - method == InteropService.System_Storage_Put || - // ExecutionEngine - method == InteropService.System_ExecutionEngine_GetCallingScriptHash || - method == InteropService.System_ExecutionEngine_GetEntryScriptHash || - method == InteropService.System_ExecutionEngine_GetExecutingScriptHash || - method == InteropService.System_ExecutionEngine_GetScriptContainer || - // Runtime - method == InteropService.System_Runtime_GetInvocationCounter || - method == InteropService.System_Runtime_GetTrigger || - method == InteropService.System_Runtime_GetTime || - method == InteropService.System_Runtime_Platform || - method == InteropService.System_Runtime_Log || - method == InteropService.System_Runtime_Notify || - // Json - method == InteropService.Neo_Json_Deserialize || - method == InteropService.Neo_Json_Serialize || - // Contract - method == InteropService.System_Contract_Call - ) + if ( + // Account + method == InteropService.Neo_Account_IsStandard || + // Storages + method == InteropService.System_Storage_GetContext || + method == InteropService.System_Storage_GetReadOnlyContext || + method == InteropService.System_Storage_Get || + method == InteropService.System_Storage_Delete || + method == InteropService.System_Storage_Put || + // ExecutionEngine + method == InteropService.System_ExecutionEngine_GetCallingScriptHash || + method == InteropService.System_ExecutionEngine_GetEntryScriptHash || + method == InteropService.System_ExecutionEngine_GetExecutingScriptHash || + method == InteropService.System_ExecutionEngine_GetScriptContainer || + // Runtime + method == InteropService.System_Runtime_CheckWitness || + method == InteropService.System_Runtime_GetNotifications || + method == InteropService.System_Runtime_GetInvocationCounter || + method == InteropService.System_Runtime_GetTrigger || + method == InteropService.System_Runtime_GetTime || + method == InteropService.System_Runtime_Platform || + method == InteropService.System_Runtime_Log || + method == InteropService.System_Runtime_Notify || + // Json + method == InteropService.Neo_Json_Deserialize || + method == InteropService.Neo_Json_Serialize || + // Contract + method == InteropService.System_Contract_Call + ) { return base.OnSysCall(method); } @@ -158,27 +154,6 @@ protected override bool OnSysCall(uint method) throw new Exception($"Syscall not found: {method.ToString("X2")} (using base call)"); } - private bool Runtime_GetNotifications() - { - byte[] data = CurrentContext.EvaluationStack.Pop().GetByteArray(); - if ((data.Length != 0) && (data.Length != UInt160.Length)) return false; - - IEnumerable notifications = new NotifyEventArgs[] - { - new NotifyEventArgs(null, UInt160.Zero, new Integer(0x01)), - new NotifyEventArgs(null, UInt160.Parse("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), new Integer(0x02)) - }; - - if (data.Length == UInt160.Length) // must filter by scriptHash - { - var hash = new UInt160(data); - notifications = notifications.Where(p => p.ScriptHash == hash); - } - - CurrentContext.EvaluationStack.Push(notifications.Select(u => new VM.Types.Array(new StackItem[] { u.ScriptHash.ToArray(), u.State })).ToArray()); - return true; - } - public bool CheckAsciiChar(string s) { for (int i = 0; i < s.Length; i++) From dee96baeea6c2a16c1853496fbb28df88732d3bf Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 19:10:08 +0200 Subject: [PATCH 17/32] Native contracts --- .../Services/Neo/Native.cs | 6 +- .../Services/Neo/NativeTest.cs | 99 +++++++++++++++++++ .../TestClasses/Contract_Native.cs | 33 +++++++ .../Utils/TestEngine.cs | 5 + 4 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/NativeTest.cs create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Native.cs diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Native.cs b/src/Neo.SmartContract.Framework/Services/Neo/Native.cs index bf95e2060..24ce78e3e 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Native.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Native.cs @@ -3,12 +3,12 @@ namespace Neo.SmartContract.Framework.Services.Neo public class Native { [Syscall("Neo.Native.Tokens.NEO")] - public static extern Contract NEO(string method, object[] arguments); + public static extern object NEO(string method, object[] arguments); [Syscall("Neo.Native.Tokens.GAS")] - public static extern Contract GAS(string method, object[] arguments); + public static extern object GAS(string method, object[] arguments); [Syscall("Neo.Native.Policy")] - public static extern Contract Policy(string method, object[] arguments); + public static extern object Policy(string method, object[] arguments); } } diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/NativeTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/NativeTest.cs new file mode 100644 index 000000000..5b114fdd1 --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/NativeTest.cs @@ -0,0 +1,99 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.Ledger; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; +using System; + +namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +{ + [TestClass] + public class NativeTest + { + private const byte Prefix_FeePerByte = 10; + + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(); + _engine.AddEntryScript("./TestClasses/Contract_Native.cs"); + } + + [TestMethod] + public void Test_NEO() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("NEO_Decimals"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(0, item.GetBigInteger()); + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("NEO_Name"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual("NEO", item.GetString()); + } + + [TestMethod] + public void Test_GAS() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("GAS_Decimals"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(8, item.GetBigInteger()); + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("GAS_Name"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual("GAS", item.GetString()); + } + + [TestMethod] + public void Test_Policy() + { + _engine.Reset(); + _engine.Snapshot.Storages.Add(CreateStorageKey(NativeContract.Policy.Hash, Prefix_FeePerByte), + new StorageItem() { Value = BitConverter.GetBytes(1024L) } + ); + + var result = _engine.ExecuteTestCaseStandard("Policy_GetFeePerByte"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(1024L, item.GetBigInteger()); + } + + StorageKey CreateStorageKey(UInt160 hash, byte prefix, byte[] key = null) + { + StorageKey storageKey = new StorageKey + { + ScriptHash = hash, + Key = new byte[sizeof(byte) + (key?.Length ?? 0)] + }; + storageKey.Key[0] = prefix; + if (key != null) + Buffer.BlockCopy(key, 0, storageKey.Key, 1, key.Length); + return storageKey; + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Native.cs b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Native.cs new file mode 100644 index 000000000..9b4ddfa9d --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Native.cs @@ -0,0 +1,33 @@ +using Neo.SmartContract.Framework.Services.Neo; +using System.Numerics; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_Native : SmartContract.Framework.SmartContract + { + public static int NEO_Decimals() + { + return (int)Native.NEO("decimals", new object[0]); + } + + public static string NEO_Name() + { + return (string)Native.NEO("name", new object[0]); + } + + public static int GAS_Decimals() + { + return (int)Native.GAS("decimals", new object[0]); + } + + public static string GAS_Name() + { + return (string)Native.GAS("name", new object[0]); + } + + public static BigInteger Policy_GetFeePerByte() + { + return (BigInteger)Native.Policy("getFeePerByte", new object[0]); + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 4a0fc9192..c040237f5 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -1,5 +1,6 @@ using Neo.Network.P2P.Payloads; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.VM; using System; using System.Collections.Generic; @@ -144,6 +145,10 @@ protected override bool OnSysCall(uint method) // Json method == InteropService.Neo_Json_Deserialize || method == InteropService.Neo_Json_Serialize || + // Native + method == NativeContract.NEO.ServiceName.ToInteropMethodHash() || + method == NativeContract.GAS.ServiceName.ToInteropMethodHash() || + method == NativeContract.Policy.ServiceName.ToInteropMethodHash() || // Contract method == InteropService.System_Contract_Call ) From 05c73d8fb41cc9458eeeda58f3ae94a8e96a51a3 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 19:15:41 +0200 Subject: [PATCH 18/32] Format --- .../Services/System/ExecutionEngineTest.cs | 4 ++-- tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs | 4 ++-- tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs | 4 ++-- tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs index dad3f2a35..c1eaf3997 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs @@ -1,10 +1,10 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Compiler.MSIL.Utils; using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.VM; using Neo.VM.Types; -using System.IO; +using System.IO; namespace Neo.Compiler.MSIL.SmartContractFramework.Services.System { diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs index e2db4d57b..3418aed1f 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestDataCache.cs @@ -1,5 +1,5 @@ -using Neo.IO; -using Neo.IO.Caching; +using Neo.IO; +using Neo.IO.Caching; using System; using System.Collections.Generic; using System.Linq; diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs index 318e902cb..42c4655fc 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestMetaDataCache.cs @@ -1,5 +1,5 @@ -using Neo.IO; -using Neo.IO.Caching; +using Neo.IO; +using Neo.IO.Caching; namespace Neo.Compiler.MSIL.Utils { diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs index 9f68e4400..ff28a4be2 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs @@ -1,7 +1,7 @@ -using Neo.IO.Caching; +using Neo.IO.Caching; using Neo.IO.Wrappers; using Neo.Ledger; -using Neo.Persistence; +using Neo.Persistence; namespace Neo.Compiler.MSIL.Utils { From c2b4e807741c73fcf8ff8e25d05398f9f953fadd Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 19 Oct 2019 19:39:38 +0200 Subject: [PATCH 19/32] Reorder UT --- .../Utils/BuildScript.cs | 3 +- .../Utils/TestEngine.cs | 2 +- .../Services/Neo/AccountTest.cs | 2 +- .../Services/Neo/JsonTest.cs | 2 +- .../Services/Neo/NativeTest.cs | 2 +- .../Services/Neo/RuntimeTest.cs | 14 ++++++--- .../Services/Neo/StorageTest.cs | 31 +++++++++++++------ .../Services/System/ExecutionEngineTest.cs | 0 .../TestClasses/Contract_Account.cs | 0 .../TestClasses/Contract_ExecutionEngine.cs | 0 .../TestClasses/Contract_Json.cs | 0 .../TestClasses/Contract_Native.cs | 0 .../TestClasses/Contract_Runtime.cs | 0 .../TestClasses/Contract_Storage.cs | 0 14 files changed, 35 insertions(+), 21 deletions(-) rename tests/{Neo.Compiler.MSIL.UnitTests/SmartContractFramework => Neo.SmartContract.Framework.UnitTests}/Services/Neo/AccountTest.cs (96%) rename tests/{Neo.Compiler.MSIL.UnitTests/SmartContractFramework => Neo.SmartContract.Framework.UnitTests}/Services/Neo/JsonTest.cs (97%) rename tests/{Neo.Compiler.MSIL.UnitTests/SmartContractFramework => Neo.SmartContract.Framework.UnitTests}/Services/Neo/NativeTest.cs (98%) rename tests/{Neo.Compiler.MSIL.UnitTests/SmartContractFramework => Neo.SmartContract.Framework.UnitTests}/Services/Neo/RuntimeTest.cs (93%) rename tests/{Neo.Compiler.MSIL.UnitTests/SmartContractFramework => Neo.SmartContract.Framework.UnitTests}/Services/Neo/StorageTest.cs (81%) rename tests/{Neo.Compiler.MSIL.UnitTests/SmartContractFramework => Neo.SmartContract.Framework.UnitTests}/Services/System/ExecutionEngineTest.cs (100%) rename tests/{Neo.Compiler.MSIL.UnitTests => Neo.SmartContract.Framework.UnitTests}/TestClasses/Contract_Account.cs (100%) rename tests/{Neo.Compiler.MSIL.UnitTests => Neo.SmartContract.Framework.UnitTests}/TestClasses/Contract_ExecutionEngine.cs (100%) rename tests/{Neo.Compiler.MSIL.UnitTests => Neo.SmartContract.Framework.UnitTests}/TestClasses/Contract_Json.cs (100%) rename tests/{Neo.Compiler.MSIL.UnitTests => Neo.SmartContract.Framework.UnitTests}/TestClasses/Contract_Native.cs (100%) rename tests/{Neo.Compiler.MSIL.UnitTests => Neo.SmartContract.Framework.UnitTests}/TestClasses/Contract_Runtime.cs (100%) rename tests/{Neo.Compiler.MSIL.UnitTests => Neo.SmartContract.Framework.UnitTests}/TestClasses/Contract_Storage.cs (100%) diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs index 8b7e16eb9..81b080eb1 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; using System.IO; -using System.Text; namespace Neo.Compiler.MSIL.Utils { - class BuildScript + public class BuildScript { public bool IsBuild { diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index c040237f5..d2cb722f7 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -7,7 +7,7 @@ namespace Neo.Compiler.MSIL.Utils { - class TestEngine : ApplicationEngine + public class TestEngine : ApplicationEngine { public const int MaxStorageKeySize = 64; public const int MaxStorageValueSize = ushort.MaxValue; diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/AccountTest.cs similarity index 96% rename from tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs rename to tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/AccountTest.cs index 86737f32f..d285e9b20 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/AccountTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/AccountTest.cs @@ -3,7 +3,7 @@ using Neo.Ledger; using Neo.VM.Types; -namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo { [TestClass] public class AccountTest diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/JsonTest.cs similarity index 97% rename from tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs rename to tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/JsonTest.cs index 49b7063ee..56f72d890 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/JsonTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/JsonTest.cs @@ -4,7 +4,7 @@ using Neo.VM.Types; using System.Text; -namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo { [TestClass] public class JsonTest diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/NativeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs similarity index 98% rename from tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/NativeTest.cs rename to tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs index 5b114fdd1..ed9eb1efb 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/NativeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs @@ -6,7 +6,7 @@ using Neo.VM.Types; using System; -namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo { [TestClass] public class NativeTest diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs similarity index 93% rename from tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs rename to tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs index feb2fff6e..a1284165c 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/RuntimeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs @@ -2,15 +2,15 @@ using Neo.Compiler.MSIL.Utils; using Neo.Network.P2P.Payloads; using Neo.Persistence; -using Neo.SmartContract; using Neo.VM; using Neo.VM.Types; using System; using System.Collections.Generic; using System.IO; using System.Text; +using NEOSmartContract = Neo.SmartContract; -namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo { [TestClass] public class RuntimeTest @@ -58,7 +58,7 @@ public void Test_InvocationCounter() _engine.Snapshot.Contracts.Add(contract, new Ledger.ContractState() { Script = _engine.InvocationStack.Peek(0).Script, - Manifest = new SmartContract.Manifest.ContractManifest() + Manifest = new NEOSmartContract.Manifest.ContractManifest() { } }); @@ -148,7 +148,9 @@ public void Test_CheckWitness() { // True - var result = _engine.ExecuteTestCaseStandard("CheckWitness", new ByteArray("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".HexToBytes())); + var result = _engine.ExecuteTestCaseStandard("CheckWitness", new ByteArray( + new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + )); Assert.AreEqual(1, result.Count); var item = result.Pop(); @@ -158,7 +160,9 @@ public void Test_CheckWitness() // False _engine.Reset(); - result = _engine.ExecuteTestCaseStandard("CheckWitness", new ByteArray("AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".HexToBytes())); + result = _engine.ExecuteTestCaseStandard("CheckWitness", new ByteArray( + new byte[] { 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + )); Assert.AreEqual(1, result.Count); item = result.Pop(); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/StorageTest.cs similarity index 81% rename from tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs rename to tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/StorageTest.cs index a61293e59..9c70de29f 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/Neo/StorageTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/StorageTest.cs @@ -1,9 +1,12 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Compiler.MSIL.Utils; using Neo.VM.Types; +using System; +using System.Collections.Generic; using System.Linq; +using NEOSmartContract = Neo.SmartContract; -namespace Neo.Compiler.MSIL.SmartContractFramework.Services.Neo +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo { [TestClass] public class StorageTest @@ -18,7 +21,7 @@ private void Put(TestEngine testengine, string method, byte[] prefix, byte[] key Assert.AreEqual(1, testengine.Snapshot.Storages.GetChangeSet() .Count(a => - a.Key.Key.SequenceEqual(prefix.Concat(key)) && + a.Key.Key.SequenceEqual(Concat(prefix, key)) && a.Item.Value.SequenceEqual(value) && !a.Item.IsConstant )); @@ -30,7 +33,7 @@ private byte[] Get(TestEngine testengine, string method, byte[] prefix, byte[] k Assert.AreEqual(1, result.Count); var rItem = result.Pop(); Assert.IsInstanceOfType(rItem, typeof(ByteArray)); - Assert.AreEqual(1, testengine.Snapshot.Storages.GetChangeSet().Count(a => a.Key.Key.SequenceEqual(prefix.Concat(key)))); + Assert.AreEqual(1, testengine.Snapshot.Storages.GetChangeSet().Count(a => a.Key.Key.SequenceEqual(Concat(prefix, key)))); return rItem.GetByteArray(); } @@ -40,7 +43,15 @@ private void Delete(TestEngine testengine, string method, byte[] prefix, byte[] Assert.AreEqual(1, result.Count); var rItem = result.Pop(); Assert.IsInstanceOfType(rItem, typeof(ByteArray)); - Assert.AreEqual(0, testengine.Snapshot.Storages.GetChangeSet().Count(a => a.Key.Key.SequenceEqual(prefix.Concat(key)))); + Assert.AreEqual(0, testengine.Snapshot.Storages.GetChangeSet().Count(a => a.Key.Key.SequenceEqual(Concat(prefix, key)))); + } + + private byte[] Concat(byte[] prefix, params byte[] key) + { + var l = new List(prefix); + l.AddRange(key); + + return l.ToArray(); } [TestMethod] @@ -51,9 +62,9 @@ public void Test_Byte() testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() { Script = testengine.EntryContext.Script, - Manifest = new SmartContract.Manifest.ContractManifest() + Manifest = new NEOSmartContract.Manifest.ContractManifest() { - Features = SmartContract.Manifest.ContractFeatures.HasStorage + Features = NEOSmartContract.Manifest.ContractFeatures.HasStorage } }); @@ -85,9 +96,9 @@ public void Test_ByteArray() testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() { Script = testengine.EntryContext.Script, - Manifest = new SmartContract.Manifest.ContractManifest() + Manifest = new NEOSmartContract.Manifest.ContractManifest() { - Features = SmartContract.Manifest.ContractFeatures.HasStorage + Features = NEOSmartContract.Manifest.ContractFeatures.HasStorage } }); @@ -119,9 +130,9 @@ public void Test_String() testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() { Script = testengine.EntryContext.Script, - Manifest = new SmartContract.Manifest.ContractManifest() + Manifest = new NEOSmartContract.Manifest.ContractManifest() { - Features = SmartContract.Manifest.ContractFeatures.HasStorage + Features = NEOSmartContract.Manifest.ContractFeatures.HasStorage } }); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/System/ExecutionEngineTest.cs similarity index 100% rename from tests/Neo.Compiler.MSIL.UnitTests/SmartContractFramework/Services/System/ExecutionEngineTest.cs rename to tests/Neo.SmartContract.Framework.UnitTests/Services/System/ExecutionEngineTest.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Account.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Account.cs similarity index 100% rename from tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Account.cs rename to tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Account.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_ExecutionEngine.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_ExecutionEngine.cs similarity index 100% rename from tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_ExecutionEngine.cs rename to tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_ExecutionEngine.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Json.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Json.cs similarity index 100% rename from tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Json.cs rename to tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Json.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Native.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Native.cs similarity index 100% rename from tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Native.cs rename to tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Native.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Runtime.cs similarity index 100% rename from tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Runtime.cs rename to tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Runtime.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Storage.cs similarity index 100% rename from tests/Neo.Compiler.MSIL.UnitTests/TestClasses/Contract_Storage.cs rename to tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Storage.cs From 0438b71aa2126771ee3db26a48683e7e4028d3d7 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 09:34:18 +0200 Subject: [PATCH 20/32] Native contract tests --- src/Neo.Compiler.MSIL/Helper.cs | 6 ++- src/Neo.Compiler.MSIL/MSIL/CctorSubVM.cs | 13 +------ src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs | 11 ++---- .../AppcallAttribute.cs | 6 +++ .../Services/Neo/Native.cs | 6 +-- .../Utils/TestEngine.cs | 11 ++++++ ...o.SmartContract.Framework.UnitTests.csproj | 7 ++++ .../Services/Neo/NativeTest.cs | 37 +++++++------------ .../Services/Neo/RuntimeTest.cs | 2 +- .../UT_SyscallTest.cs | 4 ++ 10 files changed, 55 insertions(+), 48 deletions(-) diff --git a/src/Neo.Compiler.MSIL/Helper.cs b/src/Neo.Compiler.MSIL/Helper.cs index 5a3b4a0c3..5c777f22b 100644 --- a/src/Neo.Compiler.MSIL/Helper.cs +++ b/src/Neo.Compiler.MSIL/Helper.cs @@ -35,7 +35,8 @@ public static uint ToInteropMethodHash(this byte[] method) return BitConverter.ToUInt32(sha.ComputeHash(method), 0); } } - public static byte[] HexString2Bytes(string str) + + public static byte[] HexString2Bytes(this string str) { if (str.IndexOf("0x") == 0) str = str.Substring(2); @@ -46,6 +47,7 @@ public static byte[] HexString2Bytes(string str) } return outd; } + public static byte[] OpDataToBytes(string opdata) { try // convert hex string to byte[] @@ -54,7 +56,7 @@ public static byte[] OpDataToBytes(string opdata) } catch { - return System.Text.Encoding.UTF8.GetBytes(opdata); + return Encoding.UTF8.GetBytes(opdata); } } } diff --git a/src/Neo.Compiler.MSIL/MSIL/CctorSubVM.cs b/src/Neo.Compiler.MSIL/MSIL/CctorSubVM.cs index 116dad90e..7292d8992 100644 --- a/src/Neo.Compiler.MSIL/MSIL/CctorSubVM.cs +++ b/src/Neo.Compiler.MSIL/MSIL/CctorSubVM.cs @@ -38,16 +38,6 @@ public static object Dup(object src) } } - public static byte[] HexString2Bytes(string str) - { - byte[] outd = new byte[str.Length / 2]; - for (var i = 0; i < str.Length / 2; i++) - { - outd[i] = byte.Parse(str.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); - } - return outd; - } - public static void Parse(ILMethod from, NeoModule to) { calcStack = new Stack(); @@ -193,8 +183,7 @@ public static void Parse(ILMethod from, NeoModule to) } else if (attrname == "HexToBytes")//HexString2Bytes to bytes[] { - if (text.IndexOf("0x") == 0) text = text.Substring(2); - var hex = HexString2Bytes(text); + var hex = text.HexString2Bytes(); calcStack.Push(hex); } else if (attrname == "ToBigInteger") diff --git a/src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs b/src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs index 0a15d8d47..b3c8a0f6f 100644 --- a/src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs +++ b/src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs @@ -234,13 +234,10 @@ public bool IsAppCall(Mono.Cecil.MethodDefinition defs, out byte[] hash) try { - hash = new byte[20]; - if (hashstr.Length < 40) - throw new Exception("hash too short:" + hashstr); - for (var i = 0; i < 20; i++) - { - hash[i] = byte.Parse(hashstr.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); - } + hash = hashstr.HexString2Bytes(); + if (hash.Length != 20) + throw new Exception("Wrong hash:" + hashstr); + //string hexhash 需要反序 hash = hash.Reverse().ToArray(); return true; diff --git a/src/Neo.SmartContract.Framework/AppcallAttribute.cs b/src/Neo.SmartContract.Framework/AppcallAttribute.cs index 11bbd929b..2ee89255d 100644 --- a/src/Neo.SmartContract.Framework/AppcallAttribute.cs +++ b/src/Neo.SmartContract.Framework/AppcallAttribute.cs @@ -18,6 +18,12 @@ public AppcallAttribute(byte[] scriptHash) public AppcallAttribute(string scriptHash) { if (scriptHash == null) throw new ArgumentNullException(); + + if (scriptHash.StartsWith("0x")) + { + scriptHash = scriptHash.Remove(0, 2); + } + if (scriptHash.Length != 40) throw new ArgumentException(); this.ScriptHash = new byte[scriptHash.Length / 2]; for (int i = 0; i < this.ScriptHash.Length; i++) diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Native.cs b/src/Neo.SmartContract.Framework/Services/Neo/Native.cs index 24ce78e3e..c1fd16aaa 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Native.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Native.cs @@ -2,13 +2,13 @@ namespace Neo.SmartContract.Framework.Services.Neo { public class Native { - [Syscall("Neo.Native.Tokens.NEO")] + [Appcall("0x43cf98eddbe047e198a3e5d57006311442a0ca15")] public static extern object NEO(string method, object[] arguments); - [Syscall("Neo.Native.Tokens.GAS")] + [Appcall("0xa1760976db5fcdfab2a9930e8f6ce875b2d18225")] public static extern object GAS(string method, object[] arguments); - [Syscall("Neo.Native.Policy")] + [Appcall("0x9c5699b260bd468e2160dd5d45dfd2686bba8b77")] public static extern object Policy(string method, object[] arguments); } } diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index d2cb722f7..84b3dc1ea 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -18,6 +18,15 @@ public class TestEngine : ApplicationEngine public BuildScript ScriptEntry { get; private set; } + /// + /// Set Persisting block for unit test + /// + /// Block + public void SetPersistingBlock(Block block) + { + Snapshot.GetType().GetProperty("PersistingBlock").SetValue(Snapshot, block); + } + public TestEngine(TriggerType trigger = TriggerType.Application, IVerifiable verificable = null) : base(trigger, verificable, new TestSnapshot(), 0, true) { @@ -120,6 +129,8 @@ public RandomAccessStack ExecuteTestCase(params StackItem[] args) protected override bool OnSysCall(uint method) { if ( + // Native + method == InteropService.Neo_Native_Deploy || // Account method == InteropService.Neo_Account_IsStandard || // Storages diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj index e441120b6..4c03b78a2 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj +++ b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj @@ -14,6 +14,13 @@ + + + + + + PreserveNewest + diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs index ed9eb1efb..56e12e859 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs @@ -1,18 +1,13 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Compiler.MSIL.Utils; -using Neo.Ledger; -using Neo.SmartContract.Native; using Neo.VM; using Neo.VM.Types; -using System; namespace Neo.SmartContract.Framework.UnitTests.Services.Neo { [TestClass] public class NativeTest { - private const byte Prefix_FeePerByte = 10; - private TestEngine _engine; [TestInitialize] @@ -20,6 +15,19 @@ public void Init() { _engine = new TestEngine(); _engine.AddEntryScript("./TestClasses/Contract_Native.cs"); + _engine.SetPersistingBlock(new Network.P2P.Payloads.Block() + { + Index = 0 + }); + + // Deploy native contracts + + using (var script = new ScriptBuilder()) + { + script.EmitSysCall(InteropService.Neo_Native_Deploy); + _engine.LoadScript(script.ToArray()); + _engine.Execute(); + } } [TestMethod] @@ -70,30 +78,13 @@ public void Test_GAS() public void Test_Policy() { _engine.Reset(); - _engine.Snapshot.Storages.Add(CreateStorageKey(NativeContract.Policy.Hash, Prefix_FeePerByte), - new StorageItem() { Value = BitConverter.GetBytes(1024L) } - ); - var result = _engine.ExecuteTestCaseStandard("Policy_GetFeePerByte"); Assert.AreEqual(VMState.HALT, _engine.State); Assert.AreEqual(1, result.Count); var item = result.Pop(); Assert.IsInstanceOfType(item, typeof(Integer)); - Assert.AreEqual(1024L, item.GetBigInteger()); - } - - StorageKey CreateStorageKey(UInt160 hash, byte prefix, byte[] key = null) - { - StorageKey storageKey = new StorageKey - { - ScriptHash = hash, - Key = new byte[sizeof(byte) + (key?.Length ?? 0)] - }; - storageKey.Key[0] = prefix; - if (key != null) - Buffer.BlockCopy(key, 0, storageKey.Key, 1, key.Length); - return storageKey; + Assert.AreEqual(1000L, item.GetBigInteger()); } } } diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs index a1284165c..3d00f70bb 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs @@ -92,7 +92,7 @@ public void Test_InvocationCounter() [TestMethod] public void Test_Time() { - _engine.Snapshot.GetType().GetProperty("PersistingBlock").SetValue(_engine.Snapshot, new Block() + _engine.SetPersistingBlock(new Block() { Timestamp = 123 }); diff --git a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs index e46ff30ce..2fa861994 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs @@ -42,6 +42,10 @@ public void TestAllSyscalls() foreach (var syscall in InteropService.SupportedMethods().Values) { if (syscall == "Neo.Native.Deploy") continue; + if (syscall == "Neo.Native.Tokens.NEO") continue; + if (syscall == "Neo.Native.Tokens.GAS") continue; + if (syscall == "Neo.Native.Policy") continue; + if (list.Remove(syscall)) continue; notFound.Add(syscall); From 133835382ba3ce3fd9feb6f34ee53cfff38ea01e Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 09:37:06 +0200 Subject: [PATCH 21/32] Remove unused class --- .../Services/Neo/ContractPropertyState.cs | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/Neo.SmartContract.Framework/Services/Neo/ContractPropertyState.cs diff --git a/src/Neo.SmartContract.Framework/Services/Neo/ContractPropertyState.cs b/src/Neo.SmartContract.Framework/Services/Neo/ContractPropertyState.cs deleted file mode 100644 index 2359bac94..000000000 --- a/src/Neo.SmartContract.Framework/Services/Neo/ContractPropertyState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Neo.SmartContract.Framework.Services.Neo -{ - public enum ContractPropertyState : byte - { - NoProperty = 0, - - HasStorage = 1 << 0, - Payable = 1 << 2 - } -} From ee75624e5c23a9b5664b1123208ff5e91a349c7b Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 11:48:52 +0200 Subject: [PATCH 22/32] Blockchain UT Except GetContract --- .../Utils/TestEngine.cs | 11 +- ...o.SmartContract.Framework.UnitTests.csproj | 9 +- .../{UT_OpcodeTest.cs => OpcodeTest.cs} | 2 +- .../Services/Neo/BlockchainTest.cs | 340 ++++++++++++++++++ .../Services/Neo/NativeTest.cs | 12 +- .../Services/Neo/RuntimeTest.cs | 15 +- .../{UT_SyscallTest.cs => SyscallTest.cs} | 2 +- .../TestBlockchain.cs | 52 +++ .../TestClasses/Contract_Blockchain.cs | 89 +++++ 9 files changed, 521 insertions(+), 11 deletions(-) rename tests/Neo.SmartContract.Framework.UnitTests/{UT_OpcodeTest.cs => OpcodeTest.cs} (96%) create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs rename tests/Neo.SmartContract.Framework.UnitTests/{UT_SyscallTest.cs => SyscallTest.cs} (98%) create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 84b3dc1ea..624c19185 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -2,6 +2,7 @@ using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; +using Neo.Persistence; using System; using System.Collections.Generic; @@ -27,8 +28,8 @@ public void SetPersistingBlock(Block block) Snapshot.GetType().GetProperty("PersistingBlock").SetValue(Snapshot, block); } - public TestEngine(TriggerType trigger = TriggerType.Application, IVerifiable verificable = null) - : base(trigger, verificable, new TestSnapshot(), 0, true) + public TestEngine(TriggerType trigger = TriggerType.Application, IVerifiable verificable = null, Snapshot snapshot = null) + : base(trigger, verificable, snapshot == null ? new TestSnapshot() : snapshot, 0, true) { Scripts = new Dictionary(); } @@ -156,6 +157,12 @@ protected override bool OnSysCall(uint method) // Json method == InteropService.Neo_Json_Deserialize || method == InteropService.Neo_Json_Serialize || + // Blockchain + method == InteropService.System_Blockchain_GetHeight || + method == InteropService.System_Blockchain_GetBlock || + method == InteropService.System_Blockchain_GetTransaction || + method == InteropService.System_Blockchain_GetTransactionHeight || + method == InteropService.System_Blockchain_GetTransactionFromBlock || // Native method == NativeContract.NEO.ServiceName.ToInteropMethodHash() || method == NativeContract.GAS.ServiceName.ToInteropMethodHash() || diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj index 4c03b78a2..0238b6b49 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj +++ b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj @@ -1,14 +1,15 @@ - netcoreapp2.1 + netcoreapp2.2 false - - - + + + + diff --git a/tests/Neo.SmartContract.Framework.UnitTests/UT_OpcodeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/OpcodeTest.cs similarity index 96% rename from tests/Neo.SmartContract.Framework.UnitTests/UT_OpcodeTest.cs rename to tests/Neo.SmartContract.Framework.UnitTests/OpcodeTest.cs index 70652a4eb..2965e5e6c 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/UT_OpcodeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/OpcodeTest.cs @@ -7,7 +7,7 @@ namespace Neo.SmartContract.Framework.UnitTests { [TestClass] - public class UT_OpcodeTest + public class OpcodeTest { [TestMethod] public void TestAllOpcodes() diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs new file mode 100644 index 000000000..8630b68c8 --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs @@ -0,0 +1,340 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.Ledger; +using Neo.Persistence; +using Neo.VM; +using Neo.VM.Types; +using System; +using System.Linq; +using System.Numerics; +using System.Text; + +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo +{ + [TestClass] + public class BlockchainTest + { + private Network.P2P.Payloads.Block _block; + private TestEngine _engine; + private Store _store; + + [TestInitialize] + public void Init() + { + _store = TestBlockchain.GetStore(); + var snapshot = _store.GetSnapshot(); + + _block = Blockchain.GenesisBlock; + _engine = new TestEngine(snapshot: snapshot); + _engine.AddEntryScript("./TestClasses/Contract_Blockchain.cs"); + } + + [TestMethod] + public void Test_GetHeight() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("GetHeight"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(_block.Index, item.GetBigInteger()); + } + + [TestMethod] + public void Test_GetTransactionHeight() + { + // Not found + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("GetTransactionHeight", new ByteArray(UInt256.Zero.ToArray())); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(BigInteger.MinusOne, item.GetBigInteger()); + + // Found + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("GetTransactionHeight", new ByteArray(_block.Transactions[0].Hash.ToArray())); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(_block.Index, item.GetBigInteger()); + } + + [TestMethod] + public void Test_GetBlockByHash() + { + Test_GetBlock("GetBlockByHash", new ByteArray(_block.Hash.ToArray()), new ByteArray(UInt256.Zero.ToArray())); + } + + [TestMethod] + public void Test_GetTxByHash() + { + Test_GetTransaction("GetTxByHash", new StackItem[] { new ByteArray(_block.Transactions[0].Hash.ToArray()) }, + new StackItem[] { new ByteArray(UInt256.Zero.ToArray()) }, + true); + } + + [TestMethod] + public void Test_GetTxByBlockIndex() + { + Test_GetTransaction("GetTxByBlockIndex", new StackItem[] { + new Integer(_block.Index), new Integer(0) }, + new StackItem[] { new Integer(_block.Index), new Integer(_block.Transactions.Length + 1) }, + false); + } + + [TestMethod] + public void Test_GetTxByBlockHash() + { + Test_GetTransaction("GetTxByBlockHash", new StackItem[] { + new ByteArray(_block.Hash.ToArray()), new Integer(0) }, + new StackItem[] { new ByteArray(_block.Hash.ToArray()), new Integer(_block.Transactions.Length + 1) }, + false); + } + + public void Test_GetTransaction(string method, StackItem[] foundArgs, StackItem[] notFoundArgs, bool expectedNullAsNotFound) + { + // Not found + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard(method, Concat(notFoundArgs, new ByteArray(new byte[0]))); + + if (expectedNullAsNotFound) + { + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + Assert.IsInstanceOfType(result.Pop(), typeof(Null)); + } + else + { + Assert.AreEqual(VMState.FAULT, _engine.State); + Assert.AreEqual(0, result.Count); + } + + var tx = _block.Transactions[0]; + + // Hash + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, Concat(foundArgs, new ByteArray(Encoding.UTF8.GetBytes("Hash")))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + CollectionAssert.AreEqual(tx.Hash.ToArray(), item.GetByteArray()); + + // NetworkFee + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, Concat(foundArgs, new ByteArray(Encoding.UTF8.GetBytes("NetworkFee")))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(tx.NetworkFee, item.GetBigInteger()); + + // Nonce + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, Concat(foundArgs, new ByteArray(Encoding.UTF8.GetBytes("Nonce")))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(tx.Nonce, item.GetBigInteger()); + + // SystemFee + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, Concat(foundArgs, new ByteArray(Encoding.UTF8.GetBytes("SystemFee")))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(tx.SystemFee, item.GetBigInteger()); + + // ValidUntilBlock + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, Concat(foundArgs, new ByteArray(Encoding.UTF8.GetBytes("ValidUntilBlock")))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(tx.ValidUntilBlock, item.GetBigInteger()); + + // Version + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, Concat(foundArgs, new ByteArray(Encoding.UTF8.GetBytes("Version")))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(tx.Version, item.GetBigInteger()); + + // Script + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, Concat(foundArgs, new ByteArray(Encoding.UTF8.GetBytes("Script")))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + CollectionAssert.AreEqual(tx.Script, item.GetByteArray()); + + // Sender + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, Concat(foundArgs, new ByteArray(Encoding.UTF8.GetBytes("Sender")))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + CollectionAssert.AreEqual(tx.Sender.ToArray(), item.GetByteArray()); + } + + private StackItem[] Concat(StackItem[] notFoundArgs, ByteArray byteArray) + { + return notFoundArgs.Concat(new StackItem[] { byteArray }).ToArray(); + } + + [TestMethod] + public void Test_GetBlockByIndex() + { + Test_GetBlock("GetBlockByIndex", new Integer(_block.Index), new Integer(_block.Index + 100)); + } + + public void Test_GetBlock(string method, StackItem foundArg, StackItem notFoundArg) + { + // Not found + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard(method, notFoundArg, new ByteArray(new byte[0])); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Null)); + + // Hash + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("Hash"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + CollectionAssert.AreEqual(_block.Hash.ToArray(), item.GetByteArray()); + + // Index + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("Index"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(_block.Index, item.GetBigInteger()); + + // MerkleRoot + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("MerkleRoot"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + CollectionAssert.AreEqual(_block.MerkleRoot.ToArray(), item.GetByteArray()); + + // NextConsensus + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("NextConsensus"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + CollectionAssert.AreEqual(_block.NextConsensus.ToArray(), item.GetByteArray()); + + // PrevHash + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("PrevHash"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + CollectionAssert.AreEqual(_block.PrevHash.ToArray(), item.GetByteArray()); + + // Timestamp + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("Timestamp"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(_block.Timestamp, item.GetBigInteger()); + + // TransactionsCount + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("TransactionsCount"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(_block.Transactions.Length, item.GetBigInteger()); + + // Version + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("Version"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(_block.Version, item.GetBigInteger()); + + // Uknown property + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard(method, foundArg, new ByteArray(Encoding.UTF8.GetBytes("ASD"))); + Assert.AreEqual(VMState.FAULT, _engine.State); + } + + [TestMethod] + public void GetContract() + { + // TODO: + //[Syscall("System.Blockchain.GetContract")] + //public static extern Contract GetContract(byte[] script_hash); + Assert.IsTrue(false); + } + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs index 56e12e859..cb9082f9c 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs @@ -17,7 +17,17 @@ public void Init() _engine.AddEntryScript("./TestClasses/Contract_Native.cs"); _engine.SetPersistingBlock(new Network.P2P.Payloads.Block() { - Index = 0 + Index = 0, + ConsensusData = new Network.P2P.Payloads.ConsensusData(), + Transactions = new Network.P2P.Payloads.Transaction[0], + Witness = new Network.P2P.Payloads.Witness() + { + InvocationScript = new byte[0], + VerificationScript = new byte[0] + }, + NextConsensus = UInt160.Zero, + MerkleRoot = UInt256.Zero, + PrevHash = UInt256.Zero }); // Deploy native contracts diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs index 3d00f70bb..0f4a5f31a 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs @@ -94,7 +94,18 @@ public void Test_Time() { _engine.SetPersistingBlock(new Block() { - Timestamp = 123 + Index = 123, + Timestamp = 1234, + ConsensusData = new ConsensusData(), + Transactions = new Transaction[0], + Witness = new Witness() + { + InvocationScript = new byte[0], + VerificationScript = new byte[0] + }, + NextConsensus = UInt160.Zero, + MerkleRoot = UInt256.Zero, + PrevHash = UInt256.Zero }); var result = _engine.ExecuteTestCaseStandard("GetTime"); @@ -102,7 +113,7 @@ public void Test_Time() var item = result.Pop(); Assert.IsInstanceOfType(item, typeof(Integer)); - Assert.AreEqual(123, item.GetBigInteger()); + Assert.AreEqual(1234, item.GetBigInteger()); } [TestMethod] diff --git a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/SyscallTest.cs similarity index 98% rename from tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs rename to tests/Neo.SmartContract.Framework.UnitTests/SyscallTest.cs index 2fa861994..88357a0d7 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/UT_SyscallTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/SyscallTest.cs @@ -5,7 +5,7 @@ namespace Neo.SmartContract.Framework.UnitTests { [TestClass] - public class UT_SyscallTest + public class SyscallTest { [TestMethod] public void TestAllSyscalls() diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs new file mode 100644 index 000000000..5f9c4e376 --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs @@ -0,0 +1,52 @@ +using Moq; +using Neo.Compiler.MSIL.Utils; +using Neo.Ledger; +using Neo.Persistence; + +namespace Neo.SmartContract.Framework.UnitTests +{ + public static class TestBlockchain + { + private static NeoSystem TheNeoSystem; + private static Mock _Store; + + public static Store GetStore() + { + if (_Store == null) InitializeMockNeoSystem(); + return _Store.Object; + } + + static TestBlockchain() + { + InitializeMockNeoSystem(); + GetStore(); + } + + public static NeoSystem InitializeMockNeoSystem() + { + if (TheNeoSystem == null) + { + var mockSnapshot = new TestSnapshot(); + + _Store = new Mock(); + + _Store.Setup(p => p.GetBlocks()).Returns(mockSnapshot.Blocks); + _Store.Setup(p => p.GetTransactions()).Returns(mockSnapshot.Transactions); + _Store.Setup(p => p.GetContracts()).Returns(mockSnapshot.Contracts); + _Store.Setup(p => p.GetStorages()).Returns(mockSnapshot.Storages); + _Store.Setup(p => p.GetHeaderHashList()).Returns(mockSnapshot.HeaderHashList); + _Store.Setup(p => p.GetBlockHashIndex()).Returns(mockSnapshot.BlockHashIndex); + _Store.Setup(p => p.GetHeaderHashIndex()).Returns(mockSnapshot.HeaderHashIndex); + _Store.Setup(p => p.GetSnapshot()).Returns(mockSnapshot.Clone()); + + TheNeoSystem = new NeoSystem(_Store.Object); // new Mock(mockStore.Object); + + // Ensure that blockchain is loaded + + var blockchain = Blockchain.Singleton; + } + + return TheNeoSystem; + } + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs new file mode 100644 index 000000000..f241381b3 --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs @@ -0,0 +1,89 @@ +using Neo.SmartContract.Framework.Services.Neo; +using System; +using System.Numerics; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_Blockchain : SmartContract.Framework.SmartContract + { + public static uint GetHeight() + { + return Blockchain.GetHeight(); + } + + public static BigInteger GetTransactionHeight(byte[] hash) + { + return Blockchain.GetTransactionHeight(hash); + } + + public static object GetBlockByHash(byte[] hash, string whatReturn) + { + var block = Blockchain.GetBlock(hash); + return GetBlockInfo(block, whatReturn); + } + + public static object GetBlockByIndex(uint index, string whatReturn) + { + var block = Blockchain.GetBlock(index); + return GetBlockInfo(block, whatReturn); + } + + private static object GetBlockInfo(Block block, string whatReturn) + { + if (block == null) + { + Runtime.Log("NULL Block"); + return null; + } + + if (whatReturn == "Hash") return block.Hash; + if (whatReturn == "Index") return block.Index; + if (whatReturn == "MerkleRoot") return block.MerkleRoot; + if (whatReturn == "NextConsensus") return block.NextConsensus; + if (whatReturn == "PrevHash") return block.PrevHash; + if (whatReturn == "Timestamp") return block.Timestamp; + if (whatReturn == "TransactionsCount") return block.TransactionsCount; + if (whatReturn == "Version") return block.Version; + + throw new Exception("Uknown property"); + } + + public static object GetTxByHash(byte[] hash, string whatReturn) + { + var tx = Blockchain.GetTransaction(hash); + return GetTxInfo(tx, whatReturn); + } + + public static object GetTxByBlockHash(byte[] blockHash, int txIndex, string whatReturn) + { + var tx = Blockchain.GetTransactionFromBlock(blockHash, txIndex); + return GetTxInfo(tx, whatReturn); + } + + public static object GetTxByBlockIndex(uint blockIndex, int txIndex, string whatReturn) + { + var tx = Blockchain.GetTransactionFromBlock(blockIndex, txIndex); + return GetTxInfo(tx, whatReturn); + } + + private static object GetTxInfo(Transaction tx, string whatReturn) + { + if (tx == null) + { + Runtime.Log("NULL Tx"); + return null; + } + + if (whatReturn == "Hash") return tx.Hash; + if (whatReturn == "NetworkFee") return tx.NetworkFee; + if (whatReturn == "Nonce") return tx.Nonce; + if (whatReturn == "Script") return tx.Script; + if (whatReturn == "Sender") return tx.Sender; + if (whatReturn == "SystemFee") return tx.SystemFee; + if (whatReturn == "ValidUntilBlock") return tx.ValidUntilBlock; + if (whatReturn == "Version") return tx.Version; + + throw new Exception("Uknown property"); + } + } +} From b8e67ae151ae620c2b791d3f4c235ec77be31004 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 12:11:59 +0200 Subject: [PATCH 23/32] Blockchain UT 100% --- .../Utils/TestEngine.cs | 1 + .../Services/Neo/BlockchainTest.cs | 66 +++++++++++++++++-- .../TestClasses/Contract_Blockchain.cs | 21 ++++++ 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 624c19185..150c6eeac 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -160,6 +160,7 @@ protected override bool OnSysCall(uint method) // Blockchain method == InteropService.System_Blockchain_GetHeight || method == InteropService.System_Blockchain_GetBlock || + method == InteropService.System_Blockchain_GetContract || method == InteropService.System_Blockchain_GetTransaction || method == InteropService.System_Blockchain_GetTransactionHeight || method == InteropService.System_Blockchain_GetTransactionFromBlock || diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs index 8630b68c8..41a8919e4 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs @@ -210,9 +210,9 @@ public void Test_GetTransaction(string method, StackItem[] foundArgs, StackItem[ CollectionAssert.AreEqual(tx.Sender.ToArray(), item.GetByteArray()); } - private StackItem[] Concat(StackItem[] notFoundArgs, ByteArray byteArray) + private StackItem[] Concat(StackItem[] a, ByteArray b) { - return notFoundArgs.Concat(new StackItem[] { byteArray }).ToArray(); + return a.Concat(new StackItem[] { b }).ToArray(); } [TestMethod] @@ -331,10 +331,64 @@ public void Test_GetBlock(string method, StackItem foundArg, StackItem notFoundA [TestMethod] public void GetContract() { - // TODO: - //[Syscall("System.Blockchain.GetContract")] - //public static extern Contract GetContract(byte[] script_hash); - Assert.IsTrue(false); + var contract = new ContractState() + { + Script = new byte[] { 0x01, 0x02, 0x03 }, + Manifest = new Manifest.ContractManifest() + { + Features = Manifest.ContractFeatures.HasStorage + } + }; + _engine.Snapshot.Contracts.GetOrAdd(contract.ScriptHash, () => contract); + + // Not found + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("GetContract", new ByteArray(UInt160.Zero.ToArray()), new ByteArray(new byte[0])); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Null)); + + // Found + HasStorage + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("GetContract", new ByteArray(contract.ScriptHash.ToArray()), new ByteArray(Encoding.UTF8.GetBytes("HasStorage"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(VM.Types.Boolean)); + Assert.AreEqual(contract.HasStorage, item.GetBoolean()); + + // Found + IsPayable + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("GetContract", new ByteArray(contract.ScriptHash.ToArray()), new ByteArray(Encoding.UTF8.GetBytes("IsPayable"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(VM.Types.Boolean)); + Assert.AreEqual(contract.Payable, item.GetBoolean()); + + // Found + IsPayable + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("GetContract", new ByteArray(contract.ScriptHash.ToArray()), new ByteArray(Encoding.UTF8.GetBytes("Script"))); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(VM.Types.ByteArray)); + CollectionAssert.AreEqual(contract.Script, item.GetByteArray()); + + // Found + Uknown property + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("GetContract", new ByteArray(contract.ScriptHash.ToArray()), new ByteArray(Encoding.UTF8.GetBytes("ASD"))); + Assert.AreEqual(VMState.FAULT, _engine.State); } } } diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs index f241381b3..b2d1d1e69 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs @@ -85,5 +85,26 @@ private static object GetTxInfo(Transaction tx, string whatReturn) throw new Exception("Uknown property"); } + + public static object GetContract(byte[] hash, string whatReturn) + { + var contract = Blockchain.GetContract(hash); + return GetContractInfo(contract, whatReturn); + } + + private static object GetContractInfo(Contract contract, string whatReturn) + { + if (contract == null) + { + Runtime.Log("NULL contract"); + return null; + } + + if (whatReturn == "HasStorage") return contract.HasStorage; + if (whatReturn == "IsPayable") return contract.IsPayable; + if (whatReturn == "Script") return contract.Script; + + throw new Exception("Uknown property"); + } } } From 40936fbab1209bf1c7ee4892b2e3e210bb4f96c7 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 15:27:43 +0200 Subject: [PATCH 24/32] Crypto --- .../Services/Neo/Crypto.cs | 8 +- .../Utils/TestEngine.cs | 4 + ...o.SmartContract.Framework.UnitTests.csproj | 1 - .../Services/Neo/CryptoTest.cs | 147 ++++++++++++++++++ .../TestClasses/Contract_Crypto.cs | 22 +++ 5 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/CryptoTest.cs create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Crypto.cs diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs b/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs index 6ba58b38a..bd88dc14a 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Crypto.cs @@ -1,14 +1,14 @@ namespace Neo.SmartContract.Framework.Services.Neo { - public static class Cryto + public static class Crypto { [Syscall("Neo.Crypto.CheckSig")] - public extern static bool VerifySignature(byte[] signature, byte[] pubkey); + public extern static bool VerifySignature(byte[] pubkey, byte[] signature); [Syscall("System.Crypto.Verify")] - public extern static bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey); + public extern static bool VerifySignature(byte[] message, byte[] pubkey, byte[] signature); [Syscall("Neo.Crypto.CheckMultiSig")] - public extern static bool VerifySignatures(byte[][] signature, byte[][] pubkey); + public extern static bool VerifySignatures(byte[][] pubkey, byte[][] signature); } } diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 150c6eeac..d45f9da7d 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -157,6 +157,10 @@ protected override bool OnSysCall(uint method) // Json method == InteropService.Neo_Json_Deserialize || method == InteropService.Neo_Json_Serialize || + // Crypto + method == InteropService.Neo_Crypto_CheckSig || + method == InteropService.System_Crypto_Verify || + method == InteropService.Neo_Crypto_CheckMultiSig || // Blockchain method == InteropService.System_Blockchain_GetHeight || method == InteropService.System_Blockchain_GetBlock || diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj index 0238b6b49..8768e8f59 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj +++ b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj @@ -14,7 +14,6 @@ - diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/CryptoTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/CryptoTest.cs new file mode 100644 index 000000000..4f06676a1 --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/CryptoTest.cs @@ -0,0 +1,147 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.Cryptography; +using Neo.Network.P2P; +using Neo.Network.P2P.Payloads; +using Neo.VM; +using Neo.VM.Types; +using Neo.Wallets; +using System.Linq; +using System.Security.Cryptography; + +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo +{ + [TestClass] + public class CryptoTest + { + private KeyPair _key = null; + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(TriggerType.Application, new Transaction() + { + Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], + Script = new byte[0], + Sender = UInt160.Zero, + Witnesses = new Witness[0], + NetworkFee = 1, + Nonce = 2, + SystemFee = 3, + ValidUntilBlock = 4, + Version = 5 + }); + _engine.AddEntryScript("./TestClasses/Contract_Crypto.cs"); + _key = GenerateKey(32); + } + + public static KeyPair GenerateKey(int privateKeyLength) + { + byte[] privateKey = new byte[privateKeyLength]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(privateKey); + } + return new KeyPair(privateKey); + } + + [TestMethod] + public void Test_VerifySignature() + { + byte[] signature = Crypto.Default.Sign(_engine.ScriptContainer.GetHashData(), + _key.PrivateKey, _key.PublicKey.EncodePoint(false).Skip(1).ToArray()); + + // False + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("VerifySignature", + new ByteArray(_key.PublicKey.EncodePoint(true)), new ByteArray(new byte[64])); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Boolean)); + Assert.IsFalse(item.GetBoolean()); + + // True + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("VerifySignature", + new ByteArray(_key.PublicKey.EncodePoint(true)), new ByteArray(signature)); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Boolean)); + Assert.IsTrue(item.GetBoolean()); + } + + [TestMethod] + public void Test_VerifySignatures() + { + byte[] signature = Crypto.Default.Sign(_engine.ScriptContainer.GetHashData(), + _key.PrivateKey, _key.PublicKey.EncodePoint(false).Skip(1).ToArray()); + + // False + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("VerifySignatures", + new Array(new StackItem[] { new ByteArray(_key.PublicKey.EncodePoint(true)) }), + new Array(new StackItem[] { new ByteArray(new byte[64]) })); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Boolean)); + Assert.IsFalse(item.GetBoolean()); + + // True + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("VerifySignatures", + new Array(new StackItem[] { new ByteArray(_key.PublicKey.EncodePoint(true)) }), + new Array(new StackItem[] { new ByteArray(signature) })); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Boolean)); + Assert.IsTrue(item.GetBoolean()); + } + + [TestMethod] + public void Test_VerifySignatureWithMessage() + { + byte[] signature = Crypto.Default.Sign(_engine.ScriptContainer.GetHashData(), + _key.PrivateKey, _key.PublicKey.EncodePoint(false).Skip(1).ToArray()); + + // False + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("VerifySignatureWithMessage", + new ByteArray(new byte[0]), + new ByteArray(_key.PublicKey.EncodePoint(true)), new ByteArray(signature)); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Boolean)); + Assert.IsFalse(item.GetBoolean()); + + // True + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("VerifySignatureWithMessage", + new ByteArray(_engine.ScriptContainer.GetHashData()), + new ByteArray(_key.PublicKey.EncodePoint(true)), new ByteArray(signature)); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Boolean)); + Assert.IsTrue(item.GetBoolean()); + } + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Crypto.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Crypto.cs new file mode 100644 index 000000000..a1fda86ed --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Crypto.cs @@ -0,0 +1,22 @@ +using Neo.SmartContract.Framework.Services.Neo; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_Crypto : SmartContract.Framework.SmartContract + { + public static bool VerifySignature(byte[] pubkey, byte[] signature) + { + return Crypto.VerifySignature(pubkey, signature); + } + + public static bool VerifySignatureWithMessage(byte[] message, byte[] pubkey, byte[] signature) + { + return Crypto.VerifySignature(message, pubkey, signature); + } + + public static bool VerifySignatures(byte[][] pubkeys, byte[][] signatures) + { + return Crypto.VerifySignatures(pubkeys, signatures); + } + } +} From 2373468487c72beead364e8ae55aa6f79a0efea9 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 15:39:31 +0200 Subject: [PATCH 25/32] Clean --- tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs | 11 +---------- .../Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs | 10 ++++++++++ .../Services/Neo/NativeTest.cs | 2 +- .../Services/Neo/RuntimeTest.cs | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index d45f9da7d..fccdc21f4 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -1,8 +1,8 @@ using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; -using Neo.Persistence; using System; using System.Collections.Generic; @@ -19,15 +19,6 @@ public class TestEngine : ApplicationEngine public BuildScript ScriptEntry { get; private set; } - /// - /// Set Persisting block for unit test - /// - /// Block - public void SetPersistingBlock(Block block) - { - Snapshot.GetType().GetProperty("PersistingBlock").SetValue(Snapshot, block); - } - public TestEngine(TriggerType trigger = TriggerType.Application, IVerifiable verificable = null, Snapshot snapshot = null) : base(trigger, verificable, snapshot == null ? new TestSnapshot() : snapshot, 0, true) { diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs index ff28a4be2..da339f414 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestSnapshot.cs @@ -1,6 +1,7 @@ using Neo.IO.Caching; using Neo.IO.Wrappers; using Neo.Ledger; +using Neo.Network.P2P.Payloads; using Neo.Persistence; namespace Neo.Compiler.MSIL.Utils @@ -28,5 +29,14 @@ public class TestSnapshot : Snapshot public override MetaDataCache BlockHashIndex => _BlockHashIndex; public override MetaDataCache HeaderHashIndex => _HeaderHashIndex; + + /// + /// Set Persisting block for unit test + /// + /// Block + public void SetPersistingBlock(Block block) + { + this.GetType().GetProperty("PersistingBlock").SetValue(this, block); + } } } diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs index cb9082f9c..921606371 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/NativeTest.cs @@ -15,7 +15,7 @@ public void Init() { _engine = new TestEngine(); _engine.AddEntryScript("./TestClasses/Contract_Native.cs"); - _engine.SetPersistingBlock(new Network.P2P.Payloads.Block() + ((TestSnapshot)_engine.Snapshot).SetPersistingBlock(new Network.P2P.Payloads.Block() { Index = 0, ConsensusData = new Network.P2P.Payloads.ConsensusData(), diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs index 0f4a5f31a..66bd0e8a4 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/RuntimeTest.cs @@ -92,7 +92,7 @@ public void Test_InvocationCounter() [TestMethod] public void Test_Time() { - _engine.SetPersistingBlock(new Block() + ((TestSnapshot)_engine.Snapshot).SetPersistingBlock(new Block() { Index = 123, Timestamp = 1234, From b8689531771a744cff52fab9ba36b821400ae87c Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 15:58:35 +0200 Subject: [PATCH 26/32] ReadOnly Storages --- .../Utils/TestEngine.cs | 2 + .../Services/Neo/StorageTest.cs | 54 +++++++++---------- .../TestClasses/Contract_Storage.cs | 18 +++++-- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index fccdc21f4..46d97fc0f 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -128,6 +128,8 @@ protected override bool OnSysCall(uint method) // Storages method == InteropService.System_Storage_GetContext || method == InteropService.System_Storage_GetReadOnlyContext || + method == InteropService.System_Storage_GetReadOnlyContext || + method == InteropService.System_StorageContext_AsReadOnly || method == InteropService.System_Storage_Get || method == InteropService.System_Storage_Delete || method == InteropService.System_Storage_Put || diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/StorageTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/StorageTest.cs index 9c70de29f..bbd82b177 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/StorageTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/StorageTest.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using NEOSmartContract = Neo.SmartContract; namespace Neo.SmartContract.Framework.UnitTests.Services.Neo { @@ -54,20 +53,26 @@ private byte[] Concat(byte[] prefix, params byte[] key) return l.ToArray(); } - [TestMethod] - public void Test_Byte() + TestEngine testengine; + + [TestInitialize] + public void Init() { - var testengine = new TestEngine(); + testengine = new TestEngine(); testengine.AddEntryScript("./TestClasses/Contract_Storage.cs"); testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() { Script = testengine.EntryContext.Script, - Manifest = new NEOSmartContract.Manifest.ContractManifest() + Manifest = new Manifest.ContractManifest() { - Features = NEOSmartContract.Manifest.ContractFeatures.HasStorage + Features = Manifest.ContractFeatures.HasStorage } }); + } + [TestMethod] + public void Test_Byte() + { var prefix = new byte[] { 0xAA }; var key = new byte[] { 0x01, 0x02, 0x03 }; var value = new byte[] { 0x04, 0x05, 0x06 }; @@ -91,17 +96,6 @@ public void Test_Byte() [TestMethod] public void Test_ByteArray() { - var testengine = new TestEngine(); - testengine.AddEntryScript("./TestClasses/Contract_Storage.cs"); - testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() - { - Script = testengine.EntryContext.Script, - Manifest = new NEOSmartContract.Manifest.ContractManifest() - { - Features = NEOSmartContract.Manifest.ContractFeatures.HasStorage - } - }); - var prefix = new byte[] { 0x00, 0xFF }; var key = new byte[] { 0x01, 0x02, 0x03 }; var value = new byte[] { 0x04, 0x05, 0x06 }; @@ -125,23 +119,13 @@ public void Test_ByteArray() [TestMethod] public void Test_String() { - var testengine = new TestEngine(); - testengine.AddEntryScript("./TestClasses/Contract_Storage.cs"); - testengine.Snapshot.Contracts.Add(testengine.EntryScriptHash, new Ledger.ContractState() - { - Script = testengine.EntryContext.Script, - Manifest = new NEOSmartContract.Manifest.ContractManifest() - { - Features = NEOSmartContract.Manifest.ContractFeatures.HasStorage - } - }); - var prefix = new byte[] { 0x61, 0x61 }; var key = new byte[] { 0x01, 0x02, 0x03 }; var value = new byte[] { 0x04, 0x05, 0x06 }; // Put + testengine.Reset(); Put(testengine, "TestPutString", prefix, key, value); // Get @@ -155,5 +139,19 @@ public void Test_String() testengine.Reset(); Delete(testengine, "TestDeleteString", prefix, key); } + + [TestMethod] + public void Test_ReadOnly() + { + var key = new byte[] { 0x01, 0x02, 0x03 }; + var value = new byte[] { 0x04, 0x05, 0x06 }; + + // Put + + testengine.Reset(); + var result = testengine.ExecuteTestCaseStandard("TestPutReadOnly", new ByteArray(key), new ByteArray(value)); + Assert.AreEqual(VM.VMState.FAULT, testengine.State); + Assert.AreEqual(0, result.Count); + } } } diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Storage.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Storage.cs index 0eb58a3e3..fe9866719 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Storage.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Storage.cs @@ -23,7 +23,8 @@ public static void TestDeleteByte(byte[] key) public static byte[] TestGetByte(byte[] key) { - var storage = Storage.CurrentContext.CreateMap(0xAA); + var context = Storage.CurrentReadOnlyContext; + var storage = context.CreateMap(0xAA); var value = storage.Get(key); return value; } @@ -50,7 +51,8 @@ public static void TestDeleteString(byte[] key) public static byte[] TestGetString(byte[] key) { var prefix = "aa"; - var storage = Storage.CurrentContext.CreateMap(prefix); + var context = Storage.CurrentReadOnlyContext; + var storage = context.CreateMap(prefix); var value = storage.Get(key); return value; } @@ -77,11 +79,21 @@ public static void TestDeleteByteArray(byte[] key) public static byte[] TestGetByteArray(byte[] key) { var prefix = new byte[] { 0x00, 0xFF }; - var storage = Storage.CurrentContext.CreateMap(prefix); + var context = Storage.CurrentContext.AsReadOnly; + var storage = context.CreateMap(prefix); var value = storage.Get(key); return value; } #endregion + + public static bool TestPutReadOnly(byte[] key, byte[] value) + { + var prefix = new byte[] { 0x00, 0xFF }; + var context = Storage.CurrentContext.AsReadOnly; + var storage = context.CreateMap(prefix); + storage.Put(key, value); + return true; + } } } From 7f7e22ab052abb85def62a3132c96dcd9ace556f Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 16:18:32 +0200 Subject: [PATCH 27/32] Enumerator --- .../Utils/TestEngine.cs | 5 + .../Services/Neo/EnumeratorTest.cs | 93 +++++++++++++++++++ .../TestClasses/Contract_Enumerator.cs | 36 +++++++ 3 files changed, 134 insertions(+) create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/EnumeratorTest.cs create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Enumerator.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 46d97fc0f..6a987afc5 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -133,6 +133,11 @@ protected override bool OnSysCall(uint method) method == InteropService.System_Storage_Get || method == InteropService.System_Storage_Delete || method == InteropService.System_Storage_Put || + // Enumerator + method == InteropService.Neo_Enumerator_Concat || + method == InteropService.Neo_Enumerator_Create || + method == InteropService.Neo_Enumerator_Next || + method == InteropService.Neo_Enumerator_Value || // ExecutionEngine method == InteropService.System_ExecutionEngine_GetCallingScriptHash || method == InteropService.System_ExecutionEngine_GetEntryScriptHash || diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/EnumeratorTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/EnumeratorTest.cs new file mode 100644 index 000000000..1d939fb8e --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/EnumeratorTest.cs @@ -0,0 +1,93 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.VM; +using Neo.VM.Types; + +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo +{ + [TestClass] + public class EnumeratorTest + { + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(); + _engine.AddEntryScript("./TestClasses/Contract_Enumerator.cs"); + } + + [TestMethod] + public void TestNext() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("TestNext", new Array(new StackItem[] { 1, 2, 3 })); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(6, item.GetBigInteger()); + } + + [TestMethod] + public void TestConcat() + { + // A and B + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("TestConcat", + new Array(new StackItem[] { 1, 2, 3 }), + new Array(new StackItem[] { 4, 5, 6 }) + ); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(21, item.GetBigInteger()); + + // Only A + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcat", + new Array(new StackItem[] { 1, 2, 3 }), + new Array() + ); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(6, item.GetBigInteger()); + + // Only B + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcat", + new Array(), + new Array(new StackItem[] { 4, 5, 6 }) + ); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(15, item.GetBigInteger()); + + // Empty + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcat", + new Array(), + new Array() + ); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual(0, item.GetByteLength()); + } + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Enumerator.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Enumerator.cs new file mode 100644 index 000000000..80e964add --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Enumerator.cs @@ -0,0 +1,36 @@ +using Neo.SmartContract.Framework.Services.Neo; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_Enumerator : SmartContract.Framework.SmartContract + { + public static int TestNext(byte[] a) + { + int sum = 0; + var enumerator = Enumerator.Create(a); + + while (enumerator.Next()) + { + sum += enumerator.Value; + } + + return sum; + } + + public static int TestConcat(byte[] a, byte[] b) + { + int sum = 0; + var enumeratorA = Enumerator.Create(a); + var enumeratorB = Enumerator.Create(b); + + var enumerator = enumeratorA.Concat(enumeratorB); + + while (enumerator.Next()) + { + sum += enumerator.Value; + } + + return sum; + } + } +} From 345afd2d391ba98b0f4384bdbdeab543fae60532 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 21 Oct 2019 16:45:45 +0200 Subject: [PATCH 28/32] Iterator --- .../Services/Neo/Iterator.cs | 2 +- .../Utils/TestEngine.cs | 6 + .../Services/Neo/IteratorTest.cs | 264 ++++++++++++++++++ .../TestClasses/Contract_Enumerator.cs | 7 +- .../TestClasses/Contract_Iterator.cs | 84 ++++++ 5 files changed, 358 insertions(+), 5 deletions(-) create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/IteratorTest.cs create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Iterator.cs diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Iterator.cs b/src/Neo.SmartContract.Framework/Services/Neo/Iterator.cs index bc03f4f6e..dd82d8f1b 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Iterator.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Iterator.cs @@ -5,7 +5,7 @@ namespace Neo.SmartContract.Framework.Services.Neo public class Iterator { [Syscall("Neo.Iterator.Create")] - public static extern Iterator Create(IDictionary entry); + public static extern Iterator Create(Map entry); [Syscall("Neo.Iterator.Create")] public static extern Iterator Create(IEnumerable entry); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 6a987afc5..22e404adc 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -138,6 +138,12 @@ protected override bool OnSysCall(uint method) method == InteropService.Neo_Enumerator_Create || method == InteropService.Neo_Enumerator_Next || method == InteropService.Neo_Enumerator_Value || + // Iterator + method == InteropService.Neo_Iterator_Concat || + method == InteropService.Neo_Iterator_Create || + method == InteropService.Neo_Iterator_Key || + method == InteropService.Neo_Iterator_Keys || + method == InteropService.Neo_Iterator_Values || // ExecutionEngine method == InteropService.System_ExecutionEngine_GetCallingScriptHash || method == InteropService.System_ExecutionEngine_GetEntryScriptHash || diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/IteratorTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/IteratorTest.cs new file mode 100644 index 000000000..e938ad9ed --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/IteratorTest.cs @@ -0,0 +1,264 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.VM; +using Neo.VM.Types; + +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo +{ + [TestClass] + public class IteratorTest + { + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(); + _engine.AddEntryScript("./TestClasses/Contract_Iterator.cs"); + } + + [TestMethod] + public void TestNextArray() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("TestNextArray", new Array(new StackItem[] { 1, 2, 3 })); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(6, item.GetBigInteger()); + } + + [TestMethod] + public void TestConcatArray() + { + var a = new Array(new StackItem[] { 1, 2, 3 }); + var b = new Array(new StackItem[] { 4, 5, 6 }); + + // A and B + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("TestConcatArray", a, b); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(21, item.GetBigInteger()); + + // Only A + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatArray", a, new Array()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(6, item.GetBigInteger()); + + // Only B + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatArray", new Array(), b); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(15, item.GetBigInteger()); + + // Empty + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatArray", new Array(), new Array()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual(0, item.GetByteLength()); + } + + [TestMethod] + public void TestConcatMap() + { + var a = new Map + { + [new Integer(1)] = new Integer(2), + [new Integer(3)] = new Integer(4) + }; + + var b = new Map + { + [new Integer(5)] = new Integer(6), + [new Integer(7)] = new Integer(8) + }; + + // A and B + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("TestConcatMap", a, b); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(36, item.GetBigInteger()); + + // Only A + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatMap", a, new Array()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(10, item.GetBigInteger()); + + // Only B + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatMap", new Array(), b); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(26, item.GetBigInteger()); + + // Empty + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatMap", new Array(), new Array()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual(0, item.GetByteLength()); + } + + [TestMethod] + public void TestConcatKeys() + { + var a = new Map + { + [new Integer(1)] = new Integer(2), + [new Integer(3)] = new Integer(4) + }; + + var b = new Map + { + [new Integer(5)] = new Integer(6), + [new Integer(7)] = new Integer(8) + }; + + // A and B + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("TestConcatKeys", a, b); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(16, item.GetBigInteger()); + + // Only A + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatKeys", a, new Array()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(4, item.GetBigInteger()); + + // Only B + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatKeys", new Array(), b); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(12, item.GetBigInteger()); + + // Empty + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatKeys", new Array(), new Array()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual(0, item.GetByteLength()); + } + + [TestMethod] + public void TestConcatValues() + { + var a = new Map + { + [new Integer(1)] = new Integer(2), + [new Integer(3)] = new Integer(4) + }; + + var b = new Map + { + [new Integer(5)] = new Integer(6), + [new Integer(7)] = new Integer(8) + }; + + // A and B + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("TestConcatValues", a, b); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(20, item.GetBigInteger()); + + // Only A + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatValues", a, new Array()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(6, item.GetBigInteger()); + + // Only B + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatValues", new Array(), b); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(14, item.GetBigInteger()); + + // Empty + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("TestConcatValues", new Array(), new Array()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual(0, item.GetByteLength()); + } + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Enumerator.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Enumerator.cs index 80e964add..64fcdba6b 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Enumerator.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Enumerator.cs @@ -22,12 +22,11 @@ public static int TestConcat(byte[] a, byte[] b) int sum = 0; var enumeratorA = Enumerator.Create(a); var enumeratorB = Enumerator.Create(b); + var enumeratorC = enumeratorA.Concat(enumeratorB); - var enumerator = enumeratorA.Concat(enumeratorB); - - while (enumerator.Next()) + while (enumeratorC.Next()) { - sum += enumerator.Value; + sum += enumeratorC.Value; } return sum; diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Iterator.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Iterator.cs new file mode 100644 index 000000000..f95170d87 --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Iterator.cs @@ -0,0 +1,84 @@ +using Neo.SmartContract.Framework; +using Neo.SmartContract.Framework.Services.Neo; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_Iterator : SmartContract.Framework.SmartContract + { + public static int TestNextArray(byte[] a) + { + int sum = 0; + var iterator = Iterator.Create(a); + + while (iterator.Next()) + { + sum += iterator.Value; + } + + return sum; + } + + public static int TestConcatArray(byte[] a, byte[] b) + { + int sum = 0; + var iteratorA = Iterator.Create(a); + var iteratorB = Iterator.Create(b); + var iteratorC = iteratorA.Concat(iteratorB); + + while (iteratorC.Next()) + { + sum += iteratorC.Value; + } + + return sum; + } + + public static int TestConcatMap(Map a, Map b) + { + int sum = 0; + var iteratorA = Iterator.Create(a); + var iteratorB = Iterator.Create(b); + var iteratorC = iteratorA.Concat(iteratorB); + + while (iteratorC.Next()) + { + sum += iteratorC.Key; + sum += iteratorC.Value; + } + + return sum; + } + + public static int TestConcatKeys(Map a, Map b) + { + int sum = 0; + var iteratorA = Iterator.Create(a); + var iteratorB = Iterator.Create(b); + var iteratorC = iteratorA.Concat(iteratorB); + var enumerator = iteratorC.Keys; + + while (enumerator.Next()) + { + sum += enumerator.Value; + } + + return sum; + } + + public static int TestConcatValues(Map a, Map b) + { + int sum = 0; + var iteratorA = Iterator.Create(a); + var iteratorB = Iterator.Create(b); + var iteratorC = iteratorA.Concat(iteratorB); + var enumerator = iteratorC.Values; + + while (enumerator.Next()) + { + sum += enumerator.Value; + } + + return sum; + } + } +} From 0aa22828f35fcf8297951caf31b8758c0ea43dfb Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 22 Oct 2019 18:46:24 +0200 Subject: [PATCH 29/32] Contract Unit test --- .../Neo.Compiler.MSIL.csproj | 6 +- .../Services/Neo/Contract.cs | 4 +- .../Neo.Compiler.MSIL.UnitTests.csproj | 2 +- .../UnitTest_NULL.cs | 23 ++- .../Utils/TestEngine.cs | 5 +- ...o.SmartContract.Framework.UnitTests.csproj | 2 +- .../Services/Neo/ContractTest.cs | 182 ++++++++++++++++++ .../TestClasses/Contract_Contract.cs | 27 +++ 8 files changed, 235 insertions(+), 16 deletions(-) create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/ContractTest.cs create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Contract.cs diff --git a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj index 8467f998b..568e93484 100644 --- a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj +++ b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj @@ -1,11 +1,11 @@ - + 2015-2019 The Neo Project Neo.Compiler.MSIL 2.4.1 The Neo Project - netcoreapp2.0;netstandard2.0 + netcoreapp3.0;netstandard2.1 Exe neon Neo.Compiler.MSIL @@ -23,7 +23,7 @@ - + diff --git a/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs b/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs index fc4d1dcb1..65b985300 100644 --- a/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs +++ b/src/Neo.SmartContract.Framework/Services/Neo/Contract.cs @@ -18,13 +18,13 @@ public class Contract public readonly bool IsPayable; [Syscall("System.Contract.Call")] - public static extern Contract Call(byte[] scriptHash, string method, object[] arguments); + public static extern object Call(byte[] scriptHash, string method, object[] arguments); [Syscall("Neo.Contract.Create")] public static extern Contract Create(byte[] script, string manifest); [Syscall("Neo.Contract.Update")] - public static extern Contract Update(byte[] script, string manifest); + public static extern void Update(byte[] script, string manifest); [Syscall("System.Contract.Destroy")] public static extern void Destroy(); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj b/tests/Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj index 285fab5c7..32f771d47 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj +++ b/tests/Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp3.0 false Neo.Compiler.MSIL diff --git a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_NULL.cs b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_NULL.cs index fd4f9c620..06bf04490 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_NULL.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_NULL.cs @@ -8,13 +8,21 @@ namespace Neo.Compiler.MSIL [TestClass] public class UnitTest_NULL { + private TestEngine testengine; + + [TestInitialize] + public void Init() + { + testengine = new TestEngine(); + testengine.AddEntryScript("./TestClasses/Contract_NULL.cs"); + } + [TestMethod] public void IsNull() { // True - var testengine = new TestEngine(); - testengine.AddEntryScript("./TestClasses/Contract_NULL.cs"); + testengine.Reset(); var result = testengine.ExecuteTestCaseStandard("IsNull", StackItem.Null); var item = result.Pop(); @@ -23,7 +31,7 @@ public void IsNull() // False - testengine.InvocationStack.Clear(); + testengine.Reset(); result = testengine.ExecuteTestCaseStandard("IsNull", new Integer(1)); item = result.Pop(); @@ -36,8 +44,7 @@ public void EqualNull() { // True - var testengine = new TestEngine(); - testengine.AddEntryScript("./TestClasses/Contract_NULL.cs"); + testengine.Reset(); var result = testengine.ExecuteTestCaseStandard("EqualNullA", StackItem.Null); var item = result.Pop(); @@ -46,7 +53,7 @@ public void EqualNull() // False - testengine.InvocationStack.Clear(); + testengine.Reset(); result = testengine.ExecuteTestCaseStandard("EqualNullA", new Integer(1)); item = result.Pop(); @@ -55,7 +62,7 @@ public void EqualNull() // True - testengine.InvocationStack.Clear(); + testengine.Reset(); result = testengine.ExecuteTestCaseStandard("EqualNullB", StackItem.Null); item = result.Pop(); @@ -64,7 +71,7 @@ public void EqualNull() // False - testengine.InvocationStack.Clear(); + testengine.Reset(); result = testengine.ExecuteTestCaseStandard("EqualNullB", new Integer(1)); item = result.Pop(); diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs index 22e404adc..00d718bca 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs @@ -177,7 +177,10 @@ protected override bool OnSysCall(uint method) method == NativeContract.GAS.ServiceName.ToInteropMethodHash() || method == NativeContract.Policy.ServiceName.ToInteropMethodHash() || // Contract - method == InteropService.System_Contract_Call + method == InteropService.System_Contract_Call || + method == InteropService.System_Contract_Destroy || + method == InteropService.Neo_Contract_Create || + method == InteropService.Neo_Contract_Update ) { return base.OnSysCall(method); diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj index 8768e8f59..a05b451f0 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj +++ b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.0 false diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/ContractTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/ContractTest.cs new file mode 100644 index 000000000..4e4db05da --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/ContractTest.cs @@ -0,0 +1,182 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.Utils; +using Neo.SmartContract.Manifest; +using Neo.VM; +using Neo.VM.Types; + +namespace Neo.SmartContract.Framework.UnitTests.Services.Neo +{ + [TestClass] + public class ContractTest + { + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(); + _engine.AddEntryScript("./TestClasses/Contract_Contract.cs"); + } + + [TestMethod] + public void Test_CreateCallDestroy() + { + // Create + + byte[] script; + using (var scriptBuilder = new ScriptBuilder()) + { + // Drop arguments + + scriptBuilder.Emit(VM.OpCode.DROP); + scriptBuilder.Emit(VM.OpCode.DROP); + + // Return 123 + + scriptBuilder.EmitPush(123); + script = scriptBuilder.ToArray(); + } + + var manifest = ContractManifest.CreateDefault(script.ToScriptHash()); + + // Check first + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray()); + Assert.AreEqual(VMState.FAULT, _engine.State); + + // Create + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Create", script, manifest.ToJson().ToString()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(InteropInterface)); + Assert.AreEqual(manifest.Hash, + ((InteropInterface)item).GetInterface().ScriptHash); + + // Call + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray(), Null.Null, Null.Null); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual(123, item.GetBigInteger()); + + // Destroy + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Destroy"); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual(0, item.GetByteLength()); + + // Check again for failures + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray()); + Assert.AreEqual(VMState.FAULT, _engine.State); + } + + [TestMethod] + public void Test_Update() + { + // Create + + byte[] scriptUpdate; + using (var scriptBuilder = new ScriptBuilder()) + { + // Drop arguments + + scriptBuilder.Emit(VM.OpCode.DROP); + scriptBuilder.Emit(VM.OpCode.DROP); + + // Return 124 + + scriptBuilder.EmitPush(123); + scriptBuilder.Emit(VM.OpCode.INC); + scriptUpdate = scriptBuilder.ToArray(); + } + + var manifestUpdate = ContractManifest.CreateDefault(scriptUpdate.ToScriptHash()); + + byte[] script; + using (var scriptBuilder = new ScriptBuilder()) + { + // Drop arguments + + scriptBuilder.Emit(VM.OpCode.DROP); + scriptBuilder.Emit(VM.OpCode.DROP); + + // Return 123 + + scriptBuilder.EmitPush(123); + + // Update + + scriptBuilder.EmitSysCall(InteropService.Neo_Contract_Update, scriptUpdate, manifestUpdate.ToJson().ToString()); + script = scriptBuilder.ToArray(); + } + + var manifest = ContractManifest.CreateDefault(script.ToScriptHash()); + + // Check first + + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray()); + Assert.AreEqual(VMState.FAULT, _engine.State); + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Call", manifestUpdate.Hash.ToArray()); + Assert.AreEqual(VMState.FAULT, _engine.State); + + // Create + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Create", script, manifest.ToJson().ToString()); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + var item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(InteropInterface)); + Assert.AreEqual(manifest.Hash, + ((InteropInterface)item).GetInterface().ScriptHash); + + // Call & Update + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray(), Null.Null, Null.Null); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(ByteArray)); + Assert.AreEqual(123, item.GetBigInteger()); + + // Call Again + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Call", manifestUpdate.Hash.ToArray(), Null.Null, Null.Null); + Assert.AreEqual(VMState.HALT, _engine.State); + Assert.AreEqual(1, result.Count); + + item = result.Pop(); + Assert.IsInstanceOfType(item, typeof(Integer)); + Assert.AreEqual(124, item.GetBigInteger()); + + // Check again for failures + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("Call", manifest.Hash.ToArray()); + Assert.AreEqual(VMState.FAULT, _engine.State); + } + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Contract.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Contract.cs new file mode 100644 index 000000000..44e397930 --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Contract.cs @@ -0,0 +1,27 @@ +using Neo.SmartContract.Framework.Services.Neo; + +namespace Neo.Compiler.MSIL.TestClasses +{ + public class Contract_Contract : SmartContract.Framework.SmartContract + { + public static object Call(byte[] scriptHash, string method, object[] arguments) + { + return Contract.Call(scriptHash, method, arguments); + } + + public static object Create(byte[] script, string manifest) + { + return Contract.Create(script, manifest); + } + + public static void Update(byte[] script, string manifest) + { + Contract.Update(script, manifest); + } + + public static void Destroy() + { + Contract.Destroy(); + } + } +} From c46dce4fb202c2036d914b697d652b8848785fff Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 22 Oct 2019 19:05:54 +0200 Subject: [PATCH 30/32] Format --- .../Services/Neo/BlockchainTest.cs | 1 - tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs | 2 +- .../TestClasses/Contract_Blockchain.cs | 2 +- .../TestClasses/Contract_Iterator.cs | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs index 41a8919e4..44dad0a85 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/Neo/BlockchainTest.cs @@ -4,7 +4,6 @@ using Neo.Persistence; using Neo.VM; using Neo.VM.Types; -using System; using System.Linq; using System.Numerics; using System.Text; diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs index 5f9c4e376..bd9843abc 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs @@ -39,7 +39,7 @@ public static NeoSystem InitializeMockNeoSystem() _Store.Setup(p => p.GetHeaderHashIndex()).Returns(mockSnapshot.HeaderHashIndex); _Store.Setup(p => p.GetSnapshot()).Returns(mockSnapshot.Clone()); - TheNeoSystem = new NeoSystem(_Store.Object); // new Mock(mockStore.Object); + TheNeoSystem = new NeoSystem(_Store.Object); // Ensure that blockchain is loaded diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs index b2d1d1e69..f047f43b2 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Blockchain.cs @@ -1,5 +1,5 @@ using Neo.SmartContract.Framework.Services.Neo; -using System; +using System; using System.Numerics; namespace Neo.Compiler.MSIL.TestClasses diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Iterator.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Iterator.cs index f95170d87..3f38f045e 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Iterator.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Iterator.cs @@ -1,4 +1,4 @@ -using Neo.SmartContract.Framework; +using Neo.SmartContract.Framework; using Neo.SmartContract.Framework.Services.Neo; namespace Neo.Compiler.MSIL.TestClasses From 5642b383b36d1d264af6b2fe8cba48ef0eafa254 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 22 Oct 2019 19:11:11 +0200 Subject: [PATCH 31/32] Format --- .../Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs index bd9843abc..eebf125c5 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestBlockchain.cs @@ -1,7 +1,7 @@ -using Moq; -using Neo.Compiler.MSIL.Utils; +using Moq; +using Neo.Compiler.MSIL.Utils; using Neo.Ledger; -using Neo.Persistence; +using Neo.Persistence; namespace Neo.SmartContract.Framework.UnitTests { From 7cb2633c695ab3355f65df686911766b64e568b7 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 22 Oct 2019 19:16:34 +0200 Subject: [PATCH 32/32] Revert dotnet upgrade in this PR --- src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj | 4 ++-- .../Neo.Compiler.MSIL.UnitTests.csproj | 2 +- .../Neo.SmartContract.Framework.UnitTests.csproj | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj index 568e93484..a20ad8b00 100644 --- a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj +++ b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj @@ -1,11 +1,11 @@ - + 2015-2019 The Neo Project Neo.Compiler.MSIL 2.4.1 The Neo Project - netcoreapp3.0;netstandard2.1 + netcoreapp2.0;netstandard2.0 Exe neon Neo.Compiler.MSIL diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj b/tests/Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj index 32f771d47..285fab5c7 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj +++ b/tests/Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.0 + netcoreapp2.1 false Neo.Compiler.MSIL diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj index a05b451f0..fd3a9f671 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj +++ b/tests/Neo.SmartContract.Framework.UnitTests/Neo.SmartContract.Framework.UnitTests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.0 + netcoreapp2.1 false