diff --git a/src/Neo/Network/P2P/Payloads/Signer.cs b/src/Neo/Network/P2P/Payloads/Signer.cs
index 40496dfe74..f5d9015131 100644
--- a/src/Neo/Network/P2P/Payloads/Signer.cs
+++ b/src/Neo/Network/P2P/Payloads/Signer.cs
@@ -20,13 +20,14 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Runtime.CompilerServices;
namespace Neo.Network.P2P.Payloads
{
///
/// Represents a signer of a .
///
- public class Signer : IInteroperable, ISerializable
+ public class Signer : IInteroperable, ISerializable, IEquatable
{
// This limits maximum number of AllowedContracts or AllowedGroups here
private const int MaxSubitems = 16;
@@ -66,6 +67,31 @@ public class Signer : IInteroperable, ISerializable
/*AllowedGroups*/ (Scopes.HasFlag(WitnessScope.CustomGroups) ? AllowedGroups.GetVarSize() : 0) +
/*Rules*/ (Scopes.HasFlag(WitnessScope.WitnessRules) ? Rules.GetVarSize() : 0);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool Equals(Signer other)
+ {
+ if (ReferenceEquals(this, other))
+ return true;
+ if (other is null) return false;
+ return Account == other.Account &&
+ Scopes == other.Scopes &&
+ AllowedContracts.SequenceEqual(other.AllowedContracts) &&
+ AllowedGroups.SequenceEqual(other.AllowedGroups) &&
+ Rules.SequenceEqual(other.Rules);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override bool Equals(object obj)
+ {
+ if (obj == null) return false;
+ return obj is Signer signerObj && Equals(signerObj);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(Account.GetHashCode(), Scopes);
+ }
+
public void Deserialize(ref MemoryReader reader)
{
Account = reader.ReadSerializable();
@@ -202,5 +228,23 @@ VM.Types.StackItem IInteroperable.ToStackItem(IReferenceCounter referenceCounter
Scopes.HasFlag(WitnessScope.WitnessRules) ? new VM.Types.Array(referenceCounter, Rules.Select(u => u.ToStackItem(referenceCounter))) : new VM.Types.Array(referenceCounter)
]);
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator ==(Signer left, Signer right)
+ {
+ if (left is null || right is null)
+ return Equals(left, right);
+
+ return left.Equals(right);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator !=(Signer left, Signer 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_Signers.cs b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Signers.cs
index d2358e947c..0ac918466f 100644
--- a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Signers.cs
+++ b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Signers.cs
@@ -23,6 +23,72 @@ namespace Neo.UnitTests.Network.P2P.Payloads
[TestClass]
public class UT_Signers
{
+ [TestMethod]
+ public void Test_IEquatable()
+ {
+ var ecPoint = ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1);
+ var expected = new Signer()
+ {
+ Account = UInt160.Zero,
+ Scopes = WitnessScope.Global,
+ AllowedContracts = [UInt160.Zero],
+ AllowedGroups = [ecPoint],
+ Rules = [
+ new WitnessRule
+ {
+ Condition = new BooleanCondition
+ {
+ Expression = true,
+ },
+ Action = WitnessRuleAction.Allow,
+ },
+ ]
+ };
+
+ var actual = new Signer()
+ {
+ Account = UInt160.Zero,
+ Scopes = WitnessScope.Global,
+ AllowedContracts = [UInt160.Zero],
+ AllowedGroups = [ecPoint],
+ Rules = [
+ new WitnessRule
+ {
+ Condition = new BooleanCondition
+ {
+ Expression = true,
+ },
+ Action = WitnessRuleAction.Allow,
+ },
+ ]
+ };
+
+ var notEqual = new Signer()
+ {
+ Account = UInt160.Zero,
+ Scopes = WitnessScope.WitnessRules,
+ AllowedContracts = [],
+ AllowedGroups = [],
+ Rules = []
+ };
+
+ 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));
+ }
+
+
[TestMethod]
public void Serialize_Deserialize_Global()
{