diff --git a/src/neo/Ledger/ContractState.cs b/src/neo/Ledger/ContractState.cs index 4017eb28ac..a88c3ae9ef 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 @@ -13,29 +14,20 @@ namespace Neo.Ledger public class ContractState : ICloneable, ISerializable, IInteroperable { public int Id; + public ushort UpdateCounter; + public UInt160 Hash; public byte[] Script; public ContractManifest Manifest; - 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(ushort) + UInt160.Length + Script.GetVarSize() + Manifest.Size; ContractState ICloneable.Clone() { return new ContractState { Id = Id, + UpdateCounter = UpdateCounter, + Hash = Hash, Script = Script, Manifest = Manifest.Clone() }; @@ -44,6 +36,8 @@ ContractState ICloneable.Clone() void ISerializable.Deserialize(BinaryReader reader) { Id = reader.ReadInt32(); + UpdateCounter = reader.ReadUInt16(); + Hash = reader.ReadSerializable(); Script = reader.ReadVarBytes(); Manifest = reader.ReadSerializable(); } @@ -51,6 +45,8 @@ void ISerializable.Deserialize(BinaryReader reader) void ICloneable.FromReplica(ContractState replica) { Id = replica.Id; + UpdateCounter = replica.UpdateCounter; + Hash = replica.Hash; Script = replica.Script; Manifest = replica.Manifest.Clone(); } @@ -63,15 +59,29 @@ void IInteroperable.FromStackItem(StackItem stackItem) void ISerializable.Serialize(BinaryWriter writer) { writer.Write(Id); + writer.Write(UpdateCounter); + writer.Write(Hash); writer.WriteVarBytes(Script); writer.Write(Manifest); } + /// + /// Return true if is allowed + /// + /// The contract that we are calling + /// The method that we are calling + /// Return true or false + public bool CanCall(ContractState targetContract, string targetMethod) + { + return Manifest.Permissions.Any(u => u.IsAllowed(targetContract, targetMethod)); + } + public JObject ToJson() { JObject json = new JObject(); json["id"] = Id; - json["hash"] = ScriptHash.ToString(); + json["updatecounter"] = UpdateCounter; + json["hash"] = Hash.ToString(); json["script"] = Convert.ToBase64String(Script); json["manifest"] = Manifest.ToJson(); return json; @@ -79,7 +89,7 @@ public JObject ToJson() public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new StackItem[] { 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 7e590af65b..ddff9d9d93 100644 --- a/src/neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/neo/SmartContract/ApplicationEngine.Contract.cs @@ -6,15 +6,12 @@ using Neo.SmartContract.Native; using Neo.VM; using System; -using System.Linq; using Array = Neo.VM.Types.Array; 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); @@ -28,22 +25,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 (!(ScriptContainer is Transaction tx)) + throw new InvalidOperationException(); + 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}"); - AddGas(StoragePrice * (script.Length + manifest.Length)); + AddGas(StoragePrice * (nefFile.Length + manifest.Length)); - UInt160 hash = script.ToScriptHash(); + NefFile nef = nefFile.AsSerializable(); + 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 { Id = Snapshot.ContractId.GetAndChange().NextId++, - Script = script.ToArray(), + UpdateCounter = 0, + Script = nef.Script, + Hash = hash, Manifest = ContractManifest.Parse(manifest) }; @@ -62,42 +64,35 @@ protected internal void CreateContract(byte[] script, byte[] manifest) CallContractInternal(contract, md, new Array(ReferenceCounter) { false }, CallFlags.All, ReturnTypeConvention.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(); - AddGas(StoragePrice * ((script?.Length ?? 0) + (manifest?.Length ?? 0))); + AddGas(StoragePrice * ((nefFile?.Length ?? 0) + (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 (nefFile != null) { - if (script.Length == 0 || script.Length > MaxContractLength) - throw new ArgumentException($"Invalid Script Length: {script.Length}"); - UInt160 hash_new = script.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); + if (nefFile.Length == 0) + throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}"); + + NefFile nef = nefFile.AsSerializable(); + + // Update script + contract.Script = nef.Script; } 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)) - throw new InvalidOperationException($"Invalid Manifest Hash: {contract.ScriptHash}"); + if (!contract.Manifest.IsValid(contract.Hash)) + throw new InvalidOperationException($"Invalid Manifest Hash: {contract.Hash}"); } - if (script != null) + contract.UpdateCounter++; // Increase update counter + if (nefFile != null) { ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy"); if (md != null) @@ -136,8 +131,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(contract.Manifest, method)) + ContractState currentContract = Snapshot.Contracts.TryGet(CurrentScriptHash); + 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); @@ -145,13 +140,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; @@ -161,11 +156,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 = LoadContract(contract, method.Name, flags & callingFlags); + ExecutionContext context_new = LoadContract(contract, method.Name, flags & callingFlags, false); 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 90a8168942..19bb653c9a 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, + Hash = contract.Hash, // Use the native hash Manifest = contract.Manifest }); contract.Initialize(this); diff --git a/src/neo/SmartContract/ApplicationEngine.cs b/src/neo/SmartContract/ApplicationEngine.cs index 8f61033e62..1c508f60b0 100644 --- a/src/neo/SmartContract/ApplicationEngine.cs +++ b/src/neo/SmartContract/ApplicationEngine.cs @@ -175,9 +175,9 @@ public ExecutionContext LoadContract(ContractState contract, string method, Call ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method); if (md is null) return null; - ExecutionContext context = LoadScript(contract.Script, callFlags, md.Offset); + ExecutionContext context = LoadScript(contract.Script, callFlags, contract.Hash, md.Offset); - if (NativeContract.IsNative(contract.ScriptHash)) + if (NativeContract.IsNative(contract.Hash)) { if (packParameters) { @@ -202,10 +202,15 @@ public ExecutionContext LoadContract(ContractState contract, string method, Call return 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/MethodCallback.cs b/src/neo/SmartContract/Callbacks/MethodCallback.cs index 578570a857..f2b0709d0a 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(this.contract.Manifest, method)) + ContractState currentContract = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash); + if (currentContract?.CanCall(this.contract, method) == false) throw new InvalidOperationException(); this.method = this.contract.Manifest.Abi.Methods.First(p => p.Name == method); } @@ -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/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index 9164d08770..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; @@ -170,7 +180,7 @@ internal static bool VerifyWitnesses(this IVerifiable verifiable, StoreView snap { if (NativeContract.IsNative(hashes[i])) return false; if (hashes[i] != verifiable.Witnesses[i].ScriptHash) return false; - engine.LoadScript(verification, callFlags, 0); + engine.LoadScript(verification, callFlags, hashes[i], 0); } engine.LoadScript(verifiable.Witnesses[i].InvocationScript, CallFlags.None); 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 b88260272d..a7755fa3da 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 @@ -29,11 +29,6 @@ public int Size } } - /// - /// Contract hash - /// - public UInt160 Hash => Abi.Hash; - /// /// Contract name /// @@ -76,17 +71,6 @@ public int Size /// public JObject Extra { get; set; } - /// - /// Return true if is allowed - /// - /// Manifest - /// Method - /// Return true or false - public bool CanCall(ContractManifest manifest, string method) - { - return Permissions.Any(u => u.IsAllowed(manifest, method)); - } - /// /// Parse ContractManifest from json /// @@ -179,7 +163,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..8bc2784cce 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,20 +65,20 @@ public JObject ToJson() /// /// Return true if is allowed /// - /// The manifest of which contract we are calling - /// Method + /// The contract that we are calling + /// The method that we are calling /// Return true or false - public bool IsAllowed(ContractManifest manifest, string method) + public bool IsAllowed(ContractState targetContract, string targetMethod) { if (Contract.IsHash) { - if (!Contract.Hash.Equals(manifest.Hash)) return false; + if (!Contract.Hash.Equals(targetContract.Hash)) return false; } else if (Contract.IsGroup) { - if (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); } } } diff --git a/src/neo/SmartContract/Native/NativeContract.cs b/src/neo/SmartContract/Native/NativeContract.cs index eea9db012a..3db89689fa 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((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)) @@ -66,7 +67,6 @@ protected NativeContract() SupportedStandards = new string[0], Abi = new ContractAbi() { - Hash = Hash, Events = System.Array.Empty(), Methods = descriptors.ToArray() }, diff --git a/src/neo/SmartContract/NefFile.cs b/src/neo/SmartContract/NefFile.cs index daa5d3b7f8..3420f0597d 100644 --- a/src/neo/SmartContract/NefFile.cs +++ b/src/neo/SmartContract/NefFile.cs @@ -11,13 +11,12 @@ 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 | + /// | Version | 32 bytes | Compiler version | /// +------------+-----------+------------------------------------------------------------+ /// | Script | Var bytes | Var bytes for the payload | /// +------------+-----------+------------------------------------------------------------+ + /// | Checksum | 4 bytes | First four bytes of double SHA256 hash | + /// +------------+-----------+------------------------------------------------------------+ /// public class NefFile : ISerializable { @@ -34,39 +33,34 @@ public class NefFile : ISerializable /// /// Version /// - public Version Version { get; set; } + public string Version { get; set; } /// - /// Script Hash + /// Script /// - public UInt160 ScriptHash { get; set; } + public byte[] Script { get; set; } /// /// Checksum /// public uint CheckSum { get; set; } - /// - /// Script - /// - public byte[] Script { get; set; } + public const int MaxScriptLength = 1024 * 1024; private const int HeaderSize = sizeof(uint) + // Magic - 32 + // Compiler - (sizeof(int) * 4) + // Version - UInt160.Length; // ScriptHash + (32 * 2); // Compiler+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) @@ -75,37 +69,20 @@ 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.Write(ScriptHash); + writer.WriteFixedString(Version, 32); } 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"); - } + Version = reader.ReadFixedString(32); + Script = reader.ReadVarBytes(MaxScriptLength); + if (Script.Length == 0) throw new ArgumentException($"Script can't be empty"); - Script = reader.ReadVarBytes(1024 * 1024); - - if (Script.ToScriptHash() != ScriptHash) - { - throw new FormatException("ScriptHash is different"); - } + CheckSum = reader.ReadUInt32(); + if (CheckSum != ComputeChecksum(this)) throw new FormatException("CRC verification fail"); } /// @@ -113,17 +90,9 @@ public void Deserialize(BinaryReader reader) /// /// File /// Return checksum - unsafe public static uint ComputeChecksum(NefFile file) + 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); + return BitConverter.ToUInt32(Crypto.Hash256(file.ToArray().AsSpan(..^sizeof(int)))); } } } diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index c61ebbeb3d..a764651e0d 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -397,10 +397,9 @@ public long CalculateNetworkFee(StoreView snapshot, Transaction tx) // Check verify cost using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.Clone()); if (engine.LoadContract(contract, "verify", CallFlags.None, true) is null) - throw new ArgumentException($"The smart contract {contract.ScriptHash} haven't got verify method"); - 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."); + throw new ArgumentException($"The smart contract {contract.Hash} haven't got verify method"); + 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/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/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) diff --git a/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs b/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs index 3b7cc30426..8f38dbb7c8 100644 --- a/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs +++ b/tests/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs @@ -40,13 +40,14 @@ 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); 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()); @@ -66,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); @@ -86,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); @@ -107,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); @@ -127,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/Ledger/UT_ContractState.cs b/tests/neo.UnitTests/Ledger/UT_ContractState.cs index 19bcda402e..47c8ee52cb 100644 --- a/tests/neo.UnitTests/Ledger/UT_ContractState.cs +++ b/tests/neo.UnitTests/Ledger/UT_ContractState.cs @@ -19,10 +19,11 @@ public class UT_ContractState [TestInitialize] public void TestSetup() { - manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); + manifest = TestUtils.CreateDefaultManifest(); contract = new ContractState { Script = script, + Hash = script.ToScriptHash(), Manifest = manifest }; } @@ -31,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] @@ -72,7 +73,16 @@ public void TestDeserialize() public void TestGetSize() { ISerializable newContract = contract; - newContract.Size.Should().Be(240); + newContract.Size.Should().Be(210); + } + + [TestMethod] + public void TestCanCall() + { + var temp = new ContractState() { Manifest = TestUtils.CreateDefaultManifest() }; + temp.Manifest.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); + + Assert.AreEqual(true, temp.CanCall(new ContractState() { Hash = UInt160.Zero, Manifest = TestUtils.CreateDefaultManifest() }, "AAA")); } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs b/tests/neo.UnitTests/SmartContract/Callbacks/UT_MethodCallback.cs index a26a69be60..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 }, + Hash = new byte[] { 1, 2, 3 }.ToScriptHash() }; - contract.Manifest.Abi.Hash = contract.ScriptHash; 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/Manifest/UT_ContractManifest.cs b/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs index c4b15df53d..57466e3606 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 = @"{""name"":""testManifest"",""groups"":[],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[],""extra"":null}"; + var json = @"{""name"":""testManifest"",""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 = @"{""name"":""testManifest"",""groups"":[],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""0x0000000000000000000000000000000000000000"",""methods"":[""method1"",""method2""]}],""trusts"":[],""safemethods"":[],""extra"":null}"; + var json = @"{""name"":""testManifest"",""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 = @"{""name"":""testManifest"",""groups"":[],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[""balanceOf""],""extra"":null}"; + var json = @"{""name"":""testManifest"",""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 = @"{""name"":""testManifest"",""groups"":[],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[""0x0000000000000000000000000000000000000001""],""safemethods"":[],""extra"":null}"; + var json = @"{""name"":""testManifest"",""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 = @"{""name"":""testManifest"",""groups"":[{""pubkey"":""03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"",""signature"":""QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==""}],""supportedstandards"":[],""abi"":{""hash"":""0x0000000000000000000000000000000000000000"",""methods"":[],""events"":[]},""permissions"":[{""contract"":""*"",""methods"":""*""}],""trusts"":[],""safemethods"":[],""extra"":null}"; + var json = @"{""name"":""testManifest"",""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(234, temp.Size); + var temp = TestUtils.CreateDefaultManifest(); + Assert.AreEqual(182, temp.Size); } [TestMethod] @@ -120,18 +113,10 @@ public void TestGenerator() Assert.IsNotNull(contractManifest); } - [TestMethod] - public void TestCanCall() - { - var temp = TestUtils.CreateDefaultManifest(UInt160.Zero); - temp.SafeMethods = WildcardContainer.Create(new string[] { "AAA" }); - Assert.AreEqual(true, temp.CanCall(TestUtils.CreateDefaultManifest(UInt160.Zero), "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..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; @@ -11,27 +12,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(new ContractState() { Hash = UInt160.Zero, Manifest = 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(new ContractState() { Hash = UInt160.Zero, Manifest = 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(new ContractState() { Hash = UInt160.Zero, Manifest = contractManifest3 }, "AAA")); contractPermission3.Contract = ContractPermissionDescriptor.CreateWildcard(); Random random4 = new Random(); @@ -41,11 +42,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(new ContractState() { Hash = UInt160.Zero, Manifest = contractManifest4 }, "AAA")); contractPermission4.Contract = ContractPermissionDescriptor.CreateWildcard(); } } 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(); diff --git a/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs b/tests/neo.UnitTests/SmartContract/UT_DeployedContract.cs index 1642ec64f2..16520b1049 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 }, + Hash = new byte[] { 1, 2, 3 }.ToScriptHash() }); Assert.AreEqual("0xb2e3fe334830b4741fa5d762f2ab36b90b86c49b", contract.ScriptHash.ToString()); diff --git a/tests/neo.UnitTests/SmartContract/UT_Helper.cs b/tests/neo.UnitTests/SmartContract/UT_Helper.cs index d2216ef83c..dc666fab20 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().ToString(), + 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_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index 72a682df98..bd6175cc60 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -114,60 +114,86 @@ 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] public void TestContract_Create() { + var nef = new NefFile() + { + Script = new byte[0x01], + Compiler = "", + Version = new Version(1, 2, 3, 4).ToString() + }; + nef.CheckSum = NefFile.ComputeChecksum(nef); + var nefFile = nef.ToArray(); + var manifest = TestUtils.CreateDefaultManifest(); 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, manifest.ToJson().ToByteArray(false))); - var manifest = TestUtils.CreateDefaultManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); - Assert.ThrowsException(() => engine.CreateContract(script, manifest.ToJson().ToByteArray(false))); + engine = GetEngine(true, true); + Assert.ThrowsException(() => engine.CreateContract(nefFile, new byte[ContractManifest.MaxLength + 1])); - 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[NefFile.MaxScriptLength - 1], + Compiler = "", + 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))); + engine = GetEngine(true, 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(); + engine.CreateContract(nefFile, manifest.ToJson().ToByteArray(false)); 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 }); - 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 }, + Compiler = "", + Version = new Version(1, 2, 3, 4).ToString() + }; + 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(); 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()); + var snapshot = Blockchain.Singleton.GetSnapshot(); + var state = TestUtils.GetContract(); + byte[] signature = Crypto.Sign(state.Hash.ToArray(), privkey, pubkey.EncodePoint(false).Skip(1).ToArray()); manifest.Groups = new ContractGroup[] { new ContractGroup() @@ -176,8 +202,7 @@ public void TestContract_Update() Signature = signature } }; - var snapshot = Blockchain.Singleton.GetSnapshot(); - var state = TestUtils.GetContract(); + var storageItem = new StorageItem { Value = new byte[] { 0x01 }, @@ -189,23 +214,42 @@ 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); - 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 }, + Version = new Version(1, 2, 3, 4).ToString(), + 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], + Version = new Version(1, 2, 3, 4).ToString(), + 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] @@ -224,7 +268,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 21e405f90d..8689c542f6 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -52,7 +52,8 @@ public void Runtime_GetNotifications_Test() snapshot.Contracts.Add(scriptHash2, new ContractState() { Script = script.ToArray(), - Manifest = TestUtils.CreateManifest(scriptHash2, "test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), + Hash = script.ToArray().ToScriptHash(), + Manifest = TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), }); } @@ -214,14 +215,15 @@ public void TestExecutionEngine_GetCallingScriptHash() var contract = new ContractState() { - Manifest = TestUtils.CreateManifest(scriptA.ToArray().ToScriptHash(), "test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), - Script = scriptA.ToArray() + Manifest = TestUtils.CreateManifest("test", ContractParameterType.Any, ContractParameterType.Integer, ContractParameterType.Integer), + Script = scriptA.ToArray(), + 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()); @@ -389,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] @@ -400,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(); } @@ -410,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(); } @@ -432,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 }); @@ -489,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 }); @@ -523,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 }); @@ -553,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 }); @@ -591,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)); } @@ -616,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 }) @@ -624,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]); @@ -632,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]); } @@ -689,26 +691,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_NefFile.cs b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs index 36a988d8b8..7a5412d980 100644 --- a/tests/neo.UnitTests/SmartContract/UT_NefFile.cs +++ b/tests/neo.UnitTests/SmartContract/UT_NefFile.cs @@ -13,14 +13,13 @@ 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 } }; [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 + 32 + 4 + 4); } [TestMethod] @@ -88,19 +87,17 @@ 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 } }; - file.ScriptHash = file.Script.ToScriptHash(); file.CheckSum = NefFile.ComputeChecksum(file); var data = file.ToArray(); file = data.AsSerializable(); Assert.AreEqual("".PadLeft(32, ' '), file.Compiler); - Assert.AreEqual(new Version(1, 2, 3, 4), file.Version); - Assert.AreEqual(file.Script.ToScriptHash(), file.ScriptHash); + Assert.AreEqual(new Version(1, 2, 3, 4).ToString(), file.Version); CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }, file.Script); } @@ -110,9 +107,8 @@ 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], - 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()); diff --git a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs index 1c3f430a45..e007b4c1d9 100644 --- a/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs +++ b/tests/neo.UnitTests/SmartContract/UT_SmartContractHelper.cs @@ -149,7 +149,8 @@ public void TestVerifyWitnesses() snapshot3.Contracts.Add(UInt160.Zero, new ContractState() { Script = Array.Empty(), - Manifest = TestUtils.CreateManifest(UInt160.Zero, "verify", ContractParameterType.Boolean, ContractParameterType.Signature), + Hash = Array.Empty().ToScriptHash(), + Manifest = TestUtils.CreateManifest("verify", ContractParameterType.Boolean, ContractParameterType.Signature), }); Assert.AreEqual(false, Neo.SmartContract.Helper.VerifyWitnesses(header3, snapshot3, 100)); @@ -158,10 +159,11 @@ public void TestVerifyWitnesses() var contract = new ContractState() { Script = "11".HexToBytes(), // 17 PUSH1 - Manifest = TestUtils.CreateManifest(UInt160.Zero, "verify", ContractParameterType.Boolean, ContractParameterType.Signature), // Offset = 0 + 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 b69c5f4759..13b559cc15 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -327,29 +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.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); - 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); - contracts.Add(contractA.ScriptHash, contractA); - contracts.Add(contractB.ScriptHash, contractB); - contracts.Add(contractC.ScriptHash, contractC); + 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.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 e1d78738d3..9e7d8e5cfd 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() { @@ -27,7 +27,6 @@ public static ContractManifest CreateDefaultManifest(UInt160 hash) SupportedStandards = Array.Empty(), Abi = new ContractAbi() { - Hash = hash, Events = new ContractEventDescriptor[0], Methods = new ContractMethodDescriptor[0] }, @@ -38,9 +37,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,8 @@ internal static ContractState GetContract(string method = "test", int parameters { Id = 0x43000000, Script = new byte[] { 0x01, 0x01, 0x01, 0x01 }, - Manifest = CreateManifest(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"), method, ContractParameterType.Any, Enumerable.Repeat(ContractParameterType.Any, parametersCount).ToArray()) + Hash = new byte[] { 0x01, 0x01, 0x01, 0x01 }.ToScriptHash(), + Manifest = CreateManifest(method, ContractParameterType.Any, Enumerable.Repeat(ContractParameterType.Any, parametersCount).ToArray()) }; } @@ -124,7 +124,7 @@ internal static ContractState GetContract(byte[] script) { Id = 1, Script = script, - Manifest = CreateDefaultManifest(script.ToScriptHash()) + Manifest = CreateDefaultManifest() }; } 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()); }