From 9279b775eaa56e187014bac3f66d176bacc777ae Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 3 Nov 2020 13:03:41 +0100 Subject: [PATCH 01/42] Update without hash change --- src/neo/Ledger/ContractState.cs | 28 +++---- .../ApplicationEngine.Contract.cs | 64 +++++++------- .../SmartContract/ApplicationEngine.Native.cs | 1 + src/neo/SmartContract/ApplicationEngine.cs | 20 ++++- .../Callbacks/PointerCallback.cs | 2 +- src/neo/SmartContract/Helper.cs | 4 +- .../Manifest/ContractManifest.cs | 2 +- src/neo/SmartContract/NefFile.cs | 2 + src/neo/Wallets/Wallet.cs | 4 +- src/neo/neo.csproj | 2 +- .../neo.UnitTests/Ledger/UT_ContractState.cs | 3 +- .../Callbacks/UT_MethodCallback.cs | 1 + .../SmartContract/UT_DeployedContract.cs | 3 +- .../SmartContract/UT_InteropService.NEO.cs | 83 +++++++++++++++---- .../SmartContract/UT_InteropService.cs | 16 ++-- .../SmartContract/UT_SmartContractHelper.cs | 2 + .../SmartContract/UT_Syscalls.cs | 3 + tests/neo.UnitTests/TestUtils.cs | 1 + 18 files changed, 158 insertions(+), 83 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 882abb4e2e..e2990811f8 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -15,30 +15,21 @@ public class ContractState : ICloneable, ISerializable, IInterope public int Id; public byte[] Script; public ContractManifest Manifest; + public uint Version; public bool HasStorage => Manifest.Features.HasFlag(ContractFeatures.HasStorage); public bool Payable => Manifest.Features.HasFlag(ContractFeatures.Payable); + public UInt160 ScriptHash { get; set; } - private UInt160 _scriptHash; - public UInt160 ScriptHash - { - get - { - if (_scriptHash == null) - { - _scriptHash = Script.ToScriptHash(); - } - return _scriptHash; - } - } - - int ISerializable.Size => sizeof(int) + Script.GetVarSize() + Manifest.Size; + int ISerializable.Size => sizeof(int) + sizeof(uint) + UInt160.Length + Script.GetVarSize() + Manifest.Size; ContractState ICloneable.Clone() { return new ContractState { Id = Id, + Version = Version, + ScriptHash = ScriptHash, Script = Script, Manifest = Manifest.Clone() }; @@ -47,6 +38,8 @@ ContractState ICloneable.Clone() void ISerializable.Deserialize(BinaryReader reader) { Id = reader.ReadInt32(); + Version = reader.ReadUInt32(); + ScriptHash = reader.ReadSerializable(); Script = reader.ReadVarBytes(); Manifest = reader.ReadSerializable(); } @@ -54,6 +47,8 @@ void ISerializable.Deserialize(BinaryReader reader) void ICloneable.FromReplica(ContractState replica) { Id = replica.Id; + Version = replica.Version; + ScriptHash = replica.ScriptHash; Script = replica.Script; Manifest = replica.Manifest.Clone(); } @@ -66,6 +61,8 @@ void IInteroperable.FromStackItem(StackItem stackItem) void ISerializable.Serialize(BinaryWriter writer) { writer.Write(Id); + writer.Write(Version); + writer.Write(ScriptHash); writer.WriteVarBytes(Script); writer.Write(Manifest); } @@ -74,6 +71,7 @@ public JObject ToJson() { JObject json = new JObject(); json["id"] = Id; + json["version"] = Version; json["hash"] = ScriptHash.ToString(); json["script"] = Convert.ToBase64String(Script); json["manifest"] = Manifest.ToJson(); @@ -82,7 +80,7 @@ public JObject ToJson() public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new StackItem[] { Script, Manifest.ToString(), HasStorage, Payable }); + return new Array(referenceCounter, new StackItem[] { ScriptHash.ToArray(), Script, Version, Manifest.ToString(), HasStorage, Payable }); } } } diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 2c69660fee..f786e8a9c3 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -28,22 +28,27 @@ partial class ApplicationEngine /// public static readonly InteropDescriptor System_Contract_CreateStandardAccount = Register("System.Contract.CreateStandardAccount", nameof(CreateStandardAccount), 0_00010000, CallFlags.None, true); - protected internal void CreateContract(byte[] script, byte[] manifest) + protected internal void CreateContract(byte[] nefFile, byte[] manifest) { - if (script.Length == 0 || script.Length > MaxContractLength) - throw new ArgumentException($"Invalid Script Length: {script.Length}"); + if (nefFile.Length == 0 || nefFile.Length > NefFile.MaxLength) + throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); - AddGas(StoragePrice * (script.Length + manifest.Length)); + AddGas(StoragePrice * (nefFile.Length + manifest.Length)); - UInt160 hash = script.ToScriptHash(); + NefFile nef = nefFile.AsSerializable(); + if (nef.Script.Length == 0 || nef.Script.Length > MaxContractLength) + throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); + + UInt160 hash = nefFile.ToScriptHash(); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract != null) throw new InvalidOperationException($"Contract Already Exists: {hash}"); contract = new ContractState { Id = Snapshot.ContractId.GetAndChange().NextId++, - Script = script.ToArray(), + Script = nef.Script, + ScriptHash = hash, Manifest = ContractManifest.Parse(manifest) }; @@ -62,44 +67,44 @@ protected internal void CreateContract(byte[] script, byte[] manifest) CallContractInternal(contract, md, new Array(ReferenceCounter) { false }, CallFlags.All, CheckReturnType.EnsureIsEmpty); } - protected internal void UpdateContract(byte[] script, byte[] manifest) + protected internal void UpdateContract(byte[] nefFile, byte[] manifest) { - if (script is null && manifest is null) throw new ArgumentException(); + if (nefFile is null && manifest is null) throw new ArgumentException(); + if (nefFile != null && nefFile.Length > NefFile.MaxLength) + throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); - AddGas(StoragePrice * ((script?.Length ?? 0) + (manifest?.Length ?? 0))); + NefFile nef = nefFile?.AsSerializable(); + AddGas(StoragePrice * (nef is null ? manifest.Length : nefFile.Length + (manifest?.Length ?? 0))); - var contract = Snapshot.Contracts.TryGet(CurrentScriptHash); + var contract = Snapshot.Contracts.GetAndChange(CurrentScriptHash); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {CurrentScriptHash}"); - if (script != null) + if (nef != null) { - if (script.Length == 0 || script.Length > MaxContractLength) - throw new ArgumentException($"Invalid Script Length: {script.Length}"); - UInt160 hash_new = script.ToScriptHash(); + if (nef.Script.Length == 0 || nef.Script.Length > MaxContractLength) + throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); + + UInt160 hash_new = nefFile.ToScriptHash(); if (hash_new.Equals(CurrentScriptHash) || Snapshot.Contracts.TryGet(hash_new) != null) throw new InvalidOperationException($"Adding Contract Hash Already Exist: {hash_new}"); - contract = new ContractState - { - Id = contract.Id, - Script = script.ToArray(), - Manifest = contract.Manifest - }; - contract.Manifest.Abi.Hash = hash_new; - Snapshot.Contracts.Add(hash_new, contract); - Snapshot.Contracts.Delete(CurrentScriptHash); + + // Update script and script hash + contract.Script = nef.Script.ToArray(); + contract.ScriptHash = hash_new; } if (manifest != null) { if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); - contract = Snapshot.Contracts.GetAndChange(contract.ScriptHash); - contract.Manifest = ContractManifest.Parse(manifest); - if (!contract.Manifest.IsValid(contract.ScriptHash)) + var parsedManifest = ContractManifest.Parse(manifest); + if (!parsedManifest.IsValid(contract.ScriptHash)) throw new InvalidOperationException($"Invalid Manifest Hash: {contract.ScriptHash}"); if (!contract.HasStorage && Snapshot.Storages.Find(BitConverter.GetBytes(contract.Id)).Any()) throw new InvalidOperationException($"Contract Does Not Support Storage But Uses Storage"); + contract.Manifest = parsedManifest; } - if (script != null) + contract.Version++; // Increase the version + if (nef != null) { ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy"); if (md != null) @@ -164,10 +169,9 @@ private void CallContractInternal(ContractState contract, ContractMethodDescript 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 = LoadScript(contract.Script, method.Offset); + ExecutionContext context_new = LoadScript(contract.Script, flags & callingFlags, contract.ScriptHash, method.Offset); state = context_new.GetState(); state.CallingScriptHash = callingScriptHash; - state.CallFlags = flags & callingFlags; if (NativeContract.IsNative(contract.ScriptHash)) { @@ -181,7 +185,7 @@ private void CallContractInternal(ContractState contract, ContractMethodDescript } method = contract.Manifest.Abi.GetMethod("_initialize"); - if (method != null) LoadContext(context_new.Clone(method.Offset)); + if (method != null) LoadClonedContext(context_new, method.Offset, false); } protected internal bool IsStandardContract(UInt160 hash) diff --git a/src/neo/SmartContract/ApplicationEngine.Native.cs b/src/neo/SmartContract/ApplicationEngine.Native.cs index 90a8168942..9bb0c3a91a 100644 --- a/src/neo/SmartContract/ApplicationEngine.Native.cs +++ b/src/neo/SmartContract/ApplicationEngine.Native.cs @@ -19,6 +19,7 @@ protected internal void DeployNativeContracts() { Id = contract.Id, Script = contract.Script, + ScriptHash = contract.Hash, // Not NefHash here Manifest = contract.Manifest }); contract.Initialize(this); diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index b6eccabcf2..017379269d 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -161,17 +161,29 @@ protected override void LoadContext(ExecutionContext context) base.LoadContext(context); } - internal void LoadContext(ExecutionContext context, bool checkReturnValue) + internal protected void LoadClonedContext(ExecutionContext context, int initialPosition, bool checkReturnValue) { + // Copy script hash + var state = context.GetState(); + context = context.Clone(initialPosition); + var newState = context.GetState(); + newState.CallFlags = state.CallFlags; + newState.ScriptHash = state.ScriptHash; + // Configure CurrentContext and load the cloned one if (checkReturnValue) GetInvocationState(CurrentContext).NeedCheckReturnValue = CheckReturnType.EnsureNotEmpty; LoadContext(context); } - public ExecutionContext LoadScript(Script script, CallFlags callFlags, int initialPosition = 0) + public ExecutionContext LoadScript(Script script, CallFlags callFlags, UInt160 scriptHash = null, int initialPosition = 0) { - ExecutionContext context = LoadScript(script, initialPosition); - context.GetState().CallFlags = callFlags; + // Create and configure context + ExecutionContext context = CreateContext(script, initialPosition); + var state = context.GetState(); + state.CallFlags = callFlags; + state.ScriptHash = scriptHash ?? ((byte[])script).ToScriptHash(); + // Load context + LoadContext(context); return context; } diff --git a/src/neo/SmartContract/Callbacks/PointerCallback.cs b/src/neo/SmartContract/Callbacks/PointerCallback.cs index 6c06cf284b..69a3b7419b 100644 --- a/src/neo/SmartContract/Callbacks/PointerCallback.cs +++ b/src/neo/SmartContract/Callbacks/PointerCallback.cs @@ -19,7 +19,7 @@ public PointerCallback(ExecutionContext context, Pointer pointer, int parameters public override void LoadContext(ApplicationEngine engine, Array args) { - engine.LoadContext(context.Clone(pointer), true); + engine.LoadClonedContext(context, pointer, true); 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 d3f841b84d..dd9355a806 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -177,7 +177,7 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.Clone(), gas)) { CallFlags callFlags = verifiable.Witnesses[i].StateDependent ? CallFlags.AllowStates : CallFlags.None; - ExecutionContext context = engine.LoadScript(verification, callFlags, offset); + ExecutionContext context = engine.LoadScript(verification, callFlags, hashes[i], offset); if (NativeContract.IsNative(hashes[i])) { using ScriptBuilder sb = new ScriptBuilder(); @@ -187,7 +187,7 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap } else if (init != null) { - engine.LoadContext(context.Clone(init.Offset), false); + engine.LoadClonedContext(context, init.Offset, false); } engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None); if (engine.Execute() == VMState.FAULT) return false; diff --git a/src/neo/SmartContract/Manifest/ContractManifest.cs b/src/neo/SmartContract/Manifest/ContractManifest.cs index 990a400929..66e0736139 100644 --- a/src/neo/SmartContract/Manifest/ContractManifest.cs +++ b/src/neo/SmartContract/Manifest/ContractManifest.cs @@ -15,7 +15,7 @@ public class ContractManifest : ISerializable /// /// Max length for a valid Contract Manifest /// - public const int MaxLength = 4096; + public const int MaxLength = ushort.MaxValue; /// /// Serialized size diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index daa5d3b7f8..989c75a370 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -57,6 +57,8 @@ public class NefFile : ISerializable (sizeof(int) * 4) + // Version UInt160.Length; // ScriptHash + public static readonly int MaxLength = HeaderSize + sizeof(uint) + IO.Helper.GetVarSize(1024 * 1024) + (1024 * 1024); + public int Size => HeaderSize + // Header sizeof(uint) + // Checksum diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index 603c6a50a6..91f2656e12 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -400,8 +400,8 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx) if (verify is null) throw new ArgumentException($"The smart contract {contract.ScriptHash} haven't got verify method"); ContractMethodDescriptor init = contract.Manifest.Abi.GetMethod("_initialize"); using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.Clone()); - ExecutionContext context = engine.LoadScript(contract.Script, CallFlags.None, verify.Offset); - if (init != null) engine.LoadContext(context.Clone(init.Offset), false); + ExecutionContext context = engine.LoadScript(contract.Script, CallFlags.None, contract.ScriptHash, verify.Offset); + if (init != null) engine.LoadClonedContext(context, init.Offset, false); engine.LoadScript(Array.Empty(), CallFlags.None); if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.ScriptHash} verification fault."); if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.ScriptHash} returns false."); diff --git a/src/neo/neo.csproj b/src/neo/neo.csproj index a848dc6e7b..d972cc3c66 100644 --- a/src/neo/neo.csproj +++ b/src/neo/neo.csproj @@ -28,7 +28,7 @@ - + diff --git a/tests/neo.UnitTests/Ledger/UT_ContractState.cs b/tests/neo.UnitTests/Ledger/UT_ContractState.cs index 76c48c4c3e..ce8c035a56 100644 --- a/tests/neo.UnitTests/Ledger/UT_ContractState.cs +++ b/tests/neo.UnitTests/Ledger/UT_ContractState.cs @@ -23,6 +23,7 @@ public void TestSetup() contract = new ContractState { Script = script, + ScriptHash = script.ToScriptHash(), Manifest = manifest }; } @@ -84,7 +85,7 @@ public void TestDeserialize() public void TestGetSize() { ISerializable newContract = contract; - newContract.Size.Should().Be(265); + newContract.Size.Should().Be(289); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs index a26a69be60..012740d5a7 100644 --- a/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs +++ b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs @@ -41,6 +41,7 @@ public void GetHashData() }, }, Script = new byte[] { 1, 2, 3 }, + ScriptHash = new byte[] { 1, 2, 3 }.ToScriptHash() }; contract.Manifest.Abi.Hash = contract.ScriptHash; engine.LoadScript(contract.Script); diff --git a/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs b/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs index 1642ec64f2..e1f772611f 100644 --- a/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs +++ b/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs @@ -27,7 +27,8 @@ public void TestGetAddress() } } }, - Script = new byte[] { 1, 2, 3 } + Script = new byte[] { 1, 2, 3 }, + ScriptHash = new byte[] { 1, 2, 3 }.ToScriptHash() }); Assert.AreEqual("0xb2e3fe334830b4741fa5d762f2ab36b90b86c49b", contract.ScriptHash.ToString()); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index b86276501f..9260a47e80 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -128,46 +128,72 @@ public void TestAccount_IsStandard() [TestMethod] public void TestContract_Create() { + var nef = new NefFile() + { + Script = new byte[0x01], + ScriptHash = new byte[0x01].ToScriptHash(), + Compiler = "", + Version = new Version(1, 2, 3, 4) + }; + nef.CheckSum = NefFile.ComputeChecksum(nef); + var nefFile = nef.ToArray(); var engine = GetEngine(false, true); - var script = new byte[] { 0x01 }; - Assert.ThrowsException(() => engine.CreateContract(script, new byte[ContractManifest.MaxLength + 1])); + Assert.ThrowsException(() => engine.CreateContract(nefFile, new byte[ContractManifest.MaxLength + 1])); - var manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); - Assert.ThrowsException(() => engine.CreateContract(script, manifest.ToJson().ToByteArray(false))); + var manifest = TestUtils.CreateDefaultManifest(nef.ScriptHash); + Assert.ThrowsException(() => engine.CreateContract(nefFile, manifest.ToJson().ToByteArray(false))); - var script_exceedMaxLength = new byte[ApplicationEngine.MaxContractLength + 1]; - Assert.ThrowsException(() => engine.CreateContract(script_exceedMaxLength, manifest.ToJson().ToByteArray(true))); + var script_exceedMaxLength = new NefFile() + { + Script = new byte[ApplicationEngine.MaxContractLength - 1], + ScriptHash = new byte[ApplicationEngine.MaxContractLength - 1].ToScriptHash(), + Compiler = "", + Version = new Version(1, 2, 3, 4) + }; + script_exceedMaxLength.CheckSum = NefFile.ComputeChecksum(nef); + Assert.ThrowsException(() => engine.CreateContract(script_exceedMaxLength.ToArray(), manifest.ToJson().ToByteArray(true))); + engine = GetEngine(false, true, gas: 2000_00000000); + Assert.ThrowsException(() => engine.CreateContract(script_exceedMaxLength.ToArray(), manifest.ToJson().ToByteArray(true))); var script_zeroLength = new byte[] { }; Assert.ThrowsException(() => engine.CreateContract(script_zeroLength, manifest.ToJson().ToByteArray(true))); var manifest_zeroLength = new byte[] { }; - Assert.ThrowsException(() => engine.CreateContract(script, manifest_zeroLength)); + Assert.ThrowsException(() => engine.CreateContract(nefFile, manifest_zeroLength)); - manifest.Abi.Hash = script.ToScriptHash(); - engine.CreateContract(script, manifest.ToJson().ToByteArray(false)); + manifest = TestUtils.CreateDefaultManifest(nefFile.ToScriptHash()); + engine.CreateContract(nefFile, manifest.ToJson().ToByteArray(false)); var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); snapshot.Contracts.Add(state.ScriptHash, state); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0); engine.LoadScript(new byte[] { 0x01 }); - Assert.ThrowsException(() => engine.CreateContract(state.Script, manifest.ToJson().ToByteArray(false))); + + Assert.ThrowsException(() => engine.CreateContract(nefFile, manifest.ToJson().ToByteArray(false))); } [TestMethod] public void TestContract_Update() { var engine = GetEngine(false, true); - var script = new byte[] { 0x01 }; - Assert.ThrowsException(() => engine.UpdateContract(script, new byte[0])); + var nef = new NefFile() + { + Script = new byte[] { 0x01 }, + ScriptHash = new byte[] { 0x01 }.ToScriptHash(), + Compiler = "", + Version = new Version(1, 2, 3, 4) + }; + nef.CheckSum = NefFile.ComputeChecksum(nef); + var nefFile = nef.ToArray(); + Assert.ThrowsException(() => engine.UpdateContract(nefFile, new byte[0])); - var manifest = TestUtils.CreateDefaultManifest(script.ToScriptHash()); + var manifest = TestUtils.CreateDefaultManifest(nefFile.ToScriptHash()); byte[] privkey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; KeyPair key = new KeyPair(privkey); ECPoint pubkey = key.PublicKey; - byte[] signature = Crypto.Sign(script.ToScriptHash().ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray()); + byte[] signature = Crypto.Sign(nefFile.ToScriptHash().ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray()); manifest.Groups = new ContractGroup[] { new ContractGroup() @@ -195,19 +221,40 @@ public void TestContract_Update() snapshot.Storages.Add(storageKey, storageItem); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(state.Script); - engine.UpdateContract(script, manifest.ToJson().ToByteArray(false)); + engine.UpdateContract(nefFile, manifest.ToJson().ToByteArray(false)); engine.Snapshot.Storages.Find(BitConverter.GetBytes(state.Id)).ToList().Count().Should().Be(1); } [TestMethod] public void TestContract_Update_Invalid() { + var nefFile = new NefFile() + { + Script = new byte[] { 0x01 }, + ScriptHash = new byte[] { 0x01 }.ToScriptHash(), + Version = new Version(1, 2, 3, 4), + Compiler = "" + }; + nefFile.CheckSum = NefFile.ComputeChecksum(nefFile); + var nef = nefFile.ToArray(); + var engine = GetEngine(false, true); Assert.ThrowsException(() => engine.UpdateContract(null, new byte[] { 0x01 })); - Assert.ThrowsException(() => engine.UpdateContract(new byte[] { 0x01 }, null)); + Assert.ThrowsException(() => engine.UpdateContract(nef, null)); Assert.ThrowsException(() => engine.UpdateContract(null, null)); - Assert.ThrowsException(() => engine.UpdateContract(new byte[0], new byte[] { 0x01 })); - Assert.ThrowsException(() => engine.UpdateContract(new byte[0], new byte[0])); + + nefFile = new NefFile() + { + Script = new byte[0], + ScriptHash = new byte[0].ToScriptHash(), + Version = new Version(1, 2, 3, 4), + Compiler = "" + }; + nefFile.CheckSum = NefFile.ComputeChecksum(nefFile); + nef = nefFile.ToArray(); + + Assert.ThrowsException(() => engine.UpdateContract(nef, new byte[] { 0x01 })); + Assert.ThrowsException(() => engine.UpdateContract(nef, new byte[0])); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index 85e74ef265..64130dbce2 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -52,6 +52,7 @@ public void Runtime_GetNotifications_Test() snapshot.Contracts.Add(scriptHash2, new ContractState() { Script = script.ToArray(), + ScriptHash = script.ToArray().ToScriptHash(), Manifest = TestUtils.CreateManifest(scriptHash2, "test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), }); } @@ -215,7 +216,8 @@ public void TestExecutionEngine_GetCallingScriptHash() var contract = new ContractState() { Manifest = TestUtils.CreateManifest(scriptA.ToArray().ToScriptHash(), "test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), - Script = scriptA.ToArray() + Script = scriptA.ToArray(), + ScriptHash = scriptA.ToArray().ToScriptHash() }; engine = GetEngine(true, true, false); engine.Snapshot.Contracts.Add(contract.ScriptHash, contract); @@ -700,26 +702,26 @@ public static void LogEvent(object sender, LogEventArgs args) tx.Script = new byte[] { 0x01, 0x02, 0x03 }; } - private static ApplicationEngine GetEngine(bool hasContainer = false, bool hasSnapshot = false, bool addScript = true) + private static ApplicationEngine GetEngine(bool hasContainer = false, bool hasSnapshot = false, bool addScript = true, long gas = 20_00000000) { var tx = TestUtils.GetTransaction(UInt160.Zero); - var snapshot = Blockchain.Singleton.GetSnapshot(); + var snapshot = Blockchain.Singleton.GetSnapshot().Clone(); ApplicationEngine engine; if (hasContainer && hasSnapshot) { - engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshot); + engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshot, gas); } else if (hasContainer && !hasSnapshot) { - engine = ApplicationEngine.Create(TriggerType.Application, tx, null); + engine = ApplicationEngine.Create(TriggerType.Application, tx, null, gas); } else if (!hasContainer && hasSnapshot) { - engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); + engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, gas); } else { - engine = ApplicationEngine.Create(TriggerType.Application, null, null); + engine = ApplicationEngine.Create(TriggerType.Application, null, null, gas); } if (addScript) { diff --git a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs index 1c3f430a45..e8121f65a7 100644 --- a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs @@ -149,6 +149,7 @@ public void TestVerifyWitnesses() snapshot3.Contracts.Add(UInt160.Zero, new ContractState() { Script = Array.Empty(), + ScriptHash = Array.Empty().ToScriptHash(), Manifest = TestUtils.CreateManifest(UInt160.Zero, "verify", ContractParameterType.Boolean, ContractParameterType.Signature), }); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header3, snapshot3, 100)); @@ -158,6 +159,7 @@ public void TestVerifyWitnesses() var contract = new ContractState() { Script = "11".HexToBytes(), // 17 PUSH1 + ScriptHash = "11".HexToBytes().ToScriptHash(), Manifest = TestUtils.CreateManifest(UInt160.Zero, "verify", ContractParameterType.Boolean, ContractParameterType.Signature), // Offset = 0 }; snapshot3.Contracts.Add(contract.ScriptHash, contract); diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index 654b686160..94389f96b4 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -327,6 +327,9 @@ public void System_Runtime_GetInvocationCounter() contractA = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(script.ToArray()).ToArray() }; contractB = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; contractC = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; + contractA.ScriptHash = contractA.Script.ToScriptHash(); + contractB.ScriptHash = contractB.Script.ToScriptHash(); + contractC.ScriptHash = contractC.Script.ToScriptHash(); // Init A,B,C contracts // First two drops is for drop method and arguments diff --git a/tests/neo.UnitTests/TestUtils.cs b/tests/neo.UnitTests/TestUtils.cs index 9e12f702ae..c4e7dd460a 100644 --- a/tests/neo.UnitTests/TestUtils.cs +++ b/tests/neo.UnitTests/TestUtils.cs @@ -114,6 +114,7 @@ internal static ContractState GetContract(string method = "test", int parameters { Id = 0x43000000, Script = new byte[] { 0x01, 0x01, 0x01, 0x01 }, + ScriptHash = new byte[] { 0x01, 0x01, 0x01, 0x01 }.ToScriptHash(), Manifest = CreateManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), method, ContractParameterType.Any, Enumerable.Repeat(ContractParameterType.Any, parametersCount).ToArray()) }; } From 95e29ba70a64e2af7b2fb0cc57e75a0d88a160ca Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 3 Nov 2020 13:09:41 +0100 Subject: [PATCH 02/42] Specify version --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index f786e8a9c3..208ee15cc2 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -47,6 +47,7 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) contract = new ContractState { Id = Snapshot.ContractId.GetAndChange().NextId++, + Version = 0, Script = nef.Script, ScriptHash = hash, Manifest = ContractManifest.Parse(manifest) @@ -96,12 +97,11 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) { if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); - var parsedManifest = ContractManifest.Parse(manifest); - if (!parsedManifest.IsValid(contract.ScriptHash)) + contract.Manifest = ContractManifest.Parse(manifest); + if (!contract.Manifest.IsValid(contract.ScriptHash)) throw new InvalidOperationException($"Invalid Manifest Hash: {contract.ScriptHash}"); if (!contract.HasStorage && Snapshot.Storages.Find(BitConverter.GetBytes(contract.Id)).Any()) throw new InvalidOperationException($"Contract Does Not Support Storage But Uses Storage"); - contract.Manifest = parsedManifest; } contract.Version++; // Increase the version if (nef != null) From b1de3b74fbbca8c42e6ed385e5bff037f815e0d1 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 6 Nov 2020 12:34:36 +0800 Subject: [PATCH 03/42] Update ContractState.cs --- src/neo/Ledger/ContractState.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index e2990811f8..3c88cfd7e0 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -13,13 +13,13 @@ namespace Neo.Ledger public class ContractState : ICloneable, ISerializable, IInteroperable { public int Id; + public uint Version; + public UInt160 ScriptHash; public byte[] Script; public ContractManifest Manifest; - public uint Version; public bool HasStorage => Manifest.Features.HasFlag(ContractFeatures.HasStorage); public bool Payable => Manifest.Features.HasFlag(ContractFeatures.Payable); - public UInt160 ScriptHash { get; set; } int ISerializable.Size => sizeof(int) + sizeof(uint) + UInt160.Length + Script.GetVarSize() + Manifest.Size; From ab16cea5a9acd97e64a6f0e460917634cd379f60 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 6 Nov 2020 13:30:04 +0800 Subject: [PATCH 04/42] Update ApplicationEngine.Contract.cs --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 208ee15cc2..1b6c9b2044 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -74,14 +74,14 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) if (nefFile != null && nefFile.Length > NefFile.MaxLength) throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); - NefFile nef = nefFile?.AsSerializable(); - AddGas(StoragePrice * (nef is null ? manifest.Length : nefFile.Length + (manifest?.Length ?? 0))); + AddGas(StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); var contract = Snapshot.Contracts.GetAndChange(CurrentScriptHash); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {CurrentScriptHash}"); - if (nef != null) + if (nefFile != null) { + NefFile nef = nefFile.AsSerializable(); if (nef.Script.Length == 0 || nef.Script.Length > MaxContractLength) throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); @@ -104,7 +104,7 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) throw new InvalidOperationException($"Contract Does Not Support Storage But Uses Storage"); } contract.Version++; // Increase the version - if (nef != null) + if (nefFile != null) { ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy"); if (md != null) From 9ada6b163643d56144ab8e5a5f5b714f06c742a4 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 6 Nov 2020 13:32:03 +0800 Subject: [PATCH 05/42] Update ApplicationEngine.Contract.cs --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 1b6c9b2044..95c9d96845 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -71,8 +71,6 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) protected internal void UpdateContract(byte[] nefFile, byte[] manifest) { if (nefFile is null && manifest is null) throw new ArgumentException(); - if (nefFile != null && nefFile.Length > NefFile.MaxLength) - throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); AddGas(StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); @@ -81,6 +79,9 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) if (nefFile != null) { + if (nefFile != null && nefFile.Length > NefFile.MaxLength) + throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); + NefFile nef = nefFile.AsSerializable(); if (nef.Script.Length == 0 || nef.Script.Length > MaxContractLength) throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); From 4fb82f14bece4eea2569e570bea3a5959ae9bf8f Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 6 Nov 2020 13:34:34 +0800 Subject: [PATCH 06/42] Update ApplicationEngine.Contract.cs --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 95c9d96845..8adb8953a5 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -79,7 +79,7 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) if (nefFile != null) { - if (nefFile != null && nefFile.Length > NefFile.MaxLength) + if (nefFile.Length == 0 || nefFile.Length > NefFile.MaxLength) throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); NefFile nef = nefFile.AsSerializable(); From 31a415388f7cbd2c037f85ee3f184aead784813a Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 7 Nov 2020 10:09:36 +0100 Subject: [PATCH 07/42] Change to ushort --- src/neo/Ledger/ContractState.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 3c88cfd7e0..5d36c05870 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -13,7 +13,7 @@ namespace Neo.Ledger public class ContractState : ICloneable, ISerializable, IInteroperable { public int Id; - public uint Version; + public ushort Version; public UInt160 ScriptHash; public byte[] Script; public ContractManifest Manifest; @@ -21,7 +21,7 @@ public class ContractState : ICloneable, ISerializable, IInterope public bool HasStorage => Manifest.Features.HasFlag(ContractFeatures.HasStorage); public bool Payable => Manifest.Features.HasFlag(ContractFeatures.Payable); - int ISerializable.Size => sizeof(int) + sizeof(uint) + UInt160.Length + Script.GetVarSize() + Manifest.Size; + int ISerializable.Size => sizeof(int) + sizeof(ushort) + UInt160.Length + Script.GetVarSize() + Manifest.Size; ContractState ICloneable.Clone() { @@ -38,7 +38,7 @@ ContractState ICloneable.Clone() void ISerializable.Deserialize(BinaryReader reader) { Id = reader.ReadInt32(); - Version = reader.ReadUInt32(); + Version = reader.ReadUInt16(); ScriptHash = reader.ReadSerializable(); Script = reader.ReadVarBytes(); Manifest = reader.ReadSerializable(); From b4ba71cd3bb98e6fff1489d390abda5e055c7507 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 7 Nov 2020 10:10:41 +0100 Subject: [PATCH 08/42] Return Id --- src/neo/Ledger/ContractState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 5d36c05870..be96ed17df 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -80,7 +80,7 @@ public JObject ToJson() public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new StackItem[] { ScriptHash.ToArray(), Script, Version, Manifest.ToString(), HasStorage, Payable }); + return new Array(referenceCounter, new StackItem[] { Id, Version, ScriptHash.ToArray(), Script, Manifest.ToString(), HasStorage, Payable }); } } } From 658a5976bd4d255aa040b0b9343c64ab2f420290 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 7 Nov 2020 10:15:00 +0100 Subject: [PATCH 09/42] Update ContractState.cs --- src/neo/Ledger/ContractState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index be96ed17df..c3e8d8a120 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -80,7 +80,7 @@ public JObject ToJson() public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new StackItem[] { Id, Version, ScriptHash.ToArray(), Script, Manifest.ToString(), HasStorage, Payable }); + return new Array(referenceCounter, new StackItem[] { Id, (int)Version, ScriptHash.ToArray(), Script, Manifest.ToString(), HasStorage, Payable }); } } } From be896c531d79747ce714c7c7e16c6e9f0e4f2411 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 7 Nov 2020 10:16:37 +0100 Subject: [PATCH 10/42] Remove hash_new check --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 8adb8953a5..32a8132c9e 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -86,13 +86,8 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) if (nef.Script.Length == 0 || nef.Script.Length > MaxContractLength) throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); - UInt160 hash_new = nefFile.ToScriptHash(); - if (hash_new.Equals(CurrentScriptHash) || Snapshot.Contracts.TryGet(hash_new) != null) - throw new InvalidOperationException($"Adding Contract Hash Already Exist: {hash_new}"); - - // Update script and script hash + // Update script contract.Script = nef.Script.ToArray(); - contract.ScriptHash = hash_new; } if (manifest != null) { From da309c270ebc40dfaa6dddad37ef53dd3037a90c Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 7 Nov 2020 10:17:20 +0100 Subject: [PATCH 11/42] Update ApplicationEngine.Contract.cs --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 32a8132c9e..52c8f5d086 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -87,7 +87,7 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); // Update script - contract.Script = nef.Script.ToArray(); + contract.Script = nef.Script; } if (manifest != null) { From 983586254bbd0115918209b056bb3649ea960937 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 7 Nov 2020 10:31:38 +0100 Subject: [PATCH 12/42] Fix UT --- tests/neo.UnitTests/Ledger/UT_ContractState.cs | 2 +- .../neo.UnitTests/SmartContract/UT_InteropService.NEO.cs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/neo.UnitTests/Ledger/UT_ContractState.cs b/tests/neo.UnitTests/Ledger/UT_ContractState.cs index ce8c035a56..83eb9de2f7 100644 --- a/tests/neo.UnitTests/Ledger/UT_ContractState.cs +++ b/tests/neo.UnitTests/Ledger/UT_ContractState.cs @@ -85,7 +85,7 @@ public void TestDeserialize() public void TestGetSize() { ISerializable newContract = contract; - newContract.Size.Should().Be(289); + newContract.Size.Should().Be(287); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 9260a47e80..d633022ad6 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -193,7 +193,10 @@ public void TestContract_Update() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; KeyPair key = new KeyPair(privkey); ECPoint pubkey = key.PublicKey; - byte[] signature = Crypto.Sign(nefFile.ToScriptHash().ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray()); + var snapshot = Blockchain.Singleton.GetSnapshot(); + var state = TestUtils.GetContract(); + state.Manifest.Features = ContractFeatures.HasStorage; + byte[] signature = Crypto.Sign(state.ScriptHash.ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray()); manifest.Groups = new ContractGroup[] { new ContractGroup() @@ -203,9 +206,6 @@ public void TestContract_Update() } }; manifest.Features = ContractFeatures.HasStorage; - var snapshot = Blockchain.Singleton.GetSnapshot(); - var state = TestUtils.GetContract(); - state.Manifest.Features = ContractFeatures.HasStorage; var storageItem = new StorageItem { Value = new byte[] { 0x01 }, @@ -221,6 +221,7 @@ public void TestContract_Update() snapshot.Storages.Add(storageKey, storageItem); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(state.Script); + manifest.Abi.Hash = state.ScriptHash; engine.UpdateContract(nefFile, manifest.ToJson().ToByteArray(false)); engine.Snapshot.Storages.Find(BitConverter.GetBytes(state.Id)).ToList().Count().Should().Be(1); } From 9d4f65c1456523c94e96382acd370900fd288851 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 12 Nov 2020 18:35:21 +0100 Subject: [PATCH 13/42] Remove Hash from ABI and change hash strategy --- .../ApplicationEngine.Contract.cs | 17 +++++++- .../SmartContract/Callbacks/MethodCallback.cs | 2 +- src/neo/SmartContract/Manifest/ContractAbi.cs | 8 ---- .../Manifest/ContractManifest.cs | 11 ++--- .../Manifest/ContractPermission.cs | 5 ++- .../SmartContract/Native/NativeContract.cs | 1 - .../neo.UnitTests/Ledger/UT_ContractState.cs | 4 +- .../Callbacks/UT_MethodCallback.cs | 1 - .../Manifest/UT_ContractManifest.cs | 41 ++++++++----------- .../Manifest/UT_ContractPermission.cs | 16 ++++---- .../SmartContract/UT_InteropService.NEO.cs | 10 ++--- .../SmartContract/UT_InteropService.cs | 4 +- .../SmartContract/UT_SmartContractHelper.cs | 4 +- .../SmartContract/UT_Syscalls.cs | 6 +-- tests/neo.UnitTests/TestUtils.cs | 11 +++-- 15 files changed, 65 insertions(+), 76 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 15151f09d1..9414292c70 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -28,6 +28,19 @@ partial class ApplicationEngine /// public static readonly InteropDescriptor System_Contract_CreateStandardAccount = Register("System.Contract.CreateStandardAccount", nameof(CreateStandardAccount), 0_00010000, CallFlags.None, true); + private UInt160 ContractHash(NefFile nef) + { + if (!(ScriptContainer is Transaction tx)) + throw new InvalidOperationException(); + + using var script = new ScriptBuilder(); + script.Emit(OpCode.ABORT); + script.EmitPush(tx.Sender); + + script.EmitPush(nef.ScriptHash); + return script.ToArray().ToScriptHash(); + } + protected internal void CreateContract(byte[] nefFile, byte[] manifest) { if (nefFile.Length == 0 || nefFile.Length > NefFile.MaxLength) @@ -41,7 +54,7 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) if (nef.Script.Length == 0 || nef.Script.Length > MaxContractLength) throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); - UInt160 hash = nefFile.ToScriptHash(); + UInt160 hash = ContractHash(nef); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract != null) throw new InvalidOperationException($"Contract Already Exists: {hash}"); contract = new ContractState @@ -138,7 +151,7 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg if (md is null) throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}"); ContractManifest currentManifest = Snapshot.Contracts.TryGet(CurrentScriptHash)?.Manifest; - if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method)) + if (currentManifest != null && !currentManifest.CanCall(contractHash, contract.Manifest, method)) throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contractHash} From Contract {CurrentScriptHash}"); CallContractInternal(contract, md, args, flags, convention); diff --git a/src/neo/SmartContract/Callbacks/MethodCallback.cs b/src/neo/SmartContract/Callbacks/MethodCallback.cs index 578570a857..7a32a0daaa 100644 --- a/src/neo/SmartContract/Callbacks/MethodCallback.cs +++ b/src/neo/SmartContract/Callbacks/MethodCallback.cs @@ -20,7 +20,7 @@ public MethodCallback(ApplicationEngine engine, UInt160 hash, string method) if (method.StartsWith('_')) throw new ArgumentException(); this.contract = engine.Snapshot.Contracts[hash]; ContractManifest currentManifest = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash)?.Manifest; - if (currentManifest != null && !currentManifest.CanCall(this.contract.Manifest, method)) + if (currentManifest != null && !currentManifest.CanCall(hash, this.contract.Manifest, method)) throw new InvalidOperationException(); this.method = this.contract.Manifest.Abi.Methods.First(p => p.Name == method); } diff --git a/src/neo/SmartContract/Manifest/ContractAbi.cs b/src/neo/SmartContract/Manifest/ContractAbi.cs index 6a5e559b62..a6cd7d0af1 100644 --- a/src/neo/SmartContract/Manifest/ContractAbi.cs +++ b/src/neo/SmartContract/Manifest/ContractAbi.cs @@ -11,11 +11,6 @@ public class ContractAbi { private IReadOnlyDictionary methodDictionary; - /// - /// Hash is the script hash of the contract. It is encoded as a hexadecimal string in big-endian. - /// - public UInt160 Hash { get; set; } - /// /// Methods is an array of Method objects which describe the details of each method in the contract. /// @@ -30,7 +25,6 @@ public ContractAbi Clone() { return new ContractAbi { - Hash = Hash, Methods = Methods.Select(p => p.Clone()).ToArray(), Events = Events.Select(p => p.Clone()).ToArray() }; @@ -45,7 +39,6 @@ public static ContractAbi FromJson(JObject json) { return new ContractAbi { - Hash = UInt160.Parse(json["hash"].AsString()), Methods = ((JArray)json["methods"]).Select(u => ContractMethodDescriptor.FromJson(u)).ToArray(), Events = ((JArray)json["events"]).Select(u => ContractEventDescriptor.FromJson(u)).ToArray() }; @@ -61,7 +54,6 @@ public ContractMethodDescriptor GetMethod(string name) public JObject ToJson() { var json = new JObject(); - json["hash"] = Hash.ToString(); json["methods"] = new JArray(Methods.Select(u => u.ToJson()).ToArray()); json["events"] = new JArray(Events.Select(u => u.ToJson()).ToArray()); return json; diff --git a/src/neo/SmartContract/Manifest/ContractManifest.cs b/src/neo/SmartContract/Manifest/ContractManifest.cs index 85b538f693..7a80fe3cb3 100644 --- a/src/neo/SmartContract/Manifest/ContractManifest.cs +++ b/src/neo/SmartContract/Manifest/ContractManifest.cs @@ -29,11 +29,6 @@ public int Size } } - /// - /// Contract hash - /// - public UInt160 Hash => Abi.Hash; - /// /// A group represents a set of mutually trusted contracts. A contract will trust and allow any contract in the same group to invoke it, and the user interface will not give any warnings. /// @@ -74,12 +69,13 @@ public int Size /// /// Return true if is allowed /// + /// Hash /// Manifest /// Method /// Return true or false - public bool CanCall(ContractManifest manifest, string method) + public bool CanCall(UInt160 hash, ContractManifest manifest, string method) { - return Permissions.Any(u => u.IsAllowed(manifest, method)); + return Permissions.Any(u => u.IsAllowed(hash, manifest, method)); } /// @@ -171,7 +167,6 @@ private void DeserializeFromJson(JObject json) /// Return true or false public bool IsValid(UInt160 hash) { - if (!Abi.Hash.Equals(hash)) return false; return Groups.All(u => u.IsValid(hash)); } } diff --git a/src/neo/SmartContract/Manifest/ContractPermission.cs b/src/neo/SmartContract/Manifest/ContractPermission.cs index f4084eaf0f..6f590b92cc 100644 --- a/src/neo/SmartContract/Manifest/ContractPermission.cs +++ b/src/neo/SmartContract/Manifest/ContractPermission.cs @@ -64,14 +64,15 @@ public JObject ToJson() /// /// Return true if is allowed /// + /// hash /// The manifest of which contract we are calling /// Method /// Return true or false - public bool IsAllowed(ContractManifest manifest, string method) + public bool IsAllowed(UInt160 hash, ContractManifest manifest, string method) { if (Contract.IsHash) { - if (!Contract.Hash.Equals(manifest.Hash)) return false; + if (!Contract.Hash.Equals(hash)) return false; } else if (Contract.IsGroup) { diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index ae670d74a2..378efb8531 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -66,7 +66,6 @@ protected NativeContract() SupportedStandards = new string[0], Abi = new ContractAbi() { - Hash = Hash, Events = System.Array.Empty(), Methods = descriptors.ToArray() }, diff --git a/tests/neo.UnitTests/Ledger/UT_ContractState.cs b/tests/neo.UnitTests/Ledger/UT_ContractState.cs index cfb6f221dc..6cf413d835 100644 --- a/tests/neo.UnitTests/Ledger/UT_ContractState.cs +++ b/tests/neo.UnitTests/Ledger/UT_ContractState.cs @@ -19,7 +19,7 @@ public class UT_ContractState [TestInitialize] public void TestSetup() { - manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); + manifest = TestUtils.CreateDefaultManifest(); contract = new ContractState { Script = script, @@ -73,7 +73,7 @@ public void TestDeserialize() public void TestGetSize() { ISerializable newContract = contract; - newContract.Size.Should().Be(287); + newContract.Size.Should().Be(188); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs index 012740d5a7..b4f23f56a8 100644 --- a/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs +++ b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs @@ -43,7 +43,6 @@ public void GetHashData() Script = new byte[] { 1, 2, 3 }, ScriptHash = new byte[] { 1, 2, 3 }.ToScriptHash() }; - contract.Manifest.Abi.Hash = contract.ScriptHash; engine.LoadScript(contract.Script); snapshot.Contracts.Add(contract.ScriptHash, contract); diff --git a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs index 44c621870f..802dfaae58 100644 --- a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs +++ b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs @@ -11,22 +11,22 @@ public class UT_ContractManifest [TestMethod] public void ParseFromJson_Default() { - var json = @"{""groups"":[],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[],""extra"":null}"; + var json = @"{""groups"":[],""supportedstandards"":[],""abi"":{""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - Assert.AreEqual(manifest.ToString(), TestUtils.CreateDefaultManifest(UInt160.Zero).ToString()); + Assert.AreEqual(manifest.ToString(), TestUtils.CreateDefaultManifest().ToString()); Assert.IsTrue(manifest.IsValid(UInt160.Zero)); } [TestMethod] public void ParseFromJson_Permissions() { - var json = @"{""groups"":[],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""0x0000000000000000000000000000000000000000"",""methods"":[""method1"",""method2""]}],""trusts"":[],""safemethods"":[],""extra"":null}"; + var json = @"{""groups"":[],""supportedstandards"":[],""abi"":{""methods"":[],""events"":[]},""permissions"":[{""contract"":""0x0000000000000000000000000000000000000000"",""methods"":[""method1"",""method2""]}],""trusts"":[],""safemethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - var check = TestUtils.CreateDefaultManifest(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(); check.Permissions = new[] { new ContractPermission() @@ -41,11 +41,11 @@ public void ParseFromJson_Permissions() [TestMethod] public void ParseFromJson_SafeMethods() { - var json = @"{""groups"":[],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[""balanceOf""],""extra"":null}"; + var json = @"{""groups"":[],""supportedstandards"":[],""abi"":{""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[""balanceOf""],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - var check = TestUtils.CreateDefaultManifest(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(); check.SafeMethods = WildcardContainer.Create("balanceOf"); Assert.AreEqual(manifest.ToString(), check.ToString()); } @@ -53,11 +53,11 @@ public void ParseFromJson_SafeMethods() [TestMethod] public void ParseFromJson_Trust() { - var json = @"{""groups"":[],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[""0x0000000000000000000000000000000000000001""],""safemethods"":[],""extra"":null}"; + var json = @"{""groups"":[],""supportedstandards"":[],""abi"":{""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[""0x0000000000000000000000000000000000000001""],""safemethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - var check = TestUtils.CreateDefaultManifest(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(); check.Trusts = WildcardContainer.Create(UInt160.Parse("0x0000000000000000000000000000000000000001")); Assert.AreEqual(manifest.ToString(), check.ToString()); } @@ -65,11 +65,11 @@ public void ParseFromJson_Trust() [TestMethod] public void ParseFromJson_Groups() { - var json = @"{""groups"":[{""pubkey"":""03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"",""signature"":""QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==""}],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[],""extra"":null}"; + var json = @"{""groups"":[{""pubkey"":""03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"",""signature"":""QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==""}],""supportedstandards"":[],""abi"":{""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[],""extra"":null}"; var manifest = ContractManifest.Parse(json); Assert.AreEqual(manifest.ToString(), json); - var check = TestUtils.CreateDefaultManifest(UInt160.Zero); + var check = TestUtils.CreateDefaultManifest(); check.Groups = new ContractGroup[] { new ContractGroup() { PubKey = ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1), Signature = "41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141".HexToBytes() } }; Assert.AreEqual(manifest.ToString(), check.ToString()); } @@ -89,28 +89,21 @@ public void TestDeserializeAndSerialize() MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); BinaryReader reader = new BinaryReader(stream); - var expected = TestUtils.CreateDefaultManifest(UInt160.Zero); + var expected = TestUtils.CreateDefaultManifest(); expected.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); expected.Serialize(writer); stream.Seek(0, SeekOrigin.Begin); - var actual = TestUtils.CreateDefaultManifest(UInt160.Zero); + var actual = TestUtils.CreateDefaultManifest(); actual.Deserialize(reader); Assert.AreEqual(expected.SafeMethods.ToString(), actual.SafeMethods.ToString()); Assert.AreEqual(expected.SafeMethods.Count, 1); } - [TestMethod] - public void TestGetHash() - { - var temp = TestUtils.CreateDefaultManifest(UInt160.Zero); - Assert.AreEqual(temp.Abi.Hash, temp.Hash); - } - [TestMethod] public void TestGetSize() { - var temp = TestUtils.CreateDefaultManifest(UInt160.Zero); - Assert.AreEqual(212, temp.Size); + var temp = TestUtils.CreateDefaultManifest(); + Assert.AreEqual(160, temp.Size); } [TestMethod] @@ -123,15 +116,15 @@ public void TestGenerator() [TestMethod] public void TestCanCall() { - var temp = TestUtils.CreateDefaultManifest(UInt160.Zero); + var temp = TestUtils.CreateDefaultManifest(); temp.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); - Assert.AreEqual(true, temp.CanCall(TestUtils.CreateDefaultManifest(UInt160.Zero), "AAA")); + Assert.AreEqual(true, temp.CanCall(UInt160.Zero, TestUtils.CreateDefaultManifest(), "AAA")); } [TestMethod] public void TestClone() { - var expected = TestUtils.CreateDefaultManifest(UInt160.Zero); + var expected = TestUtils.CreateDefaultManifest(); expected.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); var actual = expected.Clone(); Assert.AreEqual(actual.ToString(), expected.ToString()); diff --git a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs index 8e147f0117..f662af0496 100644 --- a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs +++ b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs @@ -11,27 +11,27 @@ public class UT_ContractPermission [TestMethod] public void TestIsAllowed() { - ContractManifest contractManifest1 = TestUtils.CreateDefaultManifest(UInt160.Zero); + ContractManifest contractManifest1 = TestUtils.CreateDefaultManifest(); ContractPermission contractPermission1 = ContractPermission.DefaultPermission; contractPermission1.Contract = ContractPermissionDescriptor.Create(UInt160.Zero); - Assert.AreEqual(true, contractPermission1.IsAllowed(contractManifest1, "AAA")); + Assert.AreEqual(true, contractPermission1.IsAllowed(UInt160.Zero, contractManifest1, "AAA")); contractPermission1.Contract = ContractPermissionDescriptor.CreateWildcard(); - ContractManifest contractManifest2 = TestUtils.CreateDefaultManifest(UInt160.Zero); + ContractManifest contractManifest2 = TestUtils.CreateDefaultManifest(); ContractPermission contractPermission2 = ContractPermission.DefaultPermission; contractPermission2.Contract = ContractPermissionDescriptor.Create(UInt160.Parse("0x0000000000000000000000000000000000000001")); - Assert.AreEqual(false, contractPermission2.IsAllowed(contractManifest2, "AAA")); + Assert.AreEqual(false, contractPermission2.IsAllowed(UInt160.Zero, contractManifest2, "AAA")); contractPermission2.Contract = ContractPermissionDescriptor.CreateWildcard(); Random random3 = new Random(); byte[] privateKey3 = new byte[32]; random3.NextBytes(privateKey3); ECPoint publicKey3 = ECCurve.Secp256r1.G * privateKey3; - ContractManifest contractManifest3 = TestUtils.CreateDefaultManifest(UInt160.Zero); + ContractManifest contractManifest3 = TestUtils.CreateDefaultManifest(); contractManifest3.Groups = new ContractGroup[] { new ContractGroup() { PubKey = publicKey3 } }; ContractPermission contractPermission3 = ContractPermission.DefaultPermission; contractPermission3.Contract = ContractPermissionDescriptor.Create(publicKey3); - Assert.AreEqual(true, contractPermission3.IsAllowed(contractManifest3, "AAA")); + Assert.AreEqual(true, contractPermission3.IsAllowed(UInt160.Zero, contractManifest3, "AAA")); contractPermission3.Contract = ContractPermissionDescriptor.CreateWildcard(); Random random4 = new Random(); @@ -41,11 +41,11 @@ public void TestIsAllowed() byte[] privateKey42 = new byte[32]; random4.NextBytes(privateKey42); ECPoint publicKey42 = ECCurve.Secp256r1.G * privateKey42; - ContractManifest contractManifest4 = TestUtils.CreateDefaultManifest(UInt160.Zero); + ContractManifest contractManifest4 = TestUtils.CreateDefaultManifest(); contractManifest4.Groups = new ContractGroup[] { new ContractGroup() { PubKey = publicKey42 } }; ContractPermission contractPermission4 = ContractPermission.DefaultPermission; contractPermission4.Contract = ContractPermissionDescriptor.Create(publicKey41); - Assert.AreEqual(false, contractPermission4.IsAllowed(contractManifest4, "AAA")); + Assert.AreEqual(false, contractPermission4.IsAllowed(UInt160.Zero, contractManifest4, "AAA")); contractPermission4.Contract = ContractPermissionDescriptor.CreateWildcard(); } } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 5edabed588..4a8675eb26 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -140,7 +140,7 @@ public void TestContract_Create() var engine = GetEngine(false, true); Assert.ThrowsException(() => engine.CreateContract(nefFile, new byte[ContractManifest.MaxLength + 1])); - var manifest = TestUtils.CreateDefaultManifest(nef.ScriptHash); + var manifest = TestUtils.CreateDefaultManifest(); Assert.ThrowsException(() => engine.CreateContract(nefFile, manifest.ToJson().ToByteArray(false))); var script_exceedMaxLength = new NefFile() @@ -152,7 +152,7 @@ public void TestContract_Create() }; script_exceedMaxLength.CheckSum = NefFile.ComputeChecksum(nef); Assert.ThrowsException(() => engine.CreateContract(script_exceedMaxLength.ToArray(), manifest.ToJson().ToByteArray(true))); - engine = GetEngine(false, true, gas: 2000_00000000); + engine = GetEngine(true, true, gas: 2000_00000000); Assert.ThrowsException(() => engine.CreateContract(script_exceedMaxLength.ToArray(), manifest.ToJson().ToByteArray(true))); var script_zeroLength = new byte[] { }; @@ -161,7 +161,7 @@ public void TestContract_Create() var manifest_zeroLength = new byte[] { }; Assert.ThrowsException(() => engine.CreateContract(nefFile, manifest_zeroLength)); - manifest = TestUtils.CreateDefaultManifest(nefFile.ToScriptHash()); + manifest = TestUtils.CreateDefaultManifest(); engine.CreateContract(nefFile, manifest.ToJson().ToByteArray(false)); var snapshot = Blockchain.Singleton.GetSnapshot(); @@ -188,14 +188,13 @@ public void TestContract_Update() var nefFile = nef.ToArray(); Assert.ThrowsException(() => engine.UpdateContract(nefFile, new byte[0])); - var manifest = TestUtils.CreateDefaultManifest(nefFile.ToScriptHash()); + var manifest = TestUtils.CreateDefaultManifest(); byte[] privkey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; KeyPair key = new KeyPair(privkey); ECPoint pubkey = key.PublicKey; var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); - state.Manifest.Features = ContractFeatures.HasStorage; byte[] signature = Crypto.Sign(state.ScriptHash.ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray()); manifest.Groups = new ContractGroup[] { @@ -221,7 +220,6 @@ public void TestContract_Update() snapshot.Storages.Add(storageKey, storageItem); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(state.Script); - manifest.Abi.Hash = state.ScriptHash; engine.UpdateContract(nefFile, manifest.ToJson().ToByteArray(false)); engine.Snapshot.Storages.Find(BitConverter.GetBytes(state.Id)).ToList().Count().Should().Be(1); } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index 530cad52ab..bac084e80f 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -53,7 +53,7 @@ public void Runtime_GetNotifications_Test() { Script = script.ToArray(), ScriptHash = script.ToArray().ToScriptHash(), - Manifest = TestUtils.CreateManifest(scriptHash2, "test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), + Manifest = TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), }); } @@ -215,7 +215,7 @@ public void TestExecutionEngine_GetCallingScriptHash() var contract = new ContractState() { - Manifest = TestUtils.CreateManifest(scriptA.ToArray().ToScriptHash(), "test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), + Manifest = TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), Script = scriptA.ToArray(), ScriptHash = scriptA.ToArray().ToScriptHash() }; diff --git a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs index e8121f65a7..90cf4e3b7b 100644 --- a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs @@ -150,7 +150,7 @@ public void TestVerifyWitnesses() { Script = Array.Empty(), ScriptHash = Array.Empty().ToScriptHash(), - Manifest = TestUtils.CreateManifest(UInt160.Zero, "verify", ContractParameterType.Boolean, ContractParameterType.Signature), + Manifest = TestUtils.CreateManifest("verify", ContractParameterType.Boolean, ContractParameterType.Signature), }); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header3, snapshot3, 100)); @@ -160,7 +160,7 @@ public void TestVerifyWitnesses() { Script = "11".HexToBytes(), // 17 PUSH1 ScriptHash = "11".HexToBytes().ToScriptHash(), - Manifest = TestUtils.CreateManifest(UInt160.Zero, "verify", ContractParameterType.Boolean, ContractParameterType.Signature), // Offset = 0 + Manifest = TestUtils.CreateManifest("verify", ContractParameterType.Boolean, ContractParameterType.Signature), // Offset = 0 }; snapshot3.Contracts.Add(contract.ScriptHash, contract); var tx = new Extensions.Nep5NativeContractExtensions.ManualWitness(contract.ScriptHash) diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index 39c220d408..e05be8815a 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -337,9 +337,9 @@ public void System_Runtime_GetInvocationCounter() contracts.Delete(contractA.ScriptHash); contracts.Delete(contractB.ScriptHash); contracts.Delete(contractC.ScriptHash); - contractA.Manifest = TestUtils.CreateManifest(contractA.ScriptHash, "dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); - contractB.Manifest = TestUtils.CreateManifest(contractA.ScriptHash, "dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); - contractC.Manifest = TestUtils.CreateManifest(contractA.ScriptHash, "dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); + contractA.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); + contractB.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); + contractC.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); contracts.Add(contractA.ScriptHash, contractA); contracts.Add(contractB.ScriptHash, contractB); contracts.Add(contractC.ScriptHash, contractC); diff --git a/tests/neo.UnitTests/TestUtils.cs b/tests/neo.UnitTests/TestUtils.cs index 17daae8227..b3788de26a 100644 --- a/tests/neo.UnitTests/TestUtils.cs +++ b/tests/neo.UnitTests/TestUtils.cs @@ -18,7 +18,7 @@ public static class TestUtils { public static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism - public static ContractManifest CreateDefaultManifest(UInt160 hash) + public static ContractManifest CreateDefaultManifest() { return new ContractManifest() { @@ -26,7 +26,6 @@ public static ContractManifest CreateDefaultManifest(UInt160 hash) SupportedStandards = Array.Empty(), Abi = new ContractAbi() { - Hash = hash, Events = new ContractEventDescriptor[0], Methods = new ContractMethodDescriptor[0] }, @@ -37,9 +36,9 @@ public static ContractManifest CreateDefaultManifest(UInt160 hash) }; } - public static ContractManifest CreateManifest(UInt160 hash, string method, ContractParameterType returnType, params ContractParameterType[] parameterTypes) + public static ContractManifest CreateManifest(string method, ContractParameterType returnType, params ContractParameterType[] parameterTypes) { - ContractManifest manifest = CreateDefaultManifest(hash); + ContractManifest manifest = CreateDefaultManifest(); manifest.Abi.Methods = new ContractMethodDescriptor[] { new ContractMethodDescriptor() @@ -114,7 +113,7 @@ internal static ContractState GetContract(string method = "test", int parameters Id = 0x43000000, Script = new byte[] { 0x01, 0x01, 0x01, 0x01 }, ScriptHash = new byte[] { 0x01, 0x01, 0x01, 0x01 }.ToScriptHash(), - Manifest = CreateManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), method, ContractParameterType.Any, Enumerable.Repeat(ContractParameterType.Any, parametersCount).ToArray()) + Manifest = CreateManifest(method, ContractParameterType.Any, Enumerable.Repeat(ContractParameterType.Any, parametersCount).ToArray()) }; } @@ -124,7 +123,7 @@ internal static ContractState GetContract(byte[] script) { Id = 1, Script = script, - Manifest = CreateDefaultManifest(script.ToScriptHash()) + Manifest = CreateDefaultManifest() }; } From ca933909b25003e2719b4b98c67af7a0ae2ff47e Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 12 Nov 2020 18:39:09 +0100 Subject: [PATCH 14/42] Clean code --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 2 +- src/neo/SmartContract/ApplicationEngine.Native.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 9414292c70..fac03520bc 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -36,8 +36,8 @@ private UInt160 ContractHash(NefFile nef) using var script = new ScriptBuilder(); script.Emit(OpCode.ABORT); script.EmitPush(tx.Sender); - script.EmitPush(nef.ScriptHash); + return script.ToArray().ToScriptHash(); } diff --git a/src/neo/SmartContract/ApplicationEngine.Native.cs b/src/neo/SmartContract/ApplicationEngine.Native.cs index 9bb0c3a91a..5b6f4ecf9e 100644 --- a/src/neo/SmartContract/ApplicationEngine.Native.cs +++ b/src/neo/SmartContract/ApplicationEngine.Native.cs @@ -19,7 +19,7 @@ protected internal void DeployNativeContracts() { Id = contract.Id, Script = contract.Script, - ScriptHash = contract.Hash, // Not NefHash here + ScriptHash = contract.Hash, // Use the native hash Manifest = contract.Manifest }); contract.Initialize(this); From 6a7912c150bde83528be7e7847318eedd2e5348d Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 12 Nov 2020 18:42:57 +0100 Subject: [PATCH 15/42] Remove MaxLength --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 4 ++-- src/neo/SmartContract/NefFile.cs | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index fac03520bc..ba65aaf8bb 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -43,7 +43,7 @@ private UInt160 ContractHash(NefFile nef) protected internal void CreateContract(byte[] nefFile, byte[] manifest) { - if (nefFile.Length == 0 || nefFile.Length > NefFile.MaxLength) + if (nefFile.Length == 0) throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); @@ -92,7 +92,7 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) if (nefFile != null) { - if (nefFile.Length == 0 || nefFile.Length > NefFile.MaxLength) + if (nefFile.Length == 0) throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); NefFile nef = nefFile.AsSerializable(); diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index 989c75a370..daa5d3b7f8 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -57,8 +57,6 @@ public class NefFile : ISerializable (sizeof(int) * 4) + // Version UInt160.Length; // ScriptHash - public static readonly int MaxLength = HeaderSize + sizeof(uint) + IO.Helper.GetVarSize(1024 * 1024) + (1024 * 1024); - public int Size => HeaderSize + // Header sizeof(uint) + // Checksum From a2618a510befe7d98196a79b95238d8fc4bcb8f3 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 13 Nov 2020 10:19:13 +0100 Subject: [PATCH 16/42] Change script size verification to nefFile --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 6 ++---- src/neo/SmartContract/NefFile.cs | 4 +++- tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index ba65aaf8bb..33a4383a0f 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -13,8 +13,6 @@ namespace Neo.SmartContract { partial class ApplicationEngine { - public const int MaxContractLength = 1024 * 1024; - public static readonly InteropDescriptor System_Contract_Create = Register("System.Contract.Create", nameof(CreateContract), 0, CallFlags.AllowModifyStates, false); public static readonly InteropDescriptor System_Contract_Update = Register("System.Contract.Update", nameof(UpdateContract), 0, CallFlags.AllowModifyStates, false); public static readonly InteropDescriptor System_Contract_Destroy = Register("System.Contract.Destroy", nameof(DestroyContract), 0_01000000, CallFlags.AllowModifyStates, false); @@ -51,7 +49,7 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) AddGas(StoragePrice * (nefFile.Length + manifest.Length)); NefFile nef = nefFile.AsSerializable(); - if (nef.Script.Length == 0 || nef.Script.Length > MaxContractLength) + if (nef.Script.Length == 0) throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); UInt160 hash = ContractHash(nef); @@ -96,7 +94,7 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); NefFile nef = nefFile.AsSerializable(); - if (nef.Script.Length == 0 || nef.Script.Length > MaxContractLength) + if (nef.Script.Length == 0) throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); // Update script diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index daa5d3b7f8..f8213d7cb4 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -51,6 +51,8 @@ public class NefFile : ISerializable /// public byte[] Script { get; set; } + public const int MaxScriptLength = 1024 * 1024; + private const int HeaderSize = sizeof(uint) + // Magic 32 + // Compiler @@ -100,7 +102,7 @@ public void Deserialize(BinaryReader reader) throw new FormatException("CRC verification fail"); } - Script = reader.ReadVarBytes(1024 * 1024); + Script = reader.ReadVarBytes(MaxScriptLength); if (Script.ToScriptHash() != ScriptHash) { diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 4a8675eb26..3f19198df8 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -145,8 +145,8 @@ public void TestContract_Create() var script_exceedMaxLength = new NefFile() { - Script = new byte[ApplicationEngine.MaxContractLength - 1], - ScriptHash = new byte[ApplicationEngine.MaxContractLength - 1].ToScriptHash(), + Script = new byte[NefFile.MaxScriptLength - 1], + ScriptHash = new byte[NefFile.MaxScriptLength - 1].ToScriptHash(), Compiler = "", Version = new Version(1, 2, 3, 4) }; From c9d024ca2da748030c994141825ef874fcdfdc49 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 13 Nov 2020 12:44:06 +0100 Subject: [PATCH 17/42] Rename Version to UpdateCounter --- src/neo/Ledger/ContractState.cs | 14 +++++++------- .../SmartContract/ApplicationEngine.Contract.cs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 57ad84b69b..54cb0c89d7 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -13,7 +13,7 @@ namespace Neo.Ledger public class ContractState : ICloneable, ISerializable, IInteroperable { public int Id; - public ushort Version; + public ushort UpdateCounter; public UInt160 ScriptHash; public byte[] Script; public ContractManifest Manifest; @@ -25,7 +25,7 @@ ContractState ICloneable.Clone() return new ContractState { Id = Id, - Version = Version, + UpdateCounter = UpdateCounter, ScriptHash = ScriptHash, Script = Script, Manifest = Manifest.Clone() @@ -35,7 +35,7 @@ ContractState ICloneable.Clone() void ISerializable.Deserialize(BinaryReader reader) { Id = reader.ReadInt32(); - Version = reader.ReadUInt16(); + UpdateCounter = reader.ReadUInt16(); ScriptHash = reader.ReadSerializable(); Script = reader.ReadVarBytes(); Manifest = reader.ReadSerializable(); @@ -44,7 +44,7 @@ void ISerializable.Deserialize(BinaryReader reader) void ICloneable.FromReplica(ContractState replica) { Id = replica.Id; - Version = replica.Version; + UpdateCounter = replica.UpdateCounter; ScriptHash = replica.ScriptHash; Script = replica.Script; Manifest = replica.Manifest.Clone(); @@ -58,7 +58,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) void ISerializable.Serialize(BinaryWriter writer) { writer.Write(Id); - writer.Write(Version); + writer.Write(UpdateCounter); writer.Write(ScriptHash); writer.WriteVarBytes(Script); writer.Write(Manifest); @@ -68,7 +68,7 @@ public JObject ToJson() { JObject json = new JObject(); json["id"] = Id; - json["version"] = Version; + json["version"] = UpdateCounter; json["hash"] = ScriptHash.ToString(); json["script"] = Convert.ToBase64String(Script); json["manifest"] = Manifest.ToJson(); @@ -77,7 +77,7 @@ public JObject ToJson() public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new StackItem[] { Id, (int)Version, ScriptHash.ToArray(), Script, Manifest.ToString() }); + return new Array(referenceCounter, new StackItem[] { Id, (int)UpdateCounter, ScriptHash.ToArray(), Script, Manifest.ToString() }); } } } diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 33a4383a0f..e1be084f98 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -58,7 +58,7 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) contract = new ContractState { Id = Snapshot.ContractId.GetAndChange().NextId++, - Version = 0, + UpdateCounter = 0, Script = nef.Script, ScriptHash = hash, Manifest = ContractManifest.Parse(manifest) @@ -108,7 +108,7 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) if (!contract.Manifest.IsValid(contract.ScriptHash)) throw new InvalidOperationException($"Invalid Manifest Hash: {contract.ScriptHash}"); } - contract.Version++; // Increase the version + contract.UpdateCounter++; // Increase update counter if (nefFile != null) { ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy"); From 09d5efdb4262d9181a8f4a6abe891e20d669106f Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 16 Nov 2020 12:22:07 +0100 Subject: [PATCH 18/42] Rename ContractState.ScriptHash to Hash --- src/neo/Ledger/ContractState.cs | 14 +++---- .../ApplicationEngine.Contract.cs | 16 ++++---- .../SmartContract/ApplicationEngine.Native.cs | 2 +- .../SmartContract/Callbacks/MethodCallback.cs | 2 +- src/neo/SmartContract/DeployedContract.cs | 2 +- src/neo/Wallets/Wallet.cs | 8 ++-- .../neo.UnitTests/Ledger/UT_ContractState.cs | 6 +-- .../Callbacks/UT_MethodCallback.cs | 10 ++--- .../SmartContract/UT_DeployedContract.cs | 2 +- .../SmartContract/UT_InteropService.NEO.cs | 14 +++---- .../SmartContract/UT_InteropService.cs | 38 +++++++++---------- .../SmartContract/UT_SmartContractHelper.cs | 8 ++-- .../SmartContract/UT_Syscalls.cs | 26 ++++++------- tests/neo.UnitTests/TestUtils.cs | 2 +- 14 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 54cb0c89d7..4902a733f1 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -14,7 +14,7 @@ public class ContractState : ICloneable, ISerializable, IInterope { public int Id; public ushort UpdateCounter; - public UInt160 ScriptHash; + public UInt160 Hash; public byte[] Script; public ContractManifest Manifest; @@ -26,7 +26,7 @@ ContractState ICloneable.Clone() { Id = Id, UpdateCounter = UpdateCounter, - ScriptHash = ScriptHash, + Hash = Hash, Script = Script, Manifest = Manifest.Clone() }; @@ -36,7 +36,7 @@ void ISerializable.Deserialize(BinaryReader reader) { Id = reader.ReadInt32(); UpdateCounter = reader.ReadUInt16(); - ScriptHash = reader.ReadSerializable(); + Hash = reader.ReadSerializable(); Script = reader.ReadVarBytes(); Manifest = reader.ReadSerializable(); } @@ -45,7 +45,7 @@ void ICloneable.FromReplica(ContractState replica) { Id = replica.Id; UpdateCounter = replica.UpdateCounter; - ScriptHash = replica.ScriptHash; + Hash = replica.Hash; Script = replica.Script; Manifest = replica.Manifest.Clone(); } @@ -59,7 +59,7 @@ void ISerializable.Serialize(BinaryWriter writer) { writer.Write(Id); writer.Write(UpdateCounter); - writer.Write(ScriptHash); + writer.Write(Hash); writer.WriteVarBytes(Script); writer.Write(Manifest); } @@ -69,7 +69,7 @@ public JObject ToJson() JObject json = new JObject(); json["id"] = Id; json["version"] = UpdateCounter; - json["hash"] = ScriptHash.ToString(); + json["hash"] = Hash.ToString(); json["script"] = Convert.ToBase64String(Script); json["manifest"] = Manifest.ToJson(); return json; @@ -77,7 +77,7 @@ public JObject ToJson() public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new StackItem[] { Id, (int)UpdateCounter, ScriptHash.ToArray(), Script, Manifest.ToString() }); + return new Array(referenceCounter, new StackItem[] { Id, (int)UpdateCounter, Hash.ToArray(), Script, Manifest.ToString() }); } } } diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index e1be084f98..1deccc4771 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -60,7 +60,7 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) Id = Snapshot.ContractId.GetAndChange().NextId++, UpdateCounter = 0, Script = nef.Script, - ScriptHash = hash, + Hash = hash, Manifest = ContractManifest.Parse(manifest) }; @@ -105,8 +105,8 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}"); contract.Manifest = ContractManifest.Parse(manifest); - if (!contract.Manifest.IsValid(contract.ScriptHash)) - throw new InvalidOperationException($"Invalid Manifest Hash: {contract.ScriptHash}"); + if (!contract.Manifest.IsValid(contract.Hash)) + throw new InvalidOperationException($"Invalid Manifest Hash: {contract.Hash}"); } contract.UpdateCounter++; // Increase update counter if (nefFile != null) @@ -157,13 +157,13 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg private void CallContractInternal(ContractState contract, ContractMethodDescriptor method, Array args, CallFlags flags, ReturnTypeConvention convention) { - if (invocationCounter.TryGetValue(contract.ScriptHash, out var counter)) + if (invocationCounter.TryGetValue(contract.Hash, out var counter)) { - invocationCounter[contract.ScriptHash] = counter + 1; + invocationCounter[contract.Hash] = counter + 1; } else { - invocationCounter[contract.ScriptHash] = 1; + invocationCounter[contract.Hash] = 1; } GetInvocationState(CurrentContext).Convention = convention; @@ -173,11 +173,11 @@ private void CallContractInternal(ContractState contract, ContractMethodDescript 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 = LoadScript(contract.Script, flags & callingFlags, contract.ScriptHash, method.Offset); + ExecutionContext context_new = LoadScript(contract.Script, flags & callingFlags, contract.Hash, method.Offset); state = context_new.GetState(); state.CallingScriptHash = callingScriptHash; - if (NativeContract.IsNative(contract.ScriptHash)) + if (NativeContract.IsNative(contract.Hash)) { context_new.EvaluationStack.Push(args); context_new.EvaluationStack.Push(method.Name); diff --git a/src/neo/SmartContract/ApplicationEngine.Native.cs b/src/neo/SmartContract/ApplicationEngine.Native.cs index 5b6f4ecf9e..19bb653c9a 100644 --- a/src/neo/SmartContract/ApplicationEngine.Native.cs +++ b/src/neo/SmartContract/ApplicationEngine.Native.cs @@ -19,7 +19,7 @@ protected internal void DeployNativeContracts() { Id = contract.Id, Script = contract.Script, - ScriptHash = contract.Hash, // Use the native hash + Hash = contract.Hash, // Use the native hash Manifest = contract.Manifest }); contract.Initialize(this); diff --git a/src/neo/SmartContract/Callbacks/MethodCallback.cs b/src/neo/SmartContract/Callbacks/MethodCallback.cs index 7a32a0daaa..6db40ee8a5 100644 --- a/src/neo/SmartContract/Callbacks/MethodCallback.cs +++ b/src/neo/SmartContract/Callbacks/MethodCallback.cs @@ -29,7 +29,7 @@ public override void LoadContext(ApplicationEngine engine, Array args) { engine.Push(args); engine.Push(method.Name); - engine.Push(contract.ScriptHash.ToArray()); + engine.Push(contract.Hash.ToArray()); } } } diff --git a/src/neo/SmartContract/DeployedContract.cs b/src/neo/SmartContract/DeployedContract.cs index e9b1c42d62..36465c37d7 100644 --- a/src/neo/SmartContract/DeployedContract.cs +++ b/src/neo/SmartContract/DeployedContract.cs @@ -14,7 +14,7 @@ public DeployedContract(ContractState contract) if (contract is null) throw new ArgumentNullException(nameof(contract)); Script = null; - ScriptHash = contract.ScriptHash; + ScriptHash = contract.Hash; ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify"); if (descriptor is null) throw new NotSupportedException("The smart contract haven't got verify method."); diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index 91f2656e12..029deab2f1 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -397,14 +397,14 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx) // Check verify cost ContractMethodDescriptor verify = contract.Manifest.Abi.GetMethod("verify"); - if (verify is null) throw new ArgumentException($"The smart contract {contract.ScriptHash} haven't got verify method"); + if (verify is null) throw new ArgumentException($"The smart contract {contract.Hash} haven't got verify method"); ContractMethodDescriptor init = contract.Manifest.Abi.GetMethod("_initialize"); using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.Clone()); - ExecutionContext context = engine.LoadScript(contract.Script, CallFlags.None, contract.ScriptHash, verify.Offset); + ExecutionContext context = engine.LoadScript(contract.Script, CallFlags.None, contract.Hash, verify.Offset); if (init != null) engine.LoadClonedContext(context, init.Offset, false); engine.LoadScript(Array.Empty(), CallFlags.None); - if (engine.Execute() == VMState.FAULT) throw new ArgumentException($"Smart contract {contract.ScriptHash} verification fault."); - if (engine.ResultStack.Count != 1 || !engine.ResultStack.Pop().GetBoolean()) throw new ArgumentException($"Smart contract {contract.ScriptHash} returns false."); + 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."); networkFee += engine.GasConsumed; } diff --git a/tests/neo.UnitTests/Ledger/UT_ContractState.cs b/tests/neo.UnitTests/Ledger/UT_ContractState.cs index 6cf413d835..50aa26c0ea 100644 --- a/tests/neo.UnitTests/Ledger/UT_ContractState.cs +++ b/tests/neo.UnitTests/Ledger/UT_ContractState.cs @@ -23,7 +23,7 @@ public void TestSetup() contract = new ContractState { Script = script, - ScriptHash = script.ToScriptHash(), + Hash = script.ToScriptHash(), Manifest = manifest }; } @@ -32,9 +32,9 @@ public void TestSetup() public void TestGetScriptHash() { // _scriptHash == null - contract.ScriptHash.Should().Be(script.ToScriptHash()); + contract.Hash.Should().Be(script.ToScriptHash()); // _scriptHash != null - contract.ScriptHash.Should().Be(script.ToScriptHash()); + contract.Hash.Should().Be(script.ToScriptHash()); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs index b4f23f56a8..2a79250bbf 100644 --- a/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs +++ b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs @@ -41,17 +41,17 @@ public void GetHashData() }, }, Script = new byte[] { 1, 2, 3 }, - ScriptHash = new byte[] { 1, 2, 3 }.ToScriptHash() + Hash = new byte[] { 1, 2, 3 }.ToScriptHash() }; engine.LoadScript(contract.Script); - snapshot.Contracts.Add(contract.ScriptHash, contract); + snapshot.Contracts.Add(contract.Hash, contract); - Assert.ThrowsException(() => new MethodCallback(engine, contract.ScriptHash, "test")); + Assert.ThrowsException(() => new MethodCallback(engine, contract.Hash, "test")); contract.Manifest.Permissions = new ContractPermission[] { - new ContractPermission() { Contract = ContractPermissionDescriptor.Create(contract.ScriptHash), + new ContractPermission() { Contract = ContractPermissionDescriptor.Create(contract.Hash), Methods= WildcardContainer.Create("test") } }; - var data = new MethodCallback(engine, contract.ScriptHash, "test"); + var data = new MethodCallback(engine, contract.Hash, "test"); Assert.AreEqual(0, engine.CurrentContext.EvaluationStack.Count); var array = new VM.Types.Array(); diff --git a/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs b/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs index e1f772611f..16520b1049 100644 --- a/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs +++ b/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs @@ -28,7 +28,7 @@ public void TestGetAddress() } }, Script = new byte[] { 1, 2, 3 }, - ScriptHash = new byte[] { 1, 2, 3 }.ToScriptHash() + Hash = new byte[] { 1, 2, 3 }.ToScriptHash() }); Assert.AreEqual("0xb2e3fe334830b4741fa5d762f2ab36b90b86c49b", contract.ScriptHash.ToString()); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 3f19198df8..f477ef8060 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -114,15 +114,15 @@ public void TestAccount_IsStandard() var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - engine.IsStandardContract(state.ScriptHash).Should().BeFalse(); + engine.IsStandardContract(state.Hash).Should().BeFalse(); state.Script = Contract.CreateSignatureRedeemScript(Blockchain.StandbyValidators[0]); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - engine.IsStandardContract(state.ScriptHash).Should().BeTrue(); + engine.IsStandardContract(state.Hash).Should().BeTrue(); } [TestMethod] @@ -166,7 +166,7 @@ public void TestContract_Create() var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, 0); engine.LoadScript(new byte[] { 0x01 }); @@ -195,7 +195,7 @@ public void TestContract_Update() ECPoint pubkey = key.PublicKey; var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); - byte[] signature = Crypto.Sign(state.ScriptHash.ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray()); + byte[] signature = Crypto.Sign(state.Hash.ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray()); manifest.Groups = new ContractGroup[] { new ContractGroup() @@ -216,7 +216,7 @@ public void TestContract_Update() Id = state.Id, Key = new byte[] { 0x01 } }; - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); snapshot.Storages.Add(storageKey, storageItem); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(state.Script); @@ -272,7 +272,7 @@ public void TestStorage_Find() Id = state.Id, Key = new byte[] { 0x01 } }; - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); snapshot.Storages.Add(storageKey, storageItem); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index bac084e80f..8689c542f6 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -52,7 +52,7 @@ public void Runtime_GetNotifications_Test() snapshot.Contracts.Add(scriptHash2, new ContractState() { Script = script.ToArray(), - ScriptHash = script.ToArray().ToScriptHash(), + Hash = script.ToArray().ToScriptHash(), Manifest = TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), }); } @@ -217,13 +217,13 @@ public void TestExecutionEngine_GetCallingScriptHash() { Manifest = TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), Script = scriptA.ToArray(), - ScriptHash = scriptA.ToArray().ToScriptHash() + Hash = scriptA.ToArray().ToScriptHash() }; engine = GetEngine(true, true, false); - engine.Snapshot.Contracts.Add(contract.ScriptHash, contract); + engine.Snapshot.Contracts.Add(contract.Hash, contract); using ScriptBuilder scriptB = new ScriptBuilder(); - scriptB.EmitAppCall(contract.ScriptHash, "test", 0, 1); + scriptB.EmitAppCall(contract.Hash, "test", 0, 1); engine.LoadScript(scriptB.ToArray()); Assert.AreEqual(VMState.HALT, engine.Execute()); @@ -391,10 +391,10 @@ public void TestBlockchain_GetContract() var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - engine.GetContract(state.ScriptHash).Should().BeSameAs(state); + engine.GetContract(state.Hash).Should().BeSameAs(state); } [TestMethod] @@ -402,7 +402,7 @@ public void TestStorage_GetContext() { var engine = GetEngine(false, true); var state = TestUtils.GetContract(); - engine.Snapshot.Contracts.Add(state.ScriptHash, state); + engine.Snapshot.Contracts.Add(state.Hash, state); engine.LoadScript(state.Script); engine.GetStorageContext().IsReadOnly.Should().BeFalse(); } @@ -412,7 +412,7 @@ public void TestStorage_GetReadOnlyContext() { var engine = GetEngine(false, true); var state = TestUtils.GetContract(); - engine.Snapshot.Contracts.Add(state.ScriptHash, state); + engine.Snapshot.Contracts.Add(state.Hash, state); engine.LoadScript(state.Script); engine.GetReadOnlyContext().IsReadOnly.Should().BeTrue(); } @@ -434,7 +434,7 @@ public void TestStorage_Get() Value = new byte[] { 0x01, 0x02, 0x03, 0x04 }, IsConstant = true }; - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); snapshot.Storages.Add(storageKey, storageItem); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); @@ -491,7 +491,7 @@ public void TestStorage_Put() Value = new byte[] { 0x01, 0x02, 0x03, 0x04 }, IsConstant = true }; - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); snapshot.Storages.Add(storageKey, storageItem); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); @@ -525,7 +525,7 @@ public void TestStorage_PutEx() Value = new byte[] { 0x01, 0x02, 0x03, 0x04 }, IsConstant = false }; - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); snapshot.Storages.Add(storageKey, storageItem); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); @@ -555,7 +555,7 @@ public void TestStorage_Delete() Value = new byte[] { 0x01, 0x02, 0x03, 0x04 }, IsConstant = false }; - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); snapshot.Storages.Add(storageKey, storageItem); engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); @@ -593,19 +593,19 @@ public void TestContract_Call() var args = new VM.Types.Array { 0, 1 }; var state = TestUtils.GetContract(method, args.Count); - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - engine.CallContract(state.ScriptHash, method, args); + engine.CallContract(state.Hash, method, args); 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.CallContract(state.ScriptHash, method, args)); + Assert.ThrowsException(() => engine.CallContract(state.Hash, method, args)); state.Manifest.Permissions[0].Methods = WildcardContainer.CreateWildcard(); - engine.CallContract(state.ScriptHash, method, args); + engine.CallContract(state.Hash, method, args); Assert.ThrowsException(() => engine.CallContract(UInt160.Zero, method, args)); } @@ -618,7 +618,7 @@ public void TestContract_CallEx() string method = "method"; var args = new VM.Types.Array { 0, 1 }; var state = TestUtils.GetContract(method, args.Count); - snapshot.Contracts.Add(state.ScriptHash, state); + snapshot.Contracts.Add(state.Hash, state); foreach (var flags in new CallFlags[] { CallFlags.None, CallFlags.AllowCall, CallFlags.AllowModifyStates, CallFlags.All }) @@ -626,7 +626,7 @@ public void TestContract_CallEx() var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); - engine.CallContractEx(state.ScriptHash, method, args, CallFlags.All); + engine.CallContractEx(state.Hash, method, args, CallFlags.All); engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); @@ -634,7 +634,7 @@ public void TestContract_CallEx() Assert.ThrowsException(() => engine.CallContractEx(UInt160.Zero, method, args, CallFlags.All)); // Call with rights - engine.CallContractEx(state.ScriptHash, method, args, flags); + engine.CallContractEx(state.Hash, method, args, flags); engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[0]); engine.CurrentContext.EvaluationStack.Pop().Should().Be(args[1]); } diff --git a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs index 90cf4e3b7b..e007b4c1d9 100644 --- a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs @@ -149,7 +149,7 @@ public void TestVerifyWitnesses() snapshot3.Contracts.Add(UInt160.Zero, new ContractState() { Script = Array.Empty(), - ScriptHash = Array.Empty().ToScriptHash(), + Hash = Array.Empty().ToScriptHash(), Manifest = TestUtils.CreateManifest("verify", ContractParameterType.Boolean, ContractParameterType.Signature), }); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header3, snapshot3, 100)); @@ -159,11 +159,11 @@ public void TestVerifyWitnesses() var contract = new ContractState() { Script = "11".HexToBytes(), // 17 PUSH1 - ScriptHash = "11".HexToBytes().ToScriptHash(), + Hash = "11".HexToBytes().ToScriptHash(), Manifest = TestUtils.CreateManifest("verify", ContractParameterType.Boolean, ContractParameterType.Signature), // Offset = 0 }; - snapshot3.Contracts.Add(contract.ScriptHash, contract); - var tx = new Extensions.Nep5NativeContractExtensions.ManualWitness(contract.ScriptHash) + snapshot3.Contracts.Add(contract.Hash, contract); + var tx = new Extensions.Nep5NativeContractExtensions.ManualWitness(contract.Hash) { Witnesses = new Witness[] { new Witness() { InvocationScript = new byte[0], VerificationScript = new byte[0] } } }; diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index e05be8815a..13b559cc15 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -327,32 +327,32 @@ public void System_Runtime_GetInvocationCounter() contractA = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(script.ToArray()).ToArray() }; contractB = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; contractC = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; - contractA.ScriptHash = contractA.Script.ToScriptHash(); - contractB.ScriptHash = contractB.Script.ToScriptHash(); - contractC.ScriptHash = contractC.Script.ToScriptHash(); + contractA.Hash = contractA.Script.ToScriptHash(); + contractB.Hash = contractB.Script.ToScriptHash(); + contractC.Hash = contractC.Script.ToScriptHash(); // Init A,B,C contracts // First two drops is for drop method and arguments - contracts.Delete(contractA.ScriptHash); - contracts.Delete(contractB.ScriptHash); - contracts.Delete(contractC.ScriptHash); + contracts.Delete(contractA.Hash); + contracts.Delete(contractB.Hash); + contracts.Delete(contractC.Hash); contractA.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); contractB.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); contractC.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer); - contracts.Add(contractA.ScriptHash, contractA); - contracts.Add(contractB.ScriptHash, contractB); - contracts.Add(contractC.ScriptHash, contractC); + contracts.Add(contractA.Hash, contractA); + contracts.Add(contractB.Hash, contractB); + contracts.Add(contractC.Hash, contractC); } // Call A,B,B,C using (var script = new ScriptBuilder()) { - script.EmitAppCall(contractA.ScriptHash, "dummyMain", 0, 1); - script.EmitAppCall(contractB.ScriptHash, "dummyMain", 0, 1); - script.EmitAppCall(contractB.ScriptHash, "dummyMain", 0, 1); - script.EmitAppCall(contractC.ScriptHash, "dummyMain", 0, 1); + 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); // Execute diff --git a/tests/neo.UnitTests/TestUtils.cs b/tests/neo.UnitTests/TestUtils.cs index b3788de26a..8238abbcad 100644 --- a/tests/neo.UnitTests/TestUtils.cs +++ b/tests/neo.UnitTests/TestUtils.cs @@ -112,7 +112,7 @@ internal static ContractState GetContract(string method = "test", int parameters { Id = 0x43000000, Script = new byte[] { 0x01, 0x01, 0x01, 0x01 }, - ScriptHash = new byte[] { 0x01, 0x01, 0x01, 0x01 }.ToScriptHash(), + Hash = new byte[] { 0x01, 0x01, 0x01, 0x01 }.ToScriptHash(), Manifest = CreateManifest(method, ContractParameterType.Any, Enumerable.Repeat(ContractParameterType.Any, parametersCount).ToArray()) }; } From 457818f93b00c3d02a153b8f6057849a14cbf121 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 18 Nov 2020 10:48:20 +0100 Subject: [PATCH 19/42] Some Erik's suggestions --- src/neo/Ledger/ContractState.cs | 2 +- .../SmartContract/ApplicationEngine.Contract.cs | 2 +- src/neo/SmartContract/NefFile.cs | 16 ++++------------ 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 4902a733f1..edd26222d2 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -68,7 +68,7 @@ public JObject ToJson() { JObject json = new JObject(); json["id"] = Id; - json["version"] = UpdateCounter; + json["updateCounter"] = UpdateCounter; json["hash"] = Hash.ToString(); json["script"] = Convert.ToBase64String(Script); json["manifest"] = Manifest.ToJson(); diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 1deccc4771..58391afd7a 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -34,7 +34,7 @@ private UInt160 ContractHash(NefFile nef) using var script = new ScriptBuilder(); script.Emit(OpCode.ABORT); script.EmitPush(tx.Sender); - script.EmitPush(nef.ScriptHash); + script.EmitPush(nef.Script); return script.ToArray().ToScriptHash(); } diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index f8213d7cb4..f0bb7a92ca 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -87,27 +87,19 @@ private void SerializeHeader(BinaryWriter writer) public void Deserialize(BinaryReader reader) { - if (reader.ReadUInt32() != Magic) - { - throw new FormatException("Wrong magic"); - } + if (reader.ReadUInt32() != Magic) throw new FormatException("Wrong magic"); Compiler = reader.ReadFixedString(32); Version = new Version(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32()); ScriptHash = reader.ReadSerializable(); CheckSum = reader.ReadUInt32(); - if (CheckSum != ComputeChecksum(this)) - { - throw new FormatException("CRC verification fail"); - } + if (CheckSum != ComputeChecksum(this)) throw new FormatException("CRC verification fail"); Script = reader.ReadVarBytes(MaxScriptLength); - if (Script.ToScriptHash() != ScriptHash) - { - throw new FormatException("ScriptHash is different"); - } + if (Script.Length == 0) throw new ArgumentException($"Script can't be empty"); + if (Script.ToScriptHash() != ScriptHash) throw new FormatException("ScriptHash is different"); } /// From 312fb081b9dcffa20d06efc0519261223e9199d4 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 18 Nov 2020 10:48:27 +0100 Subject: [PATCH 20/42] Some Erik's suggestions --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 58391afd7a..4baa1bfb05 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -49,9 +49,6 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) AddGas(StoragePrice * (nefFile.Length + manifest.Length)); NefFile nef = nefFile.AsSerializable(); - if (nef.Script.Length == 0) - throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); - UInt160 hash = ContractHash(nef); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract != null) throw new InvalidOperationException($"Contract Already Exists: {hash}"); From 12deb7bf7a82838e7037c79b28f05379b5b1edac Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 18 Nov 2020 10:59:44 +0100 Subject: [PATCH 21/42] Move CanCall --- src/neo/Ledger/ContractState.cs | 13 +++++++++++++ src/neo/SmartContract/ApplicationEngine.Contract.cs | 5 ++--- src/neo/SmartContract/Callbacks/MethodCallback.cs | 4 ++-- src/neo/SmartContract/Manifest/ContractManifest.cs | 12 ------------ tests/neo.UnitTests/Ledger/UT_ContractState.cs | 8 ++++++++ .../SmartContract/Manifest/UT_ContractManifest.cs | 8 -------- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index edd26222d2..41ecd6edf9 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -6,6 +6,7 @@ using Neo.VM.Types; using System; using System.IO; +using System.Linq; using Array = Neo.VM.Types.Array; namespace Neo.Ledger @@ -64,6 +65,18 @@ void ISerializable.Serialize(BinaryWriter writer) writer.Write(Manifest); } + /// + /// Return true if is allowed + /// + /// Hash + /// Manifest + /// Method + /// Return true or false + public bool CanCall(UInt160 hash, ContractManifest manifest, string method) + { + return Manifest.Permissions.Any(u => u.IsAllowed(hash, manifest, method)); + } + public JObject ToJson() { JObject json = new JObject(); diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 4baa1bfb05..e7ecf68146 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -6,7 +6,6 @@ using Neo.SmartContract.Native; using Neo.VM; using System; -using System.Linq; using Array = Neo.VM.Types.Array; namespace Neo.SmartContract @@ -145,8 +144,8 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method); if (md is null) throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}"); - ContractManifest currentManifest = Snapshot.Contracts.TryGet(CurrentScriptHash)?.Manifest; - if (currentManifest != null && !currentManifest.CanCall(contractHash, contract.Manifest, method)) + ContractState currentContract = Snapshot.Contracts.TryGet(CurrentScriptHash); + if (currentContract?.CanCall(contractHash, contract.Manifest, method) == false) throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contractHash} From Contract {CurrentScriptHash}"); CallContractInternal(contract, md, args, flags, convention); diff --git a/src/neo/SmartContract/Callbacks/MethodCallback.cs b/src/neo/SmartContract/Callbacks/MethodCallback.cs index 6db40ee8a5..391b6c4da2 100644 --- a/src/neo/SmartContract/Callbacks/MethodCallback.cs +++ b/src/neo/SmartContract/Callbacks/MethodCallback.cs @@ -19,8 +19,8 @@ public MethodCallback(ApplicationEngine engine, UInt160 hash, string method) { if (method.StartsWith('_')) throw new ArgumentException(); this.contract = engine.Snapshot.Contracts[hash]; - ContractManifest currentManifest = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash)?.Manifest; - if (currentManifest != null && !currentManifest.CanCall(hash, this.contract.Manifest, method)) + ContractState currentContract = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash); + if (currentContract?.CanCall(hash, this.contract.Manifest, method) == false) throw new InvalidOperationException(); this.method = this.contract.Manifest.Abi.Methods.First(p => p.Name == method); } diff --git a/src/neo/SmartContract/Manifest/ContractManifest.cs b/src/neo/SmartContract/Manifest/ContractManifest.cs index 7a80fe3cb3..5505013433 100644 --- a/src/neo/SmartContract/Manifest/ContractManifest.cs +++ b/src/neo/SmartContract/Manifest/ContractManifest.cs @@ -66,18 +66,6 @@ public int Size /// public JObject Extra { get; set; } - /// - /// Return true if is allowed - /// - /// Hash - /// Manifest - /// Method - /// Return true or false - public bool CanCall(UInt160 hash, ContractManifest manifest, string method) - { - return Permissions.Any(u => u.IsAllowed(hash, manifest, method)); - } - /// /// Parse ContractManifest from json /// diff --git a/tests/neo.UnitTests/Ledger/UT_ContractState.cs b/tests/neo.UnitTests/Ledger/UT_ContractState.cs index 50aa26c0ea..c97155cdc6 100644 --- a/tests/neo.UnitTests/Ledger/UT_ContractState.cs +++ b/tests/neo.UnitTests/Ledger/UT_ContractState.cs @@ -76,6 +76,14 @@ public void TestGetSize() newContract.Size.Should().Be(188); } + [TestMethod] + public void TestCanCall() + { + var temp = new ContractState() { Manifest = TestUtils.CreateDefaultManifest() }; + temp.Manifest.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); + Assert.AreEqual(true, temp.CanCall(UInt160.Zero, TestUtils.CreateDefaultManifest(), "AAA")); + } + [TestMethod] public void TestToJson() { diff --git a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs index 802dfaae58..f4aa741dfa 100644 --- a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs +++ b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs @@ -113,14 +113,6 @@ public void TestGenerator() Assert.IsNotNull(contractManifest); } - [TestMethod] - public void TestCanCall() - { - var temp = TestUtils.CreateDefaultManifest(); - temp.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); - Assert.AreEqual(true, temp.CanCall(UInt160.Zero, TestUtils.CreateDefaultManifest(), "AAA")); - } - [TestMethod] public void TestClone() { From 15998ac4db0007be29ea16683107976eb2c15f12 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 19 Nov 2020 18:19:48 +0100 Subject: [PATCH 22/42] Remove Script hash from NefFile --- src/neo/SmartContract/NefFile.cs | 44 +++++-------------- .../SmartContract/UT_InteropService.NEO.cs | 5 --- .../neo.UnitTests/SmartContract/UT_NefFile.cs | 15 +++---- 3 files changed, 17 insertions(+), 47 deletions(-) diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index f0bb7a92ca..467408ade5 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -12,12 +12,11 @@ namespace Neo.SmartContract /// | Magic | 4 bytes | Magic header | /// | Compiler | 32 bytes | Compiler used | /// | Version | 16 bytes | Compiler version (Mayor, Minor, Build, Version) | - /// | ScriptHash | 20 bytes | ScriptHash for the script | - /// +------------+-----------+------------------------------------------------------------+ - /// | Checksum | 4 bytes | First four bytes of double SHA256 hash | /// +------------+-----------+------------------------------------------------------------+ /// | Script | Var bytes | Var bytes for the payload | /// +------------+-----------+------------------------------------------------------------+ + /// | Checksum | 4 bytes | First four bytes of double SHA256 hash | + /// +------------+-----------+------------------------------------------------------------+ /// public class NefFile : ISerializable { @@ -36,11 +35,6 @@ public class NefFile : ISerializable /// public Version Version { get; set; } - /// - /// Script Hash - /// - public UInt160 ScriptHash { get; set; } - /// /// Checksum /// @@ -56,19 +50,18 @@ public class NefFile : ISerializable private const int HeaderSize = sizeof(uint) + // Magic 32 + // Compiler - (sizeof(int) * 4) + // Version - UInt160.Length; // ScriptHash + (sizeof(int) * 4); // Version public int Size => - HeaderSize + // Header - sizeof(uint) + // Checksum - Script.GetVarSize();// Script + HeaderSize + // Header + Script.GetVarSize() + // Script + sizeof(uint); // Checksum public void Serialize(BinaryWriter writer) { SerializeHeader(writer); - writer.Write(CheckSum); writer.WriteVarBytes(Script ?? Array.Empty()); + writer.Write(CheckSum); } private void SerializeHeader(BinaryWriter writer) @@ -81,8 +74,6 @@ private void SerializeHeader(BinaryWriter writer) writer.Write(Version.Minor); writer.Write(Version.Build); writer.Write(Version.Revision); - - writer.Write(ScriptHash); } public void Deserialize(BinaryReader reader) @@ -91,15 +82,11 @@ public void Deserialize(BinaryReader reader) Compiler = reader.ReadFixedString(32); Version = new Version(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32()); - ScriptHash = reader.ReadSerializable(); - CheckSum = reader.ReadUInt32(); - - if (CheckSum != ComputeChecksum(this)) throw new FormatException("CRC verification fail"); - Script = reader.ReadVarBytes(MaxScriptLength); - if (Script.Length == 0) throw new ArgumentException($"Script can't be empty"); - if (Script.ToScriptHash() != ScriptHash) throw new FormatException("ScriptHash is different"); + + CheckSum = reader.ReadUInt32(); + if (CheckSum != ComputeChecksum(this)) throw new FormatException("CRC verification fail"); } /// @@ -109,15 +96,8 @@ public void Deserialize(BinaryReader reader) /// Return checksum unsafe public static uint ComputeChecksum(NefFile file) { - Span header = stackalloc byte[HeaderSize]; - fixed (byte* p = header) - using (UnmanagedMemoryStream ms = new UnmanagedMemoryStream(p, HeaderSize, HeaderSize, FileAccess.Write)) - using (BinaryWriter wr = new BinaryWriter(ms, Utility.StrictUTF8, false)) - { - file.SerializeHeader(wr); - wr.Flush(); - } - return BitConverter.ToUInt32(Crypto.Hash256(header), 0); + var data = file.ToArray(); + return BitConverter.ToUInt32(Crypto.Hash256(data.AsSpan().Slice(0, data.Length - sizeof(int)))); } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index f477ef8060..205bf26ba2 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -131,7 +131,6 @@ public void TestContract_Create() var nef = new NefFile() { Script = new byte[0x01], - ScriptHash = new byte[0x01].ToScriptHash(), Compiler = "", Version = new Version(1, 2, 3, 4) }; @@ -146,7 +145,6 @@ public void TestContract_Create() var script_exceedMaxLength = new NefFile() { Script = new byte[NefFile.MaxScriptLength - 1], - ScriptHash = new byte[NefFile.MaxScriptLength - 1].ToScriptHash(), Compiler = "", Version = new Version(1, 2, 3, 4) }; @@ -180,7 +178,6 @@ public void TestContract_Update() var nef = new NefFile() { Script = new byte[] { 0x01 }, - ScriptHash = new byte[] { 0x01 }.ToScriptHash(), Compiler = "", Version = new Version(1, 2, 3, 4) }; @@ -230,7 +227,6 @@ public void TestContract_Update_Invalid() var nefFile = new NefFile() { Script = new byte[] { 0x01 }, - ScriptHash = new byte[] { 0x01 }.ToScriptHash(), Version = new Version(1, 2, 3, 4), Compiler = "" }; @@ -245,7 +241,6 @@ public void TestContract_Update_Invalid() nefFile = new NefFile() { Script = new byte[0], - ScriptHash = new byte[0].ToScriptHash(), Version = new Version(1, 2, 3, 4), Compiler = "" }; diff --git a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs index 36a988d8b8..cf8a086111 100644 --- a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs +++ b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs @@ -20,7 +20,6 @@ public class UT_NefFile [TestInitialize] public void TestSetup() { - file.ScriptHash = file.Script.ToScriptHash(); file.CheckSum = NefFile.ComputeChecksum(file); } @@ -53,8 +52,8 @@ public void TestDeserialize() action.Should().Throw(); } + file.Script = Array.Empty(); file.CheckSum = NefFile.ComputeChecksum(file); - file.ScriptHash = new byte[] { 0x01 }.ToScriptHash(); using (MemoryStream ms = new MemoryStream(1024)) using (BinaryWriter writer = new BinaryWriter(ms)) using (BinaryReader reader = new BinaryReader(ms)) @@ -63,15 +62,15 @@ public void TestDeserialize() ms.Seek(0, SeekOrigin.Begin); ISerializable newFile = new NefFile(); Action action = () => newFile.Deserialize(reader); - action.Should().Throw(); + action.Should().Throw(); } - file.ScriptHash = file.Script.ToScriptHash(); + file.Script = new byte[] { 0x01, 0x02, 0x03 }; + file.CheckSum = NefFile.ComputeChecksum(file); var data = file.ToArray(); var newFile1 = data.AsSerializable(); newFile1.Version.Should().Be(file.Version); newFile1.Compiler.Should().Be(file.Compiler); - newFile1.ScriptHash.Should().Be(file.ScriptHash); newFile1.CheckSum.Should().Be(file.CheckSum); newFile1.Script.Should().BeEquivalentTo(file.Script); } @@ -79,7 +78,7 @@ public void TestDeserialize() [TestMethod] public void TestGetSize() { - file.Size.Should().Be(4 + 32 + 16 + 20 + 4 + 4); + file.Size.Should().Be(4 + 32 + 16 + 4 + 4); } [TestMethod] @@ -92,7 +91,6 @@ public void ParseTest() Script = new byte[] { 0x01, 0x02, 0x03 } }; - file.ScriptHash = file.Script.ToScriptHash(); file.CheckSum = NefFile.ComputeChecksum(file); var data = file.ToArray(); @@ -100,7 +98,6 @@ public void ParseTest() Assert.AreEqual("".PadLeft(32, ' '), file.Compiler); Assert.AreEqual(new Version(1, 2, 3, 4), file.Version); - Assert.AreEqual(file.Script.ToScriptHash(), file.ScriptHash); CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }, file.Script); } @@ -112,7 +109,6 @@ public void LimitTest() Compiler = "".PadLeft(byte.MaxValue, ' '), Version = new Version(1, 2, 3, 4), Script = new byte[1024 * 1024], - ScriptHash = new byte[1024 * 1024].ToScriptHash(), CheckSum = 0 }; @@ -124,7 +120,6 @@ public void LimitTest() file.Compiler = ""; file.Script = new byte[(1024 * 1024) + 1]; - file.ScriptHash = file.Script.ToScriptHash(); var data = file.ToArray(); Assert.ThrowsException(() => data.AsSerializable()); From 4bcf19fa38b4af27ffff1e5a189878d6b7e7e707 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 21 Nov 2020 13:31:33 +0100 Subject: [PATCH 23/42] Move to Helper --- .../SmartContract/ApplicationEngine.Contract.cs | 15 ++------------- src/neo/SmartContract/Helper.cs | 10 ++++++++++ tests/neo.UnitTests/SmartContract/UT_Helper.cs | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index e7ecf68146..0ff66abbad 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -25,21 +25,10 @@ partial class ApplicationEngine /// public static readonly InteropDescriptor System_Contract_CreateStandardAccount = Register("System.Contract.CreateStandardAccount", nameof(CreateStandardAccount), 0_00010000, CallFlags.None, true); - private UInt160 ContractHash(NefFile nef) + protected internal void CreateContract(byte[] nefFile, byte[] manifest) { if (!(ScriptContainer is Transaction tx)) throw new InvalidOperationException(); - - using var script = new ScriptBuilder(); - script.Emit(OpCode.ABORT); - script.EmitPush(tx.Sender); - script.EmitPush(nef.Script); - - return script.ToArray().ToScriptHash(); - } - - protected internal void CreateContract(byte[] nefFile, byte[] manifest) - { if (nefFile.Length == 0) throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength) @@ -48,7 +37,7 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) AddGas(StoragePrice * (nefFile.Length + manifest.Length)); NefFile nef = nefFile.AsSerializable(); - UInt160 hash = ContractHash(nef); + UInt160 hash = Helper.ContractHash(tx.Sender, nef); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract != null) throw new InvalidOperationException($"Contract Already Exists: {hash}"); contract = new ContractState diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index dd9355a806..6fc5770448 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -130,6 +130,16 @@ public static UInt160 ToScriptHash(this ReadOnlySpan script) return new UInt160(Crypto.Hash160(script)); } + public static UInt160 ContractHash(UInt160 sender, NefFile nef) + { + using var script = new ScriptBuilder(); + script.Emit(OpCode.ABORT); + script.EmitPush(sender); + script.EmitPush(nef.Script); + + return script.ToArray().ToScriptHash(); + } + internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas, WitnessFlag filter = WitnessFlag.All) { if (gas < 0) return false; diff --git a/tests/neo.UnitTests/SmartContract/UT_Helper.cs b/tests/neo.UnitTests/SmartContract/UT_Helper.cs index d2216ef83c..5f11d507a9 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Helper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Helper.cs @@ -27,5 +27,20 @@ public void TestIsMultiSigContract() }; Assert.IsFalse(case2.IsMultiSigContract()); } + + [TestMethod] + public void TestContractHash() + { + var nef = new NefFile() + { + Compiler = "test", + Version = new System.Version(), + Script = new byte[] { 1, 2, 3 } + }; + nef.CheckSum = NefFile.ComputeChecksum(nef); + + Assert.AreEqual("0xb4b7417195feca1cdb5a99504ab641d8c220ae99", Neo.SmartContract.Helper.ContractHash(UInt160.Zero, nef).ToString()); + Assert.AreEqual("0xe56e4ee87f89a70e9138432c387ad49f2ee5b55f", Neo.SmartContract.Helper.ContractHash(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), nef).ToString()); + } } } From 92d32ee00f25a66f2e7a8623cee752472264483c Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 21 Nov 2020 13:34:10 +0100 Subject: [PATCH 24/42] Simplify ContractState --- src/neo/Ledger/ContractState.cs | 6 +++--- src/neo/SmartContract/ApplicationEngine.Contract.cs | 2 +- src/neo/SmartContract/Callbacks/MethodCallback.cs | 2 +- tests/neo.UnitTests/Ledger/UT_ContractState.cs | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 41ecd6edf9..501fd152bf 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -68,13 +68,13 @@ void ISerializable.Serialize(BinaryWriter writer) /// /// Return true if is allowed /// - /// Hash + /// State /// Manifest /// Method /// Return true or false - public bool CanCall(UInt160 hash, ContractManifest manifest, string method) + public bool CanCall(ContractState state, string method) { - return Manifest.Permissions.Any(u => u.IsAllowed(hash, manifest, method)); + return Manifest.Permissions.Any(u => u.IsAllowed(state.Hash, state.Manifest, method)); } public JObject ToJson() diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 0ff66abbad..027d79b9b8 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -134,7 +134,7 @@ private void CallContractInternal(UInt160 contractHash, string method, Array arg if (md is null) throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}"); ContractState currentContract = Snapshot.Contracts.TryGet(CurrentScriptHash); - if (currentContract?.CanCall(contractHash, contract.Manifest, method) == false) + if (currentContract?.CanCall(contract, method) == false) throw new InvalidOperationException($"Cannot Call Method {method} Of Contract {contractHash} From Contract {CurrentScriptHash}"); CallContractInternal(contract, md, args, flags, convention); diff --git a/src/neo/SmartContract/Callbacks/MethodCallback.cs b/src/neo/SmartContract/Callbacks/MethodCallback.cs index 391b6c4da2..f2b0709d0a 100644 --- a/src/neo/SmartContract/Callbacks/MethodCallback.cs +++ b/src/neo/SmartContract/Callbacks/MethodCallback.cs @@ -20,7 +20,7 @@ public MethodCallback(ApplicationEngine engine, UInt160 hash, string method) if (method.StartsWith('_')) throw new ArgumentException(); this.contract = engine.Snapshot.Contracts[hash]; ContractState currentContract = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash); - if (currentContract?.CanCall(hash, this.contract.Manifest, method) == false) + if (currentContract?.CanCall(this.contract, method) == false) throw new InvalidOperationException(); this.method = this.contract.Manifest.Abi.Methods.First(p => p.Name == method); } diff --git a/tests/neo.UnitTests/Ledger/UT_ContractState.cs b/tests/neo.UnitTests/Ledger/UT_ContractState.cs index 2c3ca885ea..47c8ee52cb 100644 --- a/tests/neo.UnitTests/Ledger/UT_ContractState.cs +++ b/tests/neo.UnitTests/Ledger/UT_ContractState.cs @@ -81,7 +81,8 @@ public void TestCanCall() { var temp = new ContractState() { Manifest = TestUtils.CreateDefaultManifest() }; temp.Manifest.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); - Assert.AreEqual(true, temp.CanCall(UInt160.Zero, TestUtils.CreateDefaultManifest(), "AAA")); + + Assert.AreEqual(true, temp.CanCall(new ContractState() { Hash = UInt160.Zero, Manifest = TestUtils.CreateDefaultManifest() }, "AAA")); } [TestMethod] From bed862eb4b98431b23a3c1b041693149f3188d73 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 21 Nov 2020 15:58:02 +0100 Subject: [PATCH 25/42] Erik's review --- src/neo/Ledger/ContractState.cs | 5 ++--- src/neo/SmartContract/Manifest/ContractPermission.cs | 10 +++++----- .../SmartContract/Manifest/UT_ContractPermission.cs | 9 +++++---- .../SmartContract/UT_InteropService.NEO.cs | 7 ++++--- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 501fd152bf..1c870c7bd4 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -69,19 +69,18 @@ void ISerializable.Serialize(BinaryWriter writer) /// Return true if is allowed /// /// State - /// Manifest /// Method /// Return true or false public bool CanCall(ContractState state, string method) { - return Manifest.Permissions.Any(u => u.IsAllowed(state.Hash, state.Manifest, method)); + return Manifest.Permissions.Any(u => u.IsAllowed(state, method)); } public JObject ToJson() { JObject json = new JObject(); json["id"] = Id; - json["updateCounter"] = UpdateCounter; + json["updatecounter"] = UpdateCounter; json["hash"] = Hash.ToString(); json["script"] = Convert.ToBase64String(Script); json["manifest"] = Manifest.ToJson(); diff --git a/src/neo/SmartContract/Manifest/ContractPermission.cs b/src/neo/SmartContract/Manifest/ContractPermission.cs index 6f590b92cc..e7e20d6a1f 100644 --- a/src/neo/SmartContract/Manifest/ContractPermission.cs +++ b/src/neo/SmartContract/Manifest/ContractPermission.cs @@ -1,4 +1,5 @@ using Neo.IO.Json; +using Neo.Ledger; using System; using System.Linq; @@ -64,19 +65,18 @@ public JObject ToJson() /// /// Return true if is allowed /// - /// hash - /// The manifest of which contract we are calling + /// State /// Method /// Return true or false - public bool IsAllowed(UInt160 hash, ContractManifest manifest, string method) + public bool IsAllowed(ContractState state, string method) { if (Contract.IsHash) { - if (!Contract.Hash.Equals(hash)) return false; + if (!Contract.Hash.Equals(state.Hash)) return false; } else if (Contract.IsGroup) { - if (manifest.Groups.All(p => !p.PubKey.Equals(Contract.Group))) return false; + if (state.Manifest.Groups.All(p => !p.PubKey.Equals(Contract.Group))) return false; } return Methods.IsWildcard || Methods.Contains(method); } diff --git a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs index f662af0496..fe2e03bc37 100644 --- a/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs +++ b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractPermission.cs @@ -1,5 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography.ECC; +using Neo.Ledger; using Neo.SmartContract.Manifest; using System; @@ -14,13 +15,13 @@ public void TestIsAllowed() ContractManifest contractManifest1 = TestUtils.CreateDefaultManifest(); ContractPermission contractPermission1 = ContractPermission.DefaultPermission; contractPermission1.Contract = ContractPermissionDescriptor.Create(UInt160.Zero); - Assert.AreEqual(true, contractPermission1.IsAllowed(UInt160.Zero, contractManifest1, "AAA")); + Assert.AreEqual(true, contractPermission1.IsAllowed(new ContractState() { Hash = UInt160.Zero, Manifest = contractManifest1 }, "AAA")); contractPermission1.Contract = ContractPermissionDescriptor.CreateWildcard(); ContractManifest contractManifest2 = TestUtils.CreateDefaultManifest(); ContractPermission contractPermission2 = ContractPermission.DefaultPermission; contractPermission2.Contract = ContractPermissionDescriptor.Create(UInt160.Parse("0x0000000000000000000000000000000000000001")); - Assert.AreEqual(false, contractPermission2.IsAllowed(UInt160.Zero, contractManifest2, "AAA")); + Assert.AreEqual(false, contractPermission2.IsAllowed(new ContractState() { Hash = UInt160.Zero, Manifest = contractManifest2 }, "AAA")); contractPermission2.Contract = ContractPermissionDescriptor.CreateWildcard(); Random random3 = new Random(); @@ -31,7 +32,7 @@ public void TestIsAllowed() contractManifest3.Groups = new ContractGroup[] { new ContractGroup() { PubKey = publicKey3 } }; ContractPermission contractPermission3 = ContractPermission.DefaultPermission; contractPermission3.Contract = ContractPermissionDescriptor.Create(publicKey3); - Assert.AreEqual(true, contractPermission3.IsAllowed(UInt160.Zero, contractManifest3, "AAA")); + Assert.AreEqual(true, contractPermission3.IsAllowed(new ContractState() { Hash = UInt160.Zero, Manifest = contractManifest3 }, "AAA")); contractPermission3.Contract = ContractPermissionDescriptor.CreateWildcard(); Random random4 = new Random(); @@ -45,7 +46,7 @@ public void TestIsAllowed() contractManifest4.Groups = new ContractGroup[] { new ContractGroup() { PubKey = publicKey42 } }; ContractPermission contractPermission4 = ContractPermission.DefaultPermission; contractPermission4.Contract = ContractPermissionDescriptor.Create(publicKey41); - Assert.AreEqual(false, contractPermission4.IsAllowed(UInt160.Zero, contractManifest4, "AAA")); + Assert.AreEqual(false, contractPermission4.IsAllowed(new ContractState() { Hash = UInt160.Zero, Manifest = contractManifest4 }, "AAA")); contractPermission4.Contract = ContractPermissionDescriptor.CreateWildcard(); } } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 205bf26ba2..e68edc33a9 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -136,12 +136,13 @@ public void TestContract_Create() }; nef.CheckSum = NefFile.ComputeChecksum(nef); var nefFile = nef.ToArray(); - var engine = GetEngine(false, true); - Assert.ThrowsException(() => engine.CreateContract(nefFile, new byte[ContractManifest.MaxLength + 1])); - var manifest = TestUtils.CreateDefaultManifest(); + var engine = GetEngine(false, true); Assert.ThrowsException(() => engine.CreateContract(nefFile, manifest.ToJson().ToByteArray(false))); + engine = GetEngine(true, true); + Assert.ThrowsException(() => engine.CreateContract(nefFile, new byte[ContractManifest.MaxLength + 1])); + var script_exceedMaxLength = new NefFile() { Script = new byte[NefFile.MaxScriptLength - 1], From 7b1b422e47f15276f277fecf96dbb7c4d674c610 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Sun, 22 Nov 2020 14:36:51 +0800 Subject: [PATCH 26/42] NefFile.GetHash() --- .../SmartContract/ApplicationEngine.Contract.cs | 2 +- src/neo/SmartContract/Helper.cs | 10 ---------- src/neo/SmartContract/NefFile.cs | 11 +++++++++++ tests/neo.UnitTests/SmartContract/UT_Helper.cs | 15 --------------- tests/neo.UnitTests/SmartContract/UT_NefFile.cs | 15 +++++++++++++++ 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 027d79b9b8..f1f3a3c028 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -37,7 +37,7 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) AddGas(StoragePrice * (nefFile.Length + manifest.Length)); NefFile nef = nefFile.AsSerializable(); - UInt160 hash = Helper.ContractHash(tx.Sender, nef); + UInt160 hash = nef.GetHash(tx.Sender); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract != null) throw new InvalidOperationException($"Contract Already Exists: {hash}"); contract = new ContractState diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index 6fc5770448..dd9355a806 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -130,16 +130,6 @@ public static UInt160 ToScriptHash(this ReadOnlySpan script) return new UInt160(Crypto.Hash160(script)); } - public static UInt160 ContractHash(UInt160 sender, NefFile nef) - { - using var script = new ScriptBuilder(); - script.Emit(OpCode.ABORT); - script.EmitPush(sender); - script.EmitPush(nef.Script); - - return script.ToArray().ToScriptHash(); - } - internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snapshot, long gas, WitnessFlag filter = WitnessFlag.All) { if (gas < 0) return false; diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index 467408ade5..80b612d279 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -1,5 +1,6 @@ using Neo.Cryptography; using Neo.IO; +using Neo.VM; using System; using System.IO; @@ -57,6 +58,16 @@ public class NefFile : ISerializable Script.GetVarSize() + // Script sizeof(uint); // Checksum + public UInt160 GetHash(UInt160 sender) + { + using var script = new ScriptBuilder(); + script.Emit(OpCode.ABORT); + script.EmitPush(sender); + script.EmitPush(Script); + + return script.ToArray().ToScriptHash(); + } + public void Serialize(BinaryWriter writer) { SerializeHeader(writer); diff --git a/tests/neo.UnitTests/SmartContract/UT_Helper.cs b/tests/neo.UnitTests/SmartContract/UT_Helper.cs index 5f11d507a9..d2216ef83c 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Helper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Helper.cs @@ -27,20 +27,5 @@ public void TestIsMultiSigContract() }; Assert.IsFalse(case2.IsMultiSigContract()); } - - [TestMethod] - public void TestContractHash() - { - var nef = new NefFile() - { - Compiler = "test", - Version = new System.Version(), - Script = new byte[] { 1, 2, 3 } - }; - nef.CheckSum = NefFile.ComputeChecksum(nef); - - Assert.AreEqual("0xb4b7417195feca1cdb5a99504ab641d8c220ae99", Neo.SmartContract.Helper.ContractHash(UInt160.Zero, nef).ToString()); - Assert.AreEqual("0xe56e4ee87f89a70e9138432c387ad49f2ee5b55f", Neo.SmartContract.Helper.ContractHash(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), nef).ToString()); - } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs index cf8a086111..19cf07a64f 100644 --- a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs +++ b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs @@ -75,6 +75,21 @@ public void TestDeserialize() newFile1.Script.Should().BeEquivalentTo(file.Script); } + [TestMethod] + public void TestGetHash() + { + var nef = new NefFile() + { + Compiler = "test", + Version = new System.Version(), + Script = new byte[] { 1, 2, 3 } + }; + nef.CheckSum = NefFile.ComputeChecksum(nef); + + Assert.AreEqual("0xb4b7417195feca1cdb5a99504ab641d8c220ae99", nef.GetHash(UInt160.Zero).ToString()); + Assert.AreEqual("0xe56e4ee87f89a70e9138432c387ad49f2ee5b55f", nef.GetHash(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")).ToString()); + } + [TestMethod] public void TestGetSize() { From 4ccf14c05b5a79356d64ee34c36e0e8916fc4d21 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Sun, 22 Nov 2020 14:44:20 +0800 Subject: [PATCH 27/42] Remove double check --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index f1f3a3c028..a71bafd76c 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -79,8 +79,6 @@ protected internal void UpdateContract(byte[] nefFile, byte[] manifest) throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); NefFile nef = nefFile.AsSerializable(); - if (nef.Script.Length == 0) - throw new ArgumentException($"Invalid Script Length: {nef.Script.Length}"); // Update script contract.Script = nef.Script; From fe709fb0c2957b84fa77fa0abb3effe1be1a7dbe Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 24 Nov 2020 21:17:28 +0100 Subject: [PATCH 28/42] Some fixes --- src/neo/SmartContract/ApplicationEngine.Contract.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index a71bafd76c..9be1ea511c 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -156,7 +156,7 @@ private void CallContractInternal(ContractState contract, ContractMethodDescript 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 = LoadScript(contract.Script, flags & callingFlags, contract.Hash, method.Offset); + ExecutionContext context_new = LoadContract(contract, method.Name, flags & callingFlags, false); state = context_new.GetState(); state.CallingScriptHash = callingScriptHash; @@ -170,9 +170,6 @@ private void CallContractInternal(ContractState contract, ContractMethodDescript for (int i = args.Count - 1; i >= 0; i--) context_new.EvaluationStack.Push(args[i]); } - - method = contract.Manifest.Abi.GetMethod("_initialize"); - if (method != null) LoadClonedContext(context_new, method.Offset, false); } protected internal bool IsStandardContract(UInt160 hash) From 1b104590f52aa770718aabd4b31d0e7175bf31ec Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 24 Nov 2020 21:26:23 +0100 Subject: [PATCH 29/42] Some fixes --- src/neo/SmartContract/ApplicationEngine.cs | 1 + src/neo/Wallets/Wallet.cs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 64624b980f..cb05ae635d 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -171,6 +171,7 @@ internal protected void LoadClonedContext(ExecutionContext context, int initialP var newState = context.GetState(); newState.CallFlags = state.CallFlags; newState.ScriptHash = state.ScriptHash; + newState.CallingScriptHash = state.CallingScriptHash; // Configure CurrentContext and load the cloned one if (checkReturnValue) GetInvocationState(CurrentContext).Convention = ReturnTypeConvention.EnsureNotEmpty; diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index bbdfe65874..8ffebcbcb8 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -398,7 +398,6 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx) using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.Clone()); if (engine.LoadContract(contract, "verify", CallFlags.None, true) is null) throw new ArgumentException($"The smart contract {contract.Hash} haven't got verify method"); - engine.LoadScript(Array.Empty(), CallFlags.None); 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."); From 582deb24ce9d261ccd8a9e222745a2eb96826a81 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 25 Nov 2020 16:09:09 +0100 Subject: [PATCH 30/42] Reduce changes --- src/neo/SmartContract/ApplicationEngine.cs | 12 ++---------- src/neo/SmartContract/Callbacks/PointerCallback.cs | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index e1b765447b..1c508f60b0 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -163,16 +163,8 @@ protected override void LoadContext(ExecutionContext context) base.LoadContext(context); } - internal protected void LoadClonedContext(ExecutionContext context, int initialPosition, bool checkReturnValue) + internal void LoadContext(ExecutionContext context, bool checkReturnValue) { - // Copy script hash - var state = context.GetState(); - context = context.Clone(initialPosition); - var newState = context.GetState(); - newState.CallFlags = state.CallFlags; - newState.ScriptHash = state.ScriptHash; - newState.CallingScriptHash = state.CallingScriptHash; - // Configure CurrentContext and load the cloned one if (checkReturnValue) GetInvocationState(CurrentContext).Convention = ReturnTypeConvention.EnsureNotEmpty; LoadContext(context); @@ -203,7 +195,7 @@ public ExecutionContext LoadContract(ContractState contract, string method, Call if (init != null) { - LoadClonedContext(context, init.Offset, false); + LoadContext(context.Clone(init.Offset), false); } } diff --git a/src/neo/SmartContract/Callbacks/PointerCallback.cs b/src/neo/SmartContract/Callbacks/PointerCallback.cs index 69a3b7419b..6c06cf284b 100644 --- a/src/neo/SmartContract/Callbacks/PointerCallback.cs +++ b/src/neo/SmartContract/Callbacks/PointerCallback.cs @@ -19,7 +19,7 @@ public PointerCallback(ExecutionContext context, Pointer pointer, int parameters public override void LoadContext(ApplicationEngine engine, Array args) { - engine.LoadClonedContext(context, pointer, true); + engine.LoadContext(context.Clone(pointer), true); for (int i = args.Count - 1; i >= 0; i--) engine.Push(args[i]); } From ba92c2e49024437fa81710f96ab8b6b5fa88969a Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Thu, 26 Nov 2020 16:25:04 +0800 Subject: [PATCH 31/42] Move GetContractHash to Helper --- .../SmartContract/ApplicationEngine.Contract.cs | 2 +- src/neo/SmartContract/Helper.cs | 10 ++++++++++ src/neo/SmartContract/NefFile.cs | 11 ----------- tests/neo.UnitTests/SmartContract/UT_Helper.cs | 15 +++++++++++++++ tests/neo.UnitTests/SmartContract/UT_NefFile.cs | 15 --------------- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Contract.cs b/src/neo/SmartContract/ApplicationEngine.Contract.cs index 9be1ea511c..ddff9d9d93 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -37,7 +37,7 @@ protected internal void CreateContract(byte[] nefFile, byte[] manifest) AddGas(StoragePrice * (nefFile.Length + manifest.Length)); NefFile nef = nefFile.AsSerializable(); - UInt160 hash = nef.GetHash(tx.Sender); + UInt160 hash = Helper.GetContractHash(tx.Sender, nef.Script); ContractState contract = Snapshot.Contracts.TryGet(hash); if (contract != null) throw new InvalidOperationException($"Contract Already Exists: {hash}"); contract = new ContractState diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index 4f21fc3186..617e5f1b39 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -15,6 +15,16 @@ public static class Helper { private const long MaxVerificationGas = 0_50000000; + public static UInt160 GetContractHash(UInt160 sender, byte[] script) + { + using var sb = new ScriptBuilder(); + sb.Emit(OpCode.ABORT); + sb.EmitPush(sender); + sb.EmitPush(script); + + return sb.ToArray().ToScriptHash(); + } + public static UInt160 GetScriptHash(this ExecutionContext context) { return context.GetState().ScriptHash; diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index 80b612d279..467408ade5 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -1,6 +1,5 @@ using Neo.Cryptography; using Neo.IO; -using Neo.VM; using System; using System.IO; @@ -58,16 +57,6 @@ public class NefFile : ISerializable Script.GetVarSize() + // Script sizeof(uint); // Checksum - public UInt160 GetHash(UInt160 sender) - { - using var script = new ScriptBuilder(); - script.Emit(OpCode.ABORT); - script.EmitPush(sender); - script.EmitPush(Script); - - return script.ToArray().ToScriptHash(); - } - public void Serialize(BinaryWriter writer) { SerializeHeader(writer); diff --git a/tests/neo.UnitTests/SmartContract/UT_Helper.cs b/tests/neo.UnitTests/SmartContract/UT_Helper.cs index d2216ef83c..a6d8dafebf 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Helper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Helper.cs @@ -6,6 +6,21 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_Helper { + [TestMethod] + public void TestGetContractHash() + { + var nef = new NefFile() + { + Compiler = "test", + Version = new System.Version(), + Script = new byte[] { 1, 2, 3 } + }; + 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()); + } + [TestMethod] public void TestIsMultiSigContract() { diff --git a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs index 19cf07a64f..cf8a086111 100644 --- a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs +++ b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs @@ -75,21 +75,6 @@ public void TestDeserialize() newFile1.Script.Should().BeEquivalentTo(file.Script); } - [TestMethod] - public void TestGetHash() - { - var nef = new NefFile() - { - Compiler = "test", - Version = new System.Version(), - Script = new byte[] { 1, 2, 3 } - }; - nef.CheckSum = NefFile.ComputeChecksum(nef); - - Assert.AreEqual("0xb4b7417195feca1cdb5a99504ab641d8c220ae99", nef.GetHash(UInt160.Zero).ToString()); - Assert.AreEqual("0xe56e4ee87f89a70e9138432c387ad49f2ee5b55f", nef.GetHash(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")).ToString()); - } - [TestMethod] public void TestGetSize() { From d8ec4bcc7c6ce58d6d459c531ad203e04e6ca038 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Thu, 26 Nov 2020 16:27:49 +0800 Subject: [PATCH 32/42] Use GetContractHash for native contracts --- src/neo/SmartContract/Native/NativeContract.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index fc649ed0b4..199c1339d7 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -1,4 +1,5 @@ using Neo.IO; +using Neo.Ledger; using Neo.SmartContract.Manifest; using Neo.SmartContract.Native.Designate; using Neo.SmartContract.Native.Oracle; @@ -42,7 +43,7 @@ protected NativeContract() sb.EmitSysCall(ApplicationEngine.Neo_Native_Call); this.Script = sb.ToArray(); } - this.Hash = Script.ToScriptHash(); + this.Hash = Helper.GetContractHash(Blockchain.GenesisBlock.Transactions[0].Sender, Script); List descriptors = new List(); List safeMethods = new List(); foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) From 2b1f913064ab4ed3417fabb36ac64fa6be887458 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Thu, 26 Nov 2020 16:53:13 +0800 Subject: [PATCH 33/42] Fix UT paritially --- tests/neo.UnitTests/Extensions/NativeContractExtensions.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs index 84ead02131..678f3dc3e4 100644 --- a/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -19,16 +19,13 @@ public static StackItem Call(this NativeContract contract, StoreView snapshot, I { var engine = ApplicationEngine.Create(TriggerType.Application, container, snapshot); - engine.LoadScript(contract.Script); + engine.LoadContract(snapshot.Contracts[contract.Hash], method, CallFlags.All, true); var script = new ScriptBuilder(); for (var i = args.Length - 1; i >= 0; i--) script.EmitPush(args[i]); - script.EmitPush(args.Length); - script.Emit(OpCode.PACK); - script.EmitPush(method); engine.LoadScript(script.ToArray()); if (engine.Execute() != VMState.HALT) From f6bc60d5adc1771cf1fd74cceb4edcf5d67c538a Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 26 Nov 2020 12:20:06 +0100 Subject: [PATCH 34/42] Some fixes --- src/neo/SmartContract/Native/NativeContract.cs | 2 +- tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs | 3 ++- tests/neo.UnitTests/VM/UT_Helper.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index 199c1339d7..3db89689fa 100644 --- a/src/neo/SmartContract/Native/NativeContract.cs +++ b/src/neo/SmartContract/Native/NativeContract.cs @@ -43,7 +43,7 @@ protected NativeContract() sb.EmitSysCall(ApplicationEngine.Neo_Native_Call); this.Script = sb.ToArray(); } - this.Hash = Helper.GetContractHash(Blockchain.GenesisBlock.Transactions[0].Sender, Script); + this.Hash = Helper.GetContractHash((new[] { (byte)OpCode.PUSH1 }).ToScriptHash(), Script); List descriptors = new List(); List safeMethods = new List(); foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) diff --git a/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs index 3b7cc30426..9bbfc5aead 100644 --- a/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs @@ -43,10 +43,11 @@ public static bool Transfer(this NativeContract contract, StoreView snapshot, by engine.LoadScript(contract.Script); var script = new ScriptBuilder(); + script.Emit(OpCode.PUSHNULL); script.EmitPush(amount); script.EmitPush(to); script.EmitPush(from); - script.EmitPush(3); + script.EmitPush(4); script.Emit(OpCode.PACK); script.EmitPush("transfer"); engine.LoadScript(script.ToArray()); diff --git a/tests/neo.UnitTests/VM/UT_Helper.cs b/tests/neo.UnitTests/VM/UT_Helper.cs index 3cdab848bf..52da42361c 100644 --- a/tests/neo.UnitTests/VM/UT_Helper.cs +++ b/tests/neo.UnitTests/VM/UT_Helper.cs @@ -117,7 +117,7 @@ public void TestMakeScript() { byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); - Assert.AreEqual("0c14000000000000000000000000000000000000000011c00c0962616c616e63654f660c14bcaf41d684c7d4ad6ee0d99da9707b9d1f0c8e6641627d5b52", + Assert.AreEqual("0c14000000000000000000000000000000000000000011c00c0962616c616e63654f660c14ddeb7e9e9bf7ad8bf773c538c464d936d819a03641627d5b52", testScript.ToHexString()); } From 84b6100edfaa4e045f289acbb87caaecdcf50200 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 26 Nov 2020 12:25:48 +0100 Subject: [PATCH 35/42] Fix UT --- .../Extensions/Nep5NativeContractExtensions.cs | 10 +++++----- .../SmartContract/Native/Tokens/UT_NeoToken.cs | 18 +++++++++--------- .../SmartContract/Native/UT_NativeContract.cs | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs index 9bbfc5aead..8f38dbb7c8 100644 --- a/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.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); + engine.LoadScript(contract.Script, CallFlags.All, 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); + engine.LoadScript(contract.Script, CallFlags.All, 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); + engine.LoadScript(contract.Script, CallFlags.All, contract.Hash); var script = new ScriptBuilder(); script.EmitPush(account); @@ -108,7 +108,7 @@ public static BigInteger Decimals(this NativeContract contract) { var engine = ApplicationEngine.Create(TriggerType.Application, null, null); - engine.LoadScript(contract.Script); + engine.LoadScript(contract.Script, CallFlags.All, contract.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -128,7 +128,7 @@ public static string Symbol(this NativeContract contract) { var engine = ApplicationEngine.Create(TriggerType.Application, null, null); - engine.LoadScript(contract.Script); + engine.LoadScript(contract.Script, CallFlags.All, contract.Hash); var script = new ScriptBuilder(); script.EmitPush(0); diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 7723d5cdc4..7bcfd50cad 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -860,7 +860,7 @@ internal static bool Check_OnPersist(StoreView snapshot) var engine = ApplicationEngine.Create(TriggerType.OnPersist, new Nep5NativeContractExtensions.ManualWitness(committeesMultisign), snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -878,7 +878,7 @@ internal static bool Check_PostPersist(StoreView snapshot) var engine = ApplicationEngine.Create(TriggerType.PostPersist, new Nep5NativeContractExtensions.ManualWitness(committeesMultisign), snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -893,7 +893,7 @@ internal static (BigInteger Value, bool State) Check_GetGasPerBlock(StoreView sn { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -917,7 +917,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 Nep5NativeContractExtensions.ManualWitness(committeeMultiSigAddr), snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(gasPerBlock); @@ -942,7 +942,7 @@ internal static (bool State, bool Result) Check_Vote(StoreView snapshot, byte[] var engine = ApplicationEngine.Create(TriggerType.Application, new Nep5NativeContractExtensions.ManualWitness(signAccount ? new UInt160(account) : UInt160.Zero), snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); @@ -972,7 +972,7 @@ internal static (bool State, bool Result) Check_RegisterValidator(StoreView snap var engine = ApplicationEngine.Create(TriggerType.Application, new Nep5NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(pubkey); @@ -996,7 +996,7 @@ internal static ECPoint[] Check_GetCommittee(StoreView snapshot) { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(0); @@ -1016,7 +1016,7 @@ internal static (BigInteger Value, bool State) Check_UnclaimedGas(StoreView snap { var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(snapshot.PersistingBlock.Index); @@ -1078,7 +1078,7 @@ internal static (bool State, bool Result) Check_UnregisterCandidate(StoreView sn var engine = ApplicationEngine.Create(TriggerType.Application, new Nep5NativeContractExtensions.ManualWitness(Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(pubkey, ECCurve.Secp256r1)).ToScriptHash()), snapshot); - engine.LoadScript(NativeContract.NEO.Script); + engine.LoadScript(NativeContract.NEO.Script, CallFlags.All, NativeContract.NEO.Hash); var script = new ScriptBuilder(); script.EmitPush(pubkey); diff --git a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 9a537553f3..263d9a85df 100644 --- a/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -100,7 +100,7 @@ public void TestInvoke() { var snapshot = Blockchain.Singleton.GetSnapshot(); ApplicationEngine engine = ApplicationEngine.Create(TriggerType.OnPersist, null, snapshot, 0); - engine.LoadScript(testNativeContract.Script); + engine.LoadScript(testNativeContract.Script, CallFlags.All, testNativeContract.Hash); ByteString method1 = new ByteString(System.Text.Encoding.Default.GetBytes("wrongMethod")); VMArray args1 = new VMArray(); From 27b6bf6d4cc8d15b17aeca1e063049658ffcb363 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 27 Nov 2020 15:09:07 +0800 Subject: [PATCH 36/42] Rename parameters --- src/neo/Ledger/ContractState.cs | 8 ++++---- src/neo/SmartContract/Manifest/ContractPermission.cs | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 1c870c7bd4..a88c3ae9ef 100644 --- a/src/neo/Ledger/ContractState.cs +++ b/src/neo/Ledger/ContractState.cs @@ -68,12 +68,12 @@ void ISerializable.Serialize(BinaryWriter writer) /// /// Return true if is allowed /// - /// State - /// Method + /// The contract that we are calling + /// The method that we are calling /// Return true or false - public bool CanCall(ContractState state, string method) + public bool CanCall(ContractState targetContract, string targetMethod) { - return Manifest.Permissions.Any(u => u.IsAllowed(state, method)); + return Manifest.Permissions.Any(u => u.IsAllowed(targetContract, targetMethod)); } public JObject ToJson() diff --git a/src/neo/SmartContract/Manifest/ContractPermission.cs b/src/neo/SmartContract/Manifest/ContractPermission.cs index e7e20d6a1f..8bc2784cce 100644 --- a/src/neo/SmartContract/Manifest/ContractPermission.cs +++ b/src/neo/SmartContract/Manifest/ContractPermission.cs @@ -65,20 +65,20 @@ public JObject ToJson() /// /// Return true if is allowed /// - /// State - /// Method + /// The contract that we are calling + /// The method that we are calling /// Return true or false - public bool IsAllowed(ContractState state, string method) + public bool IsAllowed(ContractState targetContract, string targetMethod) { if (Contract.IsHash) { - if (!Contract.Hash.Equals(state.Hash)) return false; + if (!Contract.Hash.Equals(targetContract.Hash)) return false; } else if (Contract.IsGroup) { - if (state.Manifest.Groups.All(p => !p.PubKey.Equals(Contract.Group))) return false; + if (targetContract.Manifest.Groups.All(p => !p.PubKey.Equals(Contract.Group))) return false; } - return Methods.IsWildcard || Methods.Contains(method); + return Methods.IsWildcard || Methods.Contains(targetMethod); } } } From 7177b621b7e8454aec9e4e8bdbc0fc8f6e387f5f Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 27 Nov 2020 15:12:42 +0800 Subject: [PATCH 37/42] Update NefFile.cs --- src/neo/SmartContract/NefFile.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index 467408ade5..d103b291fb 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -36,14 +36,14 @@ public class NefFile : ISerializable public Version Version { get; set; } /// - /// Checksum + /// Script /// - public uint CheckSum { get; set; } + public byte[] Script { get; set; } /// - /// Script + /// Checksum /// - public byte[] Script { get; set; } + public uint CheckSum { get; set; } public const int MaxScriptLength = 1024 * 1024; From 4b08968abc16c86e6446400cfe2bfaeff6854262 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 27 Nov 2020 15:22:44 +0800 Subject: [PATCH 38/42] Update NefFile.cs --- src/neo/SmartContract/NefFile.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index d103b291fb..116647d118 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -94,10 +94,9 @@ public void Deserialize(BinaryReader reader) /// /// File /// Return checksum - unsafe public static uint ComputeChecksum(NefFile file) + public static uint ComputeChecksum(NefFile file) { - var data = file.ToArray(); - return BitConverter.ToUInt32(Crypto.Hash256(data.AsSpan().Slice(0, data.Length - sizeof(int)))); + return BitConverter.ToUInt32(Crypto.Hash256(file.ToArray().AsSpan(..^sizeof(int)))); } } } From 13f23a294ead7957ebabf3ddc116be8621fa9d9c Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 27 Nov 2020 12:11:12 +0100 Subject: [PATCH 39/42] Change version to string --- src/neo/SmartContract/NefFile.cs | 13 +++++-------- tests/neo.UnitTests/SmartContract/UT_Helper.cs | 2 +- .../SmartContract/UT_InteropService.NEO.cs | 10 +++++----- tests/neo.UnitTests/SmartContract/UT_NefFile.cs | 8 ++++---- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index 116647d118..820182dce4 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -11,7 +11,7 @@ namespace Neo.SmartContract /// +------------+-----------+------------------------------------------------------------+ /// | Magic | 4 bytes | Magic header | /// | Compiler | 32 bytes | Compiler used | - /// | Version | 16 bytes | Compiler version (Mayor, Minor, Build, Version) | + /// | Version | 16 bytes | Compiler version | /// +------------+-----------+------------------------------------------------------------+ /// | Script | Var bytes | Var bytes for the payload | /// +------------+-----------+------------------------------------------------------------+ @@ -33,7 +33,7 @@ public class NefFile : ISerializable /// /// Version /// - public Version Version { get; set; } + public string Version { get; set; } /// /// Script @@ -50,7 +50,7 @@ public class NefFile : ISerializable private const int HeaderSize = sizeof(uint) + // Magic 32 + // Compiler - (sizeof(int) * 4); // Version + 16; // Version public int Size => HeaderSize + // Header @@ -70,10 +70,7 @@ private void SerializeHeader(BinaryWriter writer) writer.WriteFixedString(Compiler, 32); // Version - writer.Write(Version.Major); - writer.Write(Version.Minor); - writer.Write(Version.Build); - writer.Write(Version.Revision); + writer.WriteFixedString(Version, 16); } public void Deserialize(BinaryReader reader) @@ -81,7 +78,7 @@ public void Deserialize(BinaryReader reader) if (reader.ReadUInt32() != Magic) throw new FormatException("Wrong magic"); Compiler = reader.ReadFixedString(32); - Version = new Version(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32()); + Version = reader.ReadFixedString(16); Script = reader.ReadVarBytes(MaxScriptLength); if (Script.Length == 0) throw new ArgumentException($"Script can't be empty"); diff --git a/tests/neo.UnitTests/SmartContract/UT_Helper.cs b/tests/neo.UnitTests/SmartContract/UT_Helper.cs index a6d8dafebf..dc666fab20 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Helper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Helper.cs @@ -12,7 +12,7 @@ public void TestGetContractHash() var nef = new NefFile() { Compiler = "test", - Version = new System.Version(), + Version = new System.Version().ToString(), Script = new byte[] { 1, 2, 3 } }; nef.CheckSum = NefFile.ComputeChecksum(nef); diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index e68edc33a9..bd6175cc60 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -132,7 +132,7 @@ public void TestContract_Create() { Script = new byte[0x01], Compiler = "", - Version = new Version(1, 2, 3, 4) + Version = new Version(1, 2, 3, 4).ToString() }; nef.CheckSum = NefFile.ComputeChecksum(nef); var nefFile = nef.ToArray(); @@ -147,7 +147,7 @@ public void TestContract_Create() { Script = new byte[NefFile.MaxScriptLength - 1], Compiler = "", - Version = new Version(1, 2, 3, 4) + Version = new Version(1, 2, 3, 4).ToString() }; script_exceedMaxLength.CheckSum = NefFile.ComputeChecksum(nef); Assert.ThrowsException(() => engine.CreateContract(script_exceedMaxLength.ToArray(), manifest.ToJson().ToByteArray(true))); @@ -180,7 +180,7 @@ public void TestContract_Update() { Script = new byte[] { 0x01 }, Compiler = "", - Version = new Version(1, 2, 3, 4) + Version = new Version(1, 2, 3, 4).ToString() }; nef.CheckSum = NefFile.ComputeChecksum(nef); var nefFile = nef.ToArray(); @@ -228,7 +228,7 @@ public void TestContract_Update_Invalid() var nefFile = new NefFile() { Script = new byte[] { 0x01 }, - Version = new Version(1, 2, 3, 4), + Version = new Version(1, 2, 3, 4).ToString(), Compiler = "" }; nefFile.CheckSum = NefFile.ComputeChecksum(nefFile); @@ -242,7 +242,7 @@ public void TestContract_Update_Invalid() nefFile = new NefFile() { Script = new byte[0], - Version = new Version(1, 2, 3, 4), + Version = new Version(1, 2, 3, 4).ToString(), Compiler = "" }; nefFile.CheckSum = NefFile.ComputeChecksum(nefFile); diff --git a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs index cf8a086111..2887321e6c 100644 --- a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs +++ b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs @@ -13,7 +13,7 @@ public class UT_NefFile public NefFile file = new NefFile() { Compiler = "".PadLeft(32, ' '), - Version = new Version(1, 2, 3, 4), + Version = new Version(1, 2, 3, 4).ToString(), Script = new byte[] { 0x01, 0x02, 0x03 } }; @@ -87,7 +87,7 @@ public void ParseTest() var file = new NefFile() { Compiler = "".PadLeft(32, ' '), - Version = new Version(1, 2, 3, 4), + Version = new Version(1, 2, 3, 4).ToString(), Script = new byte[] { 0x01, 0x02, 0x03 } }; @@ -97,7 +97,7 @@ public void ParseTest() file = data.AsSerializable(); Assert.AreEqual("".PadLeft(32, ' '), file.Compiler); - Assert.AreEqual(new Version(1, 2, 3, 4), file.Version); + Assert.AreEqual(new Version(1, 2, 3, 4).ToString(), file.Version); CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }, file.Script); } @@ -107,7 +107,7 @@ public void LimitTest() var file = new NefFile() { Compiler = "".PadLeft(byte.MaxValue, ' '), - Version = new Version(1, 2, 3, 4), + Version = new Version(1, 2, 3, 4).ToString(), Script = new byte[1024 * 1024], CheckSum = 0 }; From ecaf7ea4ca1125f6c42c3ff656cba53aab1e0080 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 29 Nov 2020 12:39:52 +0100 Subject: [PATCH 40/42] Increase to 32 --- src/neo/SmartContract/NefFile.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index 820182dce4..238190394b 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -11,7 +11,7 @@ namespace Neo.SmartContract /// +------------+-----------+------------------------------------------------------------+ /// | Magic | 4 bytes | Magic header | /// | Compiler | 32 bytes | Compiler used | - /// | Version | 16 bytes | Compiler version | + /// | Version | 32 bytes | Compiler version | /// +------------+-----------+------------------------------------------------------------+ /// | Script | Var bytes | Var bytes for the payload | /// +------------+-----------+------------------------------------------------------------+ @@ -49,8 +49,7 @@ public class NefFile : ISerializable private const int HeaderSize = sizeof(uint) + // Magic - 32 + // Compiler - 16; // Version + (32 * 2); // Compiler+Version public int Size => HeaderSize + // Header @@ -78,7 +77,7 @@ public void Deserialize(BinaryReader reader) if (reader.ReadUInt32() != Magic) throw new FormatException("Wrong magic"); Compiler = reader.ReadFixedString(32); - Version = reader.ReadFixedString(16); + Version = reader.ReadFixedString(32); Script = reader.ReadVarBytes(MaxScriptLength); if (Script.Length == 0) throw new ArgumentException($"Script can't be empty"); From 971be0dfd66372e38da7f3449085d707d90e4a1e Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 29 Nov 2020 12:44:29 +0100 Subject: [PATCH 41/42] Fix --- src/neo/SmartContract/NefFile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index 238190394b..3420f0597d 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -69,7 +69,7 @@ private void SerializeHeader(BinaryWriter writer) writer.WriteFixedString(Compiler, 32); // Version - writer.WriteFixedString(Version, 16); + writer.WriteFixedString(Version, 32); } public void Deserialize(BinaryReader reader) From 648e646f234a33acf011065d6dd3b7d2cc8e4030 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 30 Nov 2020 10:34:31 +0100 Subject: [PATCH 42/42] Fix UT --- tests/neo.UnitTests/SmartContract/UT_NefFile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs index 2887321e6c..7a5412d980 100644 --- a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs +++ b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs @@ -78,7 +78,7 @@ public void TestDeserialize() [TestMethod] public void TestGetSize() { - file.Size.Should().Be(4 + 32 + 16 + 4 + 4); + file.Size.Should().Be(4 + 32 + 32 + 4 + 4); } [TestMethod]