From fad0a2de7de36eea9385d4b4700fce9446a7b388 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 1 Sep 2019 17:48:16 +0200 Subject: [PATCH 01/36] Add Transaction.Sender and Transaction.Script --- neo/SmartContract/InteropService.cs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 7aa7fd7284..4e7cadbff6 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -54,6 +54,8 @@ public static partial class InteropService public static readonly uint System_Block_GetTransactions = Register("System.Block.GetTransactions", Block_GetTransactions, 0_00010000, TriggerType.Application); public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, TriggerType.Application); public static readonly uint System_Transaction_GetHash = Register("System.Transaction.GetHash", Transaction_GetHash, 0_00000400, TriggerType.All); + public static readonly uint System_Transaction_GetSender = Register("System.Transaction.GetSender", Transaction_GetSender, /*TODO PRICE*/0_00000400, TriggerType.All); + public static readonly uint System_Transaction_GetNonce = Register("System.Transaction.GetNonce", Transaction_GetNonce, /*TODO PRICE*/0_00000400, TriggerType.All); 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); @@ -476,6 +478,30 @@ private static bool Transaction_GetHash(ApplicationEngine engine) return false; } + private static bool Transaction_GetSender(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + Transaction tx = _interface.GetInterface(); + if (tx == null) return false; + engine.CurrentContext.EvaluationStack.Push(tx.Sender.ToArray()); + return true; + } + return false; + } + + private static bool Transaction_GetNonce(ApplicationEngine engine) + { + if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + { + Transaction tx = _interface.GetInterface(); + if (tx == null) return false; + engine.CurrentContext.EvaluationStack.Push(tx.Nonce); + return true; + } + return false; + } + private static bool Storage_GetContext(ApplicationEngine engine) { engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext From d842dafab50b12aab9dec6db7870f58e12393094 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 1 Sep 2019 18:13:44 +0200 Subject: [PATCH 02/36] Allow to get the current Transaction --- neo/SmartContract/InteropService.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 4e7cadbff6..a2dc68ac7c 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -353,8 +353,16 @@ private static bool Blockchain_GetBlock(ApplicationEngine engine) private static bool Blockchain_GetTransaction(ApplicationEngine engine) { byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); - Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); + if (hash.Length == 0) + { + if (!(engine.ScriptContainer is Transaction tx)) return false; + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); + } + else + { + Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); + } return true; } From 4e5765fcfa0c2375e5d6def3921f794c2315ca31 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 2 Sep 2019 03:48:59 +0200 Subject: [PATCH 03/36] Update unit test, refactor transactions methods --- neo/SmartContract/InteropService.NEO.cs | 22 +++++-------------- neo/SmartContract/InteropService.cs | 29 ++++++++++--------------- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index 7f0d857fe9..d2010520e4 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -195,28 +195,16 @@ private static bool Header_GetNextConsensus(ApplicationEngine engine) private static bool Transaction_GetScript(ApplicationEngine engine) { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - Transaction tx = _interface.GetInterface(); - if (tx == null) return false; - engine.CurrentContext.EvaluationStack.Push(tx.Script); - return true; - } - return false; + return Transaction_Get(engine, (tx) => new ByteArray(tx.Script)); } private static bool Transaction_GetWitnesses(ApplicationEngine engine) { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) + return Transaction_Get(engine, (tx) => { - Transaction tx = _interface.GetInterface(); - if (tx == null) return false; - if (tx.Witnesses.Length > engine.MaxArraySize) - return false; - engine.CurrentContext.EvaluationStack.Push(WitnessWrapper.Create(tx, engine.Snapshot).Select(p => StackItem.FromInterface(p)).ToArray()); - return true; - } - return false; + if (tx.Witnesses.Length > engine.MaxArraySize) return null; + return WitnessWrapper.Create(tx, engine.Snapshot).Select(p => StackItem.FromInterface(p)).ToArray(); + }); } private static bool Witness_GetVerificationScript(ApplicationEngine engine) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index a2dc68ac7c..162887e91c 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -474,40 +474,33 @@ private static bool Block_GetTransaction(ApplicationEngine engine) return false; } - private static bool Transaction_GetHash(ApplicationEngine engine) + private static bool Transaction_Get(ApplicationEngine engine, Func input) { if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) { Transaction tx = _interface.GetInterface(); if (tx == null) return false; - engine.CurrentContext.EvaluationStack.Push(tx.Hash.ToArray()); + var item = input(tx); + if (item == null) return false; + engine.CurrentContext.EvaluationStack.Push(item); return true; } return false; } + private static bool Transaction_GetHash(ApplicationEngine engine) + { + return Transaction_Get(engine, (tx) => new ByteArray(tx.Hash.ToArray())); + } + private static bool Transaction_GetSender(ApplicationEngine engine) { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - Transaction tx = _interface.GetInterface(); - if (tx == null) return false; - engine.CurrentContext.EvaluationStack.Push(tx.Sender.ToArray()); - return true; - } - return false; + return Transaction_Get(engine, (tx) => new ByteArray(tx.Sender.ToArray())); } private static bool Transaction_GetNonce(ApplicationEngine engine) { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - Transaction tx = _interface.GetInterface(); - if (tx == null) return false; - engine.CurrentContext.EvaluationStack.Push(tx.Nonce); - return true; - } - return false; + return Transaction_Get(engine, (tx) => new Integer(tx.Nonce)); } private static bool Storage_GetContext(ApplicationEngine engine) From 1418b6bc406c8f78c1a2b3e7d35516feed2763a6 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 2 Sep 2019 03:52:40 +0200 Subject: [PATCH 04/36] UT --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 217 +++++++++++++++++++++ 1 file changed, 217 insertions(+) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 65066b9079..1f839e6de6 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -1,7 +1,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Ledger; +using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.VM; +using Neo.VM.Types; using System.Linq; namespace Neo.UnitTests.SmartContract @@ -9,6 +11,221 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_Syscalls { + [TestMethod] + public void Neo_Transaction_GetScript() + { + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + + var script = new ScriptBuilder(); + script.EmitSysCall(InteropService.Neo_Transaction_GetScript); + + // With tx + + var tx = new Transaction() { Script = new byte[] { 0x01 } }; + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + CollectionAssert.AreEqual(engine.ResultStack.Pop().GetByteArray(), tx.Script); + + // Without push + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + + // Without tx + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + } + + [TestMethod] + public void Neo_Transaction_GetHash() + { + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + + var script = new ScriptBuilder(); + script.EmitSysCall(InteropService.System_Transaction_GetHash); + + // With tx + + var tx = new Transaction() + { + Sender = UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), + Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], + Script = new byte[0], + Witnesses = new Witness[0], + }; + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + CollectionAssert.AreEqual(engine.ResultStack.Pop().GetByteArray(), tx.Hash.ToArray()); + + // Without push + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + + // Without tx + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + } + + [TestMethod] + public void Neo_Transaction_GetWitnesses() + { + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + + var script = new ScriptBuilder(); + script.EmitSysCall(InteropService.Neo_Transaction_GetWitnesses); + + // With tx + + var tx = new Transaction() + { + Witnesses = new Witness[] + { + new Witness() + { + InvocationScript = new byte[] { 0x01 }, + VerificationScript = new byte[] { 0x02 } + } + } + }; + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + var item = (Array)engine.ResultStack.Pop(); + CollectionAssert.AreEqual((item[0] as InteropInterface) + .GetInterface().VerificationScript, tx.Witnesses[0].VerificationScript.ToArray()); + + // More than expected + + tx.Witnesses = new Witness[engine.MaxArraySize + 1]; + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + + // Without push + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + + // Without tx + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + } + + [TestMethod] + public void Neo_Transaction_GetNonce() + { + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + + var script = new ScriptBuilder(); + script.EmitSysCall(InteropService.System_Transaction_GetNonce); + + // With tx + + var tx = new Transaction() { Nonce = 0x505152 }; + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(engine.ResultStack.Pop().GetBigInteger(), tx.Nonce); + + // Without push + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + + // Without tx + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + } + + [TestMethod] + public void Neo_Transaction_GetSender() + { + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + + var script = new ScriptBuilder(); + script.EmitSysCall(InteropService.System_Transaction_GetSender); + + // With tx + + var tx = new Transaction() { Sender = UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") }; + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + CollectionAssert.AreEqual(engine.ResultStack.Pop().GetByteArray(), tx.Sender.ToArray()); + + // Without push + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + + // Without tx + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + } + [TestMethod] public void System_Runtime_GetInvocationCounter() { From 008fb1133f55b863ce0e78d0dc9f7bff8453b625 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 4 Sep 2019 08:31:51 +0200 Subject: [PATCH 05/36] Summary TX object inside VM --- neo/SmartContract/InteropService.NEO.cs | 16 ------- neo/SmartContract/InteropService.cs | 64 +++++++++++-------------- 2 files changed, 29 insertions(+), 51 deletions(-) diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index d2010520e4..e4cbdb041f 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -23,8 +23,6 @@ static partial class InteropService public static readonly uint Neo_Header_GetVersion = Register("Neo.Header.GetVersion", Header_GetVersion, 0_00000400, TriggerType.Application); public static readonly uint Neo_Header_GetMerkleRoot = Register("Neo.Header.GetMerkleRoot", Header_GetMerkleRoot, 0_00000400, TriggerType.Application); public static readonly uint Neo_Header_GetNextConsensus = Register("Neo.Header.GetNextConsensus", Header_GetNextConsensus, 0_00000400, TriggerType.Application); - public static readonly uint Neo_Transaction_GetScript = Register("Neo.Transaction.GetScript", Transaction_GetScript, 0_00000400, TriggerType.All); - public static readonly uint Neo_Transaction_GetWitnesses = Register("Neo.Transaction.GetWitnesses", Transaction_GetWitnesses, 0_00010000, TriggerType.All); public static readonly uint Neo_Witness_GetVerificationScript = Register("Neo.Witness.GetVerificationScript", Witness_GetVerificationScript, 0_00000400, 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); @@ -193,20 +191,6 @@ private static bool Header_GetNextConsensus(ApplicationEngine engine) return false; } - private static bool Transaction_GetScript(ApplicationEngine engine) - { - return Transaction_Get(engine, (tx) => new ByteArray(tx.Script)); - } - - private static bool Transaction_GetWitnesses(ApplicationEngine engine) - { - return Transaction_Get(engine, (tx) => - { - if (tx.Witnesses.Length > engine.MaxArraySize) return null; - return WitnessWrapper.Create(tx, engine.Snapshot).Select(p => StackItem.FromInterface(p)).ToArray(); - }); - } - private static bool Witness_GetVerificationScript(ApplicationEngine engine) { if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 162887e91c..cb9489ee6e 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -53,9 +53,6 @@ public static partial class InteropService public static readonly uint System_Block_GetTransactionCount = Register("System.Block.GetTransactionCount", Block_GetTransactionCount, 0_00000400, TriggerType.Application); public static readonly uint System_Block_GetTransactions = Register("System.Block.GetTransactions", Block_GetTransactions, 0_00010000, TriggerType.Application); public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, TriggerType.Application); - public static readonly uint System_Transaction_GetHash = Register("System.Transaction.GetHash", Transaction_GetHash, 0_00000400, TriggerType.All); - public static readonly uint System_Transaction_GetSender = Register("System.Transaction.GetSender", Transaction_GetSender, /*TODO PRICE*/0_00000400, TriggerType.All); - public static readonly uint System_Transaction_GetNonce = Register("System.Transaction.GetNonce", Transaction_GetNonce, /*TODO PRICE*/0_00000400, TriggerType.All); 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); @@ -114,7 +111,14 @@ private static uint Register(string method, Func handle private static bool ExecutionEngine_GetScriptContainer(ApplicationEngine engine) { - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(engine.ScriptContainer)); + if (engine.ScriptContainer is Transaction tx) + { + engine.CurrentContext.EvaluationStack.Push(TransactionToStackItem(tx)); + } + else + { + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(engine.ScriptContainer)); + } return true; } @@ -445,6 +449,25 @@ private static bool Block_GetTransactionCount(ApplicationEngine engine) return false; } + private static StackItem TransactionToStackItem(Transaction tx) + { + return new VM.Types.Array + ( + new StackItem[] + { + new ByteArray(tx.Hash.ToArray()), + new ByteArray(tx.Sender.ToArray()), + new ByteArray(tx.Script), + new VM.Types.Array(tx.Witnesses.Select(u=>new ByteArray(u.VerificationScript))), + new Integer(tx.Nonce), + new Integer(tx.NetworkFee), + new Integer(tx.SystemFee), + new Integer(tx.ValidUntilBlock), + new Integer(tx.Version) + } + ); + } + private static bool Block_GetTransactions(ApplicationEngine engine) { if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) @@ -453,7 +476,7 @@ private static bool Block_GetTransactions(ApplicationEngine engine) if (block == null) return false; if (block.Transactions.Length > engine.MaxArraySize) return false; - engine.CurrentContext.EvaluationStack.Push(block.Transactions.Select(p => StackItem.FromInterface(p)).ToArray()); + engine.CurrentContext.EvaluationStack.Push(new VM.Types.Array(block.Transactions.Select(p => TransactionToStackItem(p)))); return true; } return false; @@ -468,41 +491,12 @@ private static bool Block_GetTransaction(ApplicationEngine engine) if (block == null) return false; if (index < 0 || index >= block.Transactions.Length) return false; Transaction tx = block.Transactions[index]; - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); + engine.CurrentContext.EvaluationStack.Push(TransactionToStackItem(tx)); return true; } return false; } - private static bool Transaction_Get(ApplicationEngine engine, Func input) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - Transaction tx = _interface.GetInterface(); - if (tx == null) return false; - var item = input(tx); - if (item == null) return false; - engine.CurrentContext.EvaluationStack.Push(item); - return true; - } - return false; - } - - private static bool Transaction_GetHash(ApplicationEngine engine) - { - return Transaction_Get(engine, (tx) => new ByteArray(tx.Hash.ToArray())); - } - - private static bool Transaction_GetSender(ApplicationEngine engine) - { - return Transaction_Get(engine, (tx) => new ByteArray(tx.Sender.ToArray())); - } - - private static bool Transaction_GetNonce(ApplicationEngine engine) - { - return Transaction_Get(engine, (tx) => new Integer(tx.Nonce)); - } - private static bool Storage_GetContext(ApplicationEngine engine) { engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext From 6002ce197e21a8915f0a49b7d84194e092e84f25 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 4 Sep 2019 08:36:11 +0200 Subject: [PATCH 06/36] Revert some changes --- neo/SmartContract/InteropService.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index cb9489ee6e..6db688087b 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -357,16 +357,9 @@ private static bool Blockchain_GetBlock(ApplicationEngine engine) private static bool Blockchain_GetTransaction(ApplicationEngine engine) { byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); - if (hash.Length == 0) - { - if (!(engine.ScriptContainer is Transaction tx)) return false; - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); - } - else - { - Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); - } + Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); + if (tx == null) return false; + engine.CurrentContext.EvaluationStack.Push(TransactionToStackItem(tx)); return true; } From af6ccff2f420aac182a6072d95f1c7959d5512d2 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 4 Sep 2019 17:50:27 +0200 Subject: [PATCH 07/36] Refactor to new model and UT --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 315 +++++---------------- neo/Network/P2P/Payloads/Transaction.cs | 23 +- neo/SmartContract/IInteroperable.cs | 9 + neo/SmartContract/InteropService.cs | 27 +- 4 files changed, 110 insertions(+), 264 deletions(-) create mode 100644 neo/SmartContract/IInteroperable.cs diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 1f839e6de6..8a4b3ebaf0 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -12,272 +12,107 @@ namespace Neo.UnitTests.SmartContract public class UT_Syscalls { [TestMethod] - public void Neo_Transaction_GetScript() + public void System_ExecutionEngine_GetScriptContainer() { var snapshot = TestBlockchain.GetStore().GetSnapshot(); - - var script = new ScriptBuilder(); - script.EmitSysCall(InteropService.Neo_Transaction_GetScript); - - // With tx - - var tx = new Transaction() { Script = new byte[] { 0x01 } }; - - var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); - - Assert.AreEqual(engine.Execute(), VMState.HALT); - CollectionAssert.AreEqual(engine.ResultStack.Pop().GetByteArray(), tx.Script); - - // Without push - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - - // Without tx - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - } - - [TestMethod] - public void Neo_Transaction_GetHash() - { - var snapshot = TestBlockchain.GetStore().GetSnapshot(); - - var script = new ScriptBuilder(); - script.EmitSysCall(InteropService.System_Transaction_GetHash); - - // With tx - - var tx = new Transaction() + using (var script = new ScriptBuilder()) { - Sender = UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), - Attributes = new TransactionAttribute[0], - Cosigners = new Cosigner[0], - Script = new byte[0], - Witnesses = new Witness[0], - }; - - var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); - - Assert.AreEqual(engine.Execute(), VMState.HALT); - CollectionAssert.AreEqual(engine.ResultStack.Pop().GetByteArray(), tx.Hash.ToArray()); + script.EmitSysCall(InteropService.System_ExecutionEngine_GetScriptContainer); - // Without push + // Without tx - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsNull(((InteropInterface)engine.ResultStack.Pop()).GetInterface()); - // Without tx + // With tx - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); + script.EmitSysCall(InteropService.Neo_Json_Serialize); - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - } - - [TestMethod] - public void Neo_Transaction_GetWitnesses() - { - var snapshot = TestBlockchain.GetStore().GetSnapshot(); - - var script = new ScriptBuilder(); - script.EmitSysCall(InteropService.Neo_Transaction_GetWitnesses); - - // With tx - - var tx = new Transaction() - { - Witnesses = new Witness[] + var tx = new Transaction() { - new Witness() - { - InvocationScript = new byte[] { 0x01 }, - VerificationScript = new byte[] { 0x02 } - } - } - }; - - var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); - - Assert.AreEqual(engine.Execute(), VMState.HALT); - var item = (Array)engine.ResultStack.Pop(); - CollectionAssert.AreEqual((item[0] as InteropInterface) - .GetInterface().VerificationScript, tx.Witnesses[0].VerificationScript.ToArray()); - - // More than expected - - tx.Witnesses = new Witness[engine.MaxArraySize + 1]; - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - - // Without push - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - - // Without tx - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - } - - [TestMethod] - public void Neo_Transaction_GetNonce() - { - var snapshot = TestBlockchain.GetStore().GetSnapshot(); - - var script = new ScriptBuilder(); - script.EmitSysCall(InteropService.System_Transaction_GetNonce); - - // With tx - - var tx = new Transaction() { Nonce = 0x505152 }; - - var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); - - Assert.AreEqual(engine.Execute(), VMState.HALT); - Assert.AreEqual(engine.ResultStack.Pop().GetBigInteger(), tx.Nonce); - - // Without push - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - - // Without tx - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - } - - [TestMethod] - public void Neo_Transaction_GetSender() - { - var snapshot = TestBlockchain.GetStore().GetSnapshot(); - - var script = new ScriptBuilder(); - script.EmitSysCall(InteropService.System_Transaction_GetSender); - - // With tx - - var tx = new Transaction() { Sender = UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") }; - - var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); - - Assert.AreEqual(engine.Execute(), VMState.HALT); - CollectionAssert.AreEqual(engine.ResultStack.Pop().GetByteArray(), tx.Sender.ToArray()); - - // Without push - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); - - // Without tx - - engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(new object())); - - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); + Script = new byte[] { 0x01 }, + Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], + NetworkFee = 0x02, + SystemFee = 0x03, + Nonce = 0x04, + ValidUntilBlock = 0x05, + Version = 0x06, + Witnesses = new Witness[] { new Witness() { VerificationScript = new byte[] { 0x07 } } }, + Sender = UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), + }; + + engine = new ApplicationEngine(TriggerType.Application, tx, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(engine.ResultStack.Pop().GetString(), + @"[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD"",""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",""\u0001"",[""\u0007""],4,2,3,5,6]"); + } } [TestMethod] public void System_Runtime_GetInvocationCounter() { + ContractState contractA, contractB, contractC; var snapshot = TestBlockchain.GetStore().GetSnapshot(); var contracts = (TestDataCache)snapshot.Contracts; // Call System.Runtime.GetInvocationCounter syscall - var script = new ScriptBuilder(); - script.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); + using (var script = new ScriptBuilder()) + { + contractA = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(script.ToArray()).ToArray() }; + contractB = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; + contractC = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; - // Init A,B,C contracts - // First two drops is for drop method and arguments + script.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); - var contractA = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(script.ToArray()).ToArray() }; - var contractB = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; - var contractC = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; + // Init A,B,C contracts + // First two drops is for drop method and arguments - contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractA.ScriptHash.ToArray())); - contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractB.ScriptHash.ToArray())); - contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractC.ScriptHash.ToArray())); - contracts.Add(contractA.ScriptHash, contractA); - contracts.Add(contractB.ScriptHash, contractB); - contracts.Add(contractC.ScriptHash, contractC); + contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractA.ScriptHash.ToArray())); + contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractB.ScriptHash.ToArray())); + contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractC.ScriptHash.ToArray())); + contracts.Add(contractA.ScriptHash, contractA); + contracts.Add(contractB.ScriptHash, contractB); + contracts.Add(contractC.ScriptHash, contractC); + } // Call A,B,B,C - 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); - - // Execute - - var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); - engine.LoadScript(script.ToArray()); - Assert.AreEqual(engine.Execute(), VMState.HALT); - - // Check the results - - CollectionAssert.AreEqual - ( - engine.ResultStack.Select(u => (int)((VM.Types.Integer)u).GetBigInteger()).ToArray(), - new int[] - { - 1, /* A */ - 1, /* B */ - 2, /* B */ - 1 /* C */ - } - ); + 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); + + // Execute + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + Assert.AreEqual(engine.Execute(), VMState.HALT); + + // Check the results + + CollectionAssert.AreEqual + ( + engine.ResultStack.Select(u => (int)((VM.Types.Integer)u).GetBigInteger()).ToArray(), + new int[] + { + 1, /* A */ + 1, /* B */ + 2, /* B */ + 1 /* C */ + } + ); + } } } } diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs index a2586e6da2..235c20fc09 100644 --- a/neo/Network/P2P/Payloads/Transaction.cs +++ b/neo/Network/P2P/Payloads/Transaction.cs @@ -4,6 +4,8 @@ using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; using Neo.Wallets; using System; using System.Collections.Generic; @@ -13,7 +15,7 @@ namespace Neo.Network.P2P.Payloads { - public class Transaction : IEquatable, IInventory + public class Transaction : IEquatable, IInventory, IInteroperable { public const int MaxTransactionSize = 102400; public const uint MaxValidUntilBlockIncrement = 2102400; @@ -215,5 +217,24 @@ public virtual bool Verify(Snapshot snapshot, IEnumerable mempool) if (net_fee < 0) return false; return this.VerifyWitnesses(snapshot, net_fee); } + + public StackItem ToStackItem() + { + return new VM.Types.Array + ( + new StackItem[] + { + new ByteArray(Hash.ToArray()), + new ByteArray(Sender.ToArray()), + new ByteArray(Script), + new VM.Types.Array(Witnesses.Select(u=>new ByteArray(u.VerificationScript))), + new Integer(Nonce), + new Integer(NetworkFee), + new Integer(SystemFee), + new Integer(ValidUntilBlock), + new Integer(Version) + } + ); + } } } diff --git a/neo/SmartContract/IInteroperable.cs b/neo/SmartContract/IInteroperable.cs new file mode 100644 index 0000000000..972147877c --- /dev/null +++ b/neo/SmartContract/IInteroperable.cs @@ -0,0 +1,9 @@ +using Neo.VM; + +namespace Neo.SmartContract +{ + public interface IInteroperable + { + StackItem ToStackItem(); + } +} diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 6db688087b..955495ffa6 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -113,7 +113,7 @@ private static bool ExecutionEngine_GetScriptContainer(ApplicationEngine engine) { if (engine.ScriptContainer is Transaction tx) { - engine.CurrentContext.EvaluationStack.Push(TransactionToStackItem(tx)); + engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem()); } else { @@ -359,7 +359,7 @@ private static bool Blockchain_GetTransaction(ApplicationEngine engine) byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); if (tx == null) return false; - engine.CurrentContext.EvaluationStack.Push(TransactionToStackItem(tx)); + engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem()); return true; } @@ -442,25 +442,6 @@ private static bool Block_GetTransactionCount(ApplicationEngine engine) return false; } - private static StackItem TransactionToStackItem(Transaction tx) - { - return new VM.Types.Array - ( - new StackItem[] - { - new ByteArray(tx.Hash.ToArray()), - new ByteArray(tx.Sender.ToArray()), - new ByteArray(tx.Script), - new VM.Types.Array(tx.Witnesses.Select(u=>new ByteArray(u.VerificationScript))), - new Integer(tx.Nonce), - new Integer(tx.NetworkFee), - new Integer(tx.SystemFee), - new Integer(tx.ValidUntilBlock), - new Integer(tx.Version) - } - ); - } - private static bool Block_GetTransactions(ApplicationEngine engine) { if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) @@ -469,7 +450,7 @@ private static bool Block_GetTransactions(ApplicationEngine engine) if (block == null) return false; if (block.Transactions.Length > engine.MaxArraySize) return false; - engine.CurrentContext.EvaluationStack.Push(new VM.Types.Array(block.Transactions.Select(p => TransactionToStackItem(p)))); + engine.CurrentContext.EvaluationStack.Push(new VM.Types.Array(block.Transactions.Select(tx => tx.ToStackItem()))); return true; } return false; @@ -484,7 +465,7 @@ private static bool Block_GetTransaction(ApplicationEngine engine) if (block == null) return false; if (index < 0 || index >= block.Transactions.Length) return false; Transaction tx = block.Transactions[index]; - engine.CurrentContext.EvaluationStack.Push(TransactionToStackItem(tx)); + engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem()); return true; } return false; From f094d53c2d71cbe2bf4f78091eeaa3faba1467f3 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 4 Sep 2019 17:57:11 +0200 Subject: [PATCH 08/36] Fix --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 2 ++ neo/SmartContract/InteropService.cs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 8a4b3ebaf0..1bdf5952cd 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -51,8 +51,10 @@ public void System_ExecutionEngine_GetScriptContainer() engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(2, engine.ResultStack.Count); Assert.AreEqual(engine.ResultStack.Pop().GetString(), @"[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD"",""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",""\u0001"",[""\u0007""],4,2,3,5,6]"); + Assert.AreEqual(1, engine.ResultStack.Count); } } diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 955495ffa6..17b5761863 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -111,9 +111,9 @@ private static uint Register(string method, Func handle private static bool ExecutionEngine_GetScriptContainer(ApplicationEngine engine) { - if (engine.ScriptContainer is Transaction tx) + if (engine.ScriptContainer is IInteroperable value) { - engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem()); + engine.CurrentContext.EvaluationStack.Push(value.ToStackItem()); } else { From e7c31dddb569a989e89751d819f893f8ab08327e Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 4 Sep 2019 18:00:14 +0200 Subject: [PATCH 09/36] Reduce conditional --- neo/SmartContract/InteropService.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 17b5761863..346877b48e 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -111,14 +111,9 @@ private static uint Register(string method, Func handle private static bool ExecutionEngine_GetScriptContainer(ApplicationEngine engine) { - if (engine.ScriptContainer is IInteroperable value) - { - engine.CurrentContext.EvaluationStack.Push(value.ToStackItem()); - } - else - { - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(engine.ScriptContainer)); - } + engine.CurrentContext.EvaluationStack.Push( + engine.ScriptContainer is IInteroperable value ? value.ToStackItem() : + StackItem.FromInterface(engine.ScriptContainer)); return true; } From 194bb994cb91425507c34317e60d2ccaca188185 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 5 Sep 2019 02:03:32 +0200 Subject: [PATCH 10/36] Fix ut --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 1bdf5952cd..c10e46f582 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -48,13 +48,12 @@ public void System_ExecutionEngine_GetScriptContainer() engine = new ApplicationEngine(TriggerType.Application, tx, snapshot, 0, true); engine.LoadScript(script.ToArray()); - engine.CurrentContext.EvaluationStack.Push(InteropInterface.FromInterface(tx)); Assert.AreEqual(engine.Execute(), VMState.HALT); - Assert.AreEqual(2, engine.ResultStack.Count); + Assert.AreEqual(1, engine.ResultStack.Count); Assert.AreEqual(engine.ResultStack.Pop().GetString(), @"[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD"",""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",""\u0001"",[""\u0007""],4,2,3,5,6]"); - Assert.AreEqual(1, engine.ResultStack.Count); + Assert.AreEqual(0, engine.ResultStack.Count); } } From c3eb5f5a932b9635fa95037b993a835fb9c8c392 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 5 Sep 2019 02:10:36 +0200 Subject: [PATCH 11/36] Fix ut --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index c10e46f582..3c36f5f893 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -64,16 +64,16 @@ public void System_Runtime_GetInvocationCounter() var snapshot = TestBlockchain.GetStore().GetSnapshot(); var contracts = (TestDataCache)snapshot.Contracts; - // Call System.Runtime.GetInvocationCounter syscall + // Create dummy contracts using (var script = new ScriptBuilder()) { + script.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); + contractA = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(script.ToArray()).ToArray() }; contractB = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; contractC = new ContractState() { Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP, (byte)OpCode.NOP, (byte)OpCode.NOP }.Concat(script.ToArray()).ToArray() }; - script.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter); - // Init A,B,C contracts // First two drops is for drop method and arguments From e40c9fe84feeb9fd05be5a76e49d60700d558f0a Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 10 Sep 2019 17:20:21 +0200 Subject: [PATCH 12/36] Change order --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 2 +- neo/Network/P2P/Payloads/Transaction.cs | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 3c36f5f893..102b3f9222 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -52,7 +52,7 @@ public void System_ExecutionEngine_GetScriptContainer() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.AreEqual(engine.ResultStack.Pop().GetString(), - @"[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD"",""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",""\u0001"",[""\u0007""],4,2,3,5,6]"); + @"[6,4,""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",3,2,5,""\u0001"",[""\u0007""],""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""]"); Assert.AreEqual(0, engine.ResultStack.Count); } } diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs index 235c20fc09..e0be1d0185 100644 --- a/neo/Network/P2P/Payloads/Transaction.cs +++ b/neo/Network/P2P/Payloads/Transaction.cs @@ -224,15 +224,18 @@ public StackItem ToStackItem() ( new StackItem[] { - new ByteArray(Hash.ToArray()), - new ByteArray(Sender.ToArray()), - new ByteArray(Script), - new VM.Types.Array(Witnesses.Select(u=>new ByteArray(u.VerificationScript))), + new Integer(Version), new Integer(Nonce), - new Integer(NetworkFee), + new ByteArray(Sender.ToArray()), new Integer(SystemFee), + new Integer(NetworkFee), new Integer(ValidUntilBlock), - new Integer(Version) + // Attributes + // Cosigners + new ByteArray(Script), + new VM.Types.Array(Witnesses.Select(u=>new ByteArray(u.VerificationScript))), + // Computed properties + new ByteArray(Hash.ToArray()), } ); } From 32c16683ad837e6bdf6635554de896fd3d8d226c Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 10 Sep 2019 17:53:26 +0200 Subject: [PATCH 13/36] Block --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 71 ++++++++++++++++ neo/Network/P2P/Payloads/Block.cs | 31 ++++++- neo/SmartContract/InteropService.cs | 99 +--------------------- 3 files changed, 103 insertions(+), 98 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 102b3f9222..ee20fa9611 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -11,6 +11,77 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_Syscalls { + [TestMethod] + public void System_Blockchain_GetBlock() + { + var tx = new Transaction() + { + Script = new byte[] { 0x01 }, + Attributes = new TransactionAttribute[0], + Cosigners = new Cosigner[0], + NetworkFee = 0x02, + SystemFee = 0x03, + Nonce = 0x04, + ValidUntilBlock = 0x05, + Version = 0x06, + Witnesses = new Witness[] { new Witness() { VerificationScript = new byte[] { 0x07 } } }, + Sender = UInt160.Parse("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), + }; + + var block = new Block() + { + Index = 1, + Timestamp = 2, + Version = 3, + Witness = new Witness() + { + InvocationScript = new byte[0], + VerificationScript = new byte[0] + }, + PrevHash = UInt256.Zero, + MerkleRoot = UInt256.Zero, + NextConsensus = UInt160.Zero, + ConsensusData = new ConsensusData() { Nonce = 1, PrimaryIndex = 1 }, + Transactions = new Transaction[] { tx } + }; + + var snapshot = TestBlockchain.GetStore().GetSnapshot(); + + using (var script = new ScriptBuilder()) + { + script.EmitPush(block.Hash.ToArray()); + script.EmitSysCall(InteropService.System_Blockchain_GetBlock); + script.EmitSysCall(InteropService.Neo_Json_Serialize); + + // Without block + + var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.FAULT); + Assert.AreEqual(0, engine.ResultStack.Count); + + var blocks = (TestDataCache)snapshot.Blocks; + var txs = (TestDataCache)snapshot.Transactions; + blocks.Add(block.Hash, block.Trim()); + txs.Add(tx.Hash, new TransactionState() { Transaction = tx, BlockIndex = block.Index, VMState = VMState.HALT }); + + engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + var p = engine.ResultStack.Peek().GetString(); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.AreEqual(engine.ResultStack.Pop().GetString(), + @"[3,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",2,1,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",3,[[6,4,""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",3,2,5,""\u0001"",[""\u0007""],""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""]],""Q\uFFFDy\uFFFD\uFFFD\u0003\uFFFD\uFFFD\uFFFDuF\u000Fq\u012A\b[Y\u0443\uFFFD\uFFFD}]v{8\uFFFDx\u0027\uFFFD\uFFFD""]"); + Assert.AreEqual(0, engine.ResultStack.Count); + + // Clean + blocks.Delete(block.Hash); + txs.Delete(tx.Hash); + } + } + [TestMethod] public void System_ExecutionEngine_GetScriptContainer() { diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index d339b536a0..d8b86855ae 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -2,6 +2,9 @@ using Neo.IO; using Neo.IO.Json; using Neo.Ledger; +using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System; using System.Collections.Generic; using System.IO; @@ -9,7 +12,7 @@ namespace Neo.Network.P2P.Payloads { - public class Block : BlockBase, IInventory, IEquatable + public class Block : BlockBase, IInventory, IEquatable, IInteroperable { public const int MaxContentsPerBlock = ushort.MaxValue; public const int MaxTransactionsPerBlock = MaxContentsPerBlock - 1; @@ -131,5 +134,31 @@ public TrimmedBlock Trim() ConsensusData = ConsensusData }; } + + public StackItem ToStackItem() + { + return new VM.Types.Array + ( + new StackItem[] + { + // Base + new Integer(Version), + new ByteArray(PrevHash.ToArray()), + new ByteArray(MerkleRoot.ToArray()), + new Integer(Timestamp), + new Integer(Index), + new ByteArray(NextConsensus.ToArray()), + new Integer(Version), + // Witness + + // Count + // ConsensusData + // Transactions + new VM.Types.Array(Transactions.Select(u=>u.ToStackItem())), + // Computed properties + new ByteArray(Hash.ToArray()), + } + ); + } } } diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 346877b48e..bef7cfab50 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -46,13 +46,6 @@ public static partial class InteropService 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_GetContract = Register("System.Blockchain.GetContract", Blockchain_GetContract, 0_01000000, TriggerType.Application); - public static readonly uint System_Header_GetIndex = Register("System.Header.GetIndex", Header_GetIndex, 0_00000400, TriggerType.Application); - public static readonly uint System_Header_GetHash = Register("System.Header.GetHash", Header_GetHash, 0_00000400, TriggerType.Application); - public static readonly uint System_Header_GetPrevHash = Register("System.Header.GetPrevHash", Header_GetPrevHash, 0_00000400, TriggerType.Application); - public static readonly uint System_Header_GetTimestamp = Register("System.Header.GetTimestamp", Header_GetTimestamp, 0_00000400, TriggerType.Application); - public static readonly uint System_Block_GetTransactionCount = Register("System.Block.GetTransactionCount", Block_GetTransactionCount, 0_00000400, TriggerType.Application); - public static readonly uint System_Block_GetTransactions = Register("System.Block.GetTransactions", Block_GetTransactions, 0_00010000, TriggerType.Application); - public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, 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); @@ -344,7 +337,8 @@ private static bool Blockchain_GetBlock(ApplicationEngine engine) else { Block block = engine.Snapshot.GetBlock(hash); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(block)); + if (block == null) return false; + engine.CurrentContext.EvaluationStack.Push(block.ToStackItem()); } return true; } @@ -377,95 +371,6 @@ private static bool Blockchain_GetContract(ApplicationEngine engine) return true; } - private static bool Header_GetIndex(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - BlockBase header = _interface.GetInterface(); - if (header == null) return false; - engine.CurrentContext.EvaluationStack.Push(header.Index); - return true; - } - return false; - } - - private static bool Header_GetHash(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - BlockBase header = _interface.GetInterface(); - if (header == null) return false; - engine.CurrentContext.EvaluationStack.Push(header.Hash.ToArray()); - return true; - } - return false; - } - - private static bool Header_GetPrevHash(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - BlockBase header = _interface.GetInterface(); - if (header == null) return false; - engine.CurrentContext.EvaluationStack.Push(header.PrevHash.ToArray()); - return true; - } - return false; - } - - private static bool Header_GetTimestamp(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - BlockBase header = _interface.GetInterface(); - if (header == null) return false; - engine.CurrentContext.EvaluationStack.Push(header.Timestamp); - return true; - } - return false; - } - - private static bool Block_GetTransactionCount(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - Block block = _interface.GetInterface(); - if (block == null) return false; - engine.CurrentContext.EvaluationStack.Push(block.Transactions.Length); - return true; - } - return false; - } - - private static bool Block_GetTransactions(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - Block block = _interface.GetInterface(); - if (block == null) return false; - if (block.Transactions.Length > engine.MaxArraySize) - return false; - engine.CurrentContext.EvaluationStack.Push(new VM.Types.Array(block.Transactions.Select(tx => tx.ToStackItem()))); - return true; - } - return false; - } - - private static bool Block_GetTransaction(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - Block block = _interface.GetInterface(); - int index = (int)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); - if (block == null) return false; - if (index < 0 || index >= block.Transactions.Length) return false; - Transaction tx = block.Transactions[index]; - engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem()); - return true; - } - return false; - } - private static bool Storage_GetContext(ApplicationEngine engine) { engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext From 4ddf8630f18668676f88793a6e782bd3f3417b0a Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 08:33:35 +0200 Subject: [PATCH 14/36] Some fixes --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 4 ++-- neo/Network/P2P/Payloads/Block.cs | 3 +-- neo/Network/P2P/Payloads/Transaction.cs | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index ee20fa9611..929731c3f4 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -73,7 +73,7 @@ public void System_Blockchain_GetBlock() var p = engine.ResultStack.Peek().GetString(); Assert.AreEqual(1, engine.ResultStack.Count); Assert.AreEqual(engine.ResultStack.Pop().GetString(), - @"[3,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",2,1,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",3,[[6,4,""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",3,2,5,""\u0001"",[""\u0007""],""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""]],""Q\uFFFDy\uFFFD\uFFFD\u0003\uFFFD\uFFFD\uFFFDuF\u000Fq\u012A\b[Y\u0443\uFFFD\uFFFD}]v{8\uFFFDx\u0027\uFFFD\uFFFD""]"); + @"[3,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",2,1,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""],""Q\uFFFDy\uFFFD\uFFFD\u0003\uFFFD\uFFFD\uFFFDuF\u000Fq\u012A\b[Y\u0443\uFFFD\uFFFD}]v{8\uFFFDx\u0027\uFFFD\uFFFD""]"); Assert.AreEqual(0, engine.ResultStack.Count); // Clean @@ -123,7 +123,7 @@ public void System_ExecutionEngine_GetScriptContainer() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.AreEqual(engine.ResultStack.Pop().GetString(), - @"[6,4,""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",3,2,5,""\u0001"",[""\u0007""],""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""]"); + @"[6,4,""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",3,2,5,""\u0001"",""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""]"); Assert.AreEqual(0, engine.ResultStack.Count); } } diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index d8b86855ae..7d72e72cb7 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -148,13 +148,12 @@ public StackItem ToStackItem() new Integer(Timestamp), new Integer(Index), new ByteArray(NextConsensus.ToArray()), - new Integer(Version), // Witness // Count // ConsensusData // Transactions - new VM.Types.Array(Transactions.Select(u=>u.ToStackItem())), + new VM.Types.Array(Transactions.Select(u => new ByteArray(u.Hash.ToArray()))), // Computed properties new ByteArray(Hash.ToArray()), } diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs index e0be1d0185..91a4d7e51a 100644 --- a/neo/Network/P2P/Payloads/Transaction.cs +++ b/neo/Network/P2P/Payloads/Transaction.cs @@ -233,7 +233,7 @@ public StackItem ToStackItem() // Attributes // Cosigners new ByteArray(Script), - new VM.Types.Array(Witnesses.Select(u=>new ByteArray(u.VerificationScript))), + // Witnesses // Computed properties new ByteArray(Hash.ToArray()), } From 2da33acfdf3475b58311209f2ea8454d31b0930a Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 08:40:33 +0200 Subject: [PATCH 15/36] Fix comment --- neo/Network/P2P/Payloads/Transaction.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs index 91a4d7e51a..33f4302cb9 100644 --- a/neo/Network/P2P/Payloads/Transaction.cs +++ b/neo/Network/P2P/Payloads/Transaction.cs @@ -70,7 +70,7 @@ public UInt256 Hash sizeof(byte) + //Version sizeof(uint) + //Nonce 20 + //Sender - sizeof(long) + //Gas + sizeof(long) + //SystemFee sizeof(long) + //NetworkFee sizeof(uint); //ValidUntilBlock From 02103335eca52e91c5a812274b41a16424972104 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 08:43:12 +0200 Subject: [PATCH 16/36] Fix comments --- neo/Network/P2P/Payloads/Block.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index 7d72e72cb7..b9d94a9789 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -141,7 +141,7 @@ public StackItem ToStackItem() ( new StackItem[] { - // Base + // BlockBase properties new Integer(Version), new ByteArray(PrevHash.ToArray()), new ByteArray(MerkleRoot.ToArray()), @@ -150,9 +150,9 @@ public StackItem ToStackItem() new ByteArray(NextConsensus.ToArray()), // Witness + // Block properties // Count // ConsensusData - // Transactions new VM.Types.Array(Transactions.Select(u => new ByteArray(u.Hash.ToArray()))), // Computed properties new ByteArray(Hash.ToArray()), From de35932260d4a155c3c84520fa35e71eb7925b0d Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 11:42:40 +0200 Subject: [PATCH 17/36] Move hash to the top --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 4 ++-- neo/Network/P2P/Payloads/Block.cs | 5 +++-- neo/Network/P2P/Payloads/Transaction.cs | 6 ++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 929731c3f4..19dcbbedac 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -73,7 +73,7 @@ public void System_Blockchain_GetBlock() var p = engine.ResultStack.Peek().GetString(); Assert.AreEqual(1, engine.ResultStack.Count); Assert.AreEqual(engine.ResultStack.Pop().GetString(), - @"[3,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",2,1,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""],""Q\uFFFDy\uFFFD\uFFFD\u0003\uFFFD\uFFFD\uFFFDuF\u000Fq\u012A\b[Y\u0443\uFFFD\uFFFD}]v{8\uFFFDx\u0027\uFFFD\uFFFD""]"); + @"[""Q\uFFFDy\uFFFD\uFFFD\u0003\uFFFD\uFFFD\uFFFDuF\u000Fq\u012A\b[Y\u0443\uFFFD\uFFFD}]v{8\uFFFDx\u0027\uFFFD\uFFFD"",3,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",2,1,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""]]"); Assert.AreEqual(0, engine.ResultStack.Count); // Clean @@ -123,7 +123,7 @@ public void System_ExecutionEngine_GetScriptContainer() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); Assert.AreEqual(engine.ResultStack.Pop().GetString(), - @"[6,4,""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",3,2,5,""\u0001"",""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""]"); + @"[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD"",6,4,""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",3,2,5,""\u0001""]"); Assert.AreEqual(0, engine.ResultStack.Count); } } diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index b9d94a9789..5b72da98de 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -141,6 +141,9 @@ public StackItem ToStackItem() ( new StackItem[] { + // Computed properties + new ByteArray(Hash.ToArray()), + // BlockBase properties new Integer(Version), new ByteArray(PrevHash.ToArray()), @@ -154,8 +157,6 @@ public StackItem ToStackItem() // Count // ConsensusData new VM.Types.Array(Transactions.Select(u => new ByteArray(u.Hash.ToArray()))), - // Computed properties - new ByteArray(Hash.ToArray()), } ); } diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs index 33f4302cb9..f93cd749ca 100644 --- a/neo/Network/P2P/Payloads/Transaction.cs +++ b/neo/Network/P2P/Payloads/Transaction.cs @@ -224,6 +224,10 @@ public StackItem ToStackItem() ( new StackItem[] { + // Computed properties + new ByteArray(Hash.ToArray()), + + // Transaction properties new Integer(Version), new Integer(Nonce), new ByteArray(Sender.ToArray()), @@ -234,8 +238,6 @@ public StackItem ToStackItem() // Cosigners new ByteArray(Script), // Witnesses - // Computed properties - new ByteArray(Hash.ToArray()), } ); } From 5a4ee761a426c552220f3dd5c74985f9b828b117 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 13:59:09 +0200 Subject: [PATCH 18/36] Remove GetHeader --- neo/SmartContract/InteropService.cs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index bef7cfab50..7089a1ce76 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -41,7 +41,6 @@ public static partial class InteropService public static readonly uint System_Runtime_GetNotifications = Register("System.Runtime.GetNotifications", Runtime_GetNotifications, 0_00010000, TriggerType.All); public static readonly uint System_Crypto_Verify = Register("System.Crypto.Verify", Crypto_Verify, 0_01000000, 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_GetHeader = Register("System.Blockchain.GetHeader", Blockchain_GetHeader, 0_00007000, 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); @@ -298,28 +297,6 @@ private static bool Blockchain_GetHeight(ApplicationEngine engine) return true; } - private static bool Blockchain_GetHeader(ApplicationEngine engine) - { - byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); - 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; - if (hash == null) - { - engine.CurrentContext.EvaluationStack.Push(new byte[0]); - } - else - { - Header header = engine.Snapshot.GetHeader(hash); - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(header)); - } - return true; - } - private static bool Blockchain_GetBlock(ApplicationEngine engine) { byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); From 661b80e62309433af1d39199e5e003b20a0d3116 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 14:03:36 +0200 Subject: [PATCH 19/36] Remove GetHeader --- neo/SmartContract/InteropService.NEO.cs | 39 ------------------------- 1 file changed, 39 deletions(-) diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index e4cbdb041f..798fd711b9 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -20,9 +20,6 @@ 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_CheckSig = Register("Neo.Crypto.CheckSig", Crypto_CheckSig, 0_01000000, TriggerType.All); public static readonly uint Neo_Crypto_CheckMultiSig = Register("Neo.Crypto.CheckMultiSig", Crypto_CheckMultiSig, GetCheckMultiSigPrice, TriggerType.All); - public static readonly uint Neo_Header_GetVersion = Register("Neo.Header.GetVersion", Header_GetVersion, 0_00000400, TriggerType.Application); - public static readonly uint Neo_Header_GetMerkleRoot = Register("Neo.Header.GetMerkleRoot", Header_GetMerkleRoot, 0_00000400, TriggerType.Application); - public static readonly uint Neo_Header_GetNextConsensus = Register("Neo.Header.GetNextConsensus", Header_GetNextConsensus, 0_00000400, TriggerType.Application); public static readonly uint Neo_Witness_GetVerificationScript = Register("Neo.Witness.GetVerificationScript", Witness_GetVerificationScript, 0_00000400, 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); @@ -155,42 +152,6 @@ private static bool Crypto_CheckMultiSig(ApplicationEngine engine) return true; } - private static bool Header_GetVersion(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - BlockBase header = _interface.GetInterface(); - if (header == null) return false; - engine.CurrentContext.EvaluationStack.Push(header.Version); - return true; - } - return false; - } - - private static bool Header_GetMerkleRoot(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - BlockBase header = _interface.GetInterface(); - if (header == null) return false; - engine.CurrentContext.EvaluationStack.Push(header.MerkleRoot.ToArray()); - return true; - } - return false; - } - - private static bool Header_GetNextConsensus(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - BlockBase header = _interface.GetInterface(); - if (header == null) return false; - engine.CurrentContext.EvaluationStack.Push(header.NextConsensus.ToArray()); - return true; - } - return false; - } - private static bool Witness_GetVerificationScript(ApplicationEngine engine) { if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) From 7fb7b91ebf3502df291f605eaa7ad050c20b5e98 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 18:29:56 +0200 Subject: [PATCH 20/36] Block with transactions count --- neo/Network/P2P/Payloads/Block.cs | 2 +- neo/SmartContract/InteropService.NEO.cs | 13 ------------ neo/SmartContract/InteropService.cs | 23 +++++++++++++++++++++ neo/SmartContract/WitnessWrapper.cs | 27 ------------------------- 4 files changed, 24 insertions(+), 41 deletions(-) delete mode 100644 neo/SmartContract/WitnessWrapper.cs diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index 5b72da98de..305536c38d 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -156,7 +156,7 @@ public StackItem ToStackItem() // Block properties // Count // ConsensusData - new VM.Types.Array(Transactions.Select(u => new ByteArray(u.Hash.ToArray()))), + new Integer(Transactions.Length) } ); } diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index 798fd711b9..6081b3e1fd 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -20,7 +20,6 @@ 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_CheckSig = Register("Neo.Crypto.CheckSig", Crypto_CheckSig, 0_01000000, TriggerType.All); public static readonly uint Neo_Crypto_CheckMultiSig = Register("Neo.Crypto.CheckMultiSig", Crypto_CheckMultiSig, GetCheckMultiSigPrice, TriggerType.All); - public static readonly uint Neo_Witness_GetVerificationScript = Register("Neo.Witness.GetVerificationScript", Witness_GetVerificationScript, 0_00000400, 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); @@ -152,18 +151,6 @@ private static bool Crypto_CheckMultiSig(ApplicationEngine engine) return true; } - private static bool Witness_GetVerificationScript(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - WitnessWrapper witness = _interface.GetInterface(); - if (witness == null) return false; - engine.CurrentContext.EvaluationStack.Push(witness.VerificationScript); - return true; - } - return false; - } - private static bool Account_IsStandard(ApplicationEngine engine) { UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 7089a1ce76..c89a03aa0f 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -45,6 +45,7 @@ public static partial class InteropService 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_GetContract = Register("System.Blockchain.GetContract", Blockchain_GetContract, 0_01000000, TriggerType.Application); + public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, 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); @@ -348,6 +349,28 @@ private static bool Blockchain_GetContract(ApplicationEngine engine) return true; } + private static bool Block_GetTransaction(ApplicationEngine engine) + { + byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); + 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; + + if (hash == null) return false; + + Block block = engine.Snapshot.GetBlock(hash); + if (block == null) return false; + int index = (int)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); + if (index < 0 || index >= block.Transactions.Length) return false; + Transaction tx = block.Transactions[index]; + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); + return true; + } + private static bool Storage_GetContext(ApplicationEngine engine) { engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext diff --git a/neo/SmartContract/WitnessWrapper.cs b/neo/SmartContract/WitnessWrapper.cs deleted file mode 100644 index 28019be0c2..0000000000 --- a/neo/SmartContract/WitnessWrapper.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Neo.Network.P2P.Payloads; -using Neo.Persistence; -using System.Linq; - -namespace Neo.SmartContract -{ - internal class WitnessWrapper - { - public byte[] VerificationScript; - - public static WitnessWrapper[] Create(IVerifiable verifiable, Snapshot snapshot) - { - WitnessWrapper[] wrappers = verifiable.Witnesses.Select(p => new WitnessWrapper - { - VerificationScript = p.VerificationScript - }).ToArray(); - if (wrappers.Any(p => p.VerificationScript.Length == 0)) - { - UInt160[] hashes = verifiable.GetScriptHashesForVerifying(snapshot); - for (int i = 0; i < wrappers.Length; i++) - if (wrappers[i].VerificationScript.Length == 0) - wrappers[i].VerificationScript = snapshot.Contracts[hashes[i]].Script; - } - return wrappers; - } - } -} From d9645f3c67155806e95efaeb5f2e3c59e4c67c41 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 18:42:33 +0200 Subject: [PATCH 21/36] Migrate ContractState --- neo/Ledger/ContractState.cs | 17 +++++++++++++++- neo/SmartContract/InteropService.NEO.cs | 26 ------------------------- neo/SmartContract/InteropService.cs | 10 +++------- 3 files changed, 19 insertions(+), 34 deletions(-) diff --git a/neo/Ledger/ContractState.cs b/neo/Ledger/ContractState.cs index f6c641d7d5..c369e5d59f 100644 --- a/neo/Ledger/ContractState.cs +++ b/neo/Ledger/ContractState.cs @@ -2,11 +2,13 @@ using Neo.IO.Json; using Neo.SmartContract; using Neo.SmartContract.Manifest; +using Neo.VM; +using Neo.VM.Types; using System.IO; namespace Neo.Ledger { - public class ContractState : ICloneable, ISerializable + public class ContractState : ICloneable, ISerializable, IInteroperable { public byte[] Script; public ContractManifest Manifest; @@ -72,5 +74,18 @@ public static ContractState FromJson(JObject json) contractState.Manifest = ContractManifest.FromJson(json["manifest"]); return contractState; } + + public StackItem ToStackItem() + { + return new VM.Types.Array + ( + new StackItem[] + { + new ByteArray(Script), + new Boolean(HasStorage), + new Boolean(Payable), + } + ); + } } } diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index 6081b3e1fd..e3e7862b16 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -23,8 +23,6 @@ static partial class InteropService 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_Contract_GetScript = Register("Neo.Contract.GetScript", Contract_GetScript, 0_00000400, TriggerType.Application); - public static readonly uint Neo_Contract_IsPayable = Register("Neo.Contract.IsPayable", Contract_IsPayable, 0_00000400, 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); @@ -233,30 +231,6 @@ private static bool Contract_Update(ApplicationEngine engine) return true; } - private static bool Contract_GetScript(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - ContractState contract = _interface.GetInterface(); - if (contract == null) return false; - engine.CurrentContext.EvaluationStack.Push(contract.Script); - return true; - } - return false; - } - - private static bool Contract_IsPayable(ApplicationEngine engine) - { - if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) - { - ContractState contract = _interface.GetInterface(); - if (contract == null) return false; - engine.CurrentContext.EvaluationStack.Push(contract.Payable); - return true; - } - return false; - } - private static bool Storage_Find(ApplicationEngine engine) { if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index c89a03aa0f..54cee4c91d 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -345,7 +345,7 @@ private static bool Blockchain_GetContract(ApplicationEngine engine) if (contract == null) engine.CurrentContext.EvaluationStack.Push(new byte[0]); else - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(contract)); + engine.CurrentContext.EvaluationStack.Push(contract.ToStackItem()); return true; } @@ -428,13 +428,9 @@ private static bool StorageContext_AsReadOnly(ApplicationEngine engine) private static bool Contract_Call(ApplicationEngine engine) { - StackItem contractOrHash = engine.CurrentContext.EvaluationStack.Pop(); + StackItem contractHash = engine.CurrentContext.EvaluationStack.Pop(); - ContractState contract; - if (contractOrHash is InteropInterface _interface) - contract = _interface; - else - contract = engine.Snapshot.Contracts.TryGet(new UInt160(contractOrHash.GetByteArray())); + ContractState contract = engine.Snapshot.Contracts.TryGet(new UInt160(contractHash.GetByteArray())); if (contract is null) return false; StackItem method = engine.CurrentContext.EvaluationStack.Pop(); From 17ee593670733fa498f674980fe41da3b9833ccc Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 18:47:45 +0200 Subject: [PATCH 22/36] Format --- neo/SmartContract/InteropService.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 54cee4c91d..c4879c7d33 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -45,7 +45,7 @@ public static partial class InteropService 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_GetContract = Register("System.Blockchain.GetContract", Blockchain_GetContract, 0_01000000, TriggerType.Application); - public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, TriggerType.Application); + public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, 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); @@ -349,7 +349,7 @@ private static bool Blockchain_GetContract(ApplicationEngine engine) return true; } - private static bool Block_GetTransaction(ApplicationEngine engine) + private static bool Block_GetTransaction(ApplicationEngine engine) { byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); UInt256 hash; @@ -368,7 +368,7 @@ private static bool Block_GetTransaction(ApplicationEngine engine) if (index < 0 || index >= block.Transactions.Length) return false; Transaction tx = block.Transactions[index]; engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); - return true; + return true; } private static bool Storage_GetContext(ApplicationEngine engine) From 442e901adb0caf17215ed919c8728e21c30401fc Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 11 Sep 2019 18:59:18 +0200 Subject: [PATCH 23/36] Close https://github.com/neo-project/neo/issues/1096 Close https://github.com/neo-project/neo/issues/1096 --- neo/SmartContract/InteropService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index c4879c7d33..725ccf0ea0 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -333,8 +333,8 @@ private static bool Blockchain_GetTransaction(ApplicationEngine engine) private static bool Blockchain_GetTransactionHeight(ApplicationEngine engine) { byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); - int? height = (int?)engine.Snapshot.Transactions.TryGet(new UInt256(hash))?.BlockIndex; - engine.CurrentContext.EvaluationStack.Push(height ?? -1); + var tx = engine.Snapshot.Transactions.TryGet(new UInt256(hash)); + engine.CurrentContext.EvaluationStack.Push(tx != null ? tx.BlockIndex : BigInteger.MinusOne); return true; } From 7aecf3620866afb7eeba6e0cc908074e5db8b263 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 12 Sep 2019 07:35:21 +0200 Subject: [PATCH 24/36] Update nulls --- neo/SmartContract/InteropService.cs | 41 ++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 725ccf0ea0..f3df6a5c94 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -308,16 +308,12 @@ private static bool Blockchain_GetBlock(ApplicationEngine engine) hash = new UInt256(data); else return false; - if (hash == null) - { + + Block block = hash != null ? engine.Snapshot.GetBlock(hash) : null; + if (block == null) engine.CurrentContext.EvaluationStack.Push(new byte[0]); - } else - { - Block block = engine.Snapshot.GetBlock(hash); - if (block == null) return false; engine.CurrentContext.EvaluationStack.Push(block.ToStackItem()); - } return true; } @@ -325,8 +321,10 @@ private static bool Blockchain_GetTransaction(ApplicationEngine engine) { byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); - if (tx == null) return false; - engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem()); + if (tx == null) + engine.CurrentContext.EvaluationStack.Push(new byte[0]); + else + engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem()); return true; } @@ -334,7 +332,7 @@ private static bool Blockchain_GetTransactionHeight(ApplicationEngine engine) { byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); var tx = engine.Snapshot.Transactions.TryGet(new UInt256(hash)); - engine.CurrentContext.EvaluationStack.Push(tx != null ? tx.BlockIndex : BigInteger.MinusOne); + engine.CurrentContext.EvaluationStack.Push(tx != null ? new BigInteger(tx.BlockIndex) : BigInteger.MinusOne); return true; } @@ -360,14 +358,21 @@ private static bool Block_GetTransaction(ApplicationEngine engine) else return false; - if (hash == null) return false; - - Block block = engine.Snapshot.GetBlock(hash); - if (block == null) return false; - int index = (int)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); - if (index < 0 || index >= block.Transactions.Length) return false; - Transaction tx = block.Transactions[index]; - engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); + Block block = hash != null ? engine.Snapshot.GetBlock(hash) : null; + if (block == null) + { + engine.CurrentContext.EvaluationStack.Push(new byte[0]); + } + else + { + int index = (int)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); + if (index < 0 || index >= block.Transactions.Length) return false; + Transaction tx = block.Transactions[index]; + if (tx == null) + engine.CurrentContext.EvaluationStack.Push(new byte[0]); + else + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); + } return true; } From d9d4cc2c14a56da329edfa64a70a0814d902dd6c Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 12 Sep 2019 07:40:44 +0200 Subject: [PATCH 25/36] Remove Neo.Account.IsStandard --- neo/Ledger/ContractState.cs | 1 + neo/SmartContract/InteropService.NEO.cs | 10 ---------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/neo/Ledger/ContractState.cs b/neo/Ledger/ContractState.cs index c369e5d59f..d6f14ac8de 100644 --- a/neo/Ledger/ContractState.cs +++ b/neo/Ledger/ContractState.cs @@ -84,6 +84,7 @@ public StackItem ToStackItem() new ByteArray(Script), new Boolean(HasStorage), new Boolean(Payable), + new Boolean(Script.IsStandardContract()), } ); } diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index e3e7862b16..5997879da4 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -20,7 +20,6 @@ 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_CheckSig = Register("Neo.Crypto.CheckSig", Crypto_CheckSig, 0_01000000, TriggerType.All); public static readonly uint Neo_Crypto_CheckMultiSig = Register("Neo.Crypto.CheckMultiSig", Crypto_CheckMultiSig, GetCheckMultiSigPrice, 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); @@ -149,15 +148,6 @@ private static bool Crypto_CheckMultiSig(ApplicationEngine engine) return true; } - private static bool Account_IsStandard(ApplicationEngine engine) - { - UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); - 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().GetByteArray(); From 1836c98aab4579ea518bceb1f061545ae6f8d640 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 12 Sep 2019 08:19:48 +0200 Subject: [PATCH 26/36] Revert last change --- neo/Ledger/ContractState.cs | 1 - neo/SmartContract/InteropService.NEO.cs | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/neo/Ledger/ContractState.cs b/neo/Ledger/ContractState.cs index d6f14ac8de..c369e5d59f 100644 --- a/neo/Ledger/ContractState.cs +++ b/neo/Ledger/ContractState.cs @@ -84,7 +84,6 @@ public StackItem ToStackItem() new ByteArray(Script), new Boolean(HasStorage), new Boolean(Payable), - new Boolean(Script.IsStandardContract()), } ); } diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index 5997879da4..e3e7862b16 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -20,6 +20,7 @@ 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_CheckSig = Register("Neo.Crypto.CheckSig", Crypto_CheckSig, 0_01000000, TriggerType.All); public static readonly uint Neo_Crypto_CheckMultiSig = Register("Neo.Crypto.CheckMultiSig", Crypto_CheckMultiSig, GetCheckMultiSigPrice, 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); @@ -148,6 +149,15 @@ private static bool Crypto_CheckMultiSig(ApplicationEngine engine) return true; } + private static bool Account_IsStandard(ApplicationEngine engine) + { + UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); + 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().GetByteArray(); From 238bc06bc8272a304958a1b54ade1837add572e4 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 19 Sep 2019 12:52:07 +0200 Subject: [PATCH 27/36] Fix Unit tests --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 19dcbbedac..098ccc5a26 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -51,29 +51,34 @@ public void System_Blockchain_GetBlock() { script.EmitPush(block.Hash.ToArray()); script.EmitSysCall(InteropService.System_Blockchain_GetBlock); - script.EmitSysCall(InteropService.Neo_Json_Serialize); // Without block var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); - Assert.AreEqual(engine.Execute(), VMState.FAULT); - Assert.AreEqual(0, engine.ResultStack.Count); + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(ByteArray)); + Assert.AreEqual(0, engine.ResultStack.Pop().GetByteArray().Length); + + // With block var blocks = (TestDataCache)snapshot.Blocks; var txs = (TestDataCache)snapshot.Transactions; 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); engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); var p = engine.ResultStack.Peek().GetString(); Assert.AreEqual(1, engine.ResultStack.Count); - Assert.AreEqual(engine.ResultStack.Pop().GetString(), - @"[""Q\uFFFDy\uFFFD\uFFFD\u0003\uFFFD\uFFFD\uFFFDuF\u000Fq\u012A\b[Y\u0443\uFFFD\uFFFD}]v{8\uFFFDx\u0027\uFFFD\uFFFD"",3,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",2,1,""\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"",[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD""]]"); + Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(ByteArray)); + Assert.AreEqual(engine.ResultStack.Pop().GetByteArray().ToHexString(), + "5b22515c7546464644795c75464646445c75464646445c75303030335c75464646445c75464646445c754646464475465c7530303046715c75303132415c625b595c75303434335c75464646445c75464646447d5d767b385c7546464644785c75303032375c75464646445c7546464644222c332c225c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c7530303030222c225c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c7530303030222c322c312c225c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c75303030305c7530303030222c315d"); Assert.AreEqual(0, engine.ResultStack.Count); // Clean @@ -97,6 +102,7 @@ public void System_ExecutionEngine_GetScriptContainer() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); + Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(InteropInterface)); Assert.IsNull(((InteropInterface)engine.ResultStack.Pop()).GetInterface()); // With tx @@ -122,8 +128,9 @@ public void System_ExecutionEngine_GetScriptContainer() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); - Assert.AreEqual(engine.ResultStack.Pop().GetString(), - @"[""\uFFFDD\uFFFDa\uFFFDs,\uFFFD\uFFFDf\u0007]\u0000\uFFFD\u0622\uFFFDT\uFFFD7\u00133\u0018\u0003e\uFFFD\uFFFD\u0027Z\uFFFD\/\uFFFD"",6,4,""\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"",3,2,5,""\u0001""]"); + Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(ByteArray)); + Assert.AreEqual(engine.ResultStack.Pop().GetByteArray().ToHexString(), + @"5b225c7546464644445c7546464644615c7546464644732c5c75464646445c7546464644665c75303030375d5c75303030305c75464646445c75303632325c7546464644545c7546464644375c7530303133335c75303031385c7530303033655c75464646445c75464646445c75303032375a5c75464646445c2f5c7546464644222c362c342c225c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c75464646445c7546464644222c332c322c352c225c7530303031225d"); Assert.AreEqual(0, engine.ResultStack.Count); } } From d1999149b153404da410dc2798ce640dad595606 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 19 Sep 2019 13:17:02 +0200 Subject: [PATCH 28/36] Remove unused var --- neo.UnitTests/SmartContract/UT_Syscalls.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 098ccc5a26..26bf7ea1e7 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -74,7 +74,6 @@ public void System_Blockchain_GetBlock() engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); - var p = engine.ResultStack.Peek().GetString(); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(ByteArray)); Assert.AreEqual(engine.ResultStack.Pop().GetByteArray().ToHexString(), From 944484faae25404ee8c99f7371a049e2e4850f44 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 26 Sep 2019 10:21:28 +0200 Subject: [PATCH 29/36] TrimmedBlock --- neo/SmartContract/InteropService.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index f3df6a5c94..efc97d3c0b 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -358,7 +358,7 @@ private static bool Block_GetTransaction(ApplicationEngine engine) else return false; - Block block = hash != null ? engine.Snapshot.GetBlock(hash) : null; + var block = hash != null ? engine.Snapshot.Blocks.TryGet(hash) : null; if (block == null) { engine.CurrentContext.EvaluationStack.Push(new byte[0]); @@ -366,8 +366,9 @@ private static bool Block_GetTransaction(ApplicationEngine engine) else { int index = (int)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger(); - if (index < 0 || index >= block.Transactions.Length) return false; - Transaction tx = block.Transactions[index]; + if (index < 0 || index >= block.Hashes.Length) return false; + + Transaction tx = engine.Snapshot.GetTransaction(block.Hashes[index]); if (tx == null) engine.CurrentContext.EvaluationStack.Push(new byte[0]); else From 3a9f0bf0e08205b6f284a54850ce7882b23d44b7 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 26 Sep 2019 10:23:29 +0200 Subject: [PATCH 30/36] Change fee --- neo/SmartContract/InteropService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index efc97d3c0b..e39df5fa66 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -45,7 +45,7 @@ public static partial class InteropService 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_GetContract = Register("System.Blockchain.GetContract", Blockchain_GetContract, 0_01000000, TriggerType.Application); - public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, TriggerType.Application); + public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 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); @@ -358,7 +358,7 @@ private static bool Block_GetTransaction(ApplicationEngine engine) else return false; - var block = hash != null ? engine.Snapshot.Blocks.TryGet(hash) : null; + TrimmedBlock block = hash != null ? engine.Snapshot.Blocks.TryGet(hash) : null; if (block == null) { engine.CurrentContext.EvaluationStack.Push(new byte[0]); From ec0005477f501b7654efaf3877b9890db1882ac8 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Thu, 3 Oct 2019 16:57:44 +0800 Subject: [PATCH 31/36] Neo.VM v3.0.0-CI00041 --- .../SmartContract/UT_InteropService.cs | 2 +- neo.UnitTests/SmartContract/UT_Syscalls.cs | 6 ++---- .../ApplicationEngine.OpCodePrices.cs | 2 ++ neo/SmartContract/InteropService.cs | 21 +++++++++---------- neo/neo.csproj | 2 +- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/neo.UnitTests/SmartContract/UT_InteropService.cs b/neo.UnitTests/SmartContract/UT_InteropService.cs index 6a33a32abc..dff17f2025 100644 --- a/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -85,7 +85,7 @@ public void Runtime_GetNotifications_Test() // Receive all notifications - script.EmitPush(new byte[0]); + script.Emit(OpCode.PUSHNULL); script.EmitSysCall(InteropService.System_Runtime_GetNotifications); // Execute diff --git a/neo.UnitTests/SmartContract/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs index 26bf7ea1e7..658d125e7f 100644 --- a/neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -59,8 +59,7 @@ public void System_Blockchain_GetBlock() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); - Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(ByteArray)); - Assert.AreEqual(0, engine.ResultStack.Pop().GetByteArray().Length); + Assert.IsTrue(engine.ResultStack.Peek().IsNull); // With block @@ -101,8 +100,7 @@ public void System_ExecutionEngine_GetScriptContainer() Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); - Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(InteropInterface)); - Assert.IsNull(((InteropInterface)engine.ResultStack.Pop()).GetInterface()); + Assert.IsTrue(engine.ResultStack.Peek().IsNull); // With tx diff --git a/neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/neo/SmartContract/ApplicationEngine.OpCodePrices.cs index 271a76f935..b6b65b37da 100644 --- a/neo/SmartContract/ApplicationEngine.OpCodePrices.cs +++ b/neo/SmartContract/ApplicationEngine.OpCodePrices.cs @@ -87,6 +87,7 @@ partial class ApplicationEngine [OpCode.PUSHDATA2] = 13000, [OpCode.PUSHDATA4] = 110000, [OpCode.PUSHM1] = 30, + [OpCode.PUSHNULL] = 30, [OpCode.PUSH1] = 30, [OpCode.PUSH2] = 30, [OpCode.PUSH3] = 30, @@ -114,6 +115,7 @@ partial class ApplicationEngine [OpCode.DUPFROMALTSTACK] = 60, [OpCode.TOALTSTACK] = 60, [OpCode.FROMALTSTACK] = 60, + [OpCode.ISNULL] = 60, [OpCode.XDROP] = 400, [OpCode.XSWAP] = 60, [OpCode.XTUCK] = 400, diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index e39df5fa66..59b68f7d2f 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -118,7 +118,7 @@ private static bool ExecutionEngine_GetExecutingScriptHash(ApplicationEngine eng private static bool ExecutionEngine_GetCallingScriptHash(ApplicationEngine engine) { - engine.CurrentContext.EvaluationStack.Push(engine.CallingScriptHash?.ToArray() ?? new byte[0]); + engine.CurrentContext.EvaluationStack.Push(engine.CallingScriptHash?.ToArray() ?? StackItem.Null); return true; } @@ -230,13 +230,12 @@ private static bool Runtime_Serialize(ApplicationEngine engine) private static bool Runtime_GetNotifications(ApplicationEngine engine) { - byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); - if ((data.Length != 0) && (data.Length != UInt160.Length)) return false; + StackItem item = engine.CurrentContext.EvaluationStack.Pop(); IEnumerable notifications = engine.Notifications; - if (data.Length == UInt160.Length) // must filter by scriptHash + if (!item.IsNull) // must filter by scriptHash { - var hash = new UInt160(data); + var hash = new UInt160(item.GetByteArray()); notifications = notifications.Where(p => p.ScriptHash == hash); } @@ -311,7 +310,7 @@ private static bool Blockchain_GetBlock(ApplicationEngine engine) Block block = hash != null ? engine.Snapshot.GetBlock(hash) : null; if (block == null) - engine.CurrentContext.EvaluationStack.Push(new byte[0]); + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); else engine.CurrentContext.EvaluationStack.Push(block.ToStackItem()); return true; @@ -322,7 +321,7 @@ private static bool Blockchain_GetTransaction(ApplicationEngine engine) byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); if (tx == null) - engine.CurrentContext.EvaluationStack.Push(new byte[0]); + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); else engine.CurrentContext.EvaluationStack.Push(tx.ToStackItem()); return true; @@ -341,7 +340,7 @@ private static bool Blockchain_GetContract(ApplicationEngine engine) UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); ContractState contract = engine.Snapshot.Contracts.TryGet(hash); if (contract == null) - engine.CurrentContext.EvaluationStack.Push(new byte[0]); + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); else engine.CurrentContext.EvaluationStack.Push(contract.ToStackItem()); return true; @@ -361,7 +360,7 @@ private static bool Block_GetTransaction(ApplicationEngine engine) TrimmedBlock block = hash != null ? engine.Snapshot.Blocks.TryGet(hash) : null; if (block == null) { - engine.CurrentContext.EvaluationStack.Push(new byte[0]); + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); } else { @@ -370,7 +369,7 @@ private static bool Block_GetTransaction(ApplicationEngine engine) Transaction tx = engine.Snapshot.GetTransaction(block.Hashes[index]); if (tx == null) - engine.CurrentContext.EvaluationStack.Push(new byte[0]); + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); else engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(tx)); } @@ -409,7 +408,7 @@ private static bool Storage_Get(ApplicationEngine engine) ScriptHash = context.ScriptHash, Key = key }); - engine.CurrentContext.EvaluationStack.Push(item?.Value ?? new byte[0]); + engine.CurrentContext.EvaluationStack.Push(item?.Value ?? StackItem.Null); return true; } return false; diff --git a/neo/neo.csproj b/neo/neo.csproj index 724090c004..1f0ad4c4b8 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -30,7 +30,7 @@ - + From a7ab65620705322879860dcc388471e15a4adfee Mon Sep 17 00:00:00 2001 From: erikzhang Date: Mon, 14 Oct 2019 17:15:30 +0800 Subject: [PATCH 32/36] Neo.VM v3.0.0-CI00042 --- neo/SmartContract/Helper.cs | 6 ++++++ neo/SmartContract/JsonSerializer.cs | 8 ++++++++ neo/SmartContract/StackItemType.cs | 1 + neo/VM/Helper.cs | 3 +++ neo/neo.csproj | 2 +- 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/neo/SmartContract/Helper.cs b/neo/SmartContract/Helper.cs index 6a22249cd7..809ec8345f 100644 --- a/neo/SmartContract/Helper.cs +++ b/neo/SmartContract/Helper.cs @@ -67,6 +67,9 @@ private static StackItem DeserializeStackItem(BinaryReader reader, uint maxArray undeserialized += count * 2; } break; + case StackItemType.Null: + deserialized.Push(StackItem.Null); + break; default: throw new FormatException(); } @@ -232,6 +235,9 @@ private static void SerializeStackItem(StackItem item, BinaryWriter writer) unserialized.Push(pair.Key); } break; + case Null _: + writer.Write((byte)StackItemType.Null); + break; } } } diff --git a/neo/SmartContract/JsonSerializer.cs b/neo/SmartContract/JsonSerializer.cs index a4853fc39a..1c674540f0 100644 --- a/neo/SmartContract/JsonSerializer.cs +++ b/neo/SmartContract/JsonSerializer.cs @@ -53,6 +53,10 @@ public static JObject Serialize(StackItem item) return ret; } + case Null _: + { + return JObject.Null; + } default: throw new FormatException(); } } @@ -66,6 +70,10 @@ public static StackItem Deserialize(JObject json) { switch (json) { + case null: + { + return StackItem.Null; + } case JArray array: { return array.Select(p => Deserialize(p)).ToList(); diff --git a/neo/SmartContract/StackItemType.cs b/neo/SmartContract/StackItemType.cs index b47999e157..7e19c2982b 100644 --- a/neo/SmartContract/StackItemType.cs +++ b/neo/SmartContract/StackItemType.cs @@ -9,5 +9,6 @@ internal enum StackItemType : byte Array = 0x80, Struct = 0x81, Map = 0x82, + Null = 0xff } } diff --git a/neo/VM/Helper.cs b/neo/VM/Helper.cs index d63bebb89a..c01cf561ca 100644 --- a/neo/VM/Helper.cs +++ b/neo/VM/Helper.cs @@ -149,6 +149,9 @@ public static ScriptBuilder EmitPush(this ScriptBuilder sb, object obj) case Enum data: sb.EmitPush(BigInteger.Parse(data.ToString("d"))); break; + case null: + sb.Emit(OpCode.PUSHNULL); + break; default: throw new ArgumentException(); } diff --git a/neo/neo.csproj b/neo/neo.csproj index 1f0ad4c4b8..b60b204915 100644 --- a/neo/neo.csproj +++ b/neo/neo.csproj @@ -30,7 +30,7 @@ - + From 6dc28932470c379e12b332824e36a617bb55fc4a Mon Sep 17 00:00:00 2001 From: erikzhang Date: Mon, 14 Oct 2019 17:25:26 +0800 Subject: [PATCH 33/36] Rename --- neo/SmartContract/InteropService.cs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs index 59b68f7d2f..0e891de162 100644 --- a/neo/SmartContract/InteropService.cs +++ b/neo/SmartContract/InteropService.cs @@ -44,8 +44,8 @@ public static partial class InteropService 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_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 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); @@ -335,18 +335,7 @@ private static bool Blockchain_GetTransactionHeight(ApplicationEngine engine) return true; } - private static bool Blockchain_GetContract(ApplicationEngine engine) - { - UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); - ContractState contract = engine.Snapshot.Contracts.TryGet(hash); - if (contract == null) - engine.CurrentContext.EvaluationStack.Push(StackItem.Null); - else - engine.CurrentContext.EvaluationStack.Push(contract.ToStackItem()); - return true; - } - - private static bool Block_GetTransaction(ApplicationEngine engine) + private static bool Blockchain_GetTransactionFromBlock(ApplicationEngine engine) { byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray(); UInt256 hash; @@ -376,6 +365,17 @@ private static bool Block_GetTransaction(ApplicationEngine engine) return true; } + private static bool Blockchain_GetContract(ApplicationEngine engine) + { + UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray()); + ContractState contract = engine.Snapshot.Contracts.TryGet(hash); + if (contract == null) + engine.CurrentContext.EvaluationStack.Push(StackItem.Null); + else + engine.CurrentContext.EvaluationStack.Push(contract.ToStackItem()); + return true; + } + private static bool Storage_GetContext(ApplicationEngine engine) { engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new StorageContext From 97d2bda9824d1adbacd91c2736073552c3eb8f59 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 15 Oct 2019 06:21:13 +0200 Subject: [PATCH 34/36] ContractNullParameter --- neo/SmartContract/ContractParameterType.cs | 1 + neo/VM/Helper.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/neo/SmartContract/ContractParameterType.cs b/neo/SmartContract/ContractParameterType.cs index 748ff86654..727b04cabd 100644 --- a/neo/SmartContract/ContractParameterType.cs +++ b/neo/SmartContract/ContractParameterType.cs @@ -13,6 +13,7 @@ public enum ContractParameterType : byte Array = 0x10, Map = 0x12, + Null = 0x14, InteropInterface = 0xf0, diff --git a/neo/VM/Helper.cs b/neo/VM/Helper.cs index c01cf561ca..4f07625466 100644 --- a/neo/VM/Helper.cs +++ b/neo/VM/Helper.cs @@ -63,6 +63,9 @@ public static ScriptBuilder EmitPush(this ScriptBuilder sb, ContractParameter pa { switch (parameter.Type) { + case ContractParameterType.Null: + sb.Emit(OpCode.PUSHNULL); + break; case ContractParameterType.Signature: case ContractParameterType.ByteArray: sb.EmitPush((byte[])parameter.Value); @@ -245,6 +248,12 @@ private static ContractParameter ToParameter(StackItem item, List Date: Tue, 15 Oct 2019 06:27:30 +0200 Subject: [PATCH 35/36] Clean using --- neo/SmartContract/InteropService.NEO.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs index e3e7862b16..e500eeb235 100644 --- a/neo/SmartContract/InteropService.NEO.cs +++ b/neo/SmartContract/InteropService.NEO.cs @@ -2,7 +2,6 @@ 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; From 6e35d8aa3ccc613f088a266b5e1eba82ac93c29a Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 15 Oct 2019 08:18:37 +0200 Subject: [PATCH 36/36] Revert Null in ContractParameterType --- neo/SmartContract/ContractParameterType.cs | 1 - neo/VM/Helper.cs | 14 +------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/neo/SmartContract/ContractParameterType.cs b/neo/SmartContract/ContractParameterType.cs index 727b04cabd..748ff86654 100644 --- a/neo/SmartContract/ContractParameterType.cs +++ b/neo/SmartContract/ContractParameterType.cs @@ -13,7 +13,6 @@ public enum ContractParameterType : byte Array = 0x10, Map = 0x12, - Null = 0x14, InteropInterface = 0xf0, diff --git a/neo/VM/Helper.cs b/neo/VM/Helper.cs index 4f07625466..5d2a2aa485 100644 --- a/neo/VM/Helper.cs +++ b/neo/VM/Helper.cs @@ -63,9 +63,6 @@ public static ScriptBuilder EmitPush(this ScriptBuilder sb, ContractParameter pa { switch (parameter.Type) { - case ContractParameterType.Null: - sb.Emit(OpCode.PUSHNULL); - break; case ContractParameterType.Signature: case ContractParameterType.ByteArray: sb.EmitPush((byte[])parameter.Value); @@ -248,13 +245,7 @@ private static ContractParameter ToParameter(StackItem item, List