diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index 3771278839..d50b7df5f8 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -36,6 +36,11 @@ partial class ApplicationEngine /// public const int MaxNotificationSize = 1024; + /// + /// The maximum number of notifications per application execution. + /// + public const int MaxNotificationCount = 512; + private uint random_times = 0; /// @@ -395,8 +400,15 @@ protected internal void RuntimeNotifyV1(byte[] eventName, Array state) protected internal void SendNotification(UInt160 hash, string eventName, Array state) { NotifyEventArgs notification = new(ScriptContainer, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); - Notify?.Invoke(this, notification); notifications ??= new List(); + // Restrict the number of notifications for Application executions. Do not check + // persisting triggers to avoid native persist failure. Do not check verification + // trigger since verification context is loaded with ReadOnly flag. + if (IsHardforkEnabled(Hardfork.HF_Echidna) && Trigger == TriggerType.Application && notifications.Count == MaxNotificationCount) + { + throw new InvalidOperationException($"Maximum number of notifications `{MaxNotificationCount}` is reached."); + } + Notify?.Invoke(this, notification); notifications.Add(notification); CurrentContext.GetState().NotificationCount++; }