diff --git a/src/neo/Ledger/Blockchain.cs b/src/neo/Ledger/Blockchain.cs index 819289b333..74d06806e4 100644 --- a/src/neo/Ledger/Blockchain.cs +++ b/src/neo/Ledger/Blockchain.cs @@ -157,7 +157,7 @@ private static Transaction DeployNativeContracts() byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitSysCall(InteropService.Neo_Native_Deploy); + sb.EmitSysCall(InteropService.Native.Deploy); script = sb.ToArray(); } return new Transaction diff --git a/src/neo/SmartContract/StackItemSerializer.cs b/src/neo/SmartContract/BinarySerializer.cs similarity index 99% rename from src/neo/SmartContract/StackItemSerializer.cs rename to src/neo/SmartContract/BinarySerializer.cs index 24f5128ff1..1c8f2f9088 100644 --- a/src/neo/SmartContract/StackItemSerializer.cs +++ b/src/neo/SmartContract/BinarySerializer.cs @@ -11,7 +11,7 @@ namespace Neo.SmartContract { - internal static class StackItemSerializer + internal static class BinarySerializer { public static StackItem Deserialize(byte[] data, uint maxItemSize, ReferenceCounter referenceCounter = null) { diff --git a/src/neo/SmartContract/Contract.cs b/src/neo/SmartContract/Contract.cs index 63384af675..022e6a4c3f 100644 --- a/src/neo/SmartContract/Contract.cs +++ b/src/neo/SmartContract/Contract.cs @@ -82,7 +82,7 @@ public static byte[] CreateMultiSigRedeemScript(int m, params ECPoint[] publicKe } sb.EmitPush(publicKeys.Length); sb.Emit(OpCode.PUSHNULL); - sb.EmitSysCall(InteropService.Neo_Crypto_ECDsaCheckMultiSig); + sb.EmitSysCall(InteropService.Crypto.ECDsaCheckMultiSig); return sb.ToArray(); } } @@ -102,7 +102,7 @@ public static byte[] CreateSignatureRedeemScript(ECPoint publicKey) { sb.EmitPush(publicKey.EncodePoint(true)); sb.Emit(OpCode.PUSHNULL); - sb.EmitSysCall(InteropService.Neo_Crypto_ECDsaVerify); + sb.EmitSysCall(InteropService.Crypto.ECDsaVerify); return sb.ToArray(); } } diff --git a/src/neo/SmartContract/Helper.cs b/src/neo/SmartContract/Helper.cs index 0bb328bd0a..1e6b29e7bb 100644 --- a/src/neo/SmartContract/Helper.cs +++ b/src/neo/SmartContract/Helper.cs @@ -62,7 +62,7 @@ public static bool IsMultiSigContract(this byte[] script, out int m, out int n) if (script[i++] != (byte)OpCode.PUSHNULL) return false; if (script[i++] != (byte)OpCode.SYSCALL) return false; if (script.Length != i + 4) return false; - if (BitConverter.ToUInt32(script, i) != InteropService.Neo_Crypto_ECDsaCheckMultiSig) + if (BitConverter.ToUInt32(script, i) != InteropService.Crypto.ECDsaCheckMultiSig) return false; return true; } @@ -74,7 +74,7 @@ public static bool IsSignatureContract(this byte[] script) || script[1] != 33 || script[35] != (byte)OpCode.PUSHNULL || script[36] != (byte)OpCode.SYSCALL - || BitConverter.ToUInt32(script, 37) != InteropService.Neo_Crypto_ECDsaVerify) + || BitConverter.ToUInt32(script, 37) != InteropService.Crypto.ECDsaVerify) return false; return true; } diff --git a/src/neo/SmartContract/InteropDescriptor.cs b/src/neo/SmartContract/InteropDescriptor.cs index 9ae9e5c992..5cdcf6024a 100644 --- a/src/neo/SmartContract/InteropDescriptor.cs +++ b/src/neo/SmartContract/InteropDescriptor.cs @@ -3,22 +3,22 @@ namespace Neo.SmartContract { - internal class InteropDescriptor + public class InteropDescriptor { public string Method { get; } public uint Hash { get; } - public Func Handler { get; } + internal Func Handler { get; } public long Price { get; } public Func PriceCalculator { get; } public TriggerType AllowedTriggers { get; } - public InteropDescriptor(string method, Func handler, long price, TriggerType allowedTriggers) + internal InteropDescriptor(string method, Func handler, long price, TriggerType allowedTriggers) : this(method, handler, allowedTriggers) { this.Price = price; } - public InteropDescriptor(string method, Func handler, Func priceCalculator, TriggerType allowedTriggers) + internal InteropDescriptor(string method, Func handler, Func priceCalculator, TriggerType allowedTriggers) : this(method, handler, allowedTriggers) { this.PriceCalculator = priceCalculator; @@ -36,5 +36,10 @@ public long GetPrice(EvaluationStack stack) { return PriceCalculator is null ? Price : PriceCalculator(stack); } + + public static implicit operator uint(InteropDescriptor descriptor) + { + return descriptor.Hash; + } } } diff --git a/src/neo/SmartContract/InteropService.Binary.cs b/src/neo/SmartContract/InteropService.Binary.cs new file mode 100644 index 0000000000..450e4744c5 --- /dev/null +++ b/src/neo/SmartContract/InteropService.Binary.cs @@ -0,0 +1,50 @@ +using Neo.VM; +using Neo.VM.Types; +using System; +using System.IO; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Binary + { + public static readonly InteropDescriptor Serialize = Register("System.Binary.Serialize", Binary_Serialize, 0_00100000, TriggerType.All); + public static readonly InteropDescriptor Deserialize = Register("System.Binary.Deserialize", Binary_Deserialize, 0_00500000, TriggerType.All); + + private static bool Binary_Serialize(ApplicationEngine engine) + { + byte[] serialized; + try + { + serialized = BinarySerializer.Serialize(engine.CurrentContext.EvaluationStack.Pop(), engine.MaxItemSize); + } + catch + { + return false; + } + engine.CurrentContext.EvaluationStack.Push(serialized); + return true; + } + + private static bool Binary_Deserialize(ApplicationEngine engine) + { + StackItem item; + try + { + item = BinarySerializer.Deserialize(engine.CurrentContext.EvaluationStack.Pop().GetSpan(), engine.MaxItemSize, engine.ReferenceCounter); + } + catch (FormatException) + { + return false; + } + catch (IOException) + { + return false; + } + engine.CurrentContext.EvaluationStack.Push(item); + return true; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.Blockchain.cs b/src/neo/SmartContract/InteropService.Blockchain.cs new file mode 100644 index 0000000000..d5cdad0769 --- /dev/null +++ b/src/neo/SmartContract/InteropService.Blockchain.cs @@ -0,0 +1,107 @@ +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.VM; +using Neo.VM.Types; +using System; +using System.Numerics; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Blockchain + { + public static readonly InteropDescriptor GetHeight = Register("System.Blockchain.GetHeight", Blockchain_GetHeight, 0_00000400, TriggerType.Application); + public static readonly InteropDescriptor GetBlock = Register("System.Blockchain.GetBlock", Blockchain_GetBlock, 0_02500000, TriggerType.Application); + public static readonly InteropDescriptor GetTransaction = Register("System.Blockchain.GetTransaction", Blockchain_GetTransaction, 0_01000000, TriggerType.Application); + public static readonly InteropDescriptor GetTransactionHeight = Register("System.Blockchain.GetTransactionHeight", Blockchain_GetTransactionHeight, 0_01000000, TriggerType.Application); + public static readonly InteropDescriptor GetTransactionFromBlock = Register("System.Blockchain.GetTransactionFromBlock", Blockchain_GetTransactionFromBlock, 0_01000000, TriggerType.Application); + public static readonly InteropDescriptor GetContract = Register("System.Blockchain.GetContract", Blockchain_GetContract, 0_01000000, TriggerType.Application); + + private static bool Blockchain_GetHeight(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push(engine.Snapshot.Height); + return true; + } + + private static bool Blockchain_GetBlock(ApplicationEngine engine) + { + ReadOnlySpan data = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + UInt256 hash; + if (data.Length <= 5) + hash = Ledger.Blockchain.Singleton.GetBlockHash((uint)new BigInteger(data)); + else if (data.Length == 32) + hash = new UInt256(data); + else + return false; + + Block block = hash != null ? engine.Snapshot.GetBlock(hash) : null; + if (block == null) + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + else + engine.CurrentContext.EvaluationStack.Push(block.ToStackItem(engine.ReferenceCounter)); + return true; + } + + private static bool Blockchain_GetTransaction(ApplicationEngine engine) + { + ReadOnlySpan hash = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); + if (tx == null) + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + else + engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem(engine.ReferenceCounter)); + return true; + } + + private static bool Blockchain_GetTransactionHeight(ApplicationEngine engine) + { + ReadOnlySpan hash = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + var tx = engine.Snapshot.Transactions.TryGet(new UInt256(hash)); + engine.CurrentContext.EvaluationStack.Push(tx != null ? new BigInteger(tx.BlockIndex) : BigInteger.MinusOne); + return true; + } + + private static bool Blockchain_GetTransactionFromBlock(ApplicationEngine engine) + { + ReadOnlySpan data = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + UInt256 hash; + if (data.Length <= 5) + hash = Ledger.Blockchain.Singleton.GetBlockHash((uint)new BigInteger(data)); + else if (data.Length == 32) + hash = new UInt256(data); + else + return false; + + TrimmedBlock block = hash != null ? engine.Snapshot.Blocks.TryGet(hash) : null; + if (block == null) + { + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + } + else + { + int index = (int)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); + if (index < 0 || index >= block.Hashes.Length - 1) return false; + + Transaction tx = engine.Snapshot.GetTransaction(block.Hashes[index + 1]); + if (tx == null) + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + else + engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem(engine.ReferenceCounter)); + } + return true; + } + + private static bool Blockchain_GetContract(ApplicationEngine engine) + { + UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetSpan()); + ContractState contract = engine.Snapshot.Contracts.TryGet(hash); + if (contract == null) + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + else + engine.CurrentContext.EvaluationStack.Push(contract.ToStackItem(engine.ReferenceCounter)); + return true; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.Contract.cs b/src/neo/SmartContract/InteropService.Contract.cs new file mode 100644 index 0000000000..0e50ea8f6d --- /dev/null +++ b/src/neo/SmartContract/InteropService.Contract.cs @@ -0,0 +1,153 @@ +using Neo.IO; +using Neo.Ledger; +using Neo.SmartContract.Manifest; +using Neo.VM; +using Neo.VM.Types; +using System.Linq; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Contract + { + public static readonly InteropDescriptor Create = Register("System.Contract.Create", Contract_Create, GetDeploymentPrice, TriggerType.Application); + public static readonly InteropDescriptor Update = Register("System.Contract.Update", Contract_Update, GetDeploymentPrice, TriggerType.Application); + public static readonly InteropDescriptor Destroy = Register("System.Contract.Destroy", Contract_Destroy, 0_01000000, TriggerType.Application); + public static readonly InteropDescriptor Call = Register("System.Contract.Call", Contract_Call, 0_01000000, TriggerType.System | TriggerType.Application); + public static readonly InteropDescriptor IsStandard = Register("System.Contract.IsStandard", Contract_IsStandard, 0_00030000, TriggerType.All); + + private static long GetDeploymentPrice(EvaluationStack stack) + { + int size = stack.Peek(0).GetByteLength() + stack.Peek(1).GetByteLength(); + return Storage.GasPerByte * size; + } + + private static bool Contract_Create(ApplicationEngine engine) + { + byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + if (script.Length > 1024 * 1024) return false; + + var manifest = engine.CurrentContext.EvaluationStack.Pop().GetString(); + if (manifest.Length > ContractManifest.MaxLength) return false; + + UInt160 hash = script.ToScriptHash(); + ContractState contract = engine.Snapshot.Contracts.TryGet(hash); + if (contract != null) return false; + contract = new ContractState + { + Script = script, + Manifest = ContractManifest.Parse(manifest) + }; + + if (!contract.Manifest.IsValid(hash)) return false; + + engine.Snapshot.Contracts.Add(hash, contract); + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(contract)); + return true; + } + + private static bool Contract_Update(ApplicationEngine engine) + { + byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + if (script.Length > 1024 * 1024) return false; + var manifest = engine.CurrentContext.EvaluationStack.Pop().GetString(); + if (manifest.Length > ContractManifest.MaxLength) return false; + + var contract = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash); + if (contract is null) return false; + + if (script.Length > 0) + { + UInt160 hash_new = script.ToScriptHash(); + if (hash_new.Equals(engine.CurrentScriptHash)) return false; + if (engine.Snapshot.Contracts.TryGet(hash_new) != null) return false; + contract = new ContractState + { + Script = script, + Manifest = contract.Manifest + }; + contract.Manifest.Abi.Hash = hash_new; + engine.Snapshot.Contracts.Add(hash_new, contract); + if (contract.HasStorage) + { + foreach (var (key, value) in engine.Snapshot.Storages.Find(engine.CurrentScriptHash.ToArray()).ToArray()) + { + engine.Snapshot.Storages.Add(new StorageKey + { + ScriptHash = hash_new, + Key = key.Key + }, new StorageItem + { + Value = value.Value, + IsConstant = false + }); + } + } + Contract_Destroy(engine); + } + if (manifest.Length > 0) + { + contract = engine.Snapshot.Contracts.GetAndChange(contract.ScriptHash); + contract.Manifest = ContractManifest.Parse(manifest); + if (!contract.Manifest.IsValid(contract.ScriptHash)) return false; + if (!contract.HasStorage && engine.Snapshot.Storages.Find(engine.CurrentScriptHash.ToArray()).Any()) return false; + } + + return true; + } + + private static bool Contract_Destroy(ApplicationEngine engine) + { + UInt160 hash = engine.CurrentScriptHash; + ContractState contract = engine.Snapshot.Contracts.TryGet(hash); + if (contract == null) return true; + engine.Snapshot.Contracts.Delete(hash); + if (contract.HasStorage) + foreach (var (key, _) in engine.Snapshot.Storages.Find(hash.ToArray())) + engine.Snapshot.Storages.Delete(key); + return true; + } + + private static bool Contract_Call(ApplicationEngine engine) + { + StackItem contractHash = engine.CurrentContext.EvaluationStack.Pop(); + + ContractState contract = engine.Snapshot.Contracts.TryGet(new UInt160(contractHash.GetSpan())); + if (contract is null) return false; + + StackItem method = engine.CurrentContext.EvaluationStack.Pop(); + StackItem args = engine.CurrentContext.EvaluationStack.Pop(); + ContractManifest currentManifest = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash)?.Manifest; + + if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method.GetString())) + return false; + + if (engine.InvocationCounter.TryGetValue(contract.ScriptHash, out var counter)) + { + engine.InvocationCounter[contract.ScriptHash] = counter + 1; + } + else + { + engine.InvocationCounter[contract.ScriptHash] = 1; + } + + UInt160 callingScriptHash = engine.CurrentScriptHash; + ExecutionContext context_new = engine.LoadScript(contract.Script, 1); + context_new.GetState().CallingScriptHash = callingScriptHash; + context_new.EvaluationStack.Push(args); + context_new.EvaluationStack.Push(method); + return true; + } + + private static bool Contract_IsStandard(ApplicationEngine engine) + { + UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetSpan()); + ContractState contract = engine.Snapshot.Contracts.TryGet(hash); + bool isStandard = contract is null || contract.Script.IsStandardContract(); + engine.CurrentContext.EvaluationStack.Push(isStandard); + return true; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.Crypto.cs b/src/neo/SmartContract/InteropService.Crypto.cs new file mode 100644 index 0000000000..f1c2f491e0 --- /dev/null +++ b/src/neo/SmartContract/InteropService.Crypto.cs @@ -0,0 +1,116 @@ +using Neo.Cryptography; +using Neo.Network.P2P; +using Neo.Network.P2P.Payloads; +using Neo.VM; +using Neo.VM.Types; +using System; +using System.Linq; +using Array = Neo.VM.Types.Array; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Crypto + { + public static readonly InteropDescriptor ECDsaVerify = Register("Neo.Crypto.ECDsaVerify", Crypto_ECDsaVerify, 0_01000000, TriggerType.All); + public static readonly InteropDescriptor ECDsaCheckMultiSig = Register("Neo.Crypto.ECDsaCheckMultiSig", Crypto_ECDsaCheckMultiSig, GetECDsaCheckMultiSigPrice, TriggerType.All); + + private static long GetECDsaCheckMultiSigPrice(EvaluationStack stack) + { + if (stack.Count < 2) return 0; + var item = stack.Peek(1); + int n; + if (item is Array array) n = array.Count; + else n = (int)item.GetBigInteger(); + if (n < 1) return 0; + return ECDsaVerify.Price * n; + } + + private static bool Crypto_ECDsaVerify(ApplicationEngine engine) + { + StackItem item0 = engine.CurrentContext.EvaluationStack.Pop(); + ReadOnlySpan message = item0 switch + { + InteropInterface _interface => _interface.GetInterface().GetHashData(), + Null _ => engine.ScriptContainer.GetHashData(), + _ => item0.GetSpan() + }; + ReadOnlySpan pubkey = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + ReadOnlySpan signature = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + try + { + engine.CurrentContext.EvaluationStack.Push(Cryptography.Crypto.VerifySignature(message, signature, pubkey)); + } + catch (ArgumentException) + { + engine.CurrentContext.EvaluationStack.Push(false); + } + return true; + } + + private static bool Crypto_ECDsaCheckMultiSig(ApplicationEngine engine) + { + StackItem item0 = engine.CurrentContext.EvaluationStack.Pop(); + ReadOnlySpan message = item0 switch + { + InteropInterface _interface => _interface.GetInterface().GetHashData(), + Null _ => engine.ScriptContainer.GetHashData(), + _ => item0.GetSpan() + }; + int n; + byte[][] pubkeys; + StackItem item = engine.CurrentContext.EvaluationStack.Pop(); + if (item is Array array1) + { + pubkeys = array1.Select(p => p.GetSpan().ToArray()).ToArray(); + n = pubkeys.Length; + if (n == 0) return false; + } + else + { + n = (int)item.GetBigInteger(); + if (n < 1 || n > engine.CurrentContext.EvaluationStack.Count) return false; + pubkeys = new byte[n][]; + for (int i = 0; i < n; i++) + pubkeys[i] = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + } + int m; + byte[][] signatures; + item = engine.CurrentContext.EvaluationStack.Pop(); + if (item is Array array2) + { + signatures = array2.Select(p => p.GetSpan().ToArray()).ToArray(); + m = signatures.Length; + if (m == 0 || m > n) return false; + } + else + { + m = (int)item.GetBigInteger(); + if (m < 1 || m > n || m > engine.CurrentContext.EvaluationStack.Count) return false; + signatures = new byte[m][]; + for (int i = 0; i < m; i++) + signatures[i] = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + } + bool fSuccess = true; + try + { + for (int i = 0, j = 0; fSuccess && i < m && j < n;) + { + if (Cryptography.Crypto.VerifySignature(message, signatures[i], pubkeys[j])) + i++; + j++; + if (m - i > n - j) + fSuccess = false; + } + } + catch (ArgumentException) + { + fSuccess = false; + } + engine.CurrentContext.EvaluationStack.Push(fSuccess); + return true; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.Enumerator.cs b/src/neo/SmartContract/InteropService.Enumerator.cs new file mode 100644 index 0000000000..143e040ba4 --- /dev/null +++ b/src/neo/SmartContract/InteropService.Enumerator.cs @@ -0,0 +1,69 @@ +using Neo.SmartContract.Enumerators; +using Neo.SmartContract.Iterators; +using Neo.VM.Types; +using Array = Neo.VM.Types.Array; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Enumerator + { + public static readonly InteropDescriptor Create = Register("System.Enumerator.Create", Enumerator_Create, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor Next = Register("System.Enumerator.Next", Enumerator_Next, 0_01000000, TriggerType.All); + public static readonly InteropDescriptor Value = Register("System.Enumerator.Value", Enumerator_Value, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor Concat = Register("System.Enumerator.Concat", Enumerator_Concat, 0_00000400, TriggerType.All); + + private static bool Enumerator_Create(ApplicationEngine engine) + { + IEnumerator enumerator; + switch (engine.CurrentContext.EvaluationStack.Pop()) + { + case Array array: + enumerator = new ArrayWrapper(array); + break; + case PrimitiveType primitive: + enumerator = new ByteArrayWrapper(primitive); + break; + default: + return false; + } + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(enumerator)); + return true; + } + + private static bool Enumerator_Next(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + IEnumerator enumerator = _interface.GetInterface(); + engine.CurrentContext.EvaluationStack.Push(enumerator.Next()); + return true; + } + return false; + } + + private static bool Enumerator_Value(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + IEnumerator enumerator = _interface.GetInterface(); + engine.CurrentContext.EvaluationStack.Push(enumerator.Value()); + return true; + } + return false; + } + + private static bool Enumerator_Concat(ApplicationEngine engine) + { + if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface1)) return false; + if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface2)) return false; + IEnumerator first = _interface1.GetInterface(); + IEnumerator second = _interface2.GetInterface(); + IEnumerator result = new ConcatenatedEnumerator(first, second); + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(result)); + return true; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.Iterator.cs b/src/neo/SmartContract/InteropService.Iterator.cs new file mode 100644 index 0000000000..0a99e2848b --- /dev/null +++ b/src/neo/SmartContract/InteropService.Iterator.cs @@ -0,0 +1,84 @@ +using Neo.SmartContract.Enumerators; +using Neo.SmartContract.Iterators; +using Neo.VM.Types; +using Array = Neo.VM.Types.Array; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Iterator + { + public static readonly InteropDescriptor Create = Register("System.Iterator.Create", Iterator_Create, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor Key = Register("System.Iterator.Key", Iterator_Key, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor Keys = Register("System.Iterator.Keys", Iterator_Keys, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor Values = Register("System.Iterator.Values", Iterator_Values, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor Concat = Register("System.Iterator.Concat", Iterator_Concat, 0_00000400, TriggerType.All); + + private static bool Iterator_Create(ApplicationEngine engine) + { + IIterator iterator; + switch (engine.CurrentContext.EvaluationStack.Pop()) + { + case Array array: + iterator = new ArrayWrapper(array); + break; + case Map map: + iterator = new MapWrapper(map); + break; + case PrimitiveType primitive: + iterator = new ByteArrayWrapper(primitive); + break; + default: + return false; + } + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(iterator)); + return true; + } + + private static bool Iterator_Key(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + IIterator iterator = _interface.GetInterface(); + engine.CurrentContext.EvaluationStack.Push(iterator.Key()); + return true; + } + return false; + } + + private static bool Iterator_Keys(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + IIterator iterator = _interface.GetInterface(); + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new IteratorKeysWrapper(iterator))); + return true; + } + return false; + } + + private static bool Iterator_Values(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + IIterator iterator = _interface.GetInterface(); + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new IteratorValuesWrapper(iterator))); + return true; + } + return false; + } + + private static bool Iterator_Concat(ApplicationEngine engine) + { + if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface1)) return false; + if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface2)) return false; + IIterator first = _interface1.GetInterface(); + IIterator second = _interface2.GetInterface(); + IIterator result = new ConcatenatedIterator(first, second); + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(result)); + return true; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.Json.cs b/src/neo/SmartContract/InteropService.Json.cs new file mode 100644 index 0000000000..45e12db545 --- /dev/null +++ b/src/neo/SmartContract/InteropService.Json.cs @@ -0,0 +1,45 @@ +using Neo.IO.Json; +using Neo.VM; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Json + { + public static readonly InteropDescriptor Serialize = Register("System.Json.Serialize", Json_Serialize, 0_00100000, TriggerType.All); + public static readonly InteropDescriptor Deserialize = Register("System.Json.Deserialize", Json_Deserialize, 0_00500000, TriggerType.All); + + private static bool Json_Serialize(ApplicationEngine engine) + { + var item = engine.CurrentContext.EvaluationStack.Pop(); + try + { + var json = JsonSerializer.SerializeToByteArray(item, engine.MaxItemSize); + engine.CurrentContext.EvaluationStack.Push(json); + return true; + } + catch + { + return false; + } + } + + private static bool Json_Deserialize(ApplicationEngine engine) + { + var json = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + try + { + var obj = JObject.Parse(json, 10); + var item = JsonSerializer.Deserialize(obj, engine.ReferenceCounter); + engine.CurrentContext.EvaluationStack.Push(item); + return true; + } + catch + { + return false; + } + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.NEO.cs b/src/neo/SmartContract/InteropService.NEO.cs deleted file mode 100644 index 5ba3675090..0000000000 --- a/src/neo/SmartContract/InteropService.NEO.cs +++ /dev/null @@ -1,408 +0,0 @@ -using Neo.Cryptography; -using Neo.IO; -using Neo.IO.Json; -using Neo.Ledger; -using Neo.Network.P2P; -using Neo.Network.P2P.Payloads; -using Neo.SmartContract.Enumerators; -using Neo.SmartContract.Iterators; -using Neo.SmartContract.Manifest; -using Neo.SmartContract.Native; -using Neo.VM; -using Neo.VM.Types; -using System; -using System.Linq; -using VMArray = Neo.VM.Types.Array; - -namespace Neo.SmartContract -{ - static partial class InteropService - { - public static readonly uint Neo_Native_Deploy = Register("Neo.Native.Deploy", Native_Deploy, 0, TriggerType.Application); - public static readonly uint Neo_Crypto_ECDsaVerify = Register("Neo.Crypto.ECDsaVerify", Crypto_ECDsaVerify, 0_01000000, TriggerType.All); - public static readonly uint Neo_Crypto_ECDsaCheckMultiSig = Register("Neo.Crypto.ECDsaCheckMultiSig", Crypto_ECDsaCheckMultiSig, GetECDsaCheckMultiSigPrice, TriggerType.All); - public static readonly uint Neo_Account_IsStandard = Register("Neo.Account.IsStandard", Account_IsStandard, 0_00030000, TriggerType.All); - public static readonly uint Neo_Contract_Create = Register("Neo.Contract.Create", Contract_Create, GetDeploymentPrice, TriggerType.Application); - public static readonly uint Neo_Contract_Update = Register("Neo.Contract.Update", Contract_Update, GetDeploymentPrice, TriggerType.Application); - public static readonly uint Neo_Storage_Find = Register("Neo.Storage.Find", Storage_Find, 0_01000000, TriggerType.Application); - public static readonly uint Neo_Enumerator_Create = Register("Neo.Enumerator.Create", Enumerator_Create, 0_00000400, TriggerType.All); - public static readonly uint Neo_Enumerator_Next = Register("Neo.Enumerator.Next", Enumerator_Next, 0_01000000, TriggerType.All); - public static readonly uint Neo_Enumerator_Value = Register("Neo.Enumerator.Value", Enumerator_Value, 0_00000400, TriggerType.All); - public static readonly uint Neo_Enumerator_Concat = Register("Neo.Enumerator.Concat", Enumerator_Concat, 0_00000400, TriggerType.All); - public static readonly uint Neo_Iterator_Create = Register("Neo.Iterator.Create", Iterator_Create, 0_00000400, TriggerType.All); - public static readonly uint Neo_Iterator_Key = Register("Neo.Iterator.Key", Iterator_Key, 0_00000400, TriggerType.All); - public static readonly uint Neo_Iterator_Keys = Register("Neo.Iterator.Keys", Iterator_Keys, 0_00000400, TriggerType.All); - public static readonly uint Neo_Iterator_Values = Register("Neo.Iterator.Values", Iterator_Values, 0_00000400, TriggerType.All); - public static readonly uint Neo_Iterator_Concat = Register("Neo.Iterator.Concat", Iterator_Concat, 0_00000400, TriggerType.All); - public static readonly uint Neo_Json_Serialize = Register("Neo.Json.Serialize", Json_Serialize, 0_00100000, TriggerType.All); - public static readonly uint Neo_Json_Deserialize = Register("Neo.Json.Deserialize", Json_Deserialize, 0_00500000, TriggerType.All); - - static InteropService() - { - foreach (NativeContract contract in NativeContract.Contracts) - Register(contract.ServiceName, contract.Invoke, contract.GetPrice, TriggerType.System | TriggerType.Application); - } - - private static long GetECDsaCheckMultiSigPrice(EvaluationStack stack) - { - if (stack.Count < 2) return 0; - var item = stack.Peek(1); - int n; - if (item is VMArray array) n = array.Count; - else n = (int)item.GetBigInteger(); - if (n < 1) return 0; - return GetPrice(Neo_Crypto_ECDsaVerify, stack) * n; - } - - private static long GetDeploymentPrice(EvaluationStack stack) - { - int size = stack.Peek(0).GetByteLength() + stack.Peek(1).GetByteLength(); - return GasPerByte * size; - } - - private static bool Native_Deploy(ApplicationEngine engine) - { - if (engine.Snapshot.PersistingBlock.Index != 0) return false; - foreach (NativeContract contract in NativeContract.Contracts) - { - engine.Snapshot.Contracts.Add(contract.Hash, new ContractState - { - Script = contract.Script, - Manifest = contract.Manifest - }); - contract.Initialize(engine); - } - return true; - } - - private static bool Crypto_ECDsaVerify(ApplicationEngine engine) - { - StackItem item0 = engine.CurrentContext.EvaluationStack.Pop(); - ReadOnlySpan message = item0 switch - { - InteropInterface _interface => _interface.GetInterface().GetHashData(), - Null _ => engine.ScriptContainer.GetHashData(), - _ => item0.GetSpan() - }; - ReadOnlySpan pubkey = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - ReadOnlySpan signature = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - try - { - engine.CurrentContext.EvaluationStack.Push(Crypto.VerifySignature(message, signature, pubkey)); - } - catch (ArgumentException) - { - engine.CurrentContext.EvaluationStack.Push(false); - } - return true; - } - - private static bool Crypto_ECDsaCheckMultiSig(ApplicationEngine engine) - { - StackItem item0 = engine.CurrentContext.EvaluationStack.Pop(); - ReadOnlySpan message = item0 switch - { - InteropInterface _interface => _interface.GetInterface().GetHashData(), - Null _ => engine.ScriptContainer.GetHashData(), - _ => item0.GetSpan() - }; - int n; - byte[][] pubkeys; - StackItem item = engine.CurrentContext.EvaluationStack.Pop(); - if (item is VMArray array1) - { - pubkeys = array1.Select(p => p.GetSpan().ToArray()).ToArray(); - n = pubkeys.Length; - if (n == 0) return false; - } - else - { - n = (int)item.GetBigInteger(); - if (n < 1 || n > engine.CurrentContext.EvaluationStack.Count) return false; - pubkeys = new byte[n][]; - for (int i = 0; i < n; i++) - pubkeys[i] = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - } - int m; - byte[][] signatures; - item = engine.CurrentContext.EvaluationStack.Pop(); - if (item is VMArray array2) - { - signatures = array2.Select(p => p.GetSpan().ToArray()).ToArray(); - m = signatures.Length; - if (m == 0 || m > n) return false; - } - else - { - m = (int)item.GetBigInteger(); - if (m < 1 || m > n || m > engine.CurrentContext.EvaluationStack.Count) return false; - signatures = new byte[m][]; - for (int i = 0; i < m; i++) - signatures[i] = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - } - bool fSuccess = true; - try - { - for (int i = 0, j = 0; fSuccess && i < m && j < n;) - { - if (Crypto.VerifySignature(message, signatures[i], pubkeys[j])) - i++; - j++; - if (m - i > n - j) - fSuccess = false; - } - } - catch (ArgumentException) - { - fSuccess = false; - } - engine.CurrentContext.EvaluationStack.Push(fSuccess); - return true; - } - - private static bool Account_IsStandard(ApplicationEngine engine) - { - UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetSpan()); - ContractState contract = engine.Snapshot.Contracts.TryGet(hash); - bool isStandard = contract is null || contract.Script.IsStandardContract(); - engine.CurrentContext.EvaluationStack.Push(isStandard); - return true; - } - - private static bool Contract_Create(ApplicationEngine engine) - { - byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - if (script.Length > 1024 * 1024) return false; - - var manifest = engine.CurrentContext.EvaluationStack.Pop().GetString(); - if (manifest.Length > ContractManifest.MaxLength) return false; - - UInt160 hash = script.ToScriptHash(); - ContractState contract = engine.Snapshot.Contracts.TryGet(hash); - if (contract != null) return false; - contract = new ContractState - { - Script = script, - Manifest = ContractManifest.Parse(manifest) - }; - - if (!contract.Manifest.IsValid(hash)) return false; - - engine.Snapshot.Contracts.Add(hash, contract); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(contract)); - return true; - } - - private static bool Contract_Update(ApplicationEngine engine) - { - byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - if (script.Length > 1024 * 1024) return false; - var manifest = engine.CurrentContext.EvaluationStack.Pop().GetString(); - if (manifest.Length > ContractManifest.MaxLength) return false; - - var contract = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash); - if (contract is null) return false; - - if (script.Length > 0) - { - UInt160 hash_new = script.ToScriptHash(); - if (hash_new.Equals(engine.CurrentScriptHash)) return false; - if (engine.Snapshot.Contracts.TryGet(hash_new) != null) return false; - contract = new ContractState - { - Script = script, - Manifest = contract.Manifest - }; - contract.Manifest.Abi.Hash = hash_new; - engine.Snapshot.Contracts.Add(hash_new, contract); - if (contract.HasStorage) - { - foreach (var (key, value) in engine.Snapshot.Storages.Find(engine.CurrentScriptHash.ToArray()).ToArray()) - { - engine.Snapshot.Storages.Add(new StorageKey - { - ScriptHash = hash_new, - Key = key.Key - }, new StorageItem - { - Value = value.Value, - IsConstant = false - }); - } - } - Contract_Destroy(engine); - } - if (manifest.Length > 0) - { - contract = engine.Snapshot.Contracts.GetAndChange(contract.ScriptHash); - contract.Manifest = ContractManifest.Parse(manifest); - if (!contract.Manifest.IsValid(contract.ScriptHash)) return false; - if (!contract.HasStorage && engine.Snapshot.Storages.Find(engine.CurrentScriptHash.ToArray()).Any()) return false; - } - - return true; - } - - private static bool Storage_Find(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - StorageContext context = _interface.GetInterface(); - if (!CheckStorageContext(engine, context)) return false; - byte[] prefix = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - byte[] prefix_key = StorageKey.CreateSearchPrefix(context.ScriptHash, prefix); - StorageIterator iterator = engine.AddDisposable(new StorageIterator(engine.Snapshot.Storages.Find(prefix_key).Where(p => p.Key.Key.AsSpan().StartsWith(prefix)).GetEnumerator())); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(iterator)); - return true; - } - return false; - } - - private static bool Enumerator_Create(ApplicationEngine engine) - { - IEnumerator enumerator; - switch (engine.CurrentContext.EvaluationStack.Pop()) - { - case VMArray array: - enumerator = new ArrayWrapper(array); - break; - case PrimitiveType primitive: - enumerator = new ByteArrayWrapper(primitive); - break; - default: - return false; - } - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(enumerator)); - return true; - } - - private static bool Enumerator_Next(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - IEnumerator enumerator = _interface.GetInterface(); - engine.CurrentContext.EvaluationStack.Push(enumerator.Next()); - return true; - } - return false; - } - - private static bool Enumerator_Value(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - IEnumerator enumerator = _interface.GetInterface(); - engine.CurrentContext.EvaluationStack.Push(enumerator.Value()); - return true; - } - return false; - } - - private static bool Enumerator_Concat(ApplicationEngine engine) - { - if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface1)) return false; - if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface2)) return false; - IEnumerator first = _interface1.GetInterface(); - IEnumerator second = _interface2.GetInterface(); - IEnumerator result = new ConcatenatedEnumerator(first, second); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(result)); - return true; - } - - private static bool Iterator_Create(ApplicationEngine engine) - { - IIterator iterator; - switch (engine.CurrentContext.EvaluationStack.Pop()) - { - case VMArray array: - iterator = new ArrayWrapper(array); - break; - case Map map: - iterator = new MapWrapper(map); - break; - case PrimitiveType primitive: - iterator = new ByteArrayWrapper(primitive); - break; - default: - return false; - } - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(iterator)); - return true; - } - - private static bool Iterator_Key(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - IIterator iterator = _interface.GetInterface(); - engine.CurrentContext.EvaluationStack.Push(iterator.Key()); - return true; - } - return false; - } - - private static bool Iterator_Keys(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - IIterator iterator = _interface.GetInterface(); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new IteratorKeysWrapper(iterator))); - return true; - } - return false; - } - - private static bool Iterator_Values(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - IIterator iterator = _interface.GetInterface(); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new IteratorValuesWrapper(iterator))); - return true; - } - return false; - } - - private static bool Iterator_Concat(ApplicationEngine engine) - { - if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface1)) return false; - if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface2)) return false; - IIterator first = _interface1.GetInterface(); - IIterator second = _interface2.GetInterface(); - IIterator result = new ConcatenatedIterator(first, second); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(result)); - return true; - } - - private static bool Json_Deserialize(ApplicationEngine engine) - { - var json = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - try - { - var obj = JObject.Parse(json, 10); - var item = JsonSerializer.Deserialize(obj, engine.ReferenceCounter); - engine.CurrentContext.EvaluationStack.Push(item); - return true; - } - catch - { - return false; - } - } - - private static bool Json_Serialize(ApplicationEngine engine) - { - var item = engine.CurrentContext.EvaluationStack.Pop(); - try - { - var json = JsonSerializer.SerializeToByteArray(item, engine.MaxItemSize); - engine.CurrentContext.EvaluationStack.Push(json); - return true; - } - catch - { - return false; - } - } - } -} diff --git a/src/neo/SmartContract/InteropService.Native.cs b/src/neo/SmartContract/InteropService.Native.cs new file mode 100644 index 0000000000..855a355ed5 --- /dev/null +++ b/src/neo/SmartContract/InteropService.Native.cs @@ -0,0 +1,34 @@ +using Neo.Ledger; +using Neo.SmartContract.Native; + +namespace Neo.SmartContract +{ + partial class InteropService + { + internal static class Native + { + public static readonly InteropDescriptor Deploy = Register("Neo.Native.Deploy", Native_Deploy, 0, TriggerType.Application); + + static Native() + { + foreach (NativeContract contract in NativeContract.Contracts) + Register(contract.ServiceName, contract.Invoke, contract.GetPrice, TriggerType.System | TriggerType.Application); + } + + private static bool Native_Deploy(ApplicationEngine engine) + { + if (engine.Snapshot.PersistingBlock.Index != 0) return false; + foreach (NativeContract contract in NativeContract.Contracts) + { + engine.Snapshot.Contracts.Add(contract.Hash, new ContractState + { + Script = contract.Script, + Manifest = contract.Manifest + }); + contract.Initialize(engine); + } + return true; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.Runtime.cs b/src/neo/SmartContract/InteropService.Runtime.cs new file mode 100644 index 0000000000..6a70ae844c --- /dev/null +++ b/src/neo/SmartContract/InteropService.Runtime.cs @@ -0,0 +1,215 @@ +using Neo.Cryptography.ECC; +using Neo.IO; +using Neo.Network.P2P.Payloads; +using Neo.VM; +using Neo.VM.Types; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Array = Neo.VM.Types.Array; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Runtime + { + public const int MaxNotificationSize = 1024; + + public static readonly InteropDescriptor Platform = Register("System.Runtime.Platform", Runtime_Platform, 0_00000250, TriggerType.All); + public static readonly InteropDescriptor GetTrigger = Register("System.Runtime.GetTrigger", Runtime_GetTrigger, 0_00000250, TriggerType.All); + public static readonly InteropDescriptor GetTime = Register("System.Runtime.GetTime", Runtime_GetTime, 0_00000250, TriggerType.Application); + public static readonly InteropDescriptor GetScriptContainer = Register("System.Runtime.GetScriptContainer", Runtime_GetScriptContainer, 0_00000250, TriggerType.All); + public static readonly InteropDescriptor GetExecutingScriptHash = Register("System.Runtime.GetExecutingScriptHash", Runtime_GetExecutingScriptHash, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor GetCallingScriptHash = Register("System.Runtime.GetCallingScriptHash", Runtime_GetCallingScriptHash, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor GetEntryScriptHash = Register("System.Runtime.GetEntryScriptHash", Runtime_GetEntryScriptHash, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor CheckWitness = Register("System.Runtime.CheckWitness", Runtime_CheckWitness, 0_00030000, TriggerType.All); + public static readonly InteropDescriptor GetInvocationCounter = Register("System.Runtime.GetInvocationCounter", Runtime_GetInvocationCounter, 0_00000400, TriggerType.All); + public static readonly InteropDescriptor Log = Register("System.Runtime.Log", Runtime_Log, 0_01000000, TriggerType.All); + public static readonly InteropDescriptor Notify = Register("System.Runtime.Notify", Runtime_Notify, 0_01000000, TriggerType.All); + public static readonly InteropDescriptor GetNotifications = Register("System.Runtime.GetNotifications", Runtime_GetNotifications, 0_00010000, TriggerType.All); + + private static bool CheckItemForNotification(StackItem state) + { + int size = 0; + List items_checked = new List(); + Queue items_unchecked = new Queue(); + while (true) + { + switch (state) + { + case Struct array: + foreach (StackItem item in array) + items_unchecked.Enqueue(item); + break; + case Array array: + if (items_checked.All(p => !ReferenceEquals(p, array))) + { + items_checked.Add(array); + foreach (StackItem item in array) + items_unchecked.Enqueue(item); + } + break; + case PrimitiveType primitive: + size += primitive.GetByteLength(); + break; + case Null _: + break; + case InteropInterface _: + return false; + case Map map: + if (items_checked.All(p => !ReferenceEquals(p, map))) + { + items_checked.Add(map); + foreach (var pair in map) + { + size += pair.Key.GetByteLength(); + items_unchecked.Enqueue(pair.Value); + } + } + break; + } + if (size > MaxNotificationSize) return false; + if (items_unchecked.Count == 0) return true; + state = items_unchecked.Dequeue(); + } + } + + internal static bool CheckWitnessInternal(ApplicationEngine engine, UInt160 hash) + { + if (engine.ScriptContainer is Transaction tx) + { + Cosigner usage = tx.Cosigners.FirstOrDefault(p => p.Account.Equals(hash)); + if (usage is null) return false; + if (usage.Scopes == WitnessScope.Global) return true; + if (usage.Scopes.HasFlag(WitnessScope.CalledByEntry)) + { + if (engine.CallingScriptHash == engine.EntryScriptHash) + return true; + } + if (usage.Scopes.HasFlag(WitnessScope.CustomContracts)) + { + if (usage.AllowedContracts.Contains(engine.CurrentScriptHash)) + return true; + } + if (usage.Scopes.HasFlag(WitnessScope.CustomGroups)) + { + var contract = engine.Snapshot.Contracts[engine.CallingScriptHash]; + // check if current group is the required one + if (contract.Manifest.Groups.Select(p => p.PubKey).Intersect(usage.AllowedGroups).Any()) + return true; + } + return false; + } + + // only for non-Transaction types (Block, etc) + + var hashes_for_verifying = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot); + return hashes_for_verifying.Contains(hash); + } + + private static bool Runtime_Platform(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push(Encoding.ASCII.GetBytes("NEO")); + return true; + } + + private static bool Runtime_GetTrigger(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push((int)engine.Trigger); + return true; + } + + private static bool Runtime_GetTime(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push(engine.Snapshot.PersistingBlock.Timestamp); + return true; + } + + private static bool Runtime_GetScriptContainer(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push( + engine.ScriptContainer is IInteroperable value ? value.ToStackItem(engine.ReferenceCounter) : + StackItem.FromInterface(engine.ScriptContainer)); + return true; + } + + private static bool Runtime_GetExecutingScriptHash(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push(engine.CurrentScriptHash.ToArray()); + return true; + } + + private static bool Runtime_GetCallingScriptHash(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push(engine.CallingScriptHash?.ToArray() ?? StackItem.Null); + return true; + } + + private static bool Runtime_GetEntryScriptHash(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push(engine.EntryScriptHash.ToArray()); + return true; + } + + private static bool Runtime_CheckWitness(ApplicationEngine engine) + { + ReadOnlySpan hashOrPubkey = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + UInt160 hash = hashOrPubkey.Length switch + { + 20 => new UInt160(hashOrPubkey), + 33 => SmartContract.Contract.CreateSignatureRedeemScript(ECPoint.DecodePoint(hashOrPubkey, ECCurve.Secp256r1)).ToScriptHash(), + _ => null + }; + if (hash is null) return false; + engine.CurrentContext.EvaluationStack.Push(CheckWitnessInternal(engine, hash)); + return true; + } + + private static bool Runtime_GetInvocationCounter(ApplicationEngine engine) + { + if (!engine.InvocationCounter.TryGetValue(engine.CurrentScriptHash, out var counter)) + { + return false; + } + + engine.CurrentContext.EvaluationStack.Push(counter); + return true; + } + + private static bool Runtime_Log(ApplicationEngine engine) + { + ReadOnlySpan state = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); + if (state.Length > MaxNotificationSize) return false; + string message = Encoding.UTF8.GetString(state); + engine.SendLog(engine.CurrentScriptHash, message); + return true; + } + + private static bool Runtime_Notify(ApplicationEngine engine) + { + StackItem state = engine.CurrentContext.EvaluationStack.Pop(); + if (!CheckItemForNotification(state)) return false; + engine.SendNotification(engine.CurrentScriptHash, state); + return true; + } + + private static bool Runtime_GetNotifications(ApplicationEngine engine) + { + StackItem item = engine.CurrentContext.EvaluationStack.Pop(); + + IEnumerable notifications = engine.Notifications; + if (!item.IsNull) // must filter by scriptHash + { + var hash = new UInt160(item.GetSpan()); + notifications = notifications.Where(p => p.ScriptHash == hash); + } + + if (notifications.Count() > engine.MaxStackSize) return false; + engine.Push(new Array(engine.ReferenceCounter, notifications.Select(u => new Array(engine.ReferenceCounter, new[] { u.ScriptHash.ToArray(), u.State })))); + return true; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.Storage.cs b/src/neo/SmartContract/InteropService.Storage.cs new file mode 100644 index 0000000000..ac977c69ca --- /dev/null +++ b/src/neo/SmartContract/InteropService.Storage.cs @@ -0,0 +1,180 @@ +using Neo.Ledger; +using Neo.SmartContract.Iterators; +using Neo.VM; +using Neo.VM.Types; +using System; +using System.Linq; + +namespace Neo.SmartContract +{ + partial class InteropService + { + public static class Storage + { + public const long GasPerByte = 100000; + public const int MaxKeySize = 64; + public const int MaxValueSize = ushort.MaxValue; + + public static readonly InteropDescriptor GetContext = Register("System.Storage.GetContext", Storage_GetContext, 0_00000400, TriggerType.Application); + public static readonly InteropDescriptor GetReadOnlyContext = Register("System.Storage.GetReadOnlyContext", Storage_GetReadOnlyContext, 0_00000400, TriggerType.Application); + public static readonly InteropDescriptor AsReadOnly = Register("System.Storage.AsReadOnly", Storage_AsReadOnly, 0_00000400, TriggerType.Application); + public static readonly InteropDescriptor Get = Register("System.Storage.Get", Storage_Get, 0_01000000, TriggerType.Application); + public static readonly InteropDescriptor Find = Register("System.Storage.Find", Storage_Find, 0_01000000, TriggerType.Application); + public static readonly InteropDescriptor Put = Register("System.Storage.Put", Storage_Put, GetStoragePrice, TriggerType.Application); + public static readonly InteropDescriptor PutEx = Register("System.Storage.PutEx", Storage_PutEx, GetStoragePrice, TriggerType.Application); + public static readonly InteropDescriptor Delete = Register("System.Storage.Delete", Storage_Delete, 0_01000000, TriggerType.Application); + + private static bool CheckStorageContext(ApplicationEngine engine, StorageContext context) + { + ContractState contract = engine.Snapshot.Contracts.TryGet(context.ScriptHash); + if (contract == null) return false; + if (!contract.HasStorage) return false; + return true; + } + + private static long GetStoragePrice(EvaluationStack stack) + { + return (stack.Peek(1).GetByteLength() + stack.Peek(2).GetByteLength()) * GasPerByte; + } + + private static bool PutExInternal(ApplicationEngine engine, StorageContext context, byte[] key, byte[] value, StorageFlags flags) + { + if (key.Length > MaxKeySize) return false; + if (value.Length > MaxValueSize) return false; + if (context.IsReadOnly) return false; + if (!CheckStorageContext(engine, context)) return false; + + StorageKey skey = new StorageKey + { + ScriptHash = context.ScriptHash, + Key = key + }; + + if (engine.Snapshot.Storages.TryGet(skey)?.IsConstant == true) return false; + + if (value.Length == 0 && !flags.HasFlag(StorageFlags.Constant)) + { + // If put 'value' is empty (and non-const), we remove it (implicit `Storage.Delete`) + engine.Snapshot.Storages.Delete(skey); + } + else + { + StorageItem item = engine.Snapshot.Storages.GetAndChange(skey, () => new StorageItem()); + item.Value = value; + item.IsConstant = flags.HasFlag(StorageFlags.Constant); + } + return true; + } + + private static bool Storage_GetContext(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext + { + ScriptHash = engine.CurrentScriptHash, + IsReadOnly = false + })); + return true; + } + + private static bool Storage_GetReadOnlyContext(ApplicationEngine engine) + { + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext + { + ScriptHash = engine.CurrentScriptHash, + IsReadOnly = true + })); + return true; + } + + private static bool Storage_AsReadOnly(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + StorageContext context = _interface.GetInterface(); + if (!context.IsReadOnly) + context = new StorageContext + { + ScriptHash = context.ScriptHash, + IsReadOnly = true + }; + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(context)); + return true; + } + return false; + } + + private static bool Storage_Get(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + StorageContext context = _interface.GetInterface(); + if (!CheckStorageContext(engine, context)) return false; + byte[] key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + StorageItem item = engine.Snapshot.Storages.TryGet(new StorageKey + { + ScriptHash = context.ScriptHash, + Key = key + }); + engine.CurrentContext.EvaluationStack.Push(item?.Value ?? StackItem.Null); + return true; + } + return false; + } + + private static bool Storage_Find(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + StorageContext context = _interface.GetInterface(); + if (!CheckStorageContext(engine, context)) return false; + byte[] prefix = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + byte[] prefix_key = StorageKey.CreateSearchPrefix(context.ScriptHash, prefix); + StorageIterator iterator = engine.AddDisposable(new StorageIterator(engine.Snapshot.Storages.Find(prefix_key).Where(p => p.Key.Key.AsSpan().StartsWith(prefix)).GetEnumerator())); + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(iterator)); + return true; + } + return false; + } + + private static bool Storage_Put(ApplicationEngine engine) + { + if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface)) + return false; + StorageContext context = _interface.GetInterface(); + byte[] key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + byte[] value = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + return PutExInternal(engine, context, key, value, StorageFlags.None); + } + + private static bool Storage_PutEx(ApplicationEngine engine) + { + if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface)) + return false; + StorageContext context = _interface.GetInterface(); + byte[] key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + byte[] value = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + StorageFlags flags = (StorageFlags)(byte)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); + return PutExInternal(engine, context, key, value, flags); + } + + private static bool Storage_Delete(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + StorageContext context = _interface.GetInterface(); + if (context.IsReadOnly) return false; + if (!CheckStorageContext(engine, context)) return false; + StorageKey key = new StorageKey + { + ScriptHash = context.ScriptHash, + Key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray() + }; + if (engine.Snapshot.Storages.TryGet(key)?.IsConstant == true) return false; + engine.Snapshot.Storages.Delete(key); + return true; + } + return false; + } + } + } +} diff --git a/src/neo/SmartContract/InteropService.cs b/src/neo/SmartContract/InteropService.cs index 40e1d77c5b..16a0525510 100644 --- a/src/neo/SmartContract/InteropService.cs +++ b/src/neo/SmartContract/InteropService.cs @@ -1,112 +1,18 @@ -using Neo.Cryptography; -using Neo.Cryptography.ECC; -using Neo.IO; -using Neo.Ledger; -using Neo.Network.P2P.Payloads; -using Neo.SmartContract.Manifest; using Neo.VM; -using Neo.VM.Types; using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Numerics; -using System.Text; -using Array = Neo.VM.Types.Array; +using System.Reflection; namespace Neo.SmartContract { public static partial class InteropService { - public const long GasPerByte = 100000; - public const int MaxStorageKeySize = 64; - public const int MaxStorageValueSize = ushort.MaxValue; - public const int MaxNotificationSize = 1024; - private static readonly Dictionary methods = new Dictionary(); - public static readonly uint System_ExecutionEngine_GetScriptContainer = Register("System.ExecutionEngine.GetScriptContainer", ExecutionEngine_GetScriptContainer, 0_00000250, TriggerType.All); - public static readonly uint System_ExecutionEngine_GetExecutingScriptHash = Register("System.ExecutionEngine.GetExecutingScriptHash", ExecutionEngine_GetExecutingScriptHash, 0_00000400, TriggerType.All); - public static readonly uint System_ExecutionEngine_GetCallingScriptHash = Register("System.ExecutionEngine.GetCallingScriptHash", ExecutionEngine_GetCallingScriptHash, 0_00000400, TriggerType.All); - public static readonly uint System_ExecutionEngine_GetEntryScriptHash = Register("System.ExecutionEngine.GetEntryScriptHash", ExecutionEngine_GetEntryScriptHash, 0_00000400, TriggerType.All); - public static readonly uint System_Runtime_Platform = Register("System.Runtime.Platform", Runtime_Platform, 0_00000250, TriggerType.All); - public static readonly uint System_Runtime_GetTrigger = Register("System.Runtime.GetTrigger", Runtime_GetTrigger, 0_00000250, TriggerType.All); - public static readonly uint System_Runtime_CheckWitness = Register("System.Runtime.CheckWitness", Runtime_CheckWitness, 0_00030000, TriggerType.All); - public static readonly uint System_Runtime_Notify = Register("System.Runtime.Notify", Runtime_Notify, 0_01000000, TriggerType.All); - public static readonly uint System_Runtime_Log = Register("System.Runtime.Log", Runtime_Log, 0_01000000, TriggerType.All); - public static readonly uint System_Runtime_GetTime = Register("System.Runtime.GetTime", Runtime_GetTime, 0_00000250, TriggerType.Application); - public static readonly uint System_Runtime_Serialize = Register("System.Runtime.Serialize", Runtime_Serialize, 0_00100000, TriggerType.All); - public static readonly uint System_Runtime_Deserialize = Register("System.Runtime.Deserialize", Runtime_Deserialize, 0_00500000, TriggerType.All); - public static readonly uint System_Runtime_GetInvocationCounter = Register("System.Runtime.GetInvocationCounter", Runtime_GetInvocationCounter, 0_00000400, TriggerType.All); - public static readonly uint System_Runtime_GetNotifications = Register("System.Runtime.GetNotifications", Runtime_GetNotifications, 0_00010000, TriggerType.All); - public static readonly uint System_Blockchain_GetHeight = Register("System.Blockchain.GetHeight", Blockchain_GetHeight, 0_00000400, TriggerType.Application); - public static readonly uint System_Blockchain_GetBlock = Register("System.Blockchain.GetBlock", Blockchain_GetBlock, 0_02500000, TriggerType.Application); - public static readonly uint System_Blockchain_GetTransaction = Register("System.Blockchain.GetTransaction", Blockchain_GetTransaction, 0_01000000, TriggerType.Application); - public static readonly uint System_Blockchain_GetTransactionHeight = Register("System.Blockchain.GetTransactionHeight", Blockchain_GetTransactionHeight, 0_01000000, TriggerType.Application); - public static readonly uint System_Blockchain_GetTransactionFromBlock = Register("System.Blockchain.GetTransactionFromBlock", Blockchain_GetTransactionFromBlock, 0_01000000, TriggerType.Application); - public static readonly uint System_Blockchain_GetContract = Register("System.Blockchain.GetContract", Blockchain_GetContract, 0_01000000, TriggerType.Application); - public static readonly uint System_Contract_Call = Register("System.Contract.Call", Contract_Call, 0_01000000, TriggerType.System | TriggerType.Application); - public static readonly uint System_Contract_Destroy = Register("System.Contract.Destroy", Contract_Destroy, 0_01000000, TriggerType.Application); - public static readonly uint System_Storage_GetContext = Register("System.Storage.GetContext", Storage_GetContext, 0_00000400, TriggerType.Application); - public static readonly uint System_Storage_GetReadOnlyContext = Register("System.Storage.GetReadOnlyContext", Storage_GetReadOnlyContext, 0_00000400, TriggerType.Application); - public static readonly uint System_Storage_Get = Register("System.Storage.Get", Storage_Get, 0_01000000, TriggerType.Application); - public static readonly uint System_Storage_Put = Register("System.Storage.Put", Storage_Put, GetStoragePrice, TriggerType.Application); - public static readonly uint System_Storage_PutEx = Register("System.Storage.PutEx", Storage_PutEx, GetStoragePrice, TriggerType.Application); - public static readonly uint System_Storage_Delete = Register("System.Storage.Delete", Storage_Delete, 0_01000000, TriggerType.Application); - public static readonly uint System_StorageContext_AsReadOnly = Register("System.StorageContext.AsReadOnly", StorageContext_AsReadOnly, 0_00000400, TriggerType.Application); - - private static bool CheckItemForNotification(StackItem state) - { - int size = 0; - List items_checked = new List(); - Queue items_unchecked = new Queue(); - while (true) - { - switch (state) - { - case Struct array: - foreach (StackItem item in array) - items_unchecked.Enqueue(item); - break; - case Array array: - if (items_checked.All(p => !ReferenceEquals(p, array))) - { - items_checked.Add(array); - foreach (StackItem item in array) - items_unchecked.Enqueue(item); - } - break; - case PrimitiveType primitive: - size += primitive.GetByteLength(); - break; - case Null _: - break; - case InteropInterface _: - return false; - case Map map: - if (items_checked.All(p => !ReferenceEquals(p, map))) - { - items_checked.Add(map); - foreach (var pair in map) - { - size += pair.Key.GetByteLength(); - items_unchecked.Enqueue(pair.Value); - } - } - break; - } - if (size > MaxNotificationSize) return false; - if (items_unchecked.Count == 0) return true; - state = items_unchecked.Dequeue(); - } - } - - private static bool CheckStorageContext(ApplicationEngine engine, StorageContext context) + static InteropService() { - ContractState contract = engine.Snapshot.Contracts.TryGet(context.ScriptHash); - if (contract == null) return false; - if (!contract.HasStorage) return false; - return true; + foreach (Type t in typeof(InteropService).GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)) + t.GetFields()[0].GetValue(null); } public static long GetPrice(uint hash, EvaluationStack stack) @@ -114,14 +20,9 @@ public static long GetPrice(uint hash, EvaluationStack stack) return methods[hash].GetPrice(stack); } - public static Dictionary SupportedMethods() + public static IEnumerable SupportedMethods() { - return methods.ToDictionary(p => p.Key, p => p.Value.Method); - } - - private static long GetStoragePrice(EvaluationStack stack) - { - return (stack.Peek(1).GetByteLength() + stack.Peek(2).GetByteLength()) * GasPerByte; + return methods.Values; } internal static bool Invoke(ApplicationEngine engine, uint method) @@ -133,444 +34,18 @@ internal static bool Invoke(ApplicationEngine engine, uint method) return descriptor.Handler(engine); } - private static uint Register(string method, Func handler, long price, TriggerType allowedTriggers) + private static InteropDescriptor Register(string method, Func handler, long price, TriggerType allowedTriggers) { InteropDescriptor descriptor = new InteropDescriptor(method, handler, price, allowedTriggers); methods.Add(descriptor.Hash, descriptor); - return descriptor.Hash; + return descriptor; } - private static uint Register(string method, Func handler, Func priceCalculator, TriggerType allowedTriggers) + private static InteropDescriptor Register(string method, Func handler, Func priceCalculator, TriggerType allowedTriggers) { InteropDescriptor descriptor = new InteropDescriptor(method, handler, priceCalculator, allowedTriggers); methods.Add(descriptor.Hash, descriptor); - return descriptor.Hash; - } - - private static bool ExecutionEngine_GetScriptContainer(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push( - engine.ScriptContainer is IInteroperable value ? value.ToStackItem(engine.ReferenceCounter) : - StackItem.FromInterface(engine.ScriptContainer)); - return true; - } - - private static bool ExecutionEngine_GetExecutingScriptHash(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push(engine.CurrentScriptHash.ToArray()); - return true; - } - - private static bool ExecutionEngine_GetCallingScriptHash(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push(engine.CallingScriptHash?.ToArray() ?? StackItem.Null); - return true; - } - - private static bool ExecutionEngine_GetEntryScriptHash(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push(engine.EntryScriptHash.ToArray()); - return true; - } - - private static bool Runtime_Platform(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push(Encoding.ASCII.GetBytes("NEO")); - return true; - } - - private static bool Runtime_GetTrigger(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push((int)engine.Trigger); - return true; - } - - internal static bool CheckWitness(ApplicationEngine engine, UInt160 hash) - { - if (engine.ScriptContainer is Transaction tx) - { - Cosigner usage = tx.Cosigners.FirstOrDefault(p => p.Account.Equals(hash)); - if (usage is null) return false; - if (usage.Scopes == WitnessScope.Global) return true; - if (usage.Scopes.HasFlag(WitnessScope.CalledByEntry)) - { - if (engine.CallingScriptHash == engine.EntryScriptHash) - return true; - } - if (usage.Scopes.HasFlag(WitnessScope.CustomContracts)) - { - if (usage.AllowedContracts.Contains(engine.CurrentScriptHash)) - return true; - } - if (usage.Scopes.HasFlag(WitnessScope.CustomGroups)) - { - var contract = engine.Snapshot.Contracts[engine.CallingScriptHash]; - // check if current group is the required one - if (contract.Manifest.Groups.Select(p => p.PubKey).Intersect(usage.AllowedGroups).Any()) - return true; - } - return false; - } - - // only for non-Transaction types (Block, etc) - - var hashes_for_verifying = engine.ScriptContainer.GetScriptHashesForVerifying(engine.Snapshot); - return hashes_for_verifying.Contains(hash); - } - - private static bool CheckWitness(ApplicationEngine engine, ECPoint pubkey) - { - return CheckWitness(engine, Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash()); - } - - private static bool Runtime_CheckWitness(ApplicationEngine engine) - { - ReadOnlySpan hashOrPubkey = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - bool result; - if (hashOrPubkey.Length == 20) - result = CheckWitness(engine, new UInt160(hashOrPubkey)); - else if (hashOrPubkey.Length == 33) - result = CheckWitness(engine, ECPoint.DecodePoint(hashOrPubkey, ECCurve.Secp256r1)); - else - return false; - engine.CurrentContext.EvaluationStack.Push(result); - return true; - } - - private static bool Runtime_Notify(ApplicationEngine engine) - { - StackItem state = engine.CurrentContext.EvaluationStack.Pop(); - if (!CheckItemForNotification(state)) return false; - engine.SendNotification(engine.CurrentScriptHash, state); - return true; - } - - private static bool Runtime_Log(ApplicationEngine engine) - { - ReadOnlySpan state = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - if (state.Length > MaxNotificationSize) return false; - string message = Encoding.UTF8.GetString(state); - engine.SendLog(engine.CurrentScriptHash, message); - return true; - } - - private static bool Runtime_GetTime(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push(engine.Snapshot.PersistingBlock.Timestamp); - return true; - } - - private static bool Runtime_Serialize(ApplicationEngine engine) - { - byte[] serialized; - try - { - serialized = StackItemSerializer.Serialize(engine.CurrentContext.EvaluationStack.Pop(), engine.MaxItemSize); - } - catch - { - return false; - } - engine.CurrentContext.EvaluationStack.Push(serialized); - return true; - } - - private static bool Runtime_GetNotifications(ApplicationEngine engine) - { - StackItem item = engine.CurrentContext.EvaluationStack.Pop(); - - IEnumerable notifications = engine.Notifications; - if (!item.IsNull) // must filter by scriptHash - { - var hash = new UInt160(item.GetSpan()); - notifications = notifications.Where(p => p.ScriptHash == hash); - } - - if (notifications.Count() > engine.MaxStackSize) return false; - engine.Push(new Array(engine.ReferenceCounter, notifications.Select(u => new Array(engine.ReferenceCounter, new[] { u.ScriptHash.ToArray(), u.State })))); - return true; - } - - private static bool Runtime_GetInvocationCounter(ApplicationEngine engine) - { - if (!engine.InvocationCounter.TryGetValue(engine.CurrentScriptHash, out var counter)) - { - return false; - } - - engine.CurrentContext.EvaluationStack.Push(counter); - return true; - } - - private static bool Runtime_Deserialize(ApplicationEngine engine) - { - StackItem item; - try - { - item = StackItemSerializer.Deserialize(engine.CurrentContext.EvaluationStack.Pop().GetSpan(), engine.MaxItemSize, engine.ReferenceCounter); - } - catch (FormatException) - { - return false; - } - catch (IOException) - { - return false; - } - engine.CurrentContext.EvaluationStack.Push(item); - return true; - } - - private static bool Blockchain_GetHeight(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push(engine.Snapshot.Height); - return true; - } - - private static bool Blockchain_GetBlock(ApplicationEngine engine) - { - ReadOnlySpan data = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - UInt256 hash; - if (data.Length <= 5) - hash = Blockchain.Singleton.GetBlockHash((uint)new BigInteger(data)); - else if (data.Length == 32) - hash = new UInt256(data); - else - return false; - - Block block = hash != null ? engine.Snapshot.GetBlock(hash) : null; - if (block == null) - engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - else - engine.CurrentContext.EvaluationStack.Push(block.ToStackItem(engine.ReferenceCounter)); - return true; - } - - private static bool Blockchain_GetTransaction(ApplicationEngine engine) - { - ReadOnlySpan hash = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); - if (tx == null) - engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - else - engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem(engine.ReferenceCounter)); - return true; - } - - private static bool Blockchain_GetTransactionHeight(ApplicationEngine engine) - { - ReadOnlySpan hash = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - var tx = engine.Snapshot.Transactions.TryGet(new UInt256(hash)); - engine.CurrentContext.EvaluationStack.Push(tx != null ? new BigInteger(tx.BlockIndex) : BigInteger.MinusOne); - return true; - } - - private static bool Blockchain_GetTransactionFromBlock(ApplicationEngine engine) - { - ReadOnlySpan data = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); - UInt256 hash; - if (data.Length <= 5) - hash = Blockchain.Singleton.GetBlockHash((uint)new BigInteger(data)); - else if (data.Length == 32) - hash = new UInt256(data); - else - return false; - - TrimmedBlock block = hash != null ? engine.Snapshot.Blocks.TryGet(hash) : null; - if (block == null) - { - engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - } - else - { - int index = (int)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); - if (index < 0 || index >= block.Hashes.Length - 1) return false; - - Transaction tx = engine.Snapshot.GetTransaction(block.Hashes[index + 1]); - if (tx == null) - engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - else - engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem(engine.ReferenceCounter)); - } - return true; - } - - private static bool Blockchain_GetContract(ApplicationEngine engine) - { - UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetSpan()); - ContractState contract = engine.Snapshot.Contracts.TryGet(hash); - if (contract == null) - engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - else - engine.CurrentContext.EvaluationStack.Push(contract.ToStackItem(engine.ReferenceCounter)); - return true; - } - - private static bool Storage_GetContext(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext - { - ScriptHash = engine.CurrentScriptHash, - IsReadOnly = false - })); - return true; - } - - private static bool Storage_GetReadOnlyContext(ApplicationEngine engine) - { - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext - { - ScriptHash = engine.CurrentScriptHash, - IsReadOnly = true - })); - return true; - } - - private static bool Storage_Get(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - StorageContext context = _interface.GetInterface(); - if (!CheckStorageContext(engine, context)) return false; - byte[] key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - StorageItem item = engine.Snapshot.Storages.TryGet(new StorageKey - { - ScriptHash = context.ScriptHash, - Key = key - }); - engine.CurrentContext.EvaluationStack.Push(item?.Value ?? StackItem.Null); - return true; - } - return false; - } - - private static bool StorageContext_AsReadOnly(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - StorageContext context = _interface.GetInterface(); - if (!context.IsReadOnly) - context = new StorageContext - { - ScriptHash = context.ScriptHash, - IsReadOnly = true - }; - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(context)); - return true; - } - return false; - } - - private static bool Contract_Call(ApplicationEngine engine) - { - StackItem contractHash = engine.CurrentContext.EvaluationStack.Pop(); - - ContractState contract = engine.Snapshot.Contracts.TryGet(new UInt160(contractHash.GetSpan())); - if (contract is null) return false; - - StackItem method = engine.CurrentContext.EvaluationStack.Pop(); - StackItem args = engine.CurrentContext.EvaluationStack.Pop(); - ContractManifest currentManifest = engine.Snapshot.Contracts.TryGet(engine.CurrentScriptHash)?.Manifest; - - if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method.GetString())) - return false; - - if (engine.InvocationCounter.TryGetValue(contract.ScriptHash, out var counter)) - { - engine.InvocationCounter[contract.ScriptHash] = counter + 1; - } - else - { - engine.InvocationCounter[contract.ScriptHash] = 1; - } - - UInt160 callingScriptHash = engine.CurrentScriptHash; - ExecutionContext context_new = engine.LoadScript(contract.Script, 1); - context_new.GetState().CallingScriptHash = callingScriptHash; - context_new.EvaluationStack.Push(args); - context_new.EvaluationStack.Push(method); - return true; - } - - private static bool Contract_Destroy(ApplicationEngine engine) - { - UInt160 hash = engine.CurrentScriptHash; - ContractState contract = engine.Snapshot.Contracts.TryGet(hash); - if (contract == null) return true; - engine.Snapshot.Contracts.Delete(hash); - if (contract.HasStorage) - foreach (var pair in engine.Snapshot.Storages.Find(hash.ToArray())) - engine.Snapshot.Storages.Delete(pair.Key); - return true; - } - - private static bool PutEx(ApplicationEngine engine, StorageContext context, byte[] key, byte[] value, StorageFlags flags) - { - if (key.Length > MaxStorageKeySize) return false; - if (value.Length > MaxStorageValueSize) return false; - if (context.IsReadOnly) return false; - if (!CheckStorageContext(engine, context)) return false; - - StorageKey skey = new StorageKey - { - ScriptHash = context.ScriptHash, - Key = key - }; - - if (engine.Snapshot.Storages.TryGet(skey)?.IsConstant == true) return false; - - if (value.Length == 0 && !flags.HasFlag(StorageFlags.Constant)) - { - // If put 'value' is empty (and non-const), we remove it (implicit `Storage.Delete`) - engine.Snapshot.Storages.Delete(skey); - } - else - { - StorageItem item = engine.Snapshot.Storages.GetAndChange(skey, () => new StorageItem()); - item.Value = value; - item.IsConstant = flags.HasFlag(StorageFlags.Constant); - } - return true; - } - - private static bool Storage_Put(ApplicationEngine engine) - { - if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface)) - return false; - StorageContext context = _interface.GetInterface(); - byte[] key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - byte[] value = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - return PutEx(engine, context, key, value, StorageFlags.None); - } - - private static bool Storage_PutEx(ApplicationEngine engine) - { - if (!(engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface)) - return false; - StorageContext context = _interface.GetInterface(); - byte[] key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - byte[] value = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); - StorageFlags flags = (StorageFlags)(byte)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); - return PutEx(engine, context, key, value, flags); - } - - private static bool Storage_Delete(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - StorageContext context = _interface.GetInterface(); - if (context.IsReadOnly) return false; - if (!CheckStorageContext(engine, context)) return false; - StorageKey key = new StorageKey - { - ScriptHash = context.ScriptHash, - Key = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray() - }; - if (engine.Snapshot.Storages.TryGet(key)?.IsConstant == true) return false; - engine.Snapshot.Storages.Delete(key); - return true; - } - return false; + return descriptor; } } } diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index e9b7984bce..2e48520380 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -41,7 +41,7 @@ private bool CheckValidators(ApplicationEngine engine) { UInt256 prev_hash = engine.Snapshot.PersistingBlock.PrevHash; TrimmedBlock prev_block = engine.Snapshot.Blocks[prev_hash]; - return InteropService.CheckWitness(engine, prev_block.NextConsensus); + return InteropService.Runtime.CheckWitnessInternal(engine, prev_block.NextConsensus); } internal override bool Initialize(ApplicationEngine engine) diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 546cb17032..699e09467b 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -155,7 +155,7 @@ private StackItem Vote(ApplicationEngine engine, Array args) { UInt160 account = new UInt160(args[0].GetSpan()); ECPoint[] pubkeys = ((Array)args[1]).Select(p => p.GetSpan().AsSerializable()).ToArray(); - if (!InteropService.CheckWitness(engine, account)) return false; + if (!InteropService.Runtime.CheckWitnessInternal(engine, account)) return false; StorageKey key_account = CreateAccountKey(account); if (engine.Snapshot.Storages.TryGet(key_account) is null) return false; StorageItem storage_account = engine.Snapshot.Storages.GetAndChange(key_account); diff --git a/src/neo/SmartContract/Native/Tokens/Nep5AccountState.cs b/src/neo/SmartContract/Native/Tokens/Nep5AccountState.cs index b42e93814b..76671d92c1 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5AccountState.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5AccountState.cs @@ -19,7 +19,7 @@ public Nep5AccountState(byte[] data) public void FromByteArray(byte[] data) { - FromStruct((Struct)StackItemSerializer.Deserialize(data, 34)); + FromStruct((Struct)BinarySerializer.Deserialize(data, 34)); } protected virtual void FromStruct(Struct @struct) @@ -29,7 +29,7 @@ protected virtual void FromStruct(Struct @struct) public byte[] ToByteArray() { - return StackItemSerializer.Serialize(ToStruct(), 4096); + return BinarySerializer.Serialize(ToStruct(), 4096); } protected virtual Struct ToStruct() diff --git a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs index fa9d779ace..bb92fbbd17 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -172,7 +172,7 @@ protected StackItem Transfer(ApplicationEngine engine, Array args) protected virtual bool Transfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount) { if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); - if (!from.Equals(engine.CallingScriptHash) && !InteropService.CheckWitness(engine, from)) + if (!from.Equals(engine.CallingScriptHash) && !InteropService.Runtime.CheckWitnessInternal(engine, from)) return false; ContractState contract_to = engine.Snapshot.Contracts.TryGet(to); if (contract_to?.Payable == false) return false; diff --git a/src/neo/VM/Helper.cs b/src/neo/VM/Helper.cs index a921f4411a..28dcb11904 100644 --- a/src/neo/VM/Helper.cs +++ b/src/neo/VM/Helper.cs @@ -27,7 +27,7 @@ public static ScriptBuilder EmitAppCall(this ScriptBuilder sb, UInt160 scriptHas sb.Emit(OpCode.NEWARRAY); sb.EmitPush(operation); sb.EmitPush(scriptHash); - sb.EmitSysCall(InteropService.System_Contract_Call); + sb.EmitSysCall(InteropService.Contract.Call); return sb; } @@ -39,7 +39,7 @@ public static ScriptBuilder EmitAppCall(this ScriptBuilder sb, UInt160 scriptHas sb.Emit(OpCode.PACK); sb.EmitPush(operation); sb.EmitPush(scriptHash); - sb.EmitSysCall(InteropService.System_Contract_Call); + sb.EmitSysCall(InteropService.Contract.Call); return sb; } @@ -51,7 +51,7 @@ public static ScriptBuilder EmitAppCall(this ScriptBuilder sb, UInt160 scriptHas sb.Emit(OpCode.PACK); sb.EmitPush(operation); sb.EmitPush(scriptHash); - sb.EmitSysCall(InteropService.System_Contract_Call); + sb.EmitSysCall(InteropService.Contract.Call); return sb; } diff --git a/src/neo/Wallets/Wallet.cs b/src/neo/Wallets/Wallet.cs index a616c971db..1752372bec 100644 --- a/src/neo/Wallets/Wallet.cs +++ b/src/neo/Wallets/Wallet.cs @@ -354,7 +354,7 @@ public static long CalculateNetWorkFee(byte[] witness_script, ref int size) if (witness_script.IsSignatureContract()) { size += 67 + witness_script.GetVarSize(); - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + InteropService.GetPrice(InteropService.Neo_Crypto_ECDsaVerify, null); + networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + InteropService.GetPrice(InteropService.Crypto.ECDsaVerify, null); } else if (witness_script.IsMultiSigContract(out int m, out int n)) { @@ -366,7 +366,7 @@ public static long CalculateNetWorkFee(byte[] witness_script, ref int size) networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] * n; using (ScriptBuilder sb = new ScriptBuilder()) networkFee += ApplicationEngine.OpCodePrices[(OpCode)sb.EmitPush(n).ToArray()[0]]; - networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + InteropService.GetPrice(InteropService.Neo_Crypto_ECDsaVerify, null) * n; + networkFee += ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + InteropService.GetPrice(InteropService.Crypto.ECDsaVerify, null) * n; } else { diff --git a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs index 772d11edbf..411a2139ca 100644 --- a/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs +++ b/tests/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs @@ -687,7 +687,7 @@ internal static void CheckValidator(ECPoint eCPoint, DataCache.Trackable trackable, BigInteger balance, BigInteger height, ECPoint[] votes) { - var st = (VM.Types.Struct)StackItemSerializer.Deserialize(trackable.Item.Value, 32); + var st = (VM.Types.Struct)BinarySerializer.Deserialize(trackable.Item.Value, 32); st.Count.Should().Be(3); st.Select(u => u.GetType()).ToArray().Should().BeEquivalentTo(new Type[] { typeof(VM.Types.Integer), typeof(VM.Types.Integer), typeof(VM.Types.ByteArray) }); // Balance diff --git a/tests/neo.UnitTests/SmartContract/UT_StackItemSerializer.cs b/tests/neo.UnitTests/SmartContract/UT_BinarySerializer.cs similarity index 67% rename from tests/neo.UnitTests/SmartContract/UT_StackItemSerializer.cs rename to tests/neo.UnitTests/SmartContract/UT_BinarySerializer.cs index ef92f57016..888af9a23a 100644 --- a/tests/neo.UnitTests/SmartContract/UT_StackItemSerializer.cs +++ b/tests/neo.UnitTests/SmartContract/UT_BinarySerializer.cs @@ -10,36 +10,36 @@ namespace Neo.UnitTests.SmartContract { [TestClass] - public class UT_StackItemSerializer + public class UT_BinarySerializer { private const int MaxItemSize = 1024 * 1024; [TestMethod] public void TestSerialize() { - byte[] result1 = StackItemSerializer.Serialize(new byte[5], MaxItemSize); + byte[] result1 = BinarySerializer.Serialize(new byte[5], MaxItemSize); byte[] expectedArray1 = new byte[] { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 }; Assert.AreEqual(Encoding.Default.GetString(expectedArray1), Encoding.Default.GetString(result1)); - byte[] result2 = StackItemSerializer.Serialize(true, MaxItemSize); + byte[] result2 = BinarySerializer.Serialize(true, MaxItemSize); byte[] expectedArray2 = new byte[] { 0x01, 0x01 }; Assert.AreEqual(Encoding.Default.GetString(expectedArray2), Encoding.Default.GetString(result2)); - byte[] result3 = StackItemSerializer.Serialize(1, MaxItemSize); + byte[] result3 = BinarySerializer.Serialize(1, MaxItemSize); byte[] expectedArray3 = new byte[] { 0x02, 0x01, 0x01 }; Assert.AreEqual(Encoding.Default.GetString(expectedArray3), Encoding.Default.GetString(result3)); StackItem stackItem4 = new InteropInterface(new object()); - Action action4 = () => StackItemSerializer.Serialize(stackItem4, MaxItemSize); + Action action4 = () => BinarySerializer.Serialize(stackItem4, MaxItemSize); action4.Should().Throw(); - byte[] result5 = StackItemSerializer.Serialize(1, MaxItemSize); + byte[] result5 = BinarySerializer.Serialize(1, MaxItemSize); byte[] expectedArray5 = new byte[] { 0x02, 0x01, 0x01 }; @@ -48,7 +48,7 @@ public void TestSerialize() List list6 = new List { 1 }; StackItem stackItem62 = new VM.Types.Array(list6); - byte[] result6 = StackItemSerializer.Serialize(stackItem62, MaxItemSize); + byte[] result6 = BinarySerializer.Serialize(stackItem62, MaxItemSize); byte[] expectedArray6 = new byte[] { 0x80,0x01,0x02,0x01,0x01 }; @@ -56,14 +56,14 @@ public void TestSerialize() List list7 = new List { 1 }; StackItem stackItem72 = new Struct(list7); - byte[] result7 = StackItemSerializer.Serialize(stackItem72, MaxItemSize); + byte[] result7 = BinarySerializer.Serialize(stackItem72, MaxItemSize); byte[] expectedArray7 = new byte[] { 0x81,0x01,0x02,0x01,0x01 }; Assert.AreEqual(Encoding.Default.GetString(expectedArray7), Encoding.Default.GetString(result7)); StackItem stackItem82 = new Map { [2] = 1 }; - byte[] result8 = StackItemSerializer.Serialize(stackItem82, MaxItemSize); + byte[] result8 = BinarySerializer.Serialize(stackItem82, MaxItemSize); byte[] expectedArray8 = new byte[] { 0x82,0x01,0x02,0x01,0x02,0x02,0x01,0x01 }; @@ -71,12 +71,12 @@ public void TestSerialize() Map stackItem91 = new Map(); stackItem91[1] = stackItem91; - Action action9 = () => StackItemSerializer.Serialize(stackItem91, MaxItemSize); + Action action9 = () => BinarySerializer.Serialize(stackItem91, MaxItemSize); action9.Should().Throw(); VM.Types.Array stackItem10 = new VM.Types.Array(); stackItem10.Add(stackItem10); - Action action10 = () => StackItemSerializer.Serialize(stackItem10, MaxItemSize); + Action action10 = () => BinarySerializer.Serialize(stackItem10, MaxItemSize); action10.Should().Throw(); } @@ -84,42 +84,42 @@ public void TestSerialize() public void TestDeserializeStackItem() { StackItem stackItem1 = new ByteArray(new byte[5]); - byte[] byteArray1 = StackItemSerializer.Serialize(stackItem1, MaxItemSize); - StackItem result1 = StackItemSerializer.Deserialize(byteArray1, (uint)byteArray1.Length); + byte[] byteArray1 = BinarySerializer.Serialize(stackItem1, MaxItemSize); + StackItem result1 = BinarySerializer.Deserialize(byteArray1, (uint)byteArray1.Length); Assert.AreEqual(stackItem1, result1); StackItem stackItem2 = new VM.Types.Boolean(true); - byte[] byteArray2 = StackItemSerializer.Serialize(stackItem2, MaxItemSize); - StackItem result2 = StackItemSerializer.Deserialize(byteArray2, (uint)byteArray2.Length); + byte[] byteArray2 = BinarySerializer.Serialize(stackItem2, MaxItemSize); + StackItem result2 = BinarySerializer.Deserialize(byteArray2, (uint)byteArray2.Length); Assert.AreEqual(stackItem2, result2); StackItem stackItem3 = new Integer(1); - byte[] byteArray3 = StackItemSerializer.Serialize(stackItem3, MaxItemSize); - StackItem result3 = StackItemSerializer.Deserialize(byteArray3, (uint)byteArray3.Length); + byte[] byteArray3 = BinarySerializer.Serialize(stackItem3, MaxItemSize); + StackItem result3 = BinarySerializer.Deserialize(byteArray3, (uint)byteArray3.Length); Assert.AreEqual(stackItem3, result3); - byte[] byteArray4 = StackItemSerializer.Serialize(1, MaxItemSize); + byte[] byteArray4 = BinarySerializer.Serialize(1, MaxItemSize); byteArray4[0] = 0x40; - Action action4 = () => StackItemSerializer.Deserialize(byteArray4, (uint)byteArray4.Length); + Action action4 = () => BinarySerializer.Deserialize(byteArray4, (uint)byteArray4.Length); action4.Should().Throw(); List list5 = new List { 1 }; StackItem stackItem52 = new VM.Types.Array(list5); - byte[] byteArray5 = StackItemSerializer.Serialize(stackItem52, MaxItemSize); - StackItem result5 = StackItemSerializer.Deserialize(byteArray5, (uint)byteArray5.Length); + byte[] byteArray5 = BinarySerializer.Serialize(stackItem52, MaxItemSize); + StackItem result5 = BinarySerializer.Deserialize(byteArray5, (uint)byteArray5.Length); Assert.AreEqual(((VM.Types.Array)stackItem52).Count, ((VM.Types.Array)result5).Count); Assert.AreEqual(((VM.Types.Array)stackItem52).GetEnumerator().Current, ((VM.Types.Array)result5).GetEnumerator().Current); List list6 = new List { 1 }; StackItem stackItem62 = new Struct(list6); - byte[] byteArray6 = StackItemSerializer.Serialize(stackItem62, MaxItemSize); - StackItem result6 = StackItemSerializer.Deserialize(byteArray6, (uint)byteArray6.Length); + byte[] byteArray6 = BinarySerializer.Serialize(stackItem62, MaxItemSize); + StackItem result6 = BinarySerializer.Deserialize(byteArray6, (uint)byteArray6.Length); Assert.AreEqual(((Struct)stackItem62).Count, ((Struct)result6).Count); Assert.AreEqual(((Struct)stackItem62).GetEnumerator().Current, ((Struct)result6).GetEnumerator().Current); StackItem stackItem72 = new Map { [2] = 1 }; - byte[] byteArray7 = StackItemSerializer.Serialize(stackItem72, MaxItemSize); - StackItem result7 = StackItemSerializer.Deserialize(byteArray7, (uint)byteArray7.Length); + byte[] byteArray7 = BinarySerializer.Serialize(stackItem72, MaxItemSize); + StackItem result7 = BinarySerializer.Deserialize(byteArray7, (uint)byteArray7.Length); Assert.AreEqual(((Map)stackItem72).Count, ((Map)result7).Count); CollectionAssert.AreEqual(((Map)stackItem72).Keys.ToArray(), ((Map)result7).Keys.ToArray()); CollectionAssert.AreEqual(((Map)stackItem72).Values.ToArray(), ((Map)result7).Values.ToArray()); diff --git a/tests/neo.UnitTests/SmartContract/UT_Contract.cs b/tests/neo.UnitTests/SmartContract/UT_Contract.cs index 36efd787cb..294094ccae 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Contract.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Contract.cs @@ -26,7 +26,7 @@ public void TestGetAddress() Array.Copy(key.PublicKey.EncodePoint(true), 0, expectedArray, 2, 33); expectedArray[35] = (byte)OpCode.PUSHNULL; expectedArray[36] = (byte)OpCode.SYSCALL; - Array.Copy(BitConverter.GetBytes(InteropService.Neo_Crypto_ECDsaVerify), 0, expectedArray, 37, 4); + Array.Copy(BitConverter.GetBytes(InteropService.Crypto.ECDsaVerify), 0, expectedArray, 37, 4); Assert.AreEqual(expectedArray.ToScriptHash().ToAddress(), contract.Address); } @@ -44,7 +44,7 @@ public void TestGetScriptHash() Array.Copy(key.PublicKey.EncodePoint(true), 0, expectedArray, 2, 33); expectedArray[35] = (byte)OpCode.PUSHNULL; expectedArray[36] = (byte)OpCode.SYSCALL; - Array.Copy(BitConverter.GetBytes(InteropService.Neo_Crypto_ECDsaVerify), 0, expectedArray, 37, 4); + Array.Copy(BitConverter.GetBytes(InteropService.Crypto.ECDsaVerify), 0, expectedArray, 37, 4); Assert.AreEqual(expectedArray.ToScriptHash(), contract.ScriptHash); } @@ -86,7 +86,7 @@ public void TestCreateMultiSigContract() expectedArray[71] = (byte)OpCode.PUSH2; expectedArray[72] = (byte)OpCode.PUSHNULL; expectedArray[73] = (byte)OpCode.SYSCALL; - Array.Copy(BitConverter.GetBytes(InteropService.Neo_Crypto_ECDsaCheckMultiSig), 0, expectedArray, 74, 4); + Array.Copy(BitConverter.GetBytes(InteropService.Crypto.ECDsaCheckMultiSig), 0, expectedArray, 74, 4); CollectionAssert.AreEqual(expectedArray, contract.Script); Assert.AreEqual(2, contract.ParameterList.Length); Assert.AreEqual(ContractParameterType.Signature, contract.ParameterList[0]); @@ -122,7 +122,7 @@ public void TestCreateMultiSigRedeemScript() expectedArray[71] = (byte)OpCode.PUSH2; expectedArray[72] = (byte)OpCode.PUSHNULL; expectedArray[73] = (byte)OpCode.SYSCALL; - Array.Copy(BitConverter.GetBytes(InteropService.Neo_Crypto_ECDsaCheckMultiSig), 0, expectedArray, 74, 4); + Array.Copy(BitConverter.GetBytes(InteropService.Crypto.ECDsaCheckMultiSig), 0, expectedArray, 74, 4); CollectionAssert.AreEqual(expectedArray, script); } @@ -140,7 +140,7 @@ public void TestCreateSignatureContract() Array.Copy(key.PublicKey.EncodePoint(true), 0, expectedArray, 2, 33); expectedArray[35] = (byte)OpCode.PUSHNULL; expectedArray[36] = (byte)OpCode.SYSCALL; - Array.Copy(BitConverter.GetBytes(InteropService.Neo_Crypto_ECDsaVerify), 0, expectedArray, 37, 4); + Array.Copy(BitConverter.GetBytes(InteropService.Crypto.ECDsaVerify), 0, expectedArray, 37, 4); CollectionAssert.AreEqual(expectedArray, contract.Script); Assert.AreEqual(1, contract.ParameterList.Length); Assert.AreEqual(ContractParameterType.Signature, contract.ParameterList[0]); @@ -160,7 +160,7 @@ public void TestCreateSignatureRedeemScript() Array.Copy(key.PublicKey.EncodePoint(true), 0, expectedArray, 2, 33); expectedArray[35] = (byte)OpCode.PUSHNULL; expectedArray[36] = (byte)OpCode.SYSCALL; - Array.Copy(BitConverter.GetBytes(InteropService.Neo_Crypto_ECDsaVerify), 0, expectedArray, 37, 4); + Array.Copy(BitConverter.GetBytes(InteropService.Crypto.ECDsaVerify), 0, expectedArray, 37, 4); CollectionAssert.AreEqual(expectedArray, script); } } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs index ac8a017d1f..19eb7a5d38 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -16,7 +16,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemRuntimeCheckWitnessHash); - InteropService.GetPrice(InteropService.System_Runtime_CheckWitness, ae.CurrentContext.EvaluationStack).Should().Be(0_00030000L); + InteropService.GetPrice(InteropService.Runtime.CheckWitness, ae.CurrentContext.EvaluationStack).Should().Be(0_00030000L); } // System.Storage.GetContext: 9bf667ce (price is 1) @@ -24,7 +24,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetContextHash); - InteropService.GetPrice(InteropService.System_Storage_GetContext, ae.CurrentContext.EvaluationStack).Should().Be(0_00000400L); + InteropService.GetPrice(InteropService.Storage.GetContext, ae.CurrentContext.EvaluationStack).Should().Be(0_00000400L); } // System.Storage.Get: 925de831 (price is 100) @@ -32,7 +32,7 @@ public void ApplicationEngineFixedPrices() using (ApplicationEngine ae = new ApplicationEngine(TriggerType.Application, null, null, 0)) { ae.LoadScript(SyscallSystemStorageGetHash); - InteropService.GetPrice(InteropService.System_Storage_Get, ae.CurrentContext.EvaluationStack).Should().Be(0_01000000L); + InteropService.GetPrice(InteropService.Storage.Get, ae.CurrentContext.EvaluationStack).Should().Be(0_01000000L); } } @@ -47,7 +47,7 @@ public void ApplicationEngineVariablePrices() ae.LoadScript(SyscallContractCreateHash00); debugger.StepInto(); // PUSHDATA1 debugger.StepInto(); // PUSHDATA1 - InteropService.GetPrice(InteropService.Neo_Contract_Create, ae.CurrentContext.EvaluationStack).Should().Be(0_00300000L); + InteropService.GetPrice(InteropService.Contract.Create, ae.CurrentContext.EvaluationStack).Should().Be(0_00300000L); } // System.Storage.Put: e63f1884 (requires push key and value) @@ -59,7 +59,7 @@ public void ApplicationEngineVariablePrices() debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 00 - InteropService.GetPrice(InteropService.System_Storage_Put, ae.CurrentContext.EvaluationStack).Should().Be(200000L); + InteropService.GetPrice(InteropService.Storage.Put, ae.CurrentContext.EvaluationStack).Should().Be(200000L); } // System.Storage.PutEx: 73e19b3a (requires push key and value) @@ -71,7 +71,7 @@ public void ApplicationEngineVariablePrices() debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 03 (length 1) debugger.StepInto(); // push 00 - InteropService.GetPrice(InteropService.System_Storage_PutEx, ae.CurrentContext.EvaluationStack).Should().Be(200000L); + InteropService.GetPrice(InteropService.Storage.PutEx, ae.CurrentContext.EvaluationStack).Should().Be(200000L); } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index de16dfd3a1..83700f33a0 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -34,13 +34,13 @@ public void TestCheckSig() engine.CurrentContext.EvaluationStack.Push(signature); engine.CurrentContext.EvaluationStack.Push(pubkey.EncodePoint(false)); engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaVerify).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaVerify).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeTrue(); engine.CurrentContext.EvaluationStack.Push(signature); engine.CurrentContext.EvaluationStack.Push(new byte[70]); engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaVerify).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaVerify).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeFalse(); } @@ -76,14 +76,14 @@ public void TestCrypto_CheckMultiSig() engine.CurrentContext.EvaluationStack.Push(signatures); engine.CurrentContext.EvaluationStack.Push(pubkeys); engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaCheckMultiSig).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaCheckMultiSig).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeTrue(); pubkeys = new VMArray(); engine.CurrentContext.EvaluationStack.Push(signatures); engine.CurrentContext.EvaluationStack.Push(pubkeys); engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaCheckMultiSig).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaCheckMultiSig).Should().BeFalse(); pubkeys = new VMArray { @@ -94,7 +94,7 @@ public void TestCrypto_CheckMultiSig() engine.CurrentContext.EvaluationStack.Push(signatures); engine.CurrentContext.EvaluationStack.Push(pubkeys); engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaCheckMultiSig).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaCheckMultiSig).Should().BeFalse(); pubkeys = new VMArray { @@ -109,7 +109,7 @@ public void TestCrypto_CheckMultiSig() engine.CurrentContext.EvaluationStack.Push(signatures); engine.CurrentContext.EvaluationStack.Push(pubkeys); engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaCheckMultiSig).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaCheckMultiSig).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeFalse(); pubkeys = new VMArray @@ -125,7 +125,7 @@ public void TestCrypto_CheckMultiSig() engine.CurrentContext.EvaluationStack.Push(signatures); engine.CurrentContext.EvaluationStack.Push(pubkeys); engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaCheckMultiSig).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaCheckMultiSig).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeFalse(); } @@ -138,7 +138,7 @@ public void TestAccount_IsStandard() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; engine.CurrentContext.EvaluationStack.Push(hash); - InteropService.Invoke(engine, InteropService.Neo_Account_IsStandard).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.IsStandard).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeTrue(); var snapshot = Blockchain.Singleton.GetSnapshot(); @@ -147,7 +147,7 @@ public void TestAccount_IsStandard() engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); engine.LoadScript(new byte[] { 0x01 }); engine.CurrentContext.EvaluationStack.Push(state.ScriptHash.ToArray()); - InteropService.Invoke(engine, InteropService.Neo_Account_IsStandard).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.IsStandard).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeFalse(); } @@ -157,23 +157,23 @@ public void TestContract_Create() var engine = GetEngine(false, true); var script = new byte[1024 * 1024 + 1]; engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Create).Should().BeFalse(); string manifestStr = new string(new char[ContractManifest.MaxLength + 1]); script = new byte[] { 0x01 }; engine.CurrentContext.EvaluationStack.Push(manifestStr); engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Create).Should().BeFalse(); var manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01")); engine.CurrentContext.EvaluationStack.Push(manifest.ToString()); engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Create).Should().BeFalse(); manifest.Abi.Hash = script.ToScriptHash(); engine.CurrentContext.EvaluationStack.Push(manifest.ToString()); engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.Create).Should().BeTrue(); var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); @@ -182,7 +182,7 @@ public void TestContract_Create() engine.LoadScript(new byte[] { 0x01 }); engine.CurrentContext.EvaluationStack.Push(manifest.ToString()); engine.CurrentContext.EvaluationStack.Push(state.Script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Create).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Create).Should().BeFalse(); } [TestMethod] @@ -191,18 +191,18 @@ public void TestContract_Update() var engine = GetEngine(false, true); var script = new byte[1024 * 1024 + 1]; engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Update).Should().BeFalse(); string manifestStr = new string(new char[ContractManifest.MaxLength + 1]); script = new byte[] { 0x01 }; engine.CurrentContext.EvaluationStack.Push(manifestStr); engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Update).Should().BeFalse(); manifestStr = ""; engine.CurrentContext.EvaluationStack.Push(manifestStr); engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Update).Should().BeFalse(); var manifest = ContractManifest.CreateDefault(script.ToScriptHash()); byte[] privkey = { 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, @@ -238,7 +238,7 @@ public void TestContract_Update() engine.LoadScript(state.Script); engine.CurrentContext.EvaluationStack.Push(manifest.ToString()); engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.Update).Should().BeTrue(); // Remove Storage flag with something stored @@ -250,7 +250,7 @@ public void TestContract_Update() engine.LoadScript(state.Script); engine.CurrentContext.EvaluationStack.Push(manifest.ToString()); engine.CurrentContext.EvaluationStack.Push(script); - InteropService.Invoke(engine, InteropService.Neo_Contract_Update).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Update).Should().BeFalse(); } [TestMethod] @@ -281,14 +281,14 @@ public void TestStorage_Find() ScriptHash = state.ScriptHash, IsReadOnly = false })); - InteropService.Invoke(engine, InteropService.Neo_Storage_Find).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.Find).Should().BeTrue(); var iterator = ((InteropInterface)engine.CurrentContext.EvaluationStack.Pop()).GetInterface(); iterator.Next(); var ele = iterator.Value(); ele.GetSpan().ToHexString().Should().Be(storageItem.Value.ToHexString()); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Storage_Find).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Find).Should().BeFalse(); } [TestMethod] @@ -300,14 +300,14 @@ public void TestEnumerator_Create() new byte[]{ 0x02 } }; engine.CurrentContext.EvaluationStack.Push(arr); - InteropService.Invoke(engine, InteropService.Neo_Enumerator_Create).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Enumerator.Create).Should().BeTrue(); var ret = (InteropInterface)engine.CurrentContext.EvaluationStack.Pop(); ret.GetInterface().Next(); ret.GetInterface().Value().GetSpan().ToHexString() .Should().Be(new byte[] { 0x01 }.ToHexString()); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Enumerator_Create).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Enumerator.Create).Should().BeTrue(); } [TestMethod] @@ -319,11 +319,11 @@ public void TestEnumerator_Next() new byte[]{ 0x02 } }; engine.CurrentContext.EvaluationStack.Push(new InteropInterface(new ArrayWrapper(arr))); - InteropService.Invoke(engine, InteropService.Neo_Enumerator_Next).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Enumerator.Next).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeTrue(); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Enumerator_Next).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Enumerator.Next).Should().BeFalse(); } [TestMethod] @@ -337,11 +337,11 @@ public void TestEnumerator_Value() var wrapper = new ArrayWrapper(arr); wrapper.Next(); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(wrapper)); - InteropService.Invoke(engine, InteropService.Neo_Enumerator_Value).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Enumerator.Value).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(new byte[] { 0x01 }.ToHexString()); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Enumerator_Value).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Enumerator.Value).Should().BeFalse(); } [TestMethod] @@ -360,7 +360,7 @@ public void TestEnumerator_Concat() var wrapper2 = new ArrayWrapper(arr2); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(wrapper2)); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(wrapper1)); - InteropService.Invoke(engine, InteropService.Neo_Enumerator_Concat).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Enumerator.Concat).Should().BeTrue(); var ret = ((InteropInterface)engine.CurrentContext.EvaluationStack.Pop()).GetInterface(); ret.Next().Should().BeTrue(); ret.Value().GetSpan().ToHexString().Should().Be(new byte[] { 0x01 }.ToHexString()); @@ -375,7 +375,7 @@ public void TestIterator_Create() new byte[]{ 0x02 } }; engine.CurrentContext.EvaluationStack.Push(arr); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Create).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Iterator.Create).Should().BeTrue(); var ret = (InteropInterface)engine.CurrentContext.EvaluationStack.Pop(); ret.GetInterface().Next(); ret.GetInterface().Value().GetSpan().ToHexString() @@ -383,7 +383,7 @@ public void TestIterator_Create() var interop = new InteropInterface(1); engine.CurrentContext.EvaluationStack.Push(interop); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Create).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Iterator.Create).Should().BeFalse(); var map = new Map { @@ -391,14 +391,14 @@ public void TestIterator_Create() [3] = 4 }; engine.CurrentContext.EvaluationStack.Push(map); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Create).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Iterator.Create).Should().BeTrue(); ret = (InteropInterface)engine.CurrentContext.EvaluationStack.Pop(); ret.GetInterface().Next(); ret.GetInterface().Key().GetBigInteger().Should().Be(1); ret.GetInterface().Value().GetBigInteger().Should().Be(2); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Create).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Iterator.Create).Should().BeTrue(); } [TestMethod] @@ -412,11 +412,11 @@ public void TestIterator_Key() var wrapper = new ArrayWrapper(arr); wrapper.Next(); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(wrapper)); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Key).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Iterator.Key).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetBigInteger().Should().Be(0); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Key).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Iterator.Key).Should().BeFalse(); } [TestMethod] @@ -429,13 +429,13 @@ public void TestIterator_Keys() }; var wrapper = new ArrayWrapper(arr); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(wrapper)); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Keys).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Iterator.Keys).Should().BeTrue(); var ret = ((InteropInterface)engine.CurrentContext.EvaluationStack.Pop()).GetInterface(); ret.Next(); ret.Value().GetBigInteger().Should().Be(0); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Keys).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Iterator.Keys).Should().BeFalse(); } [TestMethod] @@ -448,13 +448,13 @@ public void TestIterator_Values() }; var wrapper = new ArrayWrapper(arr); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(wrapper)); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Values).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Iterator.Values).Should().BeTrue(); var ret = ((InteropInterface)engine.CurrentContext.EvaluationStack.Pop()).GetInterface(); ret.Next(); ret.Value().GetSpan().ToHexString().Should().Be(new byte[] { 0x01 }.ToHexString()); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Values).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Iterator.Values).Should().BeFalse(); } [TestMethod] @@ -473,7 +473,7 @@ public void TestIterator_Concat() var wrapper2 = new ArrayWrapper(arr2); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(wrapper2)); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(wrapper1)); - InteropService.Invoke(engine, InteropService.Neo_Iterator_Concat).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Iterator.Concat).Should().BeTrue(); var ret = ((InteropInterface)engine.CurrentContext.EvaluationStack.Pop()).GetInterface(); ret.Next().Should().BeTrue(); ret.Value().GetSpan().ToHexString().Should().Be(new byte[] { 0x01 }.ToHexString()); @@ -484,7 +484,7 @@ public void TestJson_Deserialize() { var engine = GetEngine(); engine.CurrentContext.EvaluationStack.Push("1"); - InteropService.Invoke(engine, InteropService.Neo_Json_Deserialize).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Json.Deserialize).Should().BeTrue(); var ret = engine.CurrentContext.EvaluationStack.Pop(); ret.GetBigInteger().Should().Be(1); } @@ -494,7 +494,7 @@ public void TestJson_Serialize() { var engine = GetEngine(); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.Neo_Json_Serialize).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Json.Serialize).Should().BeTrue(); var ret = engine.CurrentContext.EvaluationStack.Pop(); ret.GetString().Should().Be("1"); } diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index 4e4b05b0c9..e3427aea5b 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -42,7 +42,7 @@ public void Runtime_GetNotifications_Test() // Notify method - script.EmitSysCall(InteropService.System_Runtime_Notify); + script.EmitSysCall(InteropService.Runtime.Notify); // Add return @@ -68,7 +68,7 @@ public void Runtime_GetNotifications_Test() // Retrive script.EmitPush(1); - script.EmitSysCall(InteropService.System_Runtime_GetNotifications); + script.EmitSysCall(InteropService.Runtime.GetNotifications); // Execute @@ -85,7 +85,7 @@ public void Runtime_GetNotifications_Test() // Notification 1 -> 13 script.EmitPush(13); - script.EmitSysCall(InteropService.System_Runtime_Notify); + script.EmitSysCall(InteropService.Runtime.Notify); // Call script @@ -98,7 +98,7 @@ public void Runtime_GetNotifications_Test() // Receive all notifications script.Emit(OpCode.PUSHNULL); - script.EmitSysCall(InteropService.System_Runtime_GetNotifications); + script.EmitSysCall(InteropService.Runtime.GetNotifications); // Execute @@ -135,7 +135,7 @@ public void Runtime_GetNotifications_Test() // Notification 1 -> 13 script.EmitPush(13); - script.EmitSysCall(InteropService.System_Runtime_Notify); + script.EmitSysCall(InteropService.Runtime.Notify); // Call script @@ -148,7 +148,7 @@ public void Runtime_GetNotifications_Test() // Receive all notifications script.EmitPush(scriptHash2.ToArray()); - script.EmitSysCall(InteropService.System_Runtime_GetNotifications); + script.EmitSysCall(InteropService.Runtime.GetNotifications); // Execute @@ -205,7 +205,7 @@ private void AssertNotification(StackItem stackItem, UInt160 scriptHash, int not public void TestExecutionEngine_GetScriptContainer() { var engine = GetEngine(true); - InteropService.Invoke(engine, InteropService.System_ExecutionEngine_GetScriptContainer).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.GetScriptContainer).Should().BeTrue(); var stackItem = ((VM.Types.Array)engine.CurrentContext.EvaluationStack.Pop()).ToArray(); stackItem.Length.Should().Be(8); stackItem[0].GetSpan().ToHexString().Should().Be(TestUtils.GetTransaction().Hash.ToArray().ToHexString()); @@ -215,7 +215,7 @@ public void TestExecutionEngine_GetScriptContainer() public void TestExecutionEngine_GetExecutingScriptHash() { var engine = GetEngine(); - InteropService.Invoke(engine, InteropService.System_ExecutionEngine_GetExecutingScriptHash).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.GetExecutingScriptHash).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString() .Should().Be(engine.CurrentScriptHash.ToArray().ToHexString()); } @@ -226,7 +226,7 @@ public void TestExecutionEngine_GetCallingScriptHash() // Test without var engine = GetEngine(true); - InteropService.Invoke(engine, InteropService.System_ExecutionEngine_GetCallingScriptHash).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.GetCallingScriptHash).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().Should().Be(StackItem.Null); // Test real @@ -234,7 +234,7 @@ public void TestExecutionEngine_GetCallingScriptHash() using ScriptBuilder scriptA = new ScriptBuilder(); scriptA.Emit(OpCode.DROP); // Drop arguments scriptA.Emit(OpCode.DROP); // Drop method - scriptA.EmitSysCall(InteropService.System_ExecutionEngine_GetCallingScriptHash); + scriptA.EmitSysCall(InteropService.Runtime.GetCallingScriptHash); var contract = new ContractState() { @@ -258,7 +258,7 @@ public void TestExecutionEngine_GetCallingScriptHash() public void TestExecutionEngine_GetEntryScriptHash() { var engine = GetEngine(); - InteropService.Invoke(engine, InteropService.System_ExecutionEngine_GetEntryScriptHash).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.GetEntryScriptHash).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString() .Should().Be(engine.EntryScriptHash.ToArray().ToHexString()); } @@ -267,7 +267,7 @@ public void TestExecutionEngine_GetEntryScriptHash() public void TestRuntime_Platform() { var engine = GetEngine(); - InteropService.Invoke(engine, InteropService.System_Runtime_Platform).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.Platform).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString() .Should().Be(Encoding.ASCII.GetBytes("NEO").ToHexString()); } @@ -276,7 +276,7 @@ public void TestRuntime_Platform() public void TestRuntime_GetTrigger() { var engine = GetEngine(); - InteropService.Invoke(engine, InteropService.System_Runtime_GetTrigger).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.GetTrigger).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetBigInteger() .Should().Be((int)engine.Trigger); } @@ -293,17 +293,17 @@ public void TestRuntime_CheckWitness() ((Transaction)engine.ScriptContainer).Sender = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); engine.CurrentContext.EvaluationStack.Push(pubkey.EncodePoint(true)); - InteropService.Invoke(engine, InteropService.System_Runtime_CheckWitness).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.CheckWitness).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Peek().GetType().Should().Be(typeof(Neo.VM.Types.Boolean)); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().Be(false); engine.CurrentContext.EvaluationStack.Push(((Transaction)engine.ScriptContainer).Sender.ToArray()); - InteropService.Invoke(engine, InteropService.System_Runtime_CheckWitness).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.CheckWitness).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Peek().GetType().Should().Be(typeof(Neo.VM.Types.Boolean)); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().Be(false); engine.CurrentContext.EvaluationStack.Push(new byte[0]); - InteropService.Invoke(engine, InteropService.System_Runtime_CheckWitness).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Runtime.CheckWitness).Should().BeFalse(); } [TestMethod] @@ -313,7 +313,7 @@ public void TestRuntime_Log() string message = "hello"; engine.CurrentContext.EvaluationStack.Push(Encoding.UTF8.GetBytes(message)); ApplicationEngine.Log += LogEvent; - InteropService.Invoke(engine, InteropService.System_Runtime_Log).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.Log).Should().BeTrue(); ((Transaction)engine.ScriptContainer).Script.ToHexString().Should().Be(new byte[] { 0x01, 0x02, 0x03 }.ToHexString()); ApplicationEngine.Log -= LogEvent; } @@ -326,7 +326,7 @@ public void TestRuntime_GetTime() var engine = GetEngine(true, true); engine.Snapshot.PersistingBlock = block; - InteropService.Invoke(engine, InteropService.System_Runtime_GetTime).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.GetTime).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetBigInteger().Should().Be(block.Timestamp); } @@ -335,15 +335,15 @@ public void TestRuntime_Serialize() { var engine = GetEngine(); engine.CurrentContext.EvaluationStack.Push(100); - InteropService.Invoke(engine, InteropService.System_Runtime_Serialize).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Binary.Serialize).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString() .Should().Be(new byte[] { 0x02, 0x01, 0x64 }.ToHexString()); engine.CurrentContext.EvaluationStack.Push(new byte[1024 * 1024 * 2]); //Larger than MaxItemSize - InteropService.Invoke(engine, InteropService.System_Runtime_Serialize).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Binary.Serialize).Should().BeFalse(); engine.CurrentContext.EvaluationStack.Push(new TestInteropInterface()); //NotSupportedException - InteropService.Invoke(engine, InteropService.System_Runtime_Serialize).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Binary.Serialize).Should().BeFalse(); } [TestMethod] @@ -351,21 +351,21 @@ public void TestRuntime_Deserialize() { var engine = GetEngine(); engine.CurrentContext.EvaluationStack.Push(100); - InteropService.Invoke(engine, InteropService.System_Runtime_Serialize).Should().BeTrue(); - InteropService.Invoke(engine, InteropService.System_Runtime_Deserialize).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Binary.Serialize).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Binary.Deserialize).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetBigInteger().Should().Be(100); engine.CurrentContext.EvaluationStack.Push(new byte[] { 0xfa, 0x01 }); //FormatException - InteropService.Invoke(engine, InteropService.System_Runtime_Deserialize).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Binary.Deserialize).Should().BeFalse(); } [TestMethod] public void TestRuntime_GetInvocationCounter() { var engine = GetEngine(); - InteropService.Invoke(engine, InteropService.System_Runtime_GetInvocationCounter).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Runtime.GetInvocationCounter).Should().BeFalse(); engine.InvocationCounter.TryAdd(engine.CurrentScriptHash, 10); - InteropService.Invoke(engine, InteropService.System_Runtime_GetInvocationCounter).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Runtime.GetInvocationCounter).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetBigInteger().Should().Be(10); } @@ -384,7 +384,7 @@ public void TestCrypto_Verify() engine.CurrentContext.EvaluationStack.Push(signature); engine.CurrentContext.EvaluationStack.Push(pubkey.EncodePoint(false)); engine.CurrentContext.EvaluationStack.Push(message); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaVerify).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaVerify).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeTrue(); byte[] wrongkey = pubkey.EncodePoint(false); @@ -392,7 +392,7 @@ public void TestCrypto_Verify() engine.CurrentContext.EvaluationStack.Push(signature); engine.CurrentContext.EvaluationStack.Push(wrongkey); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(engine.ScriptContainer)); - InteropService.Invoke(engine, InteropService.Neo_Crypto_ECDsaVerify).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Crypto.ECDsaVerify).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Peek().ToBoolean().Should().BeFalse(); } @@ -400,7 +400,7 @@ public void TestCrypto_Verify() public void TestBlockchain_GetHeight() { var engine = GetEngine(true, true); - InteropService.Invoke(engine, InteropService.System_Blockchain_GetHeight).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Blockchain.GetHeight).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetBigInteger().Should().Be(0); } @@ -410,7 +410,7 @@ public void TestBlockchain_GetBlock() var engine = GetEngine(true, true); engine.CurrentContext.EvaluationStack.Push(new byte[] { 0x01 }); - InteropService.Invoke(engine, InteropService.System_Blockchain_GetBlock).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Blockchain.GetBlock).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().Should().Be(StackItem.Null); byte[] data1 = new byte[] { 0x01, 0x01, 0x01 ,0x01, 0x01, 0x01, 0x01, 0x01, @@ -418,12 +418,12 @@ public void TestBlockchain_GetBlock() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; engine.CurrentContext.EvaluationStack.Push(data1); - InteropService.Invoke(engine, InteropService.System_Blockchain_GetBlock).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Blockchain.GetBlock).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeFalse(); byte[] data2 = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; engine.CurrentContext.EvaluationStack.Push(data2); - InteropService.Invoke(engine, InteropService.System_Blockchain_GetBlock).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Blockchain.GetBlock).Should().BeFalse(); } [TestMethod] @@ -435,7 +435,7 @@ public void TestBlockchain_GetTransaction() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; engine.CurrentContext.EvaluationStack.Push(data1); - InteropService.Invoke(engine, InteropService.System_Blockchain_GetTransaction).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Blockchain.GetTransaction).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().ToBoolean().Should().BeFalse(); } @@ -448,7 +448,7 @@ public void TestBlockchain_GetTransactionHeight() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; engine.CurrentContext.EvaluationStack.Push(data1); - InteropService.Invoke(engine, InteropService.System_Blockchain_GetTransactionHeight).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Blockchain.GetTransactionHeight).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetBigInteger().Should().Be(-1); } @@ -461,7 +461,7 @@ public void TestBlockchain_GetContract() 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; engine.CurrentContext.EvaluationStack.Push(data1); - InteropService.Invoke(engine, InteropService.System_Blockchain_GetContract).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Blockchain.GetContract).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().Should().Be(StackItem.Null); var snapshot = Blockchain.Singleton.GetSnapshot(); @@ -470,7 +470,7 @@ public void TestBlockchain_GetContract() engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); engine.LoadScript(new byte[] { 0x01 }); engine.CurrentContext.EvaluationStack.Push(state.ScriptHash.ToArray()); - InteropService.Invoke(engine, InteropService.System_Blockchain_GetContract).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Blockchain.GetContract).Should().BeTrue(); var stackItems = ((VM.Types.Array)engine.CurrentContext.EvaluationStack.Pop()).ToArray(); stackItems.Length.Should().Be(3); stackItems[0].GetType().Should().Be(typeof(ByteArray)); @@ -483,7 +483,7 @@ public void TestBlockchain_GetContract() public void TestStorage_GetContext() { var engine = GetEngine(); - InteropService.Invoke(engine, InteropService.System_Storage_GetContext).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.GetContext).Should().BeTrue(); var ret = (InteropInterface)engine.CurrentContext.EvaluationStack.Pop(); ret.GetInterface().ScriptHash.Should().Be(engine.CurrentScriptHash); ret.GetInterface().IsReadOnly.Should().BeFalse(); @@ -493,7 +493,7 @@ public void TestStorage_GetContext() public void TestStorage_GetReadOnlyContext() { var engine = GetEngine(); - InteropService.Invoke(engine, InteropService.System_Storage_GetReadOnlyContext).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.GetReadOnlyContext).Should().BeTrue(); var ret = (InteropInterface)engine.CurrentContext.EvaluationStack.Pop(); ret.GetInterface().ScriptHash.Should().Be(engine.CurrentScriptHash); ret.GetInterface().IsReadOnly.Should().BeTrue(); @@ -528,7 +528,7 @@ public void TestStorage_Get() ScriptHash = state.ScriptHash, IsReadOnly = false })); - InteropService.Invoke(engine, InteropService.System_Storage_Get).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.Get).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(storageItem.Value.ToHexString()); snapshot.Contracts.Delete(state.ScriptHash); @@ -540,10 +540,10 @@ public void TestStorage_Get() ScriptHash = state.ScriptHash, IsReadOnly = false })); - InteropService.Invoke(engine, InteropService.System_Storage_Get).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Get).Should().BeFalse(); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.System_Storage_Get).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Get).Should().BeFalse(); } [TestMethod] @@ -551,7 +551,7 @@ public void TestStorage_Put() { var engine = GetEngine(false, true); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse(); //CheckStorageContext fail var key = new byte[] { 0x01 }; @@ -565,15 +565,15 @@ public void TestStorage_Put() IsReadOnly = false }; engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse(); //key.Length > MaxStorageKeySize - key = new byte[InteropService.MaxStorageKeySize + 1]; + key = new byte[InteropService.Storage.MaxKeySize + 1]; value = new byte[] { 0x02 }; engine.CurrentContext.EvaluationStack.Push(value); engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse(); //value.Length > MaxStorageValueSize key = new byte[] { 0x01 }; @@ -581,7 +581,7 @@ public void TestStorage_Put() engine.CurrentContext.EvaluationStack.Push(value); engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse(); //context.IsReadOnly key = new byte[] { 0x01 }; @@ -590,7 +590,7 @@ public void TestStorage_Put() engine.CurrentContext.EvaluationStack.Push(value); engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse(); //storage value is constant var snapshot = Blockchain.Singleton.GetSnapshot(); @@ -616,14 +616,14 @@ public void TestStorage_Put() engine.CurrentContext.EvaluationStack.Push(value); engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeFalse(); //success storageItem.IsConstant = false; engine.CurrentContext.EvaluationStack.Push(value); engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeTrue(); //value length == 0 key = new byte[] { 0x01 }; @@ -631,7 +631,7 @@ public void TestStorage_Put() engine.CurrentContext.EvaluationStack.Push(value); engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Put).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.Put).Should().BeTrue(); } [TestMethod] @@ -639,7 +639,7 @@ public void TestStorage_PutEx() { var engine = GetEngine(false, true); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.System_Storage_PutEx).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.PutEx).Should().BeFalse(); var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); @@ -669,7 +669,7 @@ public void TestStorage_PutEx() engine.CurrentContext.EvaluationStack.Push(value); engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_PutEx).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.PutEx).Should().BeTrue(); } [TestMethod] @@ -677,7 +677,7 @@ public void TestStorage_Delete() { var engine = GetEngine(false, true); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.System_Storage_Delete).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Delete).Should().BeFalse(); var snapshot = Blockchain.Singleton.GetSnapshot(); @@ -706,20 +706,20 @@ public void TestStorage_Delete() }; engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Delete).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.Delete).Should().BeTrue(); //context is readonly storageContext.IsReadOnly = true; engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Delete).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Delete).Should().BeFalse(); //CheckStorageContext fail storageContext.IsReadOnly = false; state.Manifest.Features = ContractFeatures.NoProperty; engine.CurrentContext.EvaluationStack.Push(key); engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_Storage_Delete).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.Delete).Should().BeFalse(); } [TestMethod] @@ -727,7 +727,7 @@ public void TestStorageContext_AsReadOnly() { var engine = GetEngine(); engine.CurrentContext.EvaluationStack.Push(1); - InteropService.Invoke(engine, InteropService.System_StorageContext_AsReadOnly).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.AsReadOnly).Should().BeFalse(); var state = TestUtils.GetContract(); var storageContext = new StorageContext @@ -736,7 +736,7 @@ public void TestStorageContext_AsReadOnly() IsReadOnly = false }; engine.CurrentContext.EvaluationStack.Push(new InteropInterface(storageContext)); - InteropService.Invoke(engine, InteropService.System_StorageContext_AsReadOnly).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Storage.AsReadOnly).Should().BeTrue(); var ret = (InteropInterface)engine.CurrentContext.EvaluationStack.Pop(); ret.GetInterface().IsReadOnly.Should().Be(true); } @@ -746,7 +746,7 @@ public void TestInvoke() { var engine = new ApplicationEngine(TriggerType.Verification, null, null, 0); InteropService.Invoke(engine, 10000).Should().BeFalse(); - InteropService.Invoke(engine, InteropService.System_StorageContext_AsReadOnly).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Storage.AsReadOnly).Should().BeFalse(); } [TestMethod] @@ -764,7 +764,7 @@ public void TestContract_Call() engine.CurrentContext.EvaluationStack.Push(args); engine.CurrentContext.EvaluationStack.Push(method); engine.CurrentContext.EvaluationStack.Push(state.ScriptHash.ToArray()); - InteropService.Invoke(engine, InteropService.System_Contract_Call).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.Call).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(method.ToHexString()); engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToHexString().Should().Be(args.ToHexString()); @@ -772,25 +772,25 @@ public void TestContract_Call() engine.CurrentContext.EvaluationStack.Push(args); engine.CurrentContext.EvaluationStack.Push(method); engine.CurrentContext.EvaluationStack.Push(state.ScriptHash.ToArray()); - InteropService.Invoke(engine, InteropService.System_Contract_Call).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Call).Should().BeFalse(); state.Manifest.Permissions[0].Methods = WildcardContainer.CreateWildcard(); engine.CurrentContext.EvaluationStack.Push(args); engine.CurrentContext.EvaluationStack.Push(method); engine.CurrentContext.EvaluationStack.Push(state.ScriptHash.ToArray()); - InteropService.Invoke(engine, InteropService.System_Contract_Call).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.Call).Should().BeTrue(); engine.CurrentContext.EvaluationStack.Push(args); engine.CurrentContext.EvaluationStack.Push(method); engine.CurrentContext.EvaluationStack.Push(UInt160.Zero.ToArray()); - InteropService.Invoke(engine, InteropService.System_Contract_Call).Should().BeFalse(); + InteropService.Invoke(engine, InteropService.Contract.Call).Should().BeFalse(); } [TestMethod] public void TestContract_Destroy() { var engine = GetEngine(false, true); - InteropService.Invoke(engine, InteropService.System_Contract_Destroy).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.Destroy).Should().BeTrue(); var snapshot = Blockchain.Singleton.GetSnapshot(); var state = TestUtils.GetContract(); @@ -811,7 +811,7 @@ public void TestContract_Destroy() snapshot.Storages.Add(storageKey, storageItem); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); engine.LoadScript(new byte[0]); - InteropService.Invoke(engine, InteropService.System_Contract_Destroy).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.Destroy).Should().BeTrue(); //storages are removed snapshot = Blockchain.Singleton.GetSnapshot(); @@ -819,7 +819,7 @@ public void TestContract_Destroy() snapshot.Contracts.Add(scriptHash, state); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0); engine.LoadScript(new byte[0]); - InteropService.Invoke(engine, InteropService.System_Contract_Destroy).Should().BeTrue(); + InteropService.Invoke(engine, InteropService.Contract.Destroy).Should().BeTrue(); } public static void LogEvent(object sender, LogEventArgs args) diff --git a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs index e6c0d006c2..04f60db7ff 100644 --- a/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -57,7 +57,7 @@ public void System_Blockchain_GetBlock() using (var script = new ScriptBuilder()) { script.EmitPush(block.Hash.ToArray()); - script.EmitSysCall(InteropService.System_Blockchain_GetBlock); + script.EmitSysCall(InteropService.Blockchain.GetBlock); // Without block @@ -75,7 +75,7 @@ public void System_Blockchain_GetBlock() blocks.Add(block.Hash, block.Trim()); txs.Add(tx.Hash, new TransactionState() { Transaction = tx, BlockIndex = block.Index, VMState = VMState.HALT }); - script.EmitSysCall(InteropService.Neo_Json_Serialize); + script.EmitSysCall(InteropService.Json.Serialize); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); @@ -100,9 +100,9 @@ public void Json_Deserialize() using (var script = new ScriptBuilder()) { script.EmitPush("123"); - script.EmitSysCall(InteropService.Neo_Json_Deserialize); + script.EmitSysCall(InteropService.Json.Deserialize); script.EmitPush("null"); - script.EmitSysCall(InteropService.Neo_Json_Deserialize); + script.EmitSysCall(InteropService.Json.Deserialize); using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) { @@ -121,7 +121,7 @@ public void Json_Deserialize() using (var script = new ScriptBuilder()) { script.EmitPush("***"); - script.EmitSysCall(InteropService.Neo_Json_Deserialize); + script.EmitSysCall(InteropService.Json.Deserialize); using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) { @@ -137,7 +137,7 @@ public void Json_Deserialize() using (var script = new ScriptBuilder()) { script.EmitPush("123.45"); - script.EmitSysCall(InteropService.Neo_Json_Deserialize); + script.EmitSysCall(InteropService.Json.Deserialize); using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) { @@ -157,20 +157,20 @@ public void Json_Serialize() using (var script = new ScriptBuilder()) { script.EmitPush(5); - script.EmitSysCall(InteropService.Neo_Json_Serialize); + script.EmitSysCall(InteropService.Json.Serialize); script.Emit(OpCode.PUSH0); script.Emit(OpCode.NOT); - script.EmitSysCall(InteropService.Neo_Json_Serialize); + script.EmitSysCall(InteropService.Json.Serialize); script.EmitPush("test"); - script.EmitSysCall(InteropService.Neo_Json_Serialize); + script.EmitSysCall(InteropService.Json.Serialize); script.Emit(OpCode.PUSHNULL); - script.EmitSysCall(InteropService.Neo_Json_Serialize); + script.EmitSysCall(InteropService.Json.Serialize); script.Emit(OpCode.NEWMAP); script.Emit(OpCode.DUP); script.EmitPush("key"); script.EmitPush("value"); script.Emit(OpCode.SETITEM); - script.EmitSysCall(InteropService.Neo_Json_Serialize); + script.EmitSysCall(InteropService.Json.Serialize); using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) { @@ -191,8 +191,8 @@ public void Json_Serialize() using (var script = new ScriptBuilder()) { - script.EmitSysCall(InteropService.System_Storage_GetContext); - script.EmitSysCall(InteropService.Neo_Json_Serialize); + script.EmitSysCall(InteropService.Storage.GetContext); + script.EmitSysCall(InteropService.Json.Serialize); using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) { @@ -210,7 +210,7 @@ public void System_ExecutionEngine_GetScriptContainer() var snapshot = Blockchain.Singleton.GetSnapshot(); using (var script = new ScriptBuilder()) { - script.EmitSysCall(InteropService.System_ExecutionEngine_GetScriptContainer); + script.EmitSysCall(InteropService.Runtime.GetScriptContainer); // Without tx @@ -223,7 +223,7 @@ public void System_ExecutionEngine_GetScriptContainer() // With tx - script.EmitSysCall(InteropService.Neo_Json_Serialize); + script.EmitSysCall(InteropService.Json.Serialize); var tx = new Transaction() { @@ -262,7 +262,7 @@ public void System_Runtime_GetInvocationCounter() using (var script = new ScriptBuilder()) { - script.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); + script.EmitSysCall(InteropService.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() }; @@ -283,10 +283,10 @@ public void System_Runtime_GetInvocationCounter() using (var script = new ScriptBuilder()) { - script.EmitSysCall(InteropService.System_Contract_Call, contractA.ScriptHash.ToArray(), "dummyMain", 0); - script.EmitSysCall(InteropService.System_Contract_Call, contractB.ScriptHash.ToArray(), "dummyMain", 0); - script.EmitSysCall(InteropService.System_Contract_Call, contractB.ScriptHash.ToArray(), "dummyMain", 0); - script.EmitSysCall(InteropService.System_Contract_Call, contractC.ScriptHash.ToArray(), "dummyMain", 0); + script.EmitSysCall(InteropService.Contract.Call, contractA.ScriptHash.ToArray(), "dummyMain", 0); + script.EmitSysCall(InteropService.Contract.Call, contractB.ScriptHash.ToArray(), "dummyMain", 0); + script.EmitSysCall(InteropService.Contract.Call, contractB.ScriptHash.ToArray(), "dummyMain", 0); + script.EmitSysCall(InteropService.Contract.Call, contractC.ScriptHash.ToArray(), "dummyMain", 0); // Execute diff --git a/tests/neo.UnitTests/VM/UT_Helper.cs b/tests/neo.UnitTests/VM/UT_Helper.cs index 1923f48a66..559f9013ae 100644 --- a/tests/neo.UnitTests/VM/UT_Helper.cs +++ b/tests/neo.UnitTests/VM/UT_Helper.cs @@ -41,7 +41,7 @@ public void TestEmitAppCall1() tempArray[9] = (byte)OpCode.PUSHDATA1; tempArray[10] = 0x14;//scriptHash.Length Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 11, 20);//operation.data - uint api = InteropService.System_Contract_Call; + uint api = InteropService.Contract.Call; tempArray[31] = (byte)OpCode.SYSCALL; Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 32, 4);//api.data CollectionAssert.AreEqual(tempArray, sb.ToArray()); @@ -63,7 +63,7 @@ public void TestEmitAppCall2() tempArray[10] = (byte)OpCode.PUSHDATA1; tempArray[11] = 0x14;//scriptHash.Length Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 12, 20);//operation.data - uint api = InteropService.System_Contract_Call; + uint api = InteropService.Contract.Call; tempArray[32] = (byte)OpCode.SYSCALL; Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 33, 4);//api.data CollectionAssert.AreEqual(tempArray, sb.ToArray()); @@ -85,7 +85,7 @@ public void TestEmitAppCall3() tempArray[10] = (byte)OpCode.PUSHDATA1; tempArray[11] = 0x14;//scriptHash.Length Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 12, 20);//operation.data - uint api = InteropService.System_Contract_Call; + uint api = InteropService.Contract.Call; tempArray[32] = (byte)OpCode.SYSCALL; Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 33, 4);//api.data CollectionAssert.AreEqual(tempArray, sb.ToArray());