From 91fb44cd0036c7ff57f5954555d2c1c870a29961 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 28 Dec 2020 18:49:58 +0800 Subject: [PATCH] Dynamic Call (#2167) --- .../Network/P2P/Payloads/OracleResponse.cs | 2 +- .../ApplicationEngine.Contract.cs | 35 +++---- .../ApplicationEngine.OpCodePrices.cs | 1 + src/neo/SmartContract/ApplicationEngine.cs | 97 ++++--------------- src/neo/SmartContract/Helper.cs | 19 +++- .../SmartContract/Native/NativeContract.cs | 10 +- src/neo/VM/Helper.cs | 37 +++---- src/neo/Wallets/AssetDescriptor.cs | 4 +- src/neo/Wallets/Wallet.cs | 13 +-- src/neo/neo.csproj | 2 +- .../Extensions/NativeContractExtensions.cs | 10 +- .../Nep17NativeContractExtensions.cs | 20 +--- .../Network/P2P/Payloads/UT_Transaction.cs | 14 +-- .../SmartContract/Native/UT_NativeContract.cs | 4 +- .../SmartContract/Native/UT_NeoToken.cs | 36 +++---- .../SmartContract/UT_Contract.cs | 4 +- .../neo.UnitTests/SmartContract/UT_Helper.cs | 4 +- .../SmartContract/UT_InteropService.NEO.cs | 6 +- .../SmartContract/UT_InteropService.cs | 47 +++------ .../SmartContract/UT_OpCodePrices.cs | 2 +- .../SmartContract/UT_Syscalls.cs | 8 +- tests/neo.UnitTests/VM/UT_Helper.cs | 45 ++++----- 22 files changed, 157 insertions(+), 263 deletions(-) diff --git a/src/neo/Network/P2P/Payloads/OracleResponse.cs b/src/neo/Network/P2P/Payloads/OracleResponse.cs index c4043a3914..25f7797dbf 100644 --- a/src/neo/Network/P2P/Payloads/OracleResponse.cs +++ b/src/neo/Network/P2P/Payloads/OracleResponse.cs @@ -31,7 +31,7 @@ public class OracleResponse : TransactionAttribute static OracleResponse() { using ScriptBuilder sb = new ScriptBuilder(); - sb.EmitAppCall(NativeContract.Oracle.Hash, "finish"); + sb.EmitDynamicCall(NativeContract.Oracle.Hash, "finish", false); FixedScript = sb.ToArray(); } diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 7d43efe74e..5f274359cf 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -3,14 +3,14 @@ using Neo.SmartContract.Manifest; using Neo.SmartContract.Native; using Neo.VM; +using Neo.VM.Types; using System; -using Array = Neo.VM.Types.Array; namespace Neo.SmartContract { partial class ApplicationEngine { - public static readonly InteropDescriptor System_Contract_CallEx = Register("System.Contract.CallEx", nameof(CallContractEx), 1 << 15, CallFlags.AllowCall); + public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 1 << 15, CallFlags.AllowCall); public static readonly InteropDescriptor System_Contract_CallNative = Register("System.Contract.CallNative", nameof(CallNativeContract), 0, CallFlags.None); public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 1 << 10, CallFlags.ReadStates); public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 1 << 10, CallFlags.None); @@ -22,15 +22,20 @@ partial class ApplicationEngine public static readonly InteropDescriptor System_Contract_NativeOnPersist = Register("System.Contract.NativeOnPersist", nameof(NativeOnPersist), 0, CallFlags.WriteStates); public static readonly InteropDescriptor System_Contract_NativePostPersist = Register("System.Contract.NativePostPersist", nameof(NativePostPersist), 0, CallFlags.WriteStates); - protected internal void CallContractEx(UInt160 contractHash, string method, Array args, CallFlags callFlags) + protected internal void CallContract(UInt160 contractHash, string method, CallFlags callFlags, bool hasReturnValue, ushort pcount) { if (method.StartsWith('_')) throw new ArgumentException($"Invalid Method Name: {method}"); if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - CallContractInternal(contractHash, method, args, callFlags, ReturnTypeConvention.EnsureNotEmpty); + if (pcount > CurrentContext.EvaluationStack.Count) + throw new InvalidOperationException(); + StackItem[] args = new StackItem[pcount]; + for (int i = 0; i < pcount; i++) + args[i] = Pop(); + CallContractInternal(contractHash, method, callFlags, hasReturnValue, args); } - private void CallContractInternal(UInt160 contractHash, string method, Array args, CallFlags flags, ReturnTypeConvention convention) + private void CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); @@ -48,10 +53,10 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contractHash} From Contract {CurrentScriptHash}"); } - CallContractInternal(contract, md, args, flags, convention); + CallContractInternal(contract, md, flags, hasReturnValue, args); } - private void CallContractInternal(ContractState contract, ContractMethodDescriptor method, Array args, CallFlags flags, ReturnTypeConvention convention) + private void CallContractInternal(ContractState contract, ContractMethodDescriptor method, CallFlags flags, bool hasReturnValue, StackItem[] args) { if (invocationCounter.TryGetValue(contract.Hash, out var counter)) { @@ -62,27 +67,19 @@ private void CallContractInternal(ContractState contract, ContractMethodDescript invocationCounter[contract.Hash] = 1; } - GetInvocationState(CurrentContext).Convention = convention; - ExecutionContextState state = CurrentContext.GetState(); UInt160 callingScriptHash = state.ScriptHash; CallFlags callingFlags = state.CallFlags; - if (args.Count != method.Parameters.Length) throw new InvalidOperationException($"Method {method.Name} Expects {method.Parameters.Length} Arguments But Receives {args.Count} Arguments"); - ExecutionContext context_new = LoadContract(contract, method.Name, flags & callingFlags, false); + if (args.Length != method.Parameters.Length) throw new InvalidOperationException($"Method {method.Name} Expects {method.Parameters.Length} Arguments But Receives {args.Length} Arguments"); + ExecutionContext context_new = LoadContract(contract, method.Name, flags & callingFlags, hasReturnValue, (ushort)args.Length); state = context_new.GetState(); state.CallingScriptHash = callingScriptHash; + for (int i = args.Length - 1; i >= 0; i--) + context_new.EvaluationStack.Push(args[i]); if (NativeContract.IsNative(contract.Hash)) - { - context_new.EvaluationStack.Push(args); context_new.EvaluationStack.Push(method.Name); - } - else - { - for (int i = args.Count - 1; i >= 0; i--) - context_new.EvaluationStack.Push(args[i]); - } } protected internal void CallNativeContract(string name) diff --git a/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs index d7a3b5b604..76a8f75842 100644 --- a/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs +++ b/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs @@ -58,6 +58,7 @@ partial class ApplicationEngine [OpCode.CALL] = 1 << 9, [OpCode.CALL_L] = 1 << 9, [OpCode.CALLA] = 1 << 9, + [OpCode.CALLT] = 1 << 15, [OpCode.ABORT] = 0, [OpCode.ASSERT] = 1 << 0, [OpCode.THROW] = 1 << 9, diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 9c02bbab60..96536a6639 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -20,18 +20,6 @@ namespace Neo.SmartContract { public partial class ApplicationEngine : ExecutionEngine { - private enum ReturnTypeConvention : byte - { - None = 0, - EnsureIsEmpty = 1, - EnsureNotEmpty = 2 - } - - private class InvocationState - { - public ReturnTypeConvention Convention; - } - /// /// This constant can be used for testing scripts. /// @@ -46,7 +34,6 @@ private class InvocationState private List notifications; private List disposables; private readonly Dictionary invocationCounter = new Dictionary(); - private readonly Dictionary invocationStates = new Dictionary(); private readonly uint exec_fee_factor; internal readonly uint StoragePrice; @@ -88,7 +75,7 @@ protected override void OnFault(Exception e) internal void CallFromNativeContract(UInt160 callingScriptHash, UInt160 hash, string method, params StackItem[] args) { - CallContractInternal(hash, method, new VMArray(ReferenceCounter, args), CallFlags.All, ReturnTypeConvention.EnsureIsEmpty); + CallContractInternal(hash, method, CallFlags.All, false, args); ExecutionContextState state = CurrentContext.GetState(); state.CallingScriptHash = callingScriptHash; StepOut(); @@ -96,51 +83,19 @@ internal void CallFromNativeContract(UInt160 callingScriptHash, UInt160 hash, st internal T CallFromNativeContract(UInt160 callingScriptHash, UInt160 hash, string method, params StackItem[] args) { - CallFromNativeContract(callingScriptHash, hash, method, args); + CallContractInternal(hash, method, CallFlags.All, true, args); + ExecutionContextState state = CurrentContext.GetState(); + state.CallingScriptHash = callingScriptHash; + StepOut(); return (T)Convert(Pop(), new InteropParameterDescriptor(typeof(T))); } - protected override void ContextUnloaded(ExecutionContext context) - { - base.ContextUnloaded(context); - if (!(UncaughtException is null)) return; - if (invocationStates.Count == 0) return; - if (!invocationStates.Remove(CurrentContext, out InvocationState state)) return; - switch (state.Convention) - { - case ReturnTypeConvention.EnsureIsEmpty: - { - if (context.EvaluationStack.Count != 0) - throw new InvalidOperationException(); - break; - } - case ReturnTypeConvention.EnsureNotEmpty: - { - if (context.EvaluationStack.Count == 0) - Push(StackItem.Null); - else if (context.EvaluationStack.Count > 1) - throw new InvalidOperationException(); - break; - } - } - } - public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas = TestModeGas) { return applicationEngineProvider?.Create(trigger, container, snapshot, gas) ?? new ApplicationEngine(trigger, container, snapshot, gas); } - private InvocationState GetInvocationState(ExecutionContext context) - { - if (!invocationStates.TryGetValue(context, out InvocationState state)) - { - state = new InvocationState(); - invocationStates.Add(context, state); - } - return state; - } - protected override void LoadContext(ExecutionContext context) { // Set default execution context state @@ -152,42 +107,32 @@ protected override void LoadContext(ExecutionContext context) base.LoadContext(context); } - public ExecutionContext LoadContract(ContractState contract, string method, CallFlags callFlags, bool packParameters = false) + public ExecutionContext LoadContract(ContractState contract, string method, CallFlags callFlags, bool hasReturnValue, ushort pcount) { ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method); if (md is null) return null; - ExecutionContext context = LoadScript(contract.Script, callFlags, contract.Hash, md.Offset); + ExecutionContext context = LoadScript(contract.Script, + pcount: pcount, + rvcount: hasReturnValue ? 1 : 0, + initialPosition: md.Offset, + callFlags: callFlags, + scriptHash: contract.Hash); - if (NativeContract.IsNative(contract.Hash)) - { - if (packParameters) - { - using ScriptBuilder sb = new ScriptBuilder(); - sb.Emit(OpCode.DEPTH, OpCode.PACK); - sb.EmitPush(md.Name); - LoadScript(sb.ToArray(), CallFlags.None); - } - } - else + // Call initialization + var init = contract.Manifest.Abi.GetMethod("_initialize"); + if (init != null) { - // Call initialization - - var init = contract.Manifest.Abi.GetMethod("_initialize"); - - if (init != null) - { - LoadContext(context.Clone(init.Offset)); - } + LoadContext(context.Clone(init.Offset)); } return context; } - public ExecutionContext LoadScript(Script script, CallFlags callFlags, UInt160 scriptHash = null, int initialPosition = 0) + public ExecutionContext LoadScript(Script script, ushort pcount = 0, int rvcount = -1, int initialPosition = 0, CallFlags callFlags = CallFlags.All, UInt160 scriptHash = null) { // Create and configure context - ExecutionContext context = CreateContext(script, initialPosition); + ExecutionContext context = CreateContext(script, pcount, rvcount, initialPosition); var state = context.GetState(); state.CallFlags = callFlags; state.ScriptHash = scriptHash ?? ((byte[])script).ToScriptHash(); @@ -294,13 +239,13 @@ protected override void PreExecuteInstruction() AddGas(exec_fee_factor * OpCodePrices[CurrentContext.CurrentInstruction.OpCode]); } - private void StepOut() + internal void StepOut() { int c = InvocationStack.Count; while (State != VMState.HALT && State != VMState.FAULT && InvocationStack.Count >= c) ExecuteNext(); if (State == VMState.FAULT) - throw new InvalidOperationException("Call from native contract failed.", FaultException); + throw new InvalidOperationException("StepOut failed.", FaultException); } private static Block CreateDummyBlock(StoreView snapshot) @@ -350,7 +295,7 @@ public static ApplicationEngine Run(byte[] script, StoreView snapshot = null, IV snapshot.PersistingBlock = persistingBlock ?? snapshot.PersistingBlock ?? CreateDummyBlock(snapshot); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, gas); if (disposable != null) engine.Disposables.Add(disposable); - engine.LoadScript(script, offset); + engine.LoadScript(script, initialPosition: offset); engine.Execute(); return engine; } diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index 3ac1532a68..a84c9ec1c7 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -187,19 +187,30 @@ internal static bool VerifyWitness(this IVerifiable verifiable, StoreView snapsh { ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) return false; - if (engine.LoadContract(cs, "verify", callFlags, true) is null) + if (engine.LoadContract(cs, "verify", callFlags, true, 0) is null) return false; } else { if (NativeContract.IsNative(hash)) return false; if (hash != witness.ScriptHash) return false; - engine.LoadScript(verification, callFlags, hash, 0); + engine.LoadScript(verification, callFlags: callFlags, scriptHash: hash, initialPosition: 0); + } + + engine.LoadScript(witness.InvocationScript, callFlags: CallFlags.None); + + if (NativeContract.IsNative(hash)) + { + try + { + engine.StepOut(); + engine.Push("verify"); + } + catch { } } - engine.LoadScript(witness.InvocationScript, CallFlags.None); if (engine.Execute() == VMState.FAULT) return false; - if (engine.ResultStack.Count != 1 || !engine.ResultStack.Peek().GetBoolean()) return false; + if (!engine.ResultStack.Peek().GetBoolean()) return false; fee = engine.GasConsumed; } return true; diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index 391c01eb95..ad4adeef5c 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -107,7 +107,6 @@ internal void Invoke(ApplicationEngine engine) throw new InvalidOperationException("It is not allowed to use Neo.Native.Call directly to call native contracts. System.Contract.Call should be used."); ExecutionContext context = engine.CurrentContext; string operation = context.EvaluationStack.Pop().GetString(); - Array args = context.EvaluationStack.Pop(); ContractMethodMetadata method = methods[operation]; ExecutionContextState state = context.GetState(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) @@ -117,10 +116,7 @@ internal void Invoke(ApplicationEngine engine) if (method.NeedApplicationEngine) parameters.Add(engine); if (method.NeedSnapshot) parameters.Add(engine.Snapshot); for (int i = 0; i < method.Parameters.Length; i++) - { - StackItem item = i < args.Count ? args[i] : StackItem.Null; - parameters.Add(engine.Convert(item, method.Parameters[i])); - } + parameters.Add(engine.Convert(context.EvaluationStack.Pop(), method.Parameters[i])); object returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (method.Handler.ReturnType != typeof(void)) context.EvaluationStack.Push(engine.Convert(returnValue)); @@ -143,11 +139,11 @@ internal virtual void PostPersist(ApplicationEngine engine) { } - public ApplicationEngine TestCall(string operation, params object[] args) + public ApplicationEngine TestCall(string operation, bool hasReturnValue, params object[] args) { using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitAppCall(Hash, operation, args); + sb.EmitDynamicCall(Hash, operation, hasReturnValue, args); return ApplicationEngine.Run(sb.ToArray()); } } diff --git a/src/neo/VM/Helper.cs b/src/neo/VM/Helper.cs index 4c56216113..257de647e4 100644 --- a/src/neo/VM/Helper.cs +++ b/src/neo/VM/Helper.cs @@ -46,40 +46,40 @@ public static ScriptBuilder Emit(this ScriptBuilder sb, params OpCode[] ops) return sb; } - public static ScriptBuilder EmitAppCall(this ScriptBuilder sb, UInt160 scriptHash, string operation) + public static ScriptBuilder EmitDynamicCall(this ScriptBuilder sb, UInt160 scriptHash, string operation, bool hasReturnValue) { - sb.EmitPush(CallFlags.All); sb.EmitPush(0); - sb.Emit(OpCode.NEWARRAY); + sb.EmitPush(hasReturnValue ? 1 : 0); + sb.EmitPush(CallFlags.All); sb.EmitPush(operation); sb.EmitPush(scriptHash); - sb.EmitSysCall(ApplicationEngine.System_Contract_CallEx); + sb.EmitSysCall(ApplicationEngine.System_Contract_Call); return sb; } - public static ScriptBuilder EmitAppCall(this ScriptBuilder sb, UInt160 scriptHash, string operation, params ContractParameter[] args) + public static ScriptBuilder EmitDynamicCall(this ScriptBuilder sb, UInt160 scriptHash, string operation, bool hasReturnValue, params ContractParameter[] args) { - sb.EmitPush(CallFlags.All); for (int i = args.Length - 1; i >= 0; i--) sb.EmitPush(args[i]); sb.EmitPush(args.Length); - sb.Emit(OpCode.PACK); + sb.EmitPush(hasReturnValue ? 1 : 0); + sb.EmitPush(CallFlags.All); sb.EmitPush(operation); sb.EmitPush(scriptHash); - sb.EmitSysCall(ApplicationEngine.System_Contract_CallEx); + sb.EmitSysCall(ApplicationEngine.System_Contract_Call); return sb; } - public static ScriptBuilder EmitAppCall(this ScriptBuilder sb, UInt160 scriptHash, string operation, params object[] args) + public static ScriptBuilder EmitDynamicCall(this ScriptBuilder sb, UInt160 scriptHash, string operation, bool hasReturnValue, params object[] args) { - sb.EmitPush(CallFlags.All); for (int i = args.Length - 1; i >= 0; i--) sb.EmitPush(args[i]); sb.EmitPush(args.Length); - sb.Emit(OpCode.PACK); + sb.EmitPush(hasReturnValue ? 1 : 0); + sb.EmitPush(CallFlags.All); sb.EmitPush(operation); sb.EmitPush(scriptHash); - sb.EmitSysCall(ApplicationEngine.System_Contract_CallEx); + sb.EmitSysCall(ApplicationEngine.System_Contract_Call); return sb; } @@ -204,16 +204,11 @@ public static ScriptBuilder EmitSysCall(this ScriptBuilder sb, uint method, para /// contract operation /// operation arguments /// - public static byte[] MakeScript(this UInt160 scriptHash, string operation, params object[] args) + public static byte[] MakeScript(this UInt160 scriptHash, string operation, bool hasReturnValue, params object[] args) { - using (ScriptBuilder sb = new ScriptBuilder()) - { - if (args.Length > 0) - sb.EmitAppCall(scriptHash, operation, args); - else - sb.EmitAppCall(scriptHash, operation); - return sb.ToArray(); - } + using ScriptBuilder sb = new ScriptBuilder(); + sb.EmitDynamicCall(scriptHash, operation, hasReturnValue, args); + return sb.ToArray(); } public static JObject ToJson(this StackItem item) diff --git a/src/neo/Wallets/AssetDescriptor.cs b/src/neo/Wallets/AssetDescriptor.cs index cd9fcb8859..e13fb02589 100644 --- a/src/neo/Wallets/AssetDescriptor.cs +++ b/src/neo/Wallets/AssetDescriptor.cs @@ -23,8 +23,8 @@ public AssetDescriptor(UInt160 asset_id) byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitAppCall(asset_id, "decimals"); - sb.EmitAppCall(asset_id, "symbol"); + sb.EmitDynamicCall(asset_id, "decimals", true); + sb.EmitDynamicCall(asset_id, "symbol", true); script = sb.ToArray(); } using ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, gas: 0_10000000); diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index a5f6c9b13f..44cb5990f3 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -138,10 +138,10 @@ public BigDecimal GetBalance(UInt160 asset_id, params UInt160[] accounts) sb.EmitPush(0); foreach (UInt160 account in accounts) { - sb.EmitAppCall(asset_id, "balanceOf", account); + sb.EmitDynamicCall(asset_id, "balanceOf", true, account); sb.Emit(OpCode.ADD); } - sb.EmitAppCall(asset_id, "decimals"); + sb.EmitDynamicCall(asset_id, "decimals", true); script = sb.ToArray(); } using ApplicationEngine engine = ApplicationEngine.Run(script, gas: 20000000L * accounts.Length); @@ -265,7 +265,7 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null foreach (UInt160 account in accounts) using (ScriptBuilder sb2 = new ScriptBuilder()) { - sb2.EmitAppCall(assetId, "balanceOf", account); + sb2.EmitDynamicCall(assetId, "balanceOf", true, account); using (ApplicationEngine engine = ApplicationEngine.Run(sb2.ToArray(), snapshot)) { if (engine.State.HasFlag(VMState.FAULT)) @@ -296,7 +296,7 @@ public Transaction MakeTransaction(TransferOutput[] outputs, UInt160 from = null Scopes = WitnessScope.CalledByEntry }); } - sb.EmitAppCall(output.AssetId, "transfer", account, output.ScriptHash, value, output.Data); + sb.EmitDynamicCall(output.AssetId, "transfer", true, account, output.ScriptHash, value, output.Data); sb.Emit(OpCode.ASSERT); } } @@ -397,10 +397,11 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx) // Check verify cost using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.Clone()); - if (engine.LoadContract(contract, "verify", CallFlags.None, true) is null) + if (engine.LoadContract(contract, "verify", CallFlags.None, true, 0) is null) throw new ArgumentException($"The smart contract {contract.Hash} haven't got verify method"); + if (NativeContract.IsNative(hash)) engine.Push("verify"); if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.Hash} verification fault."); - if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.Hash} returns false."); + if (!engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.Hash} returns false."); networkFee += engine.GasConsumed; } diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index 40f9bd4524..f0ff860c79 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -29,7 +29,7 @@ - + diff --git a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs index 38c5ef651b..99c6497fb7 100644 --- a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -13,7 +13,7 @@ public static class NativeContractExtensions public static ContractState DeployContract(this StoreView snapshot, UInt160 sender, byte[] nefFile, byte[] manifest, long gas = 200_00000000) { var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.ContractManagement.Hash, "deploy", nefFile, manifest); + script.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", true, nefFile, manifest); var engine = ApplicationEngine.Create(TriggerType.Application, sender != null ? new Transaction() { Signers = new Signer[] { new Signer() { Account = sender } } } : null, snapshot, gas); @@ -34,7 +34,7 @@ public static ContractState DeployContract(this StoreView snapshot, UInt160 send public static void UpdateContract(this StoreView snapshot, UInt160 callingScriptHash, byte[] nefFile, byte[] manifest) { var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.ContractManagement.Hash, "update", nefFile, manifest); + script.EmitDynamicCall(NativeContract.ContractManagement.Hash, "update", false, nefFile, manifest); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(script.ToArray()); @@ -57,7 +57,7 @@ public static void UpdateContract(this StoreView snapshot, UInt160 callingScript public static void DestroyContract(this StoreView snapshot, UInt160 callingScriptHash) { var script = new ScriptBuilder(); - script.EmitAppCall(NativeContract.ContractManagement.Hash, "destroy"); + script.EmitDynamicCall(NativeContract.ContractManagement.Hash, "destroy", false); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(script.ToArray()); @@ -100,13 +100,13 @@ public static StackItem Call(this NativeContract contract, StoreView snapshot, I var contractState = NativeContract.ContractManagement.GetContract(snapshot, contract.Hash); if (contractState == null) throw new InvalidOperationException(); - engine.LoadContract(contractState, method, CallFlags.All, true); - var script = new ScriptBuilder(); for (var i = args.Length - 1; i >= 0; i--) script.EmitPush(args[i]); + script.EmitPush(method); + engine.LoadContract(contractState, method, CallFlags.All, contract.Manifest.Abi.GetMethod(method).ReturnType != ContractParameterType.Void, (ushort)args.Length); engine.LoadScript(script.ToArray()); if (engine.Execute() != VMState.HALT) diff --git a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs index 6b87c22863..942993b5e6 100644 --- a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs @@ -40,15 +40,13 @@ public static bool Transfer(this NativeContract contract, StoreView snapshot, by var engine = ApplicationEngine.Create(TriggerType.Application, new ManualWitness(signFrom ? new UInt160(from) : null), snapshot); - engine.LoadScript(contract.Script, CallFlags.All, contract.Hash); + engine.LoadScript(contract.Script, pcount: 4, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); script.Emit(OpCode.PUSHNULL); script.EmitPush(amount); script.EmitPush(to); script.EmitPush(from); - script.EmitPush(4); - script.Emit(OpCode.PACK); script.EmitPush("transfer"); engine.LoadScript(script.ToArray()); @@ -67,11 +65,9 @@ public static BigInteger TotalSupply(this NativeContract contract, StoreView sna { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(contract.Script, CallFlags.All, contract.Hash); + engine.LoadScript(contract.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); - script.EmitPush(0); - script.Emit(OpCode.PACK); script.EmitPush("totalSupply"); engine.LoadScript(script.ToArray()); @@ -87,12 +83,10 @@ public static BigInteger BalanceOf(this NativeContract contract, StoreView snaps { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(contract.Script, CallFlags.All, contract.Hash); + engine.LoadScript(contract.Script, pcount: 1, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); script.EmitPush(account); - script.EmitPush(1); - script.Emit(OpCode.PACK); script.EmitPush("balanceOf"); engine.LoadScript(script.ToArray()); @@ -108,11 +102,9 @@ public static BigInteger Decimals(this NativeContract contract, StoreView snapsh { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(contract.Script, CallFlags.All, contract.Hash); + engine.LoadScript(contract.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); - script.EmitPush(0); - script.Emit(OpCode.PACK); script.EmitPush("decimals"); engine.LoadScript(script.ToArray()); @@ -128,11 +120,9 @@ public static string Symbol(this NativeContract contract, StoreView snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(contract.Script, CallFlags.All, contract.Hash); + engine.LoadScript(contract.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); - script.EmitPush(0); - script.Emit(OpCode.PACK); script.EmitPush("symbol"); engine.LoadScript(script.ToArray()); diff --git a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs index ff47f3b6ee..14c5afa0e9 100644 --- a/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs +++ b/tests/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs @@ -319,7 +319,7 @@ public void FeeIsSignatureContract_TestScope_Global() { // self-transfer of 1e-8 GAS BigInteger value = (new BigDecimal(1, 8)).Value; - sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value, null); + sb.EmitDynamicCall(NativeContract.GAS.Hash, "transfer", true, acc.ScriptHash, acc.ScriptHash, value, null); sb.Emit(OpCode.ASSERT); script = sb.ToArray(); } @@ -405,7 +405,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_GAS() { // self-transfer of 1e-8 GAS BigInteger value = (new BigDecimal(1, 8)).Value; - sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value, null); + sb.EmitDynamicCall(NativeContract.GAS.Hash, "transfer", true, acc.ScriptHash, acc.ScriptHash, value, null); sb.Emit(OpCode.ASSERT); script = sb.ToArray(); } @@ -492,7 +492,7 @@ public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() { // self-transfer of 1e-8 GAS System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; - sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value, null); + sb.EmitDynamicCall(NativeContract.GAS.Hash, "transfer", true, acc.ScriptHash, acc.ScriptHash, value, null); sb.Emit(OpCode.ASSERT); script = sb.ToArray(); } @@ -580,7 +580,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_FAULT() { // self-transfer of 1e-8 GAS System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; - sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.EmitDynamicCall(NativeContract.GAS.Hash, "transfer", true, acc.ScriptHash, acc.ScriptHash, value); sb.Emit(OpCode.ASSERT); script = sb.ToArray(); } @@ -632,7 +632,7 @@ public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() { // self-transfer of 1e-8 GAS BigInteger value = (new BigDecimal(1, 8)).Value; - sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value, null); + sb.EmitDynamicCall(NativeContract.GAS.Hash, "transfer", true, acc.ScriptHash, acc.ScriptHash, value, null); sb.Emit(OpCode.ASSERT); script = sb.ToArray(); } @@ -722,7 +722,7 @@ public void FeeIsSignatureContract_TestScope_NoScopeFAULT() { // self-transfer of 1e-8 GAS BigInteger value = (new BigDecimal(1, 8)).Value; - sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); + sb.EmitDynamicCall(NativeContract.GAS.Hash, "transfer", true, acc.ScriptHash, acc.ScriptHash, value); sb.Emit(OpCode.ASSERT); script = sb.ToArray(); } @@ -985,7 +985,7 @@ public void FeeIsSignatureContract_TestScope_FeeOnly_Default() { // self-transfer of 1e-8 GAS BigInteger value = (new BigDecimal(1, 8)).Value; - sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value, null); + sb.EmitDynamicCall(NativeContract.GAS.Hash, "transfer", true, acc.ScriptHash, acc.ScriptHash, value, null); sb.Emit(OpCode.ASSERT); script = sb.ToArray(); } diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 90b54ff208..f7ccdd206d 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -99,7 +99,7 @@ public void TestInvoke() { var snapshot = Blockchain.Singleton.GetSnapshot(); ApplicationEngine engine = ApplicationEngine.Create(TriggerType.OnPersist, null, snapshot, 0); - engine.LoadScript(testNativeContract.Script, CallFlags.All, testNativeContract.Hash); + engine.LoadScript(testNativeContract.Script, callFlags: CallFlags.All, scriptHash: testNativeContract.Hash); ByteString method1 = new ByteString(System.Text.Encoding.Default.GetBytes("wrongMethod")); VMArray args1 = new VMArray(); @@ -129,7 +129,7 @@ public void TestTrigger() [TestMethod] public void TestTestCall() { - ApplicationEngine engine = testNativeContract.TestCall("System.Blockchain.GetHeight", 0); + ApplicationEngine engine = testNativeContract.TestCall("System.Blockchain.GetHeight", false, 0); engine.ResultStack.Should().BeEmpty(); } } diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs index 5ab79afe5f..02899a5a71 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs @@ -509,7 +509,7 @@ public void TestCalculateBonus() [TestMethod] public void TestGetNextBlockValidators1() { - using (ApplicationEngine engine = NativeContract.NEO.TestCall("getNextBlockValidators")) + using (ApplicationEngine engine = NativeContract.NEO.TestCall("getNextBlockValidators", true)) { var result = engine.ResultStack.Peek(); result.GetType().Should().Be(typeof(VM.Types.Array)); @@ -542,7 +542,7 @@ public void TestGetNextBlockValidators2() [TestMethod] public void TestGetCandidates1() { - using ApplicationEngine engine = NativeContract.NEO.TestCall("getCandidates"); + using ApplicationEngine engine = NativeContract.NEO.TestCall("getCandidates", true); var array = engine.ResultStack.Pop(); array.Count.Should().Be(0); } @@ -603,7 +603,7 @@ public void TestCheckCandidate() [TestMethod] public void TestGetCommittee() { - using (ApplicationEngine engine = NativeContract.NEO.TestCall("getCommittee")) + using (ApplicationEngine engine = NativeContract.NEO.TestCall("getCommittee", true)) { var result = engine.ResultStack.Peek(); result.GetType().Should().Be(typeof(VM.Types.Array)); @@ -835,7 +835,7 @@ public void TestVote() })); } - sb.EmitAppCall(NativeContract.NEO.Hash, "transfer", from, UInt160.Zero, amount, null); + sb.EmitDynamicCall(NativeContract.NEO.Hash, "transfer", true, from, UInt160.Zero, amount, null); engine.LoadScript(sb.ToArray()); engine.Execute(); var result = engine.ResultStack.Peek(); @@ -867,11 +867,9 @@ internal static (BigInteger Value, bool State) Check_GetGasPerBlock(StoreView sn { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); - script.EmitPush(0); - script.Emit(OpCode.PACK); script.EmitPush("getGasPerBlock"); engine.LoadScript(script.ToArray()); @@ -891,12 +889,10 @@ internal static (VM.Types.Boolean Value, bool State) Check_SetGasPerBlock(StoreV UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot); var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(committeeMultiSigAddr), snapshot); - engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 1, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(gasPerBlock); - script.EmitPush(1); - script.Emit(OpCode.PACK); script.EmitPush("setGasPerBlock"); engine.LoadScript(script.ToArray()); @@ -916,7 +912,7 @@ internal static (bool State, bool Result) Check_Vote(StoreView snapshot, byte[] var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(signAccount ? new UInt160(account) : UInt160.Zero), snapshot); - engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 2, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); @@ -925,8 +921,6 @@ internal static (bool State, bool Result) Check_Vote(StoreView snapshot, byte[] else script.EmitPush(pubkey); script.EmitPush(account); - script.EmitPush(2); - script.Emit(OpCode.PACK); script.EmitPush("vote"); engine.LoadScript(script.ToArray()); @@ -946,12 +940,10 @@ internal static (bool State, bool Result) Check_RegisterValidator(StoreView snap var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot); - engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 1, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(pubkey); - script.EmitPush(1); - script.Emit(OpCode.PACK); script.EmitPush("registerCandidate"); engine.LoadScript(script.ToArray()); @@ -970,11 +962,9 @@ internal static ECPoint[] Check_GetCommittee(StoreView snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 0, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); - script.EmitPush(0); - script.Emit(OpCode.PACK); script.EmitPush("getCommittee"); engine.LoadScript(script.ToArray()); @@ -990,13 +980,11 @@ internal static (BigInteger Value, bool State) Check_UnclaimedGas(StoreView snap { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 2, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(snapshot.PersistingBlock.Index); script.EmitPush(address); - script.EmitPush(2); - script.Emit(OpCode.PACK); script.EmitPush("unclaimedGas"); engine.LoadScript(script.ToArray()); @@ -1052,12 +1040,10 @@ internal static (bool State, bool Result) Check_UnregisterCandidate(StoreView sn var engine = ApplicationEngine.Create(TriggerType.Application, new Nep17NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot); - engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); + engine.LoadScript(NativeContract.NEO.Script, pcount: 1, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(pubkey); - script.EmitPush(1); - script.Emit(OpCode.PACK); script.EmitPush("unregisterCandidate"); engine.LoadScript(script.ToArray()); diff --git a/tests/neo.UnitTests/SmartContract/UT_Contract.cs b/tests/neo.UnitTests/SmartContract/UT_Contract.cs index e2843ac0de..57cea86681 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Contract.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Contract.cs @@ -180,7 +180,7 @@ public void TestSignatureRedeemScriptFee() using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, new Transaction { Signers = Array.Empty(), Attributes = Array.Empty() }, null)) { - engine.LoadScript(invocation.Concat(verification).ToArray(), CallFlags.None); + engine.LoadScript(invocation.Concat(verification).ToArray(), callFlags: CallFlags.None); engine.Execute(); engine.GasConsumed.Should().Be(fee); } @@ -208,7 +208,7 @@ public void TestCreateMultiSigRedeemScriptFee() using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, new Transaction { Signers = Array.Empty(), Attributes = Array.Empty() }, null)) { - engine.LoadScript(invocation.Concat(verification).ToArray(), CallFlags.None); + engine.LoadScript(invocation.Concat(verification).ToArray(), callFlags: CallFlags.None); engine.Execute(); engine.GasConsumed.Should().Be(fee); } diff --git a/tests/neo.UnitTests/SmartContract/UT_Helper.cs b/tests/neo.UnitTests/SmartContract/UT_Helper.cs index dc666fab20..3e5511f5a8 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Helper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Helper.cs @@ -17,8 +17,8 @@ public void TestGetContractHash() }; nef.CheckSum = NefFile.ComputeChecksum(nef); - Assert.AreEqual("0xb4b7417195feca1cdb5a99504ab641d8c220ae99", Neo.SmartContract.Helper.GetContractHash(UInt160.Zero, nef.Script).ToString()); - Assert.AreEqual("0xe56e4ee87f89a70e9138432c387ad49f2ee5b55f", Neo.SmartContract.Helper.GetContractHash(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), nef.Script).ToString()); + Assert.AreEqual("0xb8e95ff7b11c427c29355e3398722d97bd2ca069", Neo.SmartContract.Helper.GetContractHash(UInt160.Zero, nef.Script).ToString()); + Assert.AreEqual("0x435c467b8e15cb9b1474ad7ee817ffdcfededef9", Neo.SmartContract.Helper.GetContractHash(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), nef.Script).ToString()); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 09ab10c78b..0a28d223a9 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -154,15 +154,15 @@ public void TestContract_Create() script_exceedMaxLength.CheckSum = NefFile.ComputeChecksum(nef); Assert.ThrowsException(() => snapshot.DeployContract(UInt160.Zero, script_exceedMaxLength.ToArray(), manifest.ToJson().ToByteArray(true))); - var script_zeroLength = new byte[] { }; + var script_zeroLength = System.Array.Empty(); Assert.ThrowsException(() => snapshot.DeployContract(UInt160.Zero, script_zeroLength, manifest.ToJson().ToByteArray(true))); - var manifest_zeroLength = new byte[] { }; + var manifest_zeroLength = System.Array.Empty(); Assert.ThrowsException(() => snapshot.DeployContract(UInt160.Zero, nefFile, manifest_zeroLength)); manifest = TestUtils.CreateDefaultManifest(); var ret = snapshot.DeployContract(UInt160.Zero, nefFile, manifest.ToJson().ToByteArray(false)); - ret.Hash.ToString().Should().Be("0x5756874a149b9de89c7b5d34f9c37db3762f88a2"); + ret.Hash.ToString().Should().Be("0x6410935f6b153eeb85f5d95d926c075b1ef51620"); Assert.ThrowsException(() => snapshot.DeployContract(UInt160.Zero, nefFile, manifest.ToJson().ToByteArray(false))); var state = TestUtils.GetContract(); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index 8b1b1a8687..ba67c15287 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -89,7 +89,7 @@ public void Runtime_GetNotifications_Test() // Call script - script.EmitAppCall(scriptHash2, "test", "testEvent2", 1); + script.EmitDynamicCall(scriptHash2, "test", true, "testEvent2", 1); // Drop return @@ -141,7 +141,7 @@ public void Runtime_GetNotifications_Test() // Call script - script.EmitAppCall(scriptHash2, "test", "testEvent2", 1); + script.EmitDynamicCall(scriptHash2, "test", true, "testEvent2", 1); // Drop return @@ -224,7 +224,7 @@ public void TestExecutionEngine_GetCallingScriptHash() engine.Snapshot.AddContract(contract.Hash, contract); using ScriptBuilder scriptB = new ScriptBuilder(); - scriptB.EmitAppCall(contract.Hash, "test", 0, 1); + scriptB.EmitDynamicCall(contract.Hash, "test", true, 0, 1); engine.LoadScript(scriptB.ToArray()); Assert.AreEqual(VMState.HALT, engine.Execute()); @@ -598,46 +598,21 @@ public void TestContract_Call() var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - engine.CallContractEx(state.Hash, method, args, CallFlags.All); + engine.Push(args[1]); engine.Push(args[0]); + engine.CallContract(state.Hash, method, CallFlags.All, false, (ushort)args.Count); engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); state.Manifest.Permissions[0].Methods = WildcardContainer.Create("a"); - Assert.ThrowsException(() => engine.CallContractEx(state.Hash, method, args, CallFlags.All)); + engine.Push(args[1]); engine.Push(args[0]); + Assert.ThrowsException(() => engine.CallContract(state.Hash, method, CallFlags.All, false, (ushort)args.Count)); state.Manifest.Permissions[0].Methods = WildcardContainer.CreateWildcard(); - engine.CallContractEx(state.Hash, method, args, CallFlags.All); + engine.Push(args[1]); engine.Push(args[0]); + engine.CallContract(state.Hash, method, CallFlags.All, false, (ushort)args.Count); - Assert.ThrowsException(() => engine.CallContractEx(UInt160.Zero, method, args, CallFlags.All)); - } - - [TestMethod] - public void TestContract_CallEx() - { - var snapshot = Blockchain.Singleton.GetSnapshot(); - - string method = "method"; - var args = new VM.Types.Array { 0, 1 }; - var state = TestUtils.GetContract(method, args.Count); - snapshot.AddContract(state.Hash, state); - - foreach (var flags in new CallFlags[] { CallFlags.None, CallFlags.AllowCall, CallFlags.WriteStates, CallFlags.All }) - { - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(new byte[] { 0x01 }); - - engine.CallContractEx(state.Hash, method, args, CallFlags.All); - engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); - engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); - - // Contract doesn't exists - Assert.ThrowsException(() => engine.CallContractEx(UInt160.Zero, method, args, CallFlags.All)); - - // Call with rights - engine.CallContractEx(state.Hash, method, args, flags); - engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); - engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); - } + engine.Push(args[1]); engine.Push(args[0]); + Assert.ThrowsException(() => engine.CallContract(UInt160.Zero, method, CallFlags.All, false, (ushort)args.Count)); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/UT_OpCodePrices.cs b/tests/neo.UnitTests/SmartContract/UT_OpCodePrices.cs index cb04990e31..fa82f194d2 100644 --- a/tests/neo.UnitTests/SmartContract/UT_OpCodePrices.cs +++ b/tests/neo.UnitTests/SmartContract/UT_OpCodePrices.cs @@ -12,7 +12,7 @@ public class UT_OpCodePrices public void AllOpcodePriceAreSet() { foreach (OpCode opcode in Enum.GetValues(typeof(OpCode))) - Assert.IsTrue(ApplicationEngine.OpCodePrices.ContainsKey(opcode)); + Assert.IsTrue(ApplicationEngine.OpCodePrices.ContainsKey(opcode), opcode.ToString()); } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index 844d798761..3a06e062a0 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -349,10 +349,10 @@ public void System_Runtime_GetInvocationCounter() using (var script = new ScriptBuilder()) { - script.EmitAppCall(contractA.Hash, "dummyMain", 0, 1); - script.EmitAppCall(contractB.Hash, "dummyMain", 0, 1); - script.EmitAppCall(contractB.Hash, "dummyMain", 0, 1); - script.EmitAppCall(contractC.Hash, "dummyMain", 0, 1); + script.EmitDynamicCall(contractA.Hash, "dummyMain", true, 0, 1); + script.EmitDynamicCall(contractB.Hash, "dummyMain", true, 0, 1); + script.EmitDynamicCall(contractB.Hash, "dummyMain", true, 0, 1); + script.EmitDynamicCall(contractC.Hash, "dummyMain", true, 0, 1); // Execute diff --git a/tests/neo.UnitTests/VM/UT_Helper.cs b/tests/neo.UnitTests/VM/UT_Helper.cs index 252cb78566..cd84fdc773 100644 --- a/tests/neo.UnitTests/VM/UT_Helper.cs +++ b/tests/neo.UnitTests/VM/UT_Helper.cs @@ -50,23 +50,22 @@ public void TestToJson() [TestMethod] public void TestEmitAppCall1() { - //format:(byte)0x10+(byte)OpCode.NEWARRAY+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call ScriptBuilder sb = new ScriptBuilder(); - sb.EmitAppCall(UInt160.Zero, "AAAAA"); + sb.EmitDynamicCall(UInt160.Zero, "AAAAA", false); byte[] tempArray = new byte[37]; - tempArray[0] = (byte)OpCode.PUSH15; + tempArray[0] = (byte)OpCode.PUSH0; tempArray[1] = (byte)OpCode.PUSH0; - tempArray[2] = (byte)OpCode.NEWARRAY; + tempArray[2] = (byte)OpCode.PUSH15;//(byte)CallFlags.All; tempArray[3] = (byte)OpCode.PUSHDATA1; tempArray[4] = 5;//operation.Length Array.Copy(Encoding.UTF8.GetBytes("AAAAA"), 0, tempArray, 5, 5);//operation.data tempArray[10] = (byte)OpCode.PUSHDATA1; tempArray[11] = 0x14;//scriptHash.Length Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 12, 20);//operation.data - uint api = ApplicationEngine.System_Contract_CallEx; + uint api = ApplicationEngine.System_Contract_Call; tempArray[32] = (byte)OpCode.SYSCALL; Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 33, 4);//api.data - CollectionAssert.AreEqual(tempArray, sb.ToArray()); + Assert.AreEqual(tempArray.ToHexString(), sb.ToArray().ToHexString()); } [TestMethod] @@ -114,55 +113,53 @@ public void TestEmitMap() [TestMethod] public void TestEmitAppCall2() { - //format:(ContractParameter[])ContractParameter+(byte)OpCode.PACK+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call ScriptBuilder sb = new ScriptBuilder(); - sb.EmitAppCall(UInt160.Zero, "AAAAA", new ContractParameter[] { new ContractParameter(ContractParameterType.Integer) }); + sb.EmitDynamicCall(UInt160.Zero, "AAAAA", false, new ContractParameter[] { new ContractParameter(ContractParameterType.Integer) }); byte[] tempArray = new byte[38]; - tempArray[0] = (byte)OpCode.PUSH15; - tempArray[1] = (byte)OpCode.PUSH0; - tempArray[2] = (byte)OpCode.PUSH1; - tempArray[3] = (byte)OpCode.PACK; + tempArray[0] = (byte)OpCode.PUSH0; + tempArray[1] = (byte)OpCode.PUSH1; + tempArray[2] = (byte)OpCode.PUSH0; + tempArray[3] = (byte)OpCode.PUSH15;//(byte)CallFlags.All; tempArray[4] = (byte)OpCode.PUSHDATA1; tempArray[5] = 0x05;//operation.Length Array.Copy(Encoding.UTF8.GetBytes("AAAAA"), 0, tempArray, 6, 5);//operation.data tempArray[11] = (byte)OpCode.PUSHDATA1; tempArray[12] = 0x14;//scriptHash.Length Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 13, 20);//operation.data - uint api = ApplicationEngine.System_Contract_CallEx; + uint api = ApplicationEngine.System_Contract_Call; tempArray[33] = (byte)OpCode.SYSCALL; Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 34, 4);//api.data - CollectionAssert.AreEqual(tempArray, sb.ToArray()); + Assert.AreEqual(tempArray.ToHexString(), sb.ToArray().ToHexString()); } [TestMethod] public void TestEmitAppCall3() { - //format:(object[])args+(byte)OpCode.PACK+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call ScriptBuilder sb = new ScriptBuilder(); - sb.EmitAppCall(UInt160.Zero, "AAAAA", true); + sb.EmitDynamicCall(UInt160.Zero, "AAAAA", false, true); byte[] tempArray = new byte[38]; - tempArray[0] = (byte)OpCode.PUSH15; - tempArray[1] = (byte)OpCode.PUSH1;//arg - tempArray[2] = (byte)OpCode.PUSH1;//args.Length - tempArray[3] = (byte)OpCode.PACK; + tempArray[0] = (byte)OpCode.PUSH1; + tempArray[1] = (byte)OpCode.PUSH1;//arg.Length + tempArray[2] = (byte)OpCode.PUSH0;//return + tempArray[3] = (byte)OpCode.PUSH15;//(byte)CallFlags.All; tempArray[4] = (byte)OpCode.PUSHDATA1; tempArray[5] = 0x05;//operation.Length Array.Copy(Encoding.UTF8.GetBytes("AAAAA"), 0, tempArray, 6, 5);//operation.data tempArray[11] = (byte)OpCode.PUSHDATA1; tempArray[12] = 0x14;//scriptHash.Length Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 13, 20);//operation.data - uint api = ApplicationEngine.System_Contract_CallEx; + uint api = ApplicationEngine.System_Contract_Call; tempArray[33] = (byte)OpCode.SYSCALL; Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 34, 4);//api.data - CollectionAssert.AreEqual(tempArray, sb.ToArray()); + Assert.AreEqual(tempArray.ToHexString(), sb.ToArray().ToHexString()); } [TestMethod] public void TestMakeScript() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", true, UInt160.Zero); - Assert.AreEqual("1f0c14000000000000000000000000000000000000000011c00c0962616c616e63654f660c14fbedfe2ed2226592b648c4da97b9c9cd5dc1a6a641eef40cdb", + Assert.AreEqual("0c14000000000000000000000000000000000000000011111f0c0962616c616e63654f660c141717ddafdd757eec365865b963473beb617f9a1441627d5b52", testScript.ToHexString()); }