Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add event name to System.Runtime.Notify() #1701

Merged
merged 2 commits into from
Jun 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/neo/SmartContract/ApplicationEngine.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
6 changes: 3 additions & 3 deletions src/neo/SmartContract/Native/Tokens/Nep5Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)]
Expand Down Expand Up @@ -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;
}

Expand Down
8 changes: 5 additions & 3 deletions src/neo/SmartContract/NotifyEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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 };
}
}
}
27 changes: 13 additions & 14 deletions tests/neo.UnitTests/SmartContract/UT_ApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.VM.Types;

namespace Neo.UnitTests.SmartContract
{
[TestClass]
public class UT_ApplicationEngine
{
private string message = null;
private StackItem item = null;
private string eventName = null;

[TestInitialize]
public void TestSetup()
Expand All @@ -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)
Expand All @@ -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]
Expand Down
47 changes: 19 additions & 28 deletions tests/neo.UnitTests/SmartContract/UT_InteropService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -114,31 +113,33 @@ 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

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

Expand All @@ -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
Expand All @@ -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()
{
Expand Down
2 changes: 1 addition & 1 deletion tests/neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down