From 7d3dfdebc759cf56feaf070feccbb8e388dc9066 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Wed, 15 Apr 2020 16:33:25 +0800 Subject: [PATCH] Modify manifest according to the last amendment of NEP-3 (#1481) --- src/neo/SmartContract/ApplicationEngine.cs | 8 +-- src/neo/SmartContract/Helper.cs | 14 ++++-- .../SmartContract/InteropService.Contract.cs | 49 +++++++++++-------- src/neo/SmartContract/Manifest/ContractAbi.cs | 18 ++++--- .../Manifest/ContractManifest.cs | 27 +--------- .../Manifest/ContractMethodDescriptor.cs | 29 ++++------- .../SmartContract/Native/NativeContract.cs | 31 +++++++++--- .../neo.UnitTests/Ledger/UT_ContractState.cs | 4 +- .../Manifest/UT_ContractManifest.cs | 43 ++++++++-------- .../Manifest/UT_ContractPermission.cs | 8 +-- .../Native/Tokens/UT_Nep5Token.cs | 30 ++++-------- .../SmartContract/Native/UT_NativeContract.cs | 21 ++++---- .../SmartContract/UT_InteropService.NEO.cs | 4 +- .../SmartContract/UT_InteropService.cs | 43 ++++++++-------- .../SmartContract/UT_SmartContractHelper.cs | 13 ++++- .../SmartContract/UT_Syscalls.cs | 15 ++++-- tests/neo.UnitTests/TestUtils.cs | 35 +++++++++++-- 17 files changed, 213 insertions(+), 179 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index fda6a3ba84..fc11594a03 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -114,20 +114,20 @@ private static Block CreateDummyBlock(StoreView snapshot) } public static ApplicationEngine Run(byte[] script, StoreView snapshot, - IVerifiable container = null, Block persistingBlock = null, bool testMode = false, long extraGAS = default) + IVerifiable container = null, Block persistingBlock = null, int offset = 0, bool testMode = false, long extraGAS = default) { snapshot.PersistingBlock = persistingBlock ?? snapshot.PersistingBlock ?? CreateDummyBlock(snapshot); ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, container, snapshot, extraGAS, testMode); - engine.LoadScript(script); + engine.LoadScript(script).InstructionPointer = offset; engine.Execute(); return engine; } - public static ApplicationEngine Run(byte[] script, IVerifiable container = null, Block persistingBlock = null, bool testMode = false, long extraGAS = default) + public static ApplicationEngine Run(byte[] script, IVerifiable container = null, Block persistingBlock = null, int offset = 0, bool testMode = false, long extraGAS = default) { using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) { - return Run(script, snapshot, container, persistingBlock, testMode, extraGAS); + return Run(script, snapshot, container, persistingBlock, offset, testMode, extraGAS); } } diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index fc10de2acf..f2a506da6a 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -1,7 +1,9 @@ using Neo.Cryptography; using Neo.Cryptography.ECC; +using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.SmartContract.Manifest; using Neo.VM; using Neo.VM.Types; using System; @@ -143,19 +145,25 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap if (hashes.Length != verifiable.Witnesses.Length) return false; for (int i = 0; i < hashes.Length; i++) { + int offset; byte[] verification = verifiable.Witnesses[i].VerificationScript; if (verification.Length == 0) { - verification = snapshot.Contracts.TryGet(hashes[i])?.Script; - if (verification is null) return false; + ContractState cs = snapshot.Contracts.TryGet(hashes[i]); + if (cs is null) return false; + ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify"); + if (md is null) return false; + verification = cs.Script; + offset = md.Offset; } else { if (hashes[i] != verifiable.Witnesses[i].ScriptHash) return false; + offset = 0; } using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, verifiable, snapshot, gas)) { - engine.LoadScript(verification, CallFlags.ReadOnly); + engine.LoadScript(verification, CallFlags.ReadOnly).InstructionPointer = offset; engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None); if (engine.Execute() == VMState.FAULT) return false; if (!engine.ResultStack.TryPop(out StackItem result) || !result.ToBoolean()) return false; diff --git a/src/neo/SmartContract/InteropService.Contract.cs b/src/neo/SmartContract/InteropService.Contract.cs index 351345d29b..99dc91c419 100644 --- a/src/neo/SmartContract/InteropService.Contract.cs +++ b/src/neo/SmartContract/InteropService.Contract.cs @@ -3,10 +3,12 @@ using Neo.Ledger; using Neo.Persistence; using Neo.SmartContract.Manifest; +using Neo.SmartContract.Native; using Neo.VM; using Neo.VM.Types; using System; using System.Linq; +using Array = Neo.VM.Types.Array; namespace Neo.SmartContract { @@ -111,38 +113,33 @@ private static bool Contract_Destroy(ApplicationEngine engine) private static bool Contract_Call(ApplicationEngine engine) { - StackItem contractHash = engine.CurrentContext.EvaluationStack.Pop(); - StackItem method = engine.CurrentContext.EvaluationStack.Pop(); - StackItem args = engine.CurrentContext.EvaluationStack.Pop(); + if (!engine.TryPop(out ReadOnlySpan contractHash)) return false; + if (!engine.TryPop(out string method)) return false; + if (!engine.TryPop(out Array args)) return false; - return Contract_CallEx(engine, new UInt160(contractHash.GetSpan()), method, args, CallFlags.All); + return Contract_CallEx(engine, new UInt160(contractHash), method, args, CallFlags.All); } private static bool Contract_CallEx(ApplicationEngine engine) { - StackItem contractHash = engine.CurrentContext.EvaluationStack.Pop(); - StackItem method = engine.CurrentContext.EvaluationStack.Pop(); - StackItem args = engine.CurrentContext.EvaluationStack.Pop(); + if (!engine.TryPop(out ReadOnlySpan contractHash)) return false; + if (!engine.TryPop(out string method)) return false; + if (!engine.TryPop(out Array args)) return false; + if (!engine.TryPop(out int flags)) return false; - if (!engine.CurrentContext.EvaluationStack.TryPop(out var flagItem)) - { - return false; - } + if (!Enum.IsDefined(typeof(CallFlags), (CallFlags)flags)) return false; - CallFlags flags = (CallFlags)(int)flagItem.ToBigInteger(); - if (!Enum.IsDefined(typeof(CallFlags), flags)) return false; - - return Contract_CallEx(engine, new UInt160(contractHash.GetSpan()), method, args, flags); + return Contract_CallEx(engine, new UInt160(contractHash), method, args, (CallFlags)flags); } - private static bool Contract_CallEx(ApplicationEngine engine, UInt160 contractHash, StackItem method, StackItem args, CallFlags flags) + private static bool Contract_CallEx(ApplicationEngine engine, UInt160 contractHash, string method, Array args, CallFlags flags) { ContractState contract = engine.Snapshot.Contracts.TryGet(contractHash); if (contract is null) return false; ContractManifest currentManifest = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash)?.Manifest; - if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method.GetString())) + if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method)) return false; if (engine.InvocationCounter.TryGetValue(contract.ScriptHash, out var counter)) @@ -158,13 +155,25 @@ private static bool Contract_CallEx(ApplicationEngine engine, UInt160 contractHa UInt160 callingScriptHash = state.ScriptHash; CallFlags callingFlags = state.CallFlags; - ExecutionContext context_new = engine.LoadScript(contract.Script, 1); + ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method); + if (md is null) return false; + int rvcount = md.ReturnType == ContractParameterType.Void ? 0 : 1; + ExecutionContext context_new = engine.LoadScript(contract.Script, rvcount); state = context_new.GetState(); state.CallingScriptHash = callingScriptHash; state.CallFlags = flags & callingFlags; - context_new.EvaluationStack.Push(args); - context_new.EvaluationStack.Push(method); + if (NativeContract.IsNative(contractHash)) + { + context_new.EvaluationStack.Push(args); + context_new.EvaluationStack.Push(method); + } + else + { + for (int i = args.Count - 1; i >= 0; i--) + context_new.EvaluationStack.Push(args[i]); + context_new.InstructionPointer = md.Offset; + } return true; } diff --git a/src/neo/SmartContract/Manifest/ContractAbi.cs b/src/neo/SmartContract/Manifest/ContractAbi.cs index e7fb4a5272..6a5e559b62 100644 --- a/src/neo/SmartContract/Manifest/ContractAbi.cs +++ b/src/neo/SmartContract/Manifest/ContractAbi.cs @@ -1,4 +1,5 @@ using Neo.IO.Json; +using System.Collections.Generic; using System.Linq; namespace Neo.SmartContract.Manifest @@ -8,16 +9,13 @@ namespace Neo.SmartContract.Manifest /// public class ContractAbi { + private IReadOnlyDictionary methodDictionary; + /// /// Hash is the script hash of the contract. It is encoded as a hexadecimal string in big-endian. /// public UInt160 Hash { get; set; } - /// - /// Entrypoint is a Method object which describe the details of the entrypoint of the contract. - /// - public ContractMethodDescriptor EntryPoint { get; set; } - /// /// Methods is an array of Method objects which describe the details of each method in the contract. /// @@ -33,7 +31,6 @@ public ContractAbi Clone() return new ContractAbi { Hash = Hash, - EntryPoint = EntryPoint.Clone(), Methods = Methods.Select(p => p.Clone()).ToArray(), Events = Events.Select(p => p.Clone()).ToArray() }; @@ -49,17 +46,22 @@ public static ContractAbi FromJson(JObject json) return new ContractAbi { Hash = UInt160.Parse(json["hash"].AsString()), - EntryPoint = ContractMethodDescriptor.FromJson(json["entryPoint"]), Methods = ((JArray)json["methods"]).Select(u => ContractMethodDescriptor.FromJson(u)).ToArray(), Events = ((JArray)json["events"]).Select(u => ContractEventDescriptor.FromJson(u)).ToArray() }; } + public ContractMethodDescriptor GetMethod(string name) + { + methodDictionary ??= Methods.ToDictionary(p => p.Name); + methodDictionary.TryGetValue(name, out var method); + return method; + } + public JObject ToJson() { var json = new JObject(); json["hash"] = Hash.ToString(); - json["entryPoint"] = EntryPoint.ToJson(); json["methods"] = new JArray(Methods.Select(u => u.ToJson()).ToArray()); json["events"] = new JArray(Events.Select(u => u.ToJson()).ToArray()); return json; diff --git a/src/neo/SmartContract/Manifest/ContractManifest.cs b/src/neo/SmartContract/Manifest/ContractManifest.cs index 0ad289c9da..da56c1cb0f 100644 --- a/src/neo/SmartContract/Manifest/ContractManifest.cs +++ b/src/neo/SmartContract/Manifest/ContractManifest.cs @@ -15,7 +15,7 @@ public class ContractManifest : ISerializable /// /// Max length for a valid Contract Manifest /// - public const int MaxLength = 2048; + public const int MaxLength = 4096; /// /// Serialized size @@ -64,31 +64,6 @@ public class ContractManifest : ISerializable /// public JObject Extra { get; set; } - /// - /// Create Default Contract manifest - /// - /// Hash - /// Return default manifest for this contract - public static ContractManifest CreateDefault(UInt160 hash) - { - return new ContractManifest() - { - Permissions = new[] { ContractPermission.DefaultPermission }, - Abi = new ContractAbi() - { - Hash = hash, - EntryPoint = ContractMethodDescriptor.DefaultEntryPoint, - Events = new ContractEventDescriptor[0], - Methods = new ContractMethodDescriptor[0] - }, - Features = ContractFeatures.NoProperty, - Groups = new ContractGroup[0], - SafeMethods = WildcardContainer.Create(), - Trusts = WildcardContainer.Create(), - Extra = null, - }; - } - /// /// Return true if is allowed /// diff --git a/src/neo/SmartContract/Manifest/ContractMethodDescriptor.cs b/src/neo/SmartContract/Manifest/ContractMethodDescriptor.cs index 6596f86dd6..873999096a 100644 --- a/src/neo/SmartContract/Manifest/ContractMethodDescriptor.cs +++ b/src/neo/SmartContract/Manifest/ContractMethodDescriptor.cs @@ -6,27 +6,13 @@ namespace Neo.SmartContract.Manifest { public class ContractMethodDescriptor : ContractEventDescriptor { - /// - /// Default entry point - /// - public static readonly ContractMethodDescriptor DefaultEntryPoint = new ContractMethodDescriptor() + private int _offset; + + public int Offset { - Name = "Main", - Parameters = new ContractParameterDefinition[] - { - new ContractParameterDefinition() - { - Name = "operation", - Type = ContractParameterType.String - }, - new ContractParameterDefinition() - { - Name = "args", - Type = ContractParameterType.Array - } - }, - ReturnType = ContractParameterType.Any - }; + get => _offset; + set => _offset = value >= 0 ? value : throw new FormatException(); + } /// /// Returntype indicates the return type of the method. It can be one of the following values: @@ -40,6 +26,7 @@ public class ContractMethodDescriptor : ContractEventDescriptor { Name = Name, Parameters = Parameters.Select(p => p.Clone()).ToArray(), + Offset = Offset, ReturnType = ReturnType }; } @@ -55,6 +42,7 @@ public class ContractMethodDescriptor : ContractEventDescriptor { Name = json["name"].AsString(), Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson(u)).ToArray(), + Offset = (int)json["offset"].AsNumber(), ReturnType = (ContractParameterType)Enum.Parse(typeof(ContractParameterType), json["returnType"].AsString()), }; } @@ -62,6 +50,7 @@ public class ContractMethodDescriptor : ContractEventDescriptor public override JObject ToJson() { var json = base.ToJson(); + json["offset"] = Offset; json["returnType"] = ReturnType.ToString(); return json; } diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index b28f55be14..7e402ac00a 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -17,10 +17,11 @@ namespace Neo.SmartContract.Native { public abstract class NativeContract { - private static readonly List contracts = new List(); + private static readonly List contractsList = new List(); + private static readonly Dictionary contractsDictionary = new Dictionary(); private readonly Dictionary methods = new Dictionary(); - public static IReadOnlyCollection Contracts { get; } = contracts; + public static IReadOnlyCollection Contracts { get; } = contractsList; public static NeoToken NEO { get; } = new NeoToken(); public static GasToken GAS { get; } = new GasToken(); public static PolicyContract Policy { get; } = new PolicyContract(); @@ -42,7 +43,6 @@ protected NativeContract() this.Script = sb.ToArray(); } this.Hash = Script.ToScriptHash(); - this.Manifest = ContractManifest.CreateDefault(this.Hash); List descriptors = new List(); List safeMethods = new List(); foreach (MethodInfo method in GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) @@ -64,9 +64,23 @@ protected NativeContract() RequiredCallFlags = attribute.SafeMethod ? CallFlags.None : CallFlags.AllowModifyStates }); } - this.Manifest.Abi.Methods = descriptors.ToArray(); - this.Manifest.SafeMethods = WildcardContainer.Create(safeMethods.ToArray()); - contracts.Add(this); + this.Manifest = new ContractManifest + { + Permissions = new[] { ContractPermission.DefaultPermission }, + Abi = new ContractAbi() + { + Hash = Hash, + Events = new ContractEventDescriptor[0], + Methods = descriptors.ToArray() + }, + Features = ContractFeatures.NoProperty, + Groups = new ContractGroup[0], + SafeMethods = WildcardContainer.Create(safeMethods.ToArray()), + Trusts = WildcardContainer.Create(), + Extra = null, + }; + contractsList.Add(this); + contractsDictionary.Add(Hash, this); } protected StorageKey CreateStorageKey(byte prefix, byte[] key = null) @@ -102,6 +116,11 @@ internal bool Invoke(ApplicationEngine engine) return true; } + public static bool IsNative(UInt160 hash) + { + return contractsDictionary.ContainsKey(hash); + } + internal long GetPrice(EvaluationStack stack, StoreView snapshot) { return methods.TryGetValue(stack.Peek().GetString(), out ContractMethodMetadata method) ? method.Price : 0; diff --git a/tests/neo.UnitTests/Ledger/UT_ContractState.cs b/tests/neo.UnitTests/Ledger/UT_ContractState.cs index 8f730a20c0..40e4a6a23d 100644 --- a/tests/neo.UnitTests/Ledger/UT_ContractState.cs +++ b/tests/neo.UnitTests/Ledger/UT_ContractState.cs @@ -19,7 +19,7 @@ public class UT_ContractState [TestInitialize] public void TestSetup() { - manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); + manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); contract = new ContractState { Script = script, @@ -84,7 +84,7 @@ public void TestDeserialize() public void TestGetSize() { ISerializable newContract = contract; - newContract.Size.Should().Be(372); + newContract.Size.Should().Be(239); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs index 6bab91a808..1df0b7ec07 100644 --- a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs +++ b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs @@ -1,6 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography.ECC; -using Neo.IO.Json; using Neo.SmartContract.Manifest; using System.IO; @@ -12,22 +11,22 @@ public class UT_ContractManifest [TestMethod] public void ParseFromJson_Default() { - var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""entryPoint"":{""name"":""Main"",""parameters"":[{""name"":""operation"",""type"":""String""},{""name"":""args"",""type"":""Array""}],""returnType"":""Any""},""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[],""extra"":null}"; + var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - Assert.AreEqual(manifest.ToString(), ContractManifest.CreateDefault(UInt160.Zero).ToString()); + Assert.AreEqual(manifest.ToString(), TestUtils.CreateDefaultManifest(UInt160.Zero).ToString()); Assert.IsTrue(manifest.IsValid(UInt160.Zero)); } [TestMethod] public void ParseFromJson_Features() { - var json = @"{""groups"":[],""features"":{""storage"":true,""payable"":true},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""entryPoint"":{""name"":""Main"",""parameters"":[{""name"":""operation"",""type"":""String""},{""name"":""args"",""type"":""Array""}],""returnType"":""Any""},""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[],""extra"":null}"; + var json = @"{""groups"":[],""features"":{""storage"":true,""payable"":true},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToJson().ToString(), json); - var check = ContractManifest.CreateDefault(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(UInt160.Zero); check.Features = ContractFeatures.HasStorage | ContractFeatures.Payable; Assert.AreEqual(manifest.ToString(), check.ToString()); } @@ -35,11 +34,11 @@ public void ParseFromJson_Features() [TestMethod] public void ParseFromJson_Permissions() { - var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""entryPoint"":{""name"":""Main"",""parameters"":[{""name"":""operation"",""type"":""String""},{""name"":""args"",""type"":""Array""}],""returnType"":""Any""},""methods"":[],""events"":[]},""permissions"":[{""contract"":""0x0000000000000000000000000000000000000000"",""methods"":[""method1"",""method2""]}],""trusts"":[],""safeMethods"":[],""extra"":null}"; + var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""0x0000000000000000000000000000000000000000"",""methods"":[""method1"",""method2""]}],""trusts"":[],""safeMethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - var check = ContractManifest.CreateDefault(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(UInt160.Zero); check.Permissions = new[] { new ContractPermission() @@ -54,11 +53,11 @@ public void ParseFromJson_Permissions() [TestMethod] public void ParseFromJson_SafeMethods() { - var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""entryPoint"":{""name"":""Main"",""parameters"":[{""name"":""operation"",""type"":""String""},{""name"":""args"",""type"":""Array""}],""returnType"":""Any""},""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[""balanceOf""],""extra"":null}"; + var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[""balanceOf""],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - var check = ContractManifest.CreateDefault(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(UInt160.Zero); check.SafeMethods = WildcardContainer.Create("balanceOf"); Assert.AreEqual(manifest.ToString(), check.ToString()); } @@ -66,11 +65,11 @@ public void ParseFromJson_SafeMethods() [TestMethod] public void ParseFromJson_Trust() { - var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""entryPoint"":{""name"":""Main"",""parameters"":[{""name"":""operation"",""type"":""String""},{""name"":""args"",""type"":""Array""}],""returnType"":""Any""},""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[""0x0000000000000000000000000000000000000001""],""safeMethods"":[],""extra"":null}"; + var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[""0x0000000000000000000000000000000000000001""],""safeMethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - var check = ContractManifest.CreateDefault(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(UInt160.Zero); check.Trusts = WildcardContainer.Create(UInt160.Parse("0x0000000000000000000000000000000000000001")); Assert.AreEqual(manifest.ToString(), check.ToString()); } @@ -78,11 +77,11 @@ public void ParseFromJson_Trust() [TestMethod] public void ParseFromJson_Groups() { - var json = @"{""groups"":[{""pubKey"":""03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"",""signature"":""QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==""}],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""entryPoint"":{""name"":""Main"",""parameters"":[{""name"":""operation"",""type"":""String""},{""name"":""args"",""type"":""Array""}],""returnType"":""Any""},""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[],""extra"":null}"; + var json = @"{""groups"":[{""pubKey"":""03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"",""signature"":""QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==""}],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - var check = ContractManifest.CreateDefault(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(UInt160.Zero); check.Groups = new ContractGroup[] { new ContractGroup() { PubKey = ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1), Signature = "41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141".HexToBytes() } }; Assert.AreEqual(manifest.ToString(), check.ToString()); } @@ -90,7 +89,7 @@ public void ParseFromJson_Groups() [TestMethod] public void ParseFromJson_Extra() { - var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""entryPoint"":{""name"":""Main"",""parameters"":[{""name"":""operation"",""type"":""String""},{""name"":""args"",""type"":""Array""}],""returnType"":""Any""},""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[],""extra"":{""key"":""value""}}"; + var json = @"{""groups"":[],""features"":{""storage"":false,""payable"":false},""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safeMethods"":[],""extra"":{""key"":""value""}}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(json, json); Assert.AreEqual("value", manifest.Extra["key"].AsString(), false); @@ -102,11 +101,11 @@ public void TestDeserializeAndSerialize() MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); BinaryReader reader = new BinaryReader(stream); - var expected = ContractManifest.CreateDefault(UInt160.Zero); + var expected = TestUtils.CreateDefaultManifest(UInt160.Zero); expected.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); expected.Serialize(writer); stream.Seek(0, SeekOrigin.Begin); - var actual = ContractManifest.CreateDefault(UInt160.Zero); + var actual = TestUtils.CreateDefaultManifest(UInt160.Zero); actual.Deserialize(reader); Assert.AreEqual(expected.SafeMethods.ToString(), actual.SafeMethods.ToString()); Assert.AreEqual(expected.SafeMethods.Count, 1); @@ -115,15 +114,15 @@ public void TestDeserializeAndSerialize() [TestMethod] public void TestGetHash() { - var temp = ContractManifest.CreateDefault(UInt160.Zero); + var temp = TestUtils.CreateDefaultManifest(UInt160.Zero); Assert.AreEqual(temp.Abi.Hash, temp.Hash); } [TestMethod] public void TestGetSize() { - var temp = ContractManifest.CreateDefault(UInt160.Zero); - Assert.AreEqual(366, temp.Size); + var temp = TestUtils.CreateDefaultManifest(UInt160.Zero); + Assert.AreEqual(233, temp.Size); } [TestMethod] @@ -136,15 +135,15 @@ public void TestGenerator() [TestMethod] public void TestCanCall() { - var temp = ContractManifest.CreateDefault(UInt160.Zero); + var temp = TestUtils.CreateDefaultManifest(UInt160.Zero); temp.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); - Assert.AreEqual(true, temp.CanCall(ContractManifest.CreateDefault(UInt160.Zero), "AAA")); + Assert.AreEqual(true, temp.CanCall(TestUtils.CreateDefaultManifest(UInt160.Zero), "AAA")); } [TestMethod] public void TestClone() { - var expected = ContractManifest.CreateDefault(UInt160.Zero); + var expected = TestUtils.CreateDefaultManifest(UInt160.Zero); expected.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); var actual = expected.Clone(); Assert.AreEqual(actual.ToString(), expected.ToString()); diff --git a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs index 7517458423..8e147f0117 100644 --- a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs +++ b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs @@ -11,13 +11,13 @@ public class UT_ContractPermission [TestMethod] public void TestIsAllowed() { - ContractManifest contractManifest1 = ContractManifest.CreateDefault(UInt160.Zero); + ContractManifest contractManifest1 = TestUtils.CreateDefaultManifest(UInt160.Zero); ContractPermission contractPermission1 = ContractPermission.DefaultPermission; contractPermission1.Contract = ContractPermissionDescriptor.Create(UInt160.Zero); Assert.AreEqual(true, contractPermission1.IsAllowed(contractManifest1, "AAA")); contractPermission1.Contract = ContractPermissionDescriptor.CreateWildcard(); - ContractManifest contractManifest2 = ContractManifest.CreateDefault(UInt160.Zero); + ContractManifest contractManifest2 = TestUtils.CreateDefaultManifest(UInt160.Zero); ContractPermission contractPermission2 = ContractPermission.DefaultPermission; contractPermission2.Contract = ContractPermissionDescriptor.Create(UInt160.Parse("0x0000000000000000000000000000000000000001")); Assert.AreEqual(false, contractPermission2.IsAllowed(contractManifest2, "AAA")); @@ -27,7 +27,7 @@ public void TestIsAllowed() byte[] privateKey3 = new byte[32]; random3.NextBytes(privateKey3); ECPoint publicKey3 = ECCurve.Secp256r1.G * privateKey3; - ContractManifest contractManifest3 = ContractManifest.CreateDefault(UInt160.Zero); + ContractManifest contractManifest3 = TestUtils.CreateDefaultManifest(UInt160.Zero); contractManifest3.Groups = new ContractGroup[] { new ContractGroup() { PubKey = publicKey3 } }; ContractPermission contractPermission3 = ContractPermission.DefaultPermission; contractPermission3.Contract = ContractPermissionDescriptor.Create(publicKey3); @@ -41,7 +41,7 @@ public void TestIsAllowed() byte[] privateKey42 = new byte[32]; random4.NextBytes(privateKey42); ECPoint publicKey42 = ECCurve.Secp256r1.G * privateKey42; - ContractManifest contractManifest4 = ContractManifest.CreateDefault(UInt160.Zero); + ContractManifest contractManifest4 = TestUtils.CreateDefaultManifest(UInt160.Zero); contractManifest4.Groups = new ContractGroup[] { new ContractGroup() { PubKey = publicKey42 } }; ContractPermission contractPermission4 = ContractPermission.DefaultPermission; contractPermission4.Contract = ContractPermissionDescriptor.Create(publicKey41); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_Nep5Token.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_Nep5Token.cs index 1e31914441..f248c5e820 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_Nep5Token.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_Nep5Token.cs @@ -1,3 +1,4 @@ +using Akka.TestKit.Xunit2; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Ledger; @@ -11,30 +12,28 @@ namespace Neo.UnitTests.SmartContract.Native.Tokens { [TestClass] - public class UT_Nep5Token + public class UT_Nep5Token : TestKit { + [TestInitialize] + public void TestSetup() + { + TestBlockchain.InitializeMockNeoSystem(); + } + protected const byte Prefix_TotalSupply = 11; + private static readonly TestNep5Token test = new TestNep5Token(); [TestMethod] public void TestTotalSupply() { var snapshot = Blockchain.Singleton.GetSnapshot(); - TestNep5Token test = new TestNep5Token(); StorageItem item = new StorageItem { Value = new byte[] { 0x01 } }; var key = CreateStorageKey(Prefix_TotalSupply); - var ServiceHash = "test".ToInteropMethodHash(); - byte[] script = null; - using (ScriptBuilder sb = new ScriptBuilder()) - { - sb.EmitSysCall(ServiceHash); - script = sb.ToArray(); - } - var Hash = script.ToScriptHash(); key.Id = test.Id; snapshot.Storages.Add(key, item); @@ -48,7 +47,6 @@ public void TestTotalSupplyDecimal() { var snapshot = Blockchain.Singleton.GetSnapshot(); - TestNep5Token test = new TestNep5Token(); BigInteger totalSupply = 100_000_000; totalSupply *= test.Factor; @@ -58,14 +56,6 @@ public void TestTotalSupplyDecimal() }; var key = CreateStorageKey(Prefix_TotalSupply); - var ServiceHash = "test".ToInteropMethodHash(); - byte[] script = null; - using (ScriptBuilder sb = new ScriptBuilder()) - { - sb.EmitSysCall(ServiceHash); - script = sb.ToArray(); - } - var Hash = script.ToScriptHash(); key.Id = test.Id; snapshot.Storages.Add(key, item); @@ -98,7 +88,7 @@ public class TestNep5Token : Nep5Token public override byte Decimals => 8; - public override string ServiceName => "test"; + public override string ServiceName => "testNep5Token"; public new StackItem TotalSupply(ApplicationEngine engine, VM.Types.Array args) { diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index bbcbcd9d1d..b56527ccd8 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -19,23 +19,25 @@ public void TestSetup() TestBlockchain.InitializeMockNeoSystem(); } + private static readonly TestNativeContract testNativeContract = new TestNativeContract(); + [TestMethod] public void TestInitialize() { ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0); - TestNativeContract pc = new TestNativeContract(); - pc.Initialize(ae).Should().BeTrue(); + + testNativeContract.Initialize(ae).Should().BeTrue(); ae = new ApplicationEngine(TriggerType.System, null, null, 0); - Action action = () => pc.Initialize(ae); + Action action = () => testNativeContract.Initialize(ae); action.Should().Throw(); } [TestMethod] public void TestInvoke() { - ApplicationEngine engine1 = new ApplicationEngine(TriggerType.Application, null, Blockchain.Singleton.GetSnapshot(), 0); - TestNativeContract testNativeContract = new TestNativeContract(); + var snapshot = Blockchain.Singleton.GetSnapshot(); + ApplicationEngine engine1 = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); ScriptBuilder sb1 = new ScriptBuilder(); @@ -43,7 +45,7 @@ public void TestInvoke() engine1.LoadScript(sb1.ToArray()); testNativeContract.Invoke(engine1).Should().BeFalse(); - ApplicationEngine engine2 = new ApplicationEngine(TriggerType.Application, null, Blockchain.Singleton.GetSnapshot(), 0); + ApplicationEngine engine2 = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); ScriptBuilder sb2 = new ScriptBuilder(); sb2.EmitSysCall("test".ToInteropMethodHash()); @@ -65,14 +67,14 @@ public void TestInvoke() [TestMethod] public void TestOnPersistWithArgs() { - ApplicationEngine engine1 = new ApplicationEngine(TriggerType.Application, null, Blockchain.Singleton.GetSnapshot(), 0); - TestNativeContract testNativeContract = new TestNativeContract(); + var snapshot = Blockchain.Singleton.GetSnapshot(); + ApplicationEngine engine1 = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); VMArray args = new VMArray(); VM.Types.Boolean result1 = new VM.Types.Boolean(false); testNativeContract.TestOnPersist(engine1, args).Should().Be(result1); - ApplicationEngine engine2 = new ApplicationEngine(TriggerType.System, null, Blockchain.Singleton.GetSnapshot(), 0); + ApplicationEngine engine2 = new ApplicationEngine(TriggerType.System, null, snapshot, 0); VM.Types.Boolean result2 = new VM.Types.Boolean(true); testNativeContract.TestOnPersist(engine2, args).Should().Be(result2); } @@ -80,7 +82,6 @@ public void TestOnPersistWithArgs() [TestMethod] public void TestTestCall() { - TestNativeContract testNativeContract = new TestNativeContract(); ApplicationEngine engine = testNativeContract.TestCall("System.Blockchain.GetHeight", 0); engine.ResultStack.Should().BeEmpty(); } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index c187a08043..914e6bb012 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -166,7 +166,7 @@ public void TestContract_Create() engine.CurrentContext.EvaluationStack.Push(script); InteropService.Invoke(engine, InteropService.Contract.Create).Should().BeFalse(); - var manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); + var manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); engine.CurrentContext.EvaluationStack.Push(manifest.ToString()); engine.CurrentContext.EvaluationStack.Push(script); InteropService.Invoke(engine, InteropService.Contract.Create).Should().BeFalse(); @@ -205,7 +205,7 @@ public void TestContract_Update() engine.CurrentContext.EvaluationStack.Push(script); InteropService.Invoke(engine, InteropService.Contract.Update).Should().BeFalse(); - var manifest = ContractManifest.CreateDefault(script.ToScriptHash()); + var manifest = TestUtils.CreateDefaultManifest(script.ToScriptHash()); byte[] privkey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; KeyPair key = new KeyPair(privkey); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index f1420fac23..0db5358f7c 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -45,16 +45,17 @@ public void Runtime_GetNotifications_Test() // Add return script.EmitPush(true); + script.Emit(OpCode.RET); // Mock contract scriptHash2 = script.ToArray().ToScriptHash(); snapshot.Contracts.Delete(scriptHash2); - snapshot.Contracts.Add(scriptHash2, new Neo.Ledger.ContractState() + snapshot.Contracts.Add(scriptHash2, new ContractState() { Script = script.ToArray(), - Manifest = ContractManifest.CreateDefault(scriptHash2), + Manifest = TestUtils.CreateDefaultManifest(scriptHash2, "test"), }); } @@ -87,7 +88,7 @@ public void Runtime_GetNotifications_Test() // Call script - script.EmitAppCall(scriptHash2, "test"); + script.EmitAppCall(scriptHash2, "test", 2, 1); // Drop return @@ -113,13 +114,13 @@ public void Runtime_GetNotifications_Test() // Check syscall result - AssertNotification(array[1], scriptHash2, "test"); + AssertNotification(array[1], scriptHash2, 2); AssertNotification(array[0], currentScriptHash, 13); // Check notifications Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash); - Assert.AreEqual("test", engine.Notifications[1].State.GetString()); + Assert.AreEqual(2, engine.Notifications[1].State.GetBigInteger()); Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash); Assert.AreEqual(13, engine.Notifications[0].State.GetBigInteger()); @@ -137,7 +138,7 @@ public void Runtime_GetNotifications_Test() // Call script - script.EmitAppCall(scriptHash2, "test"); + script.EmitAppCall(scriptHash2, "test", 2, 1); // Drop return @@ -163,12 +164,12 @@ public void Runtime_GetNotifications_Test() // Check syscall result - AssertNotification(array[0], scriptHash2, "test"); + AssertNotification(array[0], scriptHash2, 2); // Check notifications Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash); - Assert.AreEqual("test", engine.Notifications[1].State.GetString()); + Assert.AreEqual(2, engine.Notifications[1].State.GetBigInteger()); Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash); Assert.AreEqual(13, engine.Notifications[0].State.GetBigInteger()); @@ -236,15 +237,14 @@ public void TestExecutionEngine_GetCallingScriptHash() var contract = new ContractState() { - Manifest = ContractManifest.CreateDefault(scriptA.ToArray().ToScriptHash()), + Manifest = TestUtils.CreateDefaultManifest(scriptA.ToArray().ToScriptHash(), "test"), Script = scriptA.ToArray() }; - engine = GetEngine(true, true, false); engine.Snapshot.Contracts.Add(contract.ScriptHash, contract); using ScriptBuilder scriptB = new ScriptBuilder(); - scriptB.EmitAppCall(contract.ScriptHash, ""); + scriptB.EmitAppCall(contract.ScriptHash, "test", 0, 1); engine.LoadScript(scriptB.ToArray()); Assert.AreEqual(VMState.HALT, engine.Execute()); @@ -736,10 +736,11 @@ public void TestInvoke() public void TestContract_Call() { var snapshot = Blockchain.Singleton.GetSnapshot(); - var state = TestUtils.GetContract(); + var state = TestUtils.GetContract("method"); state.Manifest.Features = ContractFeatures.HasStorage; byte[] method = Encoding.UTF8.GetBytes("method"); - byte[] args = new byte[0]; + var args = new VM.Types.Array { 0, 1 }; + snapshot.Contracts.Add(state.ScriptHash, state); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); engine.LoadScript(new byte[] { 0x01 }); @@ -748,8 +749,8 @@ public void TestContract_Call() engine.CurrentContext.EvaluationStack.Push(method); engine.CurrentContext.EvaluationStack.Push(state.ScriptHash.ToArray()); InteropService.Invoke(engine, InteropService.Contract.Call).Should().BeTrue(); - engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(method.ToHexString()); - engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(args.ToHexString()); + engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); + engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); state.Manifest.Permissions[0].Methods = WildcardContainer.Create("a"); engine.CurrentContext.EvaluationStack.Push(args); @@ -774,12 +775,12 @@ public void TestContract_CallEx() { var snapshot = Blockchain.Singleton.GetSnapshot(); - var state = TestUtils.GetContract(); + var state = TestUtils.GetContract("method"); state.Manifest.Features = ContractFeatures.HasStorage; snapshot.Contracts.Add(state.ScriptHash, state); byte[] method = Encoding.UTF8.GetBytes("method"); - byte[] args = new byte[0]; + var args = new VM.Types.Array { 0, 1 }; foreach (var flags in new CallFlags[] { CallFlags.None, CallFlags.AllowCall, CallFlags.AllowModifyStates, CallFlags.All }) { @@ -791,8 +792,8 @@ public void TestContract_CallEx() engine.CurrentContext.EvaluationStack.Push(method); engine.CurrentContext.EvaluationStack.Push(state.ScriptHash.ToArray()); InteropService.Invoke(engine, InteropService.Contract.CallEx).Should().BeTrue(); - engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(method.ToHexString()); - engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(args.ToHexString()); + engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); + engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); // Contract doesn't exists @@ -809,8 +810,8 @@ public void TestContract_CallEx() engine.CurrentContext.EvaluationStack.Push(method); engine.CurrentContext.EvaluationStack.Push(state.ScriptHash.ToArray()); InteropService.Invoke(engine, InteropService.Contract.CallEx).Should().BeTrue(); - engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(method.ToHexString()); - engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(args.ToHexString()); + engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); + engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); // Check rights diff --git a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs index 8be6866885..ac62d746ab 100644 --- a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs @@ -14,10 +14,16 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_SmartContractHelper { + [TestInitialize] + public void TestSetup() + { + TestBlockchain.InitializeMockNeoSystem(); + } + [TestMethod] public void TestIsMultiSigContract() { - Neo.Cryptography.ECC.ECPoint[] publicKeys1 = new Neo.Cryptography.ECC.ECPoint[20]; + ECPoint[] publicKeys1 = new ECPoint[20]; for (int i = 0; i < 20; i++) { byte[] privateKey1 = new byte[32]; @@ -151,7 +157,10 @@ public void TestVerifyWitnesses() block3.NextConsensus = UInt160.Zero; snapshot3.Blocks.Add(index3, block3); Header header3 = new Header() { PrevHash = index3, Witness = new Witness { VerificationScript = new byte[0] } }; - snapshot3.Contracts.Add(UInt160.Zero, new ContractState()); + snapshot3.Contracts.Add(UInt160.Zero, new ContractState() + { + Manifest = TestUtils.CreateDefaultManifest(UInt160.Zero, "verify"), + }); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header3, snapshot3, 100)); } } diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index 9979ca8648..c516d1a871 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -3,8 +3,10 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.SmartContract; +using Neo.SmartContract.Manifest; using Neo.VM; using Neo.VM.Types; +using System.Collections.Generic; using System.Linq; namespace Neo.UnitTests.SmartContract @@ -340,6 +342,9 @@ public void System_Runtime_GetInvocationCounter() contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractA.ScriptHash.ToArray())); contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractB.ScriptHash.ToArray())); contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractC.ScriptHash.ToArray())); + contractA.Manifest = TestUtils.CreateDefaultManifest(contractA.ScriptHash, "dummyMain"); + contractB.Manifest = TestUtils.CreateDefaultManifest(contractA.ScriptHash, "dummyMain"); + contractC.Manifest = TestUtils.CreateDefaultManifest(contractA.ScriptHash, "dummyMain"); contracts.Add(contractA.ScriptHash, contractA); contracts.Add(contractB.ScriptHash, contractB); contracts.Add(contractC.ScriptHash, contractC); @@ -349,16 +354,16 @@ public void System_Runtime_GetInvocationCounter() using (var script = new ScriptBuilder()) { - script.EmitSysCall(InteropService.Contract.Call, contractA.ScriptHash.ToArray(), "dummyMain", 0); - script.EmitSysCall(InteropService.Contract.Call, contractB.ScriptHash.ToArray(), "dummyMain", 0); - script.EmitSysCall(InteropService.Contract.Call, contractB.ScriptHash.ToArray(), "dummyMain", 0); - script.EmitSysCall(InteropService.Contract.Call, contractC.ScriptHash.ToArray(), "dummyMain", 0); + script.EmitAppCall(contractA.ScriptHash, "dummyMain", 0, 1); + script.EmitAppCall(contractB.ScriptHash, "dummyMain", 0, 1); + script.EmitAppCall(contractB.ScriptHash, "dummyMain", 0, 1); + script.EmitAppCall(contractC.ScriptHash, "dummyMain", 0, 1); // Execute var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); - Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(VMState.HALT, engine.Execute()); // Check the results diff --git a/tests/neo.UnitTests/TestUtils.cs b/tests/neo.UnitTests/TestUtils.cs index cf3a59c92a..0338ff32c1 100644 --- a/tests/neo.UnitTests/TestUtils.cs +++ b/tests/neo.UnitTests/TestUtils.cs @@ -3,8 +3,8 @@ using Neo.IO.Json; using Neo.Ledger; using Neo.Network.P2P.Payloads; -using Neo.SmartContract.Manifest; using Neo.SmartContract; +using Neo.SmartContract.Manifest; using Neo.VM; using Neo.Wallets.NEP6; using System; @@ -17,6 +17,33 @@ public static class TestUtils { public static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism + public static ContractManifest CreateDefaultManifest(UInt160 hash, string method = null) + { + return new ContractManifest() + { + Permissions = new[] { ContractPermission.DefaultPermission }, + Abi = new ContractAbi() + { + Hash = hash, + Events = new ContractEventDescriptor[0], + Methods = method == null ? new ContractMethodDescriptor[0] : new ContractMethodDescriptor[] + { + new ContractMethodDescriptor() + { + Name = method, + Parameters = new ContractParameterDefinition[0], + ReturnType = ContractParameterType.Integer + } + } + }, + Features = ContractFeatures.NoProperty, + Groups = new ContractGroup[0], + SafeMethods = WildcardContainer.Create(), + Trusts = WildcardContainer.Create(), + Extra = null, + }; + } + public static byte[] GetByteArray(int length, byte firstByte) { byte[] array = new byte[length]; @@ -56,13 +83,13 @@ public static Transaction GetTransaction() }; } - internal static ContractState GetContract() + internal static ContractState GetContract(string method = null) { return new ContractState { Id = 0x43000000, Script = new byte[] { 0x01, 0x01, 0x01, 0x01 }, - Manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")) + Manifest = CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), method) }; } @@ -72,7 +99,7 @@ internal static ContractState GetContract(byte[] script) { Id = 1, Script = script, - Manifest = ContractManifest.CreateDefault(script.ToScriptHash()) + Manifest = CreateDefaultManifest(script.ToScriptHash()) }; }