From 6cbb77ae14d2a6760b86d0dec63944010191725d Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 15 Jun 2020 20:12:15 +0800 Subject: [PATCH] Add event name to System.Runtime.Notify() (#1701) --- .../ApplicationEngine.Runtime.cs | 10 ++-- .../SmartContract/Native/Tokens/Nep5Token.cs | 6 +-- src/neo/SmartContract/NotifyEventArgs.cs | 8 ++-- .../SmartContract/UT_ApplicationEngine.cs | 27 +++++------ .../SmartContract/UT_InteropService.cs | 47 ++++++++----------- .../SmartContract/UT_NotifyEventArgs.cs | 2 +- 6 files changed, 47 insertions(+), 53 deletions(-) diff --git a/src/neo/SmartContract/ApplicationEngine.Runtime.cs b/src/neo/SmartContract/ApplicationEngine.Runtime.cs index 9610222a2d..92bab2ad36 100644 --- a/src/neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/neo/SmartContract/ApplicationEngine.Runtime.cs @@ -12,6 +12,7 @@ namespace Neo.SmartContract { partial class ApplicationEngine { + public const int MaxEventName = 32; public const int MaxNotificationSize = 1024; public static readonly InteropDescriptor System_Runtime_Platform = Register("System.Runtime.Platform", nameof(GetPlatform), 0_00000250, TriggerType.All, CallFlags.None); @@ -146,15 +147,16 @@ internal void RuntimeLog(byte[] state) Log?.Invoke(this, new LogEventArgs(ScriptContainer, CurrentScriptHash, message)); } - internal void RuntimeNotify(StackItem state) + internal void RuntimeNotify(byte[] eventName, Array state) { + if (eventName.Length > MaxEventName) throw new ArgumentException(); if (!CheckItemForNotification(state)) throw new ArgumentException(); - SendNotification(CurrentScriptHash, state); + SendNotification(CurrentScriptHash, Encoding.UTF8.GetString(eventName), state); } - internal void SendNotification(UInt160 script_hash, StackItem state) + internal void SendNotification(UInt160 hash, string eventName, Array state) { - NotifyEventArgs notification = new NotifyEventArgs(ScriptContainer, script_hash, state); + NotifyEventArgs notification = new NotifyEventArgs(ScriptContainer, hash, eventName, state); Notify?.Invoke(this, notification); notifications.Add(notification); } diff --git a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs index f8b190ef92..852f1f00da 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -79,7 +79,7 @@ internal protected virtual void Mint(ApplicationEngine engine, UInt160 account, BigInteger totalSupply = new BigInteger(storage.Value); totalSupply += amount; storage.Value = totalSupply.ToByteArrayStandard(); - engine.SendNotification(Hash, new Array(new StackItem[] { "Transfer", StackItem.Null, account.ToArray(), amount })); + engine.SendNotification(Hash, "Transfer", new Array { StackItem.Null, account.ToArray(), amount }); } internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, BigInteger amount) @@ -99,7 +99,7 @@ internal protected virtual void Burn(ApplicationEngine engine, UInt160 account, BigInteger totalSupply = new BigInteger(storage.Value); totalSupply -= amount; storage.Value = totalSupply.ToByteArrayStandard(); - engine.SendNotification(Hash, new Array(new StackItem[] { "Transfer", account.ToArray(), StackItem.Null, amount })); + engine.SendNotification(Hash, "Transfer", new Array { account.ToArray(), StackItem.Null, amount }); } [ContractMethod(0_01000000, CallFlags.AllowStates)] @@ -159,7 +159,7 @@ protected virtual bool Transfer(ApplicationEngine engine, UInt160 from, UInt160 state_to.Balance += amount; } } - engine.SendNotification(Hash, new Array(new StackItem[] { "Transfer", from.ToArray(), to.ToArray(), amount })); + engine.SendNotification(Hash, "Transfer", new Array { from.ToArray(), to.ToArray(), amount }); return true; } diff --git a/src/neo/SmartContract/NotifyEventArgs.cs b/src/neo/SmartContract/NotifyEventArgs.cs index 7b52c2a570..d2a0d94605 100644 --- a/src/neo/SmartContract/NotifyEventArgs.cs +++ b/src/neo/SmartContract/NotifyEventArgs.cs @@ -11,12 +11,14 @@ public class NotifyEventArgs : EventArgs, IInteroperable { public IVerifiable ScriptContainer { get; } public UInt160 ScriptHash { get; } - public StackItem State { get; } + public string EventName { get; } + public Array State { get; } - public NotifyEventArgs(IVerifiable container, UInt160 script_hash, StackItem state) + public NotifyEventArgs(IVerifiable container, UInt160 script_hash, string eventName, Array state) { this.ScriptContainer = container; this.ScriptHash = script_hash; + this.EventName = eventName; this.State = state; } @@ -27,7 +29,7 @@ public void FromStackItem(StackItem stackItem) public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new[] { ScriptHash.ToArray(), State }); + return new Array(referenceCounter) { ScriptHash.ToArray(), EventName, State }; } } } diff --git a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs index a05a5e9f88..447c5b9f4f 100644 --- a/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs +++ b/tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs @@ -6,7 +6,6 @@ using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract; -using Neo.VM.Types; namespace Neo.UnitTests.SmartContract { @@ -14,7 +13,7 @@ namespace Neo.UnitTests.SmartContract public class UT_ApplicationEngine { private string message = null; - private StackItem item = null; + private string eventName = null; [TestInitialize] public void TestSetup() @@ -28,23 +27,23 @@ public void TestNotify() var snapshot = Blockchain.Singleton.GetSnapshot(); var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true); ApplicationEngine.Notify += Test_Notify1; - StackItem notifyItem = "TestItem"; + const string notifyEvent = "TestEvent"; - engine.SendNotification(UInt160.Zero, notifyItem); - item.Should().Be(notifyItem); + engine.SendNotification(UInt160.Zero, notifyEvent, null); + eventName.Should().Be(notifyEvent); ApplicationEngine.Notify += Test_Notify2; - engine.SendNotification(UInt160.Zero, notifyItem); - item.Should().Be(null); + engine.SendNotification(UInt160.Zero, notifyEvent, null); + eventName.Should().Be(null); - item = notifyItem; + eventName = notifyEvent; ApplicationEngine.Notify -= Test_Notify1; - engine.SendNotification(UInt160.Zero, notifyItem); - item.Should().Be(null); + engine.SendNotification(UInt160.Zero, notifyEvent, null); + eventName.Should().Be(null); ApplicationEngine.Notify -= Test_Notify2; - engine.SendNotification(UInt160.Zero, notifyItem); - item.Should().Be(null); + engine.SendNotification(UInt160.Zero, notifyEvent, null); + eventName.Should().Be(null); } private void Test_Log1(object sender, LogEventArgs e) @@ -59,12 +58,12 @@ private void Test_Log2(object sender, LogEventArgs e) private void Test_Notify1(object sender, NotifyEventArgs e) { - item = e.State; + eventName = e.EventName; } private void Test_Notify2(object sender, NotifyEventArgs e) { - item = null; + eventName = null; } [TestMethod] diff --git a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs index 5b83133e37..a72fb896c3 100644 --- a/tests/neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/neo.UnitTests/SmartContract/UT_InteropService.cs @@ -34,12 +34,9 @@ public void Runtime_GetNotifications_Test() using (var script = new ScriptBuilder()) { - // Drop arguments - - script.Emit(OpCode.NIP); - // Notify method + script.Emit(OpCode.SWAP, OpCode.NEWARRAY, OpCode.SWAP); script.EmitSysCall(ApplicationEngine.System_Runtime_Notify); // Add return @@ -81,14 +78,16 @@ public void Runtime_GetNotifications_Test() using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true)) using (var script = new ScriptBuilder()) { - // Notification 1 -> 13 + // Notification - script.EmitPush(13); + script.EmitPush(0); + script.Emit(OpCode.NEWARRAY); + script.EmitPush("testEvent1"); script.EmitSysCall(ApplicationEngine.System_Runtime_Notify); // Call script - script.EmitAppCall(scriptHash2, "test", 2, 1); + script.EmitAppCall(scriptHash2, "test", "testEvent2", 1); // Drop return @@ -114,16 +113,16 @@ public void Runtime_GetNotifications_Test() // Check syscall result - AssertNotification(array[1], scriptHash2, 2); - AssertNotification(array[0], currentScriptHash, 13); + AssertNotification(array[1], scriptHash2, "testEvent2"); + AssertNotification(array[0], currentScriptHash, "testEvent1"); // Check notifications Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash); - Assert.AreEqual(2, engine.Notifications[1].State.GetBigInteger()); + Assert.AreEqual("testEvent2", engine.Notifications[1].EventName); Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash); - Assert.AreEqual(13, engine.Notifications[0].State.GetBigInteger()); + Assert.AreEqual("testEvent1", engine.Notifications[0].EventName); } // Script notifications @@ -131,14 +130,16 @@ public void Runtime_GetNotifications_Test() using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true)) using (var script = new ScriptBuilder()) { - // Notification 1 -> 13 + // Notification - script.EmitPush(13); + script.EmitPush(0); + script.Emit(OpCode.NEWARRAY); + script.EmitPush("testEvent1"); script.EmitSysCall(ApplicationEngine.System_Runtime_Notify); // Call script - script.EmitAppCall(scriptHash2, "test", 2, 1); + script.EmitAppCall(scriptHash2, "test", "testEvent2", 1); // Drop return @@ -164,15 +165,15 @@ public void Runtime_GetNotifications_Test() // Check syscall result - AssertNotification(array[0], scriptHash2, 2); + AssertNotification(array[0], scriptHash2, "testEvent2"); // Check notifications Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash); - Assert.AreEqual(2, engine.Notifications[1].State.GetBigInteger()); + Assert.AreEqual("testEvent2", engine.Notifications[1].EventName); Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash); - Assert.AreEqual(13, engine.Notifications[0].State.GetBigInteger()); + Assert.AreEqual("testEvent1", engine.Notifications[0].EventName); } // Clean storage @@ -185,21 +186,11 @@ private void AssertNotification(StackItem stackItem, UInt160 scriptHash, string Assert.IsInstanceOfType(stackItem, typeof(VM.Types.Array)); var array = (VM.Types.Array)stackItem; - Assert.AreEqual(2, array.Count); + Assert.AreEqual(3, array.Count); CollectionAssert.AreEqual(scriptHash.ToArray(), array[0].GetSpan().ToArray()); Assert.AreEqual(notification, array[1].GetString()); } - private void AssertNotification(StackItem stackItem, UInt160 scriptHash, int notification) - { - Assert.IsInstanceOfType(stackItem, typeof(VM.Types.Array)); - - var array = (VM.Types.Array)stackItem; - Assert.AreEqual(2, array.Count); - CollectionAssert.AreEqual(scriptHash.ToArray(), array[0].GetSpan().ToArray()); - Assert.AreEqual(notification, array[1].GetBigInteger()); - } - [TestMethod] public void TestExecutionEngine_GetScriptContainer() { diff --git a/tests/neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs b/tests/neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs index d86a9d208e..e83f8fd7fc 100644 --- a/tests/neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs +++ b/tests/neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs @@ -13,7 +13,7 @@ public void TestGetScriptContainer() { IVerifiable container = new TestVerifiable(); UInt160 script_hash = new byte[] { 0x00 }.ToScriptHash(); - NotifyEventArgs args = new NotifyEventArgs(container, script_hash, 0); + NotifyEventArgs args = new NotifyEventArgs(container, script_hash, "Test", null); args.ScriptContainer.Should().Be(container); } }