From 93bc0004d976b8db7f46dd4cda4e608dc38c6f33 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Sun, 20 Dec 2020 00:21:17 +0800 Subject: [PATCH 1/7] CI00257 --- .../Network/P2P/Payloads/OracleResponse.cs | 2 +- .../ApplicationEngine.Callback.cs | 8 +- .../ApplicationEngine.Contract.cs | 35 +++--- src/neo/SmartContract/ApplicationEngine.cs | 101 ++++-------------- .../SmartContract/Callbacks/CallbackBase.cs | 4 +- .../SmartContract/Callbacks/MethodCallback.cs | 8 +- .../Callbacks/PointerCallback.cs | 9 +- .../Callbacks/SyscallCallback.cs | 5 +- 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 | 8 +- .../Nep17NativeContractExtensions.cs | 10 +- .../Network/P2P/Payloads/UT_Transaction.cs | 14 +-- .../Callbacks/UT_MethodCallback.cs | 4 +- .../SmartContract/Native/UT_NativeContract.cs | 4 +- .../SmartContract/Native/UT_NeoToken.cs | 22 ++-- .../SmartContract/UT_Contract.cs | 4 +- .../SmartContract/UT_InteropService.cs | 6 +- .../SmartContract/UT_Syscalls.cs | 8 +- tests/neo.UnitTests/VM/UT_Helper.cs | 14 +-- 24 files changed, 143 insertions(+), 208 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.Callback.cs b/src/neo/SmartContract/ApplicationEngine.Callback.cs index efa3804183..c3066b081e 100644 --- a/src/neo/SmartContract/ApplicationEngine.Callback.cs +++ b/src/neo/SmartContract/ApplicationEngine.Callback.cs @@ -1,7 +1,5 @@ using Neo.SmartContract.Callbacks; using Neo.VM.Types; -using System; -using Array = Neo.VM.Types.Array; namespace Neo.SmartContract { @@ -12,11 +10,9 @@ partial class ApplicationEngine public static readonly InteropDescriptor System_Callback_CreateFromSyscall = Register("System.Callback.CreateFromSyscall", nameof(CreateCallbackFromSyscall), 1 << 4, CallFlags.None, false); public static readonly InteropDescriptor System_Callback_Invoke = Register("System.Callback.Invoke", nameof(InvokeCallback), 1 << 15, CallFlags.AllowCall, false); - protected internal void InvokeCallback(CallbackBase callback, Array args) + protected internal void InvokeCallback(CallbackBase callback) { - if (args.Count != callback.ParametersCount) - throw new InvalidOperationException(); - callback.LoadContext(this, args); + callback.LoadContext(this); if (callback is SyscallCallback syscallCallback) OnSysCall(syscallCallback.Method); } diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 78133563f2..0c2dcdebd2 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, false); + public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 1 << 15, CallFlags.AllowCall, false); public static readonly InteropDescriptor System_Contract_CallNative = Register("System.Contract.CallNative", nameof(CallNativeContract), 0, CallFlags.None, false); public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 1 << 10, CallFlags.ReadStates, true); public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 1 << 10, CallFlags.None, false); @@ -22,15 +22,20 @@ partial class ApplicationEngine public static readonly InteropDescriptor System_Contract_NativeOnPersist = Register("System.Contract.NativeOnPersist", nameof(NativeOnPersist), 0, CallFlags.WriteStates, false); public static readonly InteropDescriptor System_Contract_NativePostPersist = Register("System.Contract.NativePostPersist", nameof(NativePostPersist), 0, CallFlags.WriteStates, false); - 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.cs b/src/neo/SmartContract/ApplicationEngine.cs index 90892e1227..06e7b38f0c 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,49 +107,37 @@ protected override void LoadContext(ExecutionContext context) base.LoadContext(context); } - internal void LoadContext(ExecutionContext context, bool checkReturnValue) + internal void LoadClonedContext(ExecutionContext context) { - if (checkReturnValue) - GetInvocationState(CurrentContext).Convention = ReturnTypeConvention.EnsureNotEmpty; 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), false); - } + 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(); @@ -301,13 +244,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) @@ -357,7 +300,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/Callbacks/CallbackBase.cs b/src/neo/SmartContract/Callbacks/CallbackBase.cs index 7444e9fa85..f0d9f7d820 100644 --- a/src/neo/SmartContract/Callbacks/CallbackBase.cs +++ b/src/neo/SmartContract/Callbacks/CallbackBase.cs @@ -1,11 +1,9 @@ -using Neo.VM.Types; - namespace Neo.SmartContract.Callbacks { public abstract class CallbackBase { public abstract int ParametersCount { get; } - public abstract void LoadContext(ApplicationEngine engine, Array args); + public abstract void LoadContext(ApplicationEngine engine); } } diff --git a/src/neo/SmartContract/Callbacks/MethodCallback.cs b/src/neo/SmartContract/Callbacks/MethodCallback.cs index 7bcc8d5ab4..c43979e4b3 100644 --- a/src/neo/SmartContract/Callbacks/MethodCallback.cs +++ b/src/neo/SmartContract/Callbacks/MethodCallback.cs @@ -3,7 +3,6 @@ using Neo.SmartContract.Native; using System; using System.Linq; -using Array = Neo.VM.Types.Array; namespace Neo.SmartContract.Callbacks { @@ -15,7 +14,7 @@ public class MethodCallback : SyscallCallback public override int ParametersCount => method.Parameters.Length; public MethodCallback(ApplicationEngine engine, UInt160 hash, string method) - : base(ApplicationEngine.System_Contract_CallEx, false) + : base(ApplicationEngine.System_Contract_Call, false) { if (method.StartsWith('_')) throw new ArgumentException(); this.contract = NativeContract.ContractManagement.GetContract(engine.Snapshot, hash); @@ -25,10 +24,11 @@ public MethodCallback(ApplicationEngine engine, UInt160 hash, string method) this.method = this.contract.Manifest.Abi.Methods.First(p => p.Name == method); } - public override void LoadContext(ApplicationEngine engine, Array args) + public override void LoadContext(ApplicationEngine engine) { + engine.Push(ParametersCount); + engine.Push(method.ReturnType == ContractParameterType.Void ? 0 : 1); engine.Push((byte)CallFlags.All); - engine.Push(args); engine.Push(method.Name); engine.Push(contract.Hash.ToArray()); } diff --git a/src/neo/SmartContract/Callbacks/PointerCallback.cs b/src/neo/SmartContract/Callbacks/PointerCallback.cs index 6c06cf284b..0bef992e6e 100644 --- a/src/neo/SmartContract/Callbacks/PointerCallback.cs +++ b/src/neo/SmartContract/Callbacks/PointerCallback.cs @@ -17,10 +17,13 @@ public PointerCallback(ExecutionContext context, Pointer pointer, int parameters this.ParametersCount = parametersCount; } - public override void LoadContext(ApplicationEngine engine, Array args) + public override void LoadContext(ApplicationEngine engine) { - engine.LoadContext(context.Clone(pointer), true); - for (int i = args.Count - 1; i >= 0; i--) + StackItem[] args = new StackItem[ParametersCount]; + for (int i = 0; i < args.Length; i++) + args[i] = engine.Pop(); + engine.LoadClonedContext(context.Clone(pointer)); + for (int i = args.Length - 1; i >= 0; i--) engine.Push(args[i]); } } diff --git a/src/neo/SmartContract/Callbacks/SyscallCallback.cs b/src/neo/SmartContract/Callbacks/SyscallCallback.cs index eab1eb7c67..06a963074c 100644 --- a/src/neo/SmartContract/Callbacks/SyscallCallback.cs +++ b/src/neo/SmartContract/Callbacks/SyscallCallback.cs @@ -1,5 +1,4 @@ using System; -using Array = Neo.VM.Types.Array; namespace Neo.SmartContract.Callbacks { @@ -15,10 +14,8 @@ public SyscallCallback(uint method, bool check = true) throw new InvalidOperationException("This SYSCALL is not allowed for creating callback."); } - public override void LoadContext(ApplicationEngine engine, Array args) + public override void LoadContext(ApplicationEngine engine) { - for (int i = args.Count - 1; i >= 0; i--) - engine.Push(args[i]); } } } 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 2b704e0510..3999d2eefd 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 70f26f4593..0a1cde32ec 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -28,7 +28,7 @@ - + diff --git a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs index 38c5ef651b..78430592f5 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,7 +100,7 @@ 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); + engine.LoadContract(contractState, method, CallFlags.All, true, (ushort)args.Length); var script = new ScriptBuilder(); diff --git a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs index 6b87c22863..354500d422 100644 --- a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs @@ -40,7 +40,7 @@ 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, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); script.Emit(OpCode.PUSHNULL); @@ -67,7 +67,7 @@ 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, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -87,7 +87,7 @@ 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, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); script.EmitPush(account); @@ -108,7 +108,7 @@ 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, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -128,7 +128,7 @@ 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, callFlags: CallFlags.All, scriptHash: contract.Hash); var script = new ScriptBuilder(); script.EmitPush(0); 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/Callbacks/UT_MethodCallback.cs b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs index bc39a51725..8372aff489 100644 --- a/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs +++ b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs @@ -55,14 +55,12 @@ public void GetHashData() var data = new MethodCallback(engine, contract.Hash, "test"); Assert.AreEqual(0, engine.CurrentContext.EvaluationStack.Count); - var array = new VM.Types.Array(); - data.LoadContext(engine, array); + data.LoadContext(engine); Assert.AreEqual(4, engine.CurrentContext.EvaluationStack.Count); Assert.AreEqual("9bc4860bb936abf262d7a51f74b4304833fee3b2", engine.Pop().GetSpan().ToHexString()); Assert.AreEqual("test", engine.Pop().GetString()); - Assert.IsTrue(engine.Pop() == array); } } } 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..e5431b0eb5 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,7 +867,7 @@ 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, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -891,7 +891,7 @@ 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, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(gasPerBlock); @@ -916,7 +916,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, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); @@ -946,7 +946,7 @@ 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, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(pubkey); @@ -970,7 +970,7 @@ 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, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -990,7 +990,7 @@ 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, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(snapshot.PersistingBlock.Index); @@ -1052,7 +1052,7 @@ 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, callFlags: CallFlags.All, scriptHash: NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(pubkey); 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_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index 8b1b1a8687..47913a0224 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()); 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..e4c8a9853d 100644 --- a/tests/neo.UnitTests/VM/UT_Helper.cs +++ b/tests/neo.UnitTests/VM/UT_Helper.cs @@ -52,7 +52,7 @@ 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[1] = (byte)OpCode.PUSH0; @@ -63,7 +63,7 @@ public void TestEmitAppCall1() 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()); @@ -116,7 +116,7 @@ public void TestEmitAppCall2() { //format:(ContractParameter[])ContractParameter+(byte)OpCode.PACK+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call ScriptBuilder sb = new ScriptBuilder(); - sb.EmitAppCall(UInt160.Zero, "AAAAA", new ContractParameter[] { new ContractParameter(ContractParameterType.Integer) }); + sb.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; @@ -128,7 +128,7 @@ public void TestEmitAppCall2() 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()); @@ -139,7 +139,7 @@ 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 @@ -151,7 +151,7 @@ public void TestEmitAppCall3() 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()); @@ -160,7 +160,7 @@ public void TestEmitAppCall3() [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", testScript.ToHexString()); From 9ba5e2e592f1974ad7b18facaaaf89473161e399 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 27 Dec 2020 13:12:10 +0100 Subject: [PATCH 2/7] Some ut fixes --- .../ApplicationEngine.OpCodePrices.cs | 1 + .../neo.UnitTests/SmartContract/UT_Helper.cs | 4 +-- .../SmartContract/UT_InteropService.cs | 21 ++++++++----- .../SmartContract/UT_OpCodePrices.cs | 2 +- tests/neo.UnitTests/VM/UT_Helper.cs | 31 +++++++++---------- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs index d7a3b5b604..267eb4307b 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 << 9, [OpCode.ABORT] = 0, [OpCode.ASSERT] = 1 << 0, [OpCode.THROW] = 1 << 9, 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.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index 47913a0224..c31deccc56 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -598,17 +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); + foreach (var i in args) engine.Push(i); + 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)); + foreach (var i in args) engine.Push(i); + 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); + foreach (var i in args) engine.Push(i); + engine.CallContract(state.Hash, method, CallFlags.All, false, (ushort)args.Count); - Assert.ThrowsException(() => engine.CallContractEx(UInt160.Zero, method, args, CallFlags.All)); + foreach (var i in args) engine.Push(i); + Assert.ThrowsException(() => engine.CallContract(UInt160.Zero, method, CallFlags.All, false, (ushort)args.Count)); } [TestMethod] @@ -626,15 +630,18 @@ public void TestContract_CallEx() var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - engine.CallContractEx(state.Hash, method, args, CallFlags.All); + foreach (var i in args) engine.Push(i); + 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]); // Contract doesn't exists - Assert.ThrowsException(() => engine.CallContractEx(UInt160.Zero, method, args, CallFlags.All)); + foreach (var i in args) engine.Push(i); + Assert.ThrowsException(() => engine.CallContract(UInt160.Zero, method, CallFlags.All, false, (ushort)args.Count)); // Call with rights - engine.CallContractEx(state.Hash, method, args, flags); + foreach (var i in args) engine.Push(i); + engine.CallContract(state.Hash, method, flags, false, (ushort)args.Count); engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); } 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/VM/UT_Helper.cs b/tests/neo.UnitTests/VM/UT_Helper.cs index e4c8a9853d..cd84fdc773 100644 --- a/tests/neo.UnitTests/VM/UT_Helper.cs +++ b/tests/neo.UnitTests/VM/UT_Helper.cs @@ -50,13 +50,12 @@ 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.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 @@ -66,7 +65,7 @@ public void TestEmitAppCall1() 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,14 +113,13 @@ 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.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 @@ -131,20 +129,19 @@ public void TestEmitAppCall2() 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.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 @@ -154,7 +151,7 @@ public void TestEmitAppCall3() 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] @@ -162,7 +159,7 @@ public void TestMakeScript() { byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", true, UInt160.Zero); - Assert.AreEqual("1f0c14000000000000000000000000000000000000000011c00c0962616c616e63654f660c14fbedfe2ed2226592b648c4da97b9c9cd5dc1a6a641eef40cdb", + Assert.AreEqual("0c14000000000000000000000000000000000000000011111f0c0962616c616e63654f660c141717ddafdd757eec365865b963473beb617f9a1441627d5b52", testScript.ToHexString()); } From ee48b831e9d1129631fc827b2bdd9f53d04c523d Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Sun, 27 Dec 2020 22:08:31 +0800 Subject: [PATCH 3/7] Fix merge --- src/neo/neo.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index b7566e848d..f0ff860c79 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -28,10 +28,7 @@ - - - From 52c018b77da1cc2653d112a4503e70019f8bc97c Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 27 Dec 2020 18:29:07 +0100 Subject: [PATCH 4/7] Change price --- src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs index 267eb4307b..76a8f75842 100644 --- a/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs +++ b/src/neo/SmartContract/ApplicationEngine.OpCodePrices.cs @@ -58,7 +58,7 @@ partial class ApplicationEngine [OpCode.CALL] = 1 << 9, [OpCode.CALL_L] = 1 << 9, [OpCode.CALLA] = 1 << 9, - [OpCode.CALLT] = 1 << 9, + [OpCode.CALLT] = 1 << 15, [OpCode.ABORT] = 0, [OpCode.ASSERT] = 1 << 0, [OpCode.THROW] = 1 << 9, From b2f61e59b03c45fdefc4601952ce669e9db0aa0e Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 27 Dec 2020 19:15:14 +0100 Subject: [PATCH 5/7] Some fixes --- src/neo/SmartContract/ApplicationEngine.cs | 15 ++++++- .../Extensions/NativeContractExtensions.cs | 3 +- .../SmartContract/UT_InteropService.NEO.cs | 6 +-- .../SmartContract/UT_InteropService.cs | 40 ++----------------- 4 files changed, 22 insertions(+), 42 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 96536a6639..864a7b35a2 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -112,7 +112,20 @@ public ExecutionContext LoadContract(ContractState contract, string method, Call ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method); if (md is null) return null; - ExecutionContext context = LoadScript(contract.Script, + byte[] script; + if (NativeContract.IsNative(contract.Hash)) + { + using ScriptBuilder sb = new ScriptBuilder(); + sb.EmitPush(md.Name); + sb.EmitRaw(contract.Script); + script = sb.ToArray(); + } + else + { + script = contract.Script; + } + + ExecutionContext context = LoadScript(script, pcount: pcount, rvcount: hasReturnValue ? 1 : 0, initialPosition: md.Offset, diff --git a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs index 78430592f5..1275910472 100644 --- a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -100,13 +100,12 @@ 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, (ushort)args.Length); - var script = new ScriptBuilder(); for (var i = args.Length - 1; i >= 0; i--) script.EmitPush(args[i]); + 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/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 c31deccc56..ba67c15287 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -598,55 +598,23 @@ public void TestContract_Call() var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - foreach (var i in args) engine.Push(i); + 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"); - foreach (var i in args) engine.Push(i); + 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(); - foreach (var i in args) engine.Push(i); + engine.Push(args[1]); engine.Push(args[0]); engine.CallContract(state.Hash, method, CallFlags.All, false, (ushort)args.Count); - foreach (var i in args) engine.Push(i); + engine.Push(args[1]); engine.Push(args[0]); Assert.ThrowsException(() => engine.CallContract(UInt160.Zero, method, CallFlags.All, false, (ushort)args.Count)); } - [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 }); - - foreach (var i in args) engine.Push(i); - 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]); - - // Contract doesn't exists - foreach (var i in args) engine.Push(i); - Assert.ThrowsException(() => engine.CallContract(UInt160.Zero, method, CallFlags.All, false, (ushort)args.Count)); - - // Call with rights - foreach (var i in args) engine.Push(i); - engine.CallContract(state.Hash, method, flags, false, (ushort)args.Count); - engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); - engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); - } - } - [TestMethod] public void TestContract_Destroy() { From 765d62136798aff1e28142932a06005112b8e348 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 27 Dec 2020 19:24:36 +0100 Subject: [PATCH 6/7] Fix UT --- .../Nep17NativeContractExtensions.cs | 20 ++++--------- .../SmartContract/Native/UT_NeoToken.cs | 28 +++++-------------- 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep17NativeContractExtensions.cs index 354500d422..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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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/SmartContract/Native/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs index e5431b0eb5..02899a5a71 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs @@ -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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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: CallFlags.All, scriptHash: 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()); From a072ed3900a485a6d7c9ff518dfd1acf26c016e4 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 27 Dec 2020 20:01:32 +0100 Subject: [PATCH 7/7] Fix ut --- src/neo/SmartContract/ApplicationEngine.cs | 15 +-------------- .../Extensions/NativeContractExtensions.cs | 1 + 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 864a7b35a2..96536a6639 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -112,20 +112,7 @@ public ExecutionContext LoadContract(ContractState contract, string method, Call ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method); if (md is null) return null; - byte[] script; - if (NativeContract.IsNative(contract.Hash)) - { - using ScriptBuilder sb = new ScriptBuilder(); - sb.EmitPush(md.Name); - sb.EmitRaw(contract.Script); - script = sb.ToArray(); - } - else - { - script = contract.Script; - } - - ExecutionContext context = LoadScript(script, + ExecutionContext context = LoadScript(contract.Script, pcount: pcount, rvcount: hasReturnValue ? 1 : 0, initialPosition: md.Offset, diff --git a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs index 1275910472..99c6497fb7 100644 --- a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -105,6 +105,7 @@ public static StackItem Call(this NativeContract contract, StoreView snapshot, I 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());