diff --git a/src/Neo/IEventHandlers/ILogHandler.cs b/src/Neo/IEventHandlers/ILogHandler.cs index aa74ce9d9e..9243672c98 100644 --- a/src/Neo/IEventHandlers/ILogHandler.cs +++ b/src/Neo/IEventHandlers/ILogHandler.cs @@ -21,6 +21,6 @@ public interface ILogHandler /// /// The source of the event. /// The arguments of the log. - void ApplicationEngine_Log_Handler(object sender, LogEventArgs logEventArgs); + void ApplicationEngine_Log_Handler(ApplicationEngine sender, LogEventArgs logEventArgs); } } diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index ac571595ec..0dc65337d5 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -44,15 +44,24 @@ public partial class ApplicationEngine : ExecutionEngine /// public const long TestModeGas = 20_00000000; + public delegate void OnInstanceHandlerEvent(ApplicationEngine engine); + public delegate void OnLogEvent(ApplicationEngine engine, LogEventArgs args); + public delegate void OnNotifyEvent(ApplicationEngine engine, NotifyEventArgs args); + /// /// Triggered when a contract calls System.Runtime.Notify. /// - public static event EventHandler Notify; + public event OnNotifyEvent Notify; /// /// Triggered when a contract calls System.Runtime.Log. /// - public static event EventHandler Log; + public event OnLogEvent Log; + + /// + /// On Application Engine + /// + public static OnInstanceHandlerEvent InstanceHandler; private static Dictionary services; // Total amount of GAS spent to execute. @@ -435,8 +444,11 @@ public static ApplicationEngine Create(TriggerType trigger, IVerifiable containe // Adjust jump table according persistingBlock var jumpTable = settings == null || settings.IsHardforkEnabled(Hardfork.HF_Echidna, index) ? DefaultJumpTable : NotEchidnaJumpTable; - return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable) + var engine = Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable); + + InstanceHandler?.Invoke(engine); + return engine; } /// diff --git a/src/Plugins/ApplicationLogs/LogReader.cs b/src/Plugins/ApplicationLogs/LogReader.cs index 76fef9b547..9e451ad583 100644 --- a/src/Plugins/ApplicationLogs/LogReader.cs +++ b/src/Plugins/ApplicationLogs/LogReader.cs @@ -62,10 +62,15 @@ public override void Dispose() Blockchain.Committing -= ((ICommittingHandler)this).Blockchain_Committing_Handler; Blockchain.Committed -= ((ICommittedHandler)this).Blockchain_Committed_Handler; if (Settings.Default.Debug) - ApplicationEngine.Log -= ((ILogHandler)this).ApplicationEngine_Log_Handler; + ApplicationEngine.InstanceHandler -= ConfigureAppEngine; GC.SuppressFinalize(this); } + private void ConfigureAppEngine(ApplicationEngine engine) + { + engine.Log += ((ILogHandler)this).ApplicationEngine_Log_Handler; + } + protected override void Configure() { Settings.Load(GetConfiguration()); @@ -82,7 +87,7 @@ protected override void OnSystemLoaded(NeoSystem system) RpcServerPlugin.RegisterMethods(this, Settings.Default.Network); if (Settings.Default.Debug) - ApplicationEngine.Log += ((ILogHandler)this).ApplicationEngine_Log_Handler; + ApplicationEngine.InstanceHandler += ConfigureAppEngine; } #endregion @@ -240,7 +245,7 @@ void ICommittedHandler.Blockchain_Committed_Handler(NeoSystem system, Block bloc _neostore.CommitBlockLog(); } - void ILogHandler.ApplicationEngine_Log_Handler(object sender, LogEventArgs e) + void ILogHandler.ApplicationEngine_Log_Handler(ApplicationEngine sender, LogEventArgs e) { if (Settings.Default.Debug == false) return; diff --git a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs index 2dad5dc458..789885a051 100644 --- a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -126,12 +126,34 @@ public static void DeleteContract(this DataCache snapshot, UInt160 hash) public static StackItem Call(this NativeContract contract, DataCache snapshot, string method, params ContractParameter[] args) { - return Call(contract, snapshot, null, null, method, args); + return Call(contract, snapshot, null, null, method, null, args); } - public static StackItem Call(this NativeContract contract, DataCache snapshot, IVerifiable container, Block persistingBlock, string method, params ContractParameter[] args) + public static StackItem Call(this NativeContract contract, DataCache snapshot, string method, ApplicationEngine.OnNotifyEvent onNotify, params ContractParameter[] args) + { + return Call(contract, snapshot, null, null, method, onNotify, args); + } + + public static StackItem Call( + this NativeContract contract, DataCache snapshot, IVerifiable container, + Block persistingBlock, string method, params ContractParameter[] args + ) + { + return Call(contract, snapshot, container, persistingBlock, method, null, args); + } + + public static StackItem Call( + this NativeContract contract, DataCache snapshot, IVerifiable container, + Block persistingBlock, string method, ApplicationEngine.OnNotifyEvent onNotify, params ContractParameter[] args + ) { using var engine = ApplicationEngine.Create(TriggerType.Application, container, snapshot, persistingBlock, settings: TestProtocolSettings.Default); + + if (onNotify != null) + { + engine.Notify += onNotify; + } + return Call(contract, engine, method, args); } diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs index 9f4d84c987..33e9072ba6 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs @@ -58,20 +58,18 @@ public void TestSetAndGet() foreach (var role in roles) { var snapshot1 = _snapshotCache.CloneCache(); - UInt160 committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot1); - List notifications = new List(); - EventHandler ev = (o, e) => notifications.Add(e); - ApplicationEngine.Notify += ev; + var committeeMultiSigAddr = NativeContract.NEO.GetCommitteeAddress(snapshot1); + List notifications = []; + void Ev(ApplicationEngine o, NotifyEventArgs e) => notifications.Add(e); var ret = NativeContract.RoleManagement.Call( snapshot1, new Nep17NativeContractExtensions.ManualWitness(committeeMultiSigAddr), new Block { Header = new Header() }, - "designateAsRole", + "designateAsRole", Ev, new ContractParameter(ContractParameterType.Integer) { Value = new BigInteger((int)role) }, new ContractParameter(ContractParameterType.Array) { Value = publicKeys.Select(p => new ContractParameter(ContractParameterType.ByteArray) { Value = p.ToArray() }).ToList() } ); snapshot1.Commit(); - ApplicationEngine.Notify -= ev; Assert.AreEqual(1, notifications.Count); Assert.AreEqual("Designation", notifications[0].EventName); var snapshot2 = _snapshotCache.CloneCache(); diff --git a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.cs b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.cs index c40164191a..9a766f0353 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.cs @@ -34,22 +34,22 @@ public void TestNotify() var snapshotCache = TestBlockchain.GetTestSnapshotCache(); using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, settings: TestProtocolSettings.Default); engine.LoadScript(System.Array.Empty()); - ApplicationEngine.Notify += Test_Notify1; + engine.Notify += Test_Notify1; const string notifyEvent = "TestEvent"; engine.SendNotification(UInt160.Zero, notifyEvent, new Array()); Assert.AreEqual(notifyEvent, eventName); - ApplicationEngine.Notify += Test_Notify2; + engine.Notify += Test_Notify2; engine.SendNotification(UInt160.Zero, notifyEvent, new Array()); Assert.IsNull(eventName); eventName = notifyEvent; - ApplicationEngine.Notify -= Test_Notify1; + engine.Notify -= Test_Notify1; engine.SendNotification(UInt160.Zero, notifyEvent, new Array()); Assert.IsNull(eventName); - ApplicationEngine.Notify -= Test_Notify2; + engine.Notify -= Test_Notify2; engine.SendNotification(UInt160.Zero, notifyEvent, new Array()); Assert.IsNull(eventName); } diff --git a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs index df469f0dff..f54d4fb2a1 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs @@ -368,10 +368,10 @@ public void TestRuntime_Log() { var engine = GetEngine(true); var message = "hello"; - ApplicationEngine.Log += LogEvent; + engine.Log += LogEvent; engine.RuntimeLog(Encoding.UTF8.GetBytes(message)); Assert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }.ToHexString(), ((Transaction)engine.ScriptContainer).Script.Span.ToHexString()); - ApplicationEngine.Log -= LogEvent; + engine.Log -= LogEvent; } [TestMethod]