From 4fecf64912879660df254c85e7db8e4bbed4946c Mon Sep 17 00:00:00 2001 From: erikzhang Date: Thu, 18 Jun 2020 15:27:51 +0800 Subject: [PATCH] Update to Neo.VM.3.0.0-CI00226 --- .../ApplicationEngine.Contract.cs | 6 +-- .../SmartContract/ApplicationEngine.Crypto.cs | 2 +- .../SmartContract/ApplicationEngine.Native.cs | 3 +- .../ApplicationEngine.Storage.cs | 2 +- src/neo/SmartContract/ApplicationEngine.cs | 40 +++++-------------- src/neo/SmartContract/ContainerPlaceholder.cs | 2 +- src/neo/SmartContract/Helper.cs | 3 +- .../SmartContract/Native/NativeContract.cs | 17 ++++---- src/neo/neo.csproj | 2 +- .../Native/Tokens/UT_GasToken.cs | 2 +- .../Native/Tokens/UT_NeoToken.cs | 4 +- .../SmartContract/Native/UT_NativeContract.cs | 5 ++- .../SmartContract/UT_ApplicationEngine.cs | 14 ------- .../SmartContract/UT_Syscalls.cs | 14 +++---- 14 files changed, 41 insertions(+), 75 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index ab0e1ac8f4..55a919c17f 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -32,8 +32,7 @@ internal ContractState CreateContract(byte[] script, byte[] manifest) if (script.Length == 0 || script.Length > MaxContractLength || manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) throw new ArgumentException(); - if (!AddGas(StoragePrice * (script.Length + manifest.Length))) - throw new InvalidOperationException(); + AddGas(StoragePrice * (script.Length + manifest.Length)); UInt160 hash = script.ToScriptHash(); ContractState contract = Snapshot.Contracts.TryGet(hash); @@ -53,8 +52,7 @@ internal ContractState CreateContract(byte[] script, byte[] manifest) internal void UpdateContract(byte[] script, byte[] manifest) { - if (!AddGas(StoragePrice * (script?.Length ?? 0 + manifest?.Length ?? 0))) - throw new InvalidOperationException(); + AddGas(StoragePrice * (script?.Length ?? 0 + manifest?.Length ?? 0)); var contract = Snapshot.Contracts.TryGet(CurrentScriptHash); if (contract is null) throw new InvalidOperationException(); diff --git a/src/neo/SmartContract/ApplicationEngine.Crypto.cs b/src/neo/SmartContract/ApplicationEngine.Crypto.cs index 70533d900c..7ce7933884 100644 --- a/src/neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/neo/SmartContract/ApplicationEngine.Crypto.cs @@ -89,7 +89,7 @@ private bool CheckMultiSigWithECDsa(StackItem item0, byte[][] pubkeys, byte[][] _ => item0.GetSpan() }; if (n == 0 || m == 0 || m > n) throw new ArgumentException(); - if (!AddGas(ECDsaVerifyPrice * n)) throw new InvalidOperationException(); + AddGas(ECDsaVerifyPrice * n); try { for (int i = 0, j = 0; i < m && j < n;) diff --git a/src/neo/SmartContract/ApplicationEngine.Native.cs b/src/neo/SmartContract/ApplicationEngine.Native.cs index e413df7b17..074b9b8dd2 100644 --- a/src/neo/SmartContract/ApplicationEngine.Native.cs +++ b/src/neo/SmartContract/ApplicationEngine.Native.cs @@ -27,8 +27,7 @@ internal void DeployNativeContracts() internal void CallNativeContract(string name) { - if (!NativeContract.GetContract(name).Invoke(this)) - throw new InvalidOperationException(); + NativeContract.GetContract(name).Invoke(this); } } } diff --git a/src/neo/SmartContract/ApplicationEngine.Storage.cs b/src/neo/SmartContract/ApplicationEngine.Storage.cs index b579c5f37f..7d1934aba7 100644 --- a/src/neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/neo/SmartContract/ApplicationEngine.Storage.cs @@ -105,7 +105,7 @@ private void PutExInternal(StorageContext context, byte[] key, byte[] value, Sto else newDataSize = value.Length - item.Value.Length; } - if (!AddGas(newDataSize * StoragePrice)) throw new InvalidOperationException(); + AddGas(newDataSize * StoragePrice); item.Value = value; item.IsConstant = flags.HasFlag(StorageFlags.Constant); diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index cc3ceb36a8..d3a49390da 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -9,7 +9,6 @@ using System.Linq; using System.Numerics; using System.Reflection; -using System.Text; using Array = System.Array; using VMArray = Neo.VM.Types.Array; @@ -49,10 +48,11 @@ public ApplicationEngine(TriggerType trigger, IVerifiable container, StoreView s this.Snapshot = snapshot; } - internal bool AddGas(long gas) + internal void AddGas(long gas) { GasConsumed = checked(GasConsumed + gas); - return testMode || GasConsumed <= gas_amount; + if (!testMode && GasConsumed > gas_amount) + throw new InvalidOperationException("Insufficient GAS."); } protected override void ContextUnloaded(ExecutionContext context) @@ -147,17 +147,15 @@ public override void Dispose() base.Dispose(); } - protected override bool OnSysCall(uint method) + protected override void OnSysCall(uint method) { - if (!services.TryGetValue(method, out InteropDescriptor descriptor)) - return false; + InteropDescriptor descriptor = services[method]; if (!descriptor.AllowedTriggers.HasFlag(Trigger)) - return false; + throw new InvalidOperationException($"Cannot call this SYSCALL with the trigger {Trigger}."); ExecutionContextState state = CurrentContext.GetState(); if (!state.CallFlags.HasFlag(descriptor.RequiredCallFlags)) - return false; - if (!AddGas(descriptor.FixedPrice)) - return false; + throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state.CallFlags}."); + AddGas(descriptor.FixedPrice); List parameters = descriptor.Parameters.Length > 0 ? new List() : null; @@ -166,14 +164,12 @@ protected override bool OnSysCall(uint method) object returnValue = descriptor.Handler.Invoke(this, parameters?.ToArray()); if (descriptor.Handler.ReturnType != typeof(void)) Push(Convert(returnValue)); - return true; } - protected override bool PreExecuteInstruction() + protected override void PreExecuteInstruction() { - if (CurrentContext.InstructionPointer >= CurrentContext.Script.Length) - return true; - return AddGas(OpCodePrices[CurrentContext.CurrentInstruction.OpCode]); + if (CurrentContext.InstructionPointer < CurrentContext.Script.Length) + AddGas(OpCodePrices[CurrentContext.CurrentInstruction.OpCode]); } private static Block CreateDummyBlock(StoreView snapshot) @@ -224,19 +220,5 @@ public static ApplicationEngine Run(byte[] script, IVerifiable container = null, return Run(script, snapshot, container, persistingBlock, offset, testMode, extraGAS); } } - - public bool TryPop(out string s) - { - if (TryPop(out ReadOnlySpan b)) - { - s = Encoding.UTF8.GetString(b); - return true; - } - else - { - s = default; - return false; - } - } } } diff --git a/src/neo/SmartContract/ContainerPlaceholder.cs b/src/neo/SmartContract/ContainerPlaceholder.cs index 72eb68e48d..757d77ccbc 100644 --- a/src/neo/SmartContract/ContainerPlaceholder.cs +++ b/src/neo/SmartContract/ContainerPlaceholder.cs @@ -14,7 +14,7 @@ public ContainerPlaceholder(StackItemType type, int count) ElementCount = count; } - public override bool Equals(object obj) => throw new NotSupportedException(); + public override bool Equals(StackItem other) => throw new NotSupportedException(); public override int GetHashCode() => throw new NotSupportedException(); diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index b8fe4450a3..d9299e30f3 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -5,7 +5,6 @@ using Neo.Persistence; using Neo.SmartContract.Manifest; using Neo.VM; -using Neo.VM.Types; using System; using System.Buffers.Binary; using System.Collections.Generic; @@ -165,7 +164,7 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap engine.LoadScript(verification, CallFlags.ReadOnly).InstructionPointer = offset; engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None); if (engine.Execute() == VMState.FAULT) return false; - if (!engine.ResultStack.TryPop(out StackItem result) || !result.ToBoolean()) return false; + if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().ToBoolean()) return false; gas -= engine.GasConsumed; } } diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index 5deed39568..81564fb942 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -108,15 +108,17 @@ public static NativeContract GetContract(string name) return contract; } - internal bool Invoke(ApplicationEngine engine) + internal void Invoke(ApplicationEngine engine) { - if (!engine.CurrentScriptHash.Equals(Hash)) return false; - if (!engine.TryPop(out string operation)) return false; - if (!engine.TryPop(out Array args)) return false; - if (!methods.TryGetValue(operation, out ContractMethodMetadata method)) return false; + if (!engine.CurrentScriptHash.Equals(Hash)) + throw new InvalidOperationException("It is not allowed to use Neo.Native.Call directly to call native contracts. System.Contract.Call should be used."); + string operation = engine.PopString(); + Array args = engine.Pop(); + ContractMethodMetadata method = methods[operation]; ExecutionContextState state = engine.CurrentContext.GetState(); - if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) return false; - if (!engine.AddGas(method.Price)) return false; + if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) + throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}."); + engine.AddGas(method.Price); List parameters = new List(); if (method.NeedApplicationEngine) parameters.Add(engine); if (method.NeedSnapshot) parameters.Add(engine.Snapshot); @@ -128,7 +130,6 @@ internal bool Invoke(ApplicationEngine engine) object returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (method.Handler.ReturnType != typeof(void)) engine.Push(engine.Convert(returnValue)); - return true; } public static bool IsNative(UInt160 hash) diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index 978c6af877..edc2301bf1 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -27,7 +27,7 @@ - + diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs index f7be52f9a6..e2910ae1e5 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs @@ -133,7 +133,7 @@ public void Check_BadScript() script.Emit(OpCode.NOP); engine.LoadScript(script.ToArray()); - NativeContract.GAS.Invoke(engine).Should().BeFalse(); + Assert.ThrowsException(() => NativeContract.GAS.Invoke(engine)); } } } diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 591cca7abe..8b4b4b0123 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -215,7 +215,7 @@ public void Check_BadScript() script.Emit(OpCode.NOP); engine.LoadScript(script.ToArray()); - NativeContract.NEO.Invoke(engine).Should().BeFalse(); + Assert.ThrowsException(() => NativeContract.NEO.Invoke(engine)); } [TestMethod] @@ -283,7 +283,7 @@ public void TestGetRegisteredValidators1() { using (ApplicationEngine engine = NativeContract.NEO.TestCall("getCandidates")) { - engine.ResultStack.TryPop(out VM.Types.Array array).Should().BeTrue(); + var array = engine.ResultStack.Pop(); array.Count.Should().Be(21); ((VM.Types.Struct)array[0])[0].GetSpan().ToHexString().Should().Be("020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639"); ((VM.Types.Struct)array[0])[1].GetBigInteger().Should().Be(new BigInteger(1785714)); diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index aa58ba157c..90970a506b 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -5,6 +5,7 @@ using Neo.SmartContract.Native; using Neo.VM.Types; using System; +using System.Collections.Generic; using VMArray = Neo.VM.Types.Array; namespace Neo.UnitTests.SmartContract.Native @@ -38,13 +39,13 @@ public void TestInvoke() VMArray args1 = new VMArray(); engine.CurrentContext.EvaluationStack.Push(args1); engine.CurrentContext.EvaluationStack.Push(method1); - testNativeContract.Invoke(engine).Should().BeFalse(); + Assert.ThrowsException(() => testNativeContract.Invoke(engine)); ByteString method2 = new ByteString(System.Text.Encoding.Default.GetBytes("onPersist")); VMArray args2 = new VMArray(); engine.CurrentContext.EvaluationStack.Push(args2); engine.CurrentContext.EvaluationStack.Push(method2); - testNativeContract.Invoke(engine).Should().BeTrue(); + testNativeContract.Invoke(engine); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs index 447c5b9f4f..187ba61024 100644 --- a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs +++ b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs @@ -3,8 +3,6 @@ using Neo.IO; using Neo.IO.Caching; using Neo.Ledger; -using Neo.Network.P2P.Payloads; -using Neo.Persistence; using Neo.SmartContract; namespace Neo.UnitTests.SmartContract @@ -78,18 +76,6 @@ public void TestCreateDummyBlock() } } - public class TestApplicationEngine : ApplicationEngine - { - public TestApplicationEngine(TriggerType trigger, IVerifiable container, StoreView snapshot, long gas, bool testMode = false) : base(trigger, container, snapshot, gas, testMode) - { - } - - public bool GetOnSysCall(uint method) - { - return OnSysCall(method); - } - } - public class TestMetaDataCache : MetaDataCache where T : class, ICloneable, ISerializable, new() { public TestMetaDataCache() diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index 3c583d73ef..77989b557e 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -126,8 +126,8 @@ public void Json_Deserialize() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(2, engine.ResultStack.Count); - Assert.IsTrue(engine.ResultStack.TryPop(out _)); - Assert.IsTrue(engine.ResultStack.TryPop(out var i) && i.GetBigInteger() == 123); + engine.ResultStack.Pop(); + Assert.IsTrue(engine.ResultStack.Pop().GetBigInteger() == 123); } } @@ -194,11 +194,11 @@ public void Json_Serialize() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(5, engine.ResultStack.Count); - Assert.IsTrue(engine.ResultStack.TryPop(out var m) && m.GetString() == "{\"key\":\"dmFsdWU=\"}"); - Assert.IsTrue(engine.ResultStack.TryPop(out var n) && n.GetString() == "null"); - Assert.IsTrue(engine.ResultStack.TryPop(out var s) && s.GetString() == "\"dGVzdA==\""); - Assert.IsTrue(engine.ResultStack.TryPop(out var b) && b.GetString() == "true"); - Assert.IsTrue(engine.ResultStack.TryPop(out var i) && i.GetString() == "5"); + Assert.IsTrue(engine.ResultStack.Pop().GetString() == "{\"key\":\"dmFsdWU=\"}"); + Assert.IsTrue(engine.ResultStack.Pop().GetString() == "null"); + Assert.IsTrue(engine.ResultStack.Pop().GetString() == "\"dGVzdA==\""); + Assert.IsTrue(engine.ResultStack.Pop().GetString() == "true"); + Assert.IsTrue(engine.ResultStack.Pop().GetString() == "5"); } }