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)); + } + } +}