diff --git a/src/Neo/Network/P2P/Payloads/WitnessRule.cs b/src/Neo/Network/P2P/Payloads/WitnessRule.cs
index 8552f0798e..08ab3911b2 100644
--- a/src/Neo/Network/P2P/Payloads/WitnessRule.cs
+++ b/src/Neo/Network/P2P/Payloads/WitnessRule.cs
@@ -17,13 +17,14 @@
using Neo.VM.Types;
using System;
using System.IO;
+using System.Runtime.CompilerServices;
namespace Neo.Network.P2P.Payloads
{
///
/// The rule used to describe the scope of the witness.
///
- public class WitnessRule : IInteroperable, ISerializable
+ public class WitnessRule : IInteroperable, ISerializable, IEquatable
{
///
/// Indicates the action to be taken if the current context meets with the rule.
@@ -37,6 +38,27 @@ public class WitnessRule : IInteroperable, ISerializable
int ISerializable.Size => sizeof(WitnessRuleAction) + Condition.Size;
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool Equals(WitnessRule other)
+ {
+ if (ReferenceEquals(this, other)) return true;
+ if (other is null) return false;
+ return Action == other.Action &&
+ Condition == other.Condition;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ return obj is WitnessRule wr && Equals(wr);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Action, Condition.GetHashCode());
+ }
+
void ISerializable.Deserialize(ref MemoryReader reader)
{
Action = (WitnessRuleAction)reader.ReadByte();
@@ -96,5 +118,23 @@ public StackItem ToStackItem(IReferenceCounter referenceCounter)
Condition.ToStackItem(referenceCounter)
});
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator ==(WitnessRule left, WitnessRule right)
+ {
+ if (left is null || right is null)
+ return Equals(left, right);
+
+ return left.Equals(right);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator !=(WitnessRule left, WitnessRule right)
+ {
+ if (left is null || right is null)
+ return !Equals(left, right);
+
+ return !left.Equals(right);
+ }
}
}
diff --git a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_WitnessRule.cs b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_WitnessRule.cs
new file mode 100644
index 0000000000..6d211942c1
--- /dev/null
+++ b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_WitnessRule.cs
@@ -0,0 +1,72 @@
+// Copyright (C) 2015-2024 The Neo Project.
+//
+// UT_WitnessRule.cs file belongs to the neo project and is free
+// software distributed under the MIT software license, see the
+// accompanying file LICENSE in the main directory of the
+// repository or http://www.opensource.org/licenses/mit-license.php
+// for more details.
+//
+// Redistribution and use in source and binary forms with or without
+// modifications are permitted.
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Network.P2P.Payloads;
+using Neo.Network.P2P.Payloads.Conditions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Neo.UnitTests.Network.P2P.Payloads
+{
+ [TestClass]
+ public class UT_WitnessRule
+ {
+ [TestMethod]
+ public void Test_IEquatable()
+ {
+ var expected = new WitnessRule
+ {
+ Action = WitnessRuleAction.Allow,
+ Condition = new BooleanCondition
+ {
+ Expression = true,
+ }
+ };
+
+ var actual = new WitnessRule
+ {
+ Action = WitnessRuleAction.Allow,
+ Condition = new BooleanCondition
+ {
+ Expression = true,
+ }
+ };
+
+ var notEqual = new WitnessRule
+ {
+ Action = WitnessRuleAction.Deny,
+ Condition = new BooleanCondition
+ {
+ Expression = false,
+ }
+ };
+
+ Assert.IsTrue(expected.Equals(expected));
+
+ Assert.AreEqual(expected, actual);
+ Assert.IsTrue(expected == actual);
+ Assert.IsTrue(expected.Equals(actual));
+
+ Assert.AreNotEqual(expected, notEqual);
+ Assert.IsTrue(expected != notEqual);
+ Assert.IsFalse(expected.Equals(notEqual));
+
+ Assert.IsFalse(expected == null);
+ Assert.IsFalse(null == expected);
+ Assert.AreNotEqual(expected, null);
+ Assert.IsFalse(expected.Equals(null));
+ }
+ }
+}