diff --git a/.editorconfig b/.editorconfig
index 5acd074d26..175ec7b14e 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -15,3 +15,5 @@ insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
end_of_line = lf
+
+dotnet_diagnostic.CS1591.severity = silent
diff --git a/src/neo/BigDecimal.cs b/src/neo/BigDecimal.cs
index 45e2ae770c..45e41ce124 100644
--- a/src/neo/BigDecimal.cs
+++ b/src/neo/BigDecimal.cs
@@ -3,20 +3,34 @@
namespace Neo
{
+ ///
+ /// Represents a fixed-point number of arbitrary precision.
+ ///
public struct BigDecimal
{
private readonly BigInteger value;
private readonly byte decimals;
+ ///
+ /// The value of the number.
+ ///
public BigInteger Value => value;
+
+ ///
+ /// The number of decimal places for this number.
+ ///
public byte Decimals => decimals;
+
+ ///
+ /// The sign of the number.
+ ///
public int Sign => value.Sign;
///
- /// Create BigDecimal from BigInteger
+ /// Initializes a new instance of the struct.
///
- /// Value
- /// Decimals
+ /// The value of the number.
+ /// The number of decimal places for this number.
public BigDecimal(BigInteger value, byte decimals)
{
this.value = value;
@@ -24,29 +38,34 @@ public BigDecimal(BigInteger value, byte decimals)
}
///
- /// Create BigDecimal from decimal
+ /// Initializes a new instance of the struct with the value of .
///
- /// Value
+ /// The value of the number.
public unsafe BigDecimal(decimal value)
{
- ReadOnlySpan buffer = new ReadOnlySpan(&value, sizeof(decimal));
+ ReadOnlySpan buffer = new(&value, sizeof(decimal));
this.decimals = buffer[14];
this.value = new BigInteger(decimal.Multiply((decimal)Math.Pow(10, decimals), value));
}
///
- /// Create BigDecimal from decimal
+ /// Initializes a new instance of the struct with the value of .
///
- /// Value
- /// Decimals
+ /// The value of the number.
+ /// The number of decimal places for this number.
public unsafe BigDecimal(decimal value, byte decimals)
{
- ReadOnlySpan buffer = new ReadOnlySpan(&value, sizeof(decimal));
+ ReadOnlySpan buffer = new(&value, sizeof(decimal));
if (buffer[14] > decimals) throw new ArgumentException(null, nameof(value));
this.value = new BigInteger(decimal.Multiply((decimal)Math.Pow(10, decimals), value));
this.decimals = decimals;
}
+ ///
+ /// Changes the decimals of the .
+ ///
+ /// The new decimals field.
+ /// The that has the new number of decimal places.
public BigDecimal ChangeDecimals(byte decimals)
{
if (this.decimals == decimals) return this;
@@ -60,11 +79,18 @@ public BigDecimal ChangeDecimals(byte decimals)
BigInteger divisor = BigInteger.Pow(10, this.decimals - decimals);
value = BigInteger.DivRem(this.value, divisor, out BigInteger remainder);
if (remainder > BigInteger.Zero)
- throw new ArgumentOutOfRangeException();
+ throw new ArgumentOutOfRangeException(nameof(decimals));
}
return new BigDecimal(value, decimals);
}
+ ///
+ /// Parses a from the specified .
+ ///
+ /// A number represented by a .
+ /// The number of decimal places for this number.
+ /// The parsed .
+ /// is not in the correct format.
public static BigDecimal Parse(string s, byte decimals)
{
if (!TryParse(s, decimals, out BigDecimal result))
@@ -72,6 +98,10 @@ public static BigDecimal Parse(string s, byte decimals)
return result;
}
+ ///
+ /// Gets a representing the number.
+ ///
+ /// The representing the number.
public override string ToString()
{
BigInteger divisor = BigInteger.Pow(10, decimals);
@@ -80,15 +110,22 @@ public override string ToString()
return $"{result}.{remainder.ToString("d" + decimals)}".TrimEnd('0');
}
+ ///
+ /// Parses a from the specified .
+ ///
+ /// A number represented by a .
+ /// The number of decimal places for this number.
+ /// The parsed .
+ /// if a number is successfully parsed; otherwise, .
public static bool TryParse(string s, byte decimals, out BigDecimal result)
{
int e = 0;
int index = s.IndexOfAny(new[] { 'e', 'E' });
if (index >= 0)
{
- if (!sbyte.TryParse(s.Substring(index + 1), out sbyte e_temp))
+ if (!sbyte.TryParse(s[(index + 1)..], out sbyte e_temp))
{
- result = default(BigDecimal);
+ result = default;
return false;
}
e = e_temp;
@@ -104,14 +141,14 @@ public static bool TryParse(string s, byte decimals, out BigDecimal result)
int ds = e + decimals;
if (ds < 0)
{
- result = default(BigDecimal);
+ result = default;
return false;
}
if (ds > 0)
s += new string('0', ds);
if (!BigInteger.TryParse(s, out BigInteger value))
{
- result = default(BigDecimal);
+ result = default;
return false;
}
result = new BigDecimal(value, decimals);
diff --git a/src/neo/Cryptography/Base58.cs b/src/neo/Cryptography/Base58.cs
index f571f9540d..7e05a7141e 100644
--- a/src/neo/Cryptography/Base58.cs
+++ b/src/neo/Cryptography/Base58.cs
@@ -6,10 +6,21 @@
namespace Neo.Cryptography
{
+ ///
+ /// A helper class for base-58 encoder.
+ ///
public static class Base58
{
+ ///
+ /// Represents the alphabet of the base-58 encoder.
+ ///
public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
+ ///
+ /// Converts the specified , which encodes binary data as base-58 digits, to an equivalent byte array. The encoded contains the checksum of the binary data.
+ ///
+ /// The to convert.
+ /// A byte array that is equivalent to .
public static byte[] Base58CheckDecode(this string input)
{
if (input is null) throw new ArgumentNullException(nameof(input));
@@ -23,6 +34,11 @@ public static byte[] Base58CheckDecode(this string input)
return ret;
}
+ ///
+ /// Converts a byte array to its equivalent representation that is encoded with base-58 digits. The encoded contains the checksum of the binary data.
+ ///
+ /// The byte array to convert.
+ /// The representation, in base-58, of the contents of .
public static string Base58CheckEncode(this ReadOnlySpan data)
{
byte[] checksum = data.Sha256().Sha256();
@@ -34,6 +50,11 @@ public static string Base58CheckEncode(this ReadOnlySpan data)
return ret;
}
+ ///
+ /// Converts the specified , which encodes binary data as base-58 digits, to an equivalent byte array.
+ ///
+ /// The to convert.
+ /// A byte array that is equivalent to .
public static byte[] Decode(string input)
{
// Decode Base58 string to BigInteger
@@ -55,10 +76,15 @@ public static byte[] Decode(string input)
return Concat(leadingZeros, bytesWithoutLeadingZeros);
}
+ ///
+ /// Converts a byte array to its equivalent representation that is encoded with base-58 digits.
+ ///
+ /// The byte array to convert.
+ /// The representation, in base-58, of the contents of .
public static string Encode(ReadOnlySpan input)
{
// Decode byte[] to BigInteger
- BigInteger value = new BigInteger(input, isUnsigned: true, isBigEndian: true);
+ BigInteger value = new(input, isUnsigned: true, isBigEndian: true);
// Encode BigInteger to Base58 string
var sb = new StringBuilder();
diff --git a/src/neo/Cryptography/BloomFilter.cs b/src/neo/Cryptography/BloomFilter.cs
index 32cfa50dd4..67af4c2102 100644
--- a/src/neo/Cryptography/BloomFilter.cs
+++ b/src/neo/Cryptography/BloomFilter.cs
@@ -4,17 +4,36 @@
namespace Neo.Cryptography
{
+ ///
+ /// Represents a bloom filter.
+ ///
public class BloomFilter
{
private readonly uint[] seeds;
private readonly BitArray bits;
+ ///
+ /// The number of hash functions used by the bloom filter.
+ ///
public int K => seeds.Length;
+ ///
+ /// The size of the bit array used by the bloom filter.
+ ///
public int M => bits.Length;
+ ///
+ /// Used to generate the seeds of the murmur hash functions.
+ ///
public uint Tweak { get; private set; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The size of the bit array used by the bloom filter.
+ /// The number of hash functions used by the bloom filter.
+ /// Used to generate the seeds of the murmur hash functions.
+ /// The initial elements contained in this object.
public BloomFilter(int m, int k, uint nTweak, byte[] elements = null)
{
if (k < 0 || m < 0) throw new ArgumentOutOfRangeException();
@@ -24,12 +43,21 @@ public BloomFilter(int m, int k, uint nTweak, byte[] elements = null)
this.Tweak = nTweak;
}
+ ///
+ /// Adds an element to the .
+ ///
+ /// The object to add to the .
public void Add(byte[] element)
{
foreach (uint i in seeds.AsParallel().Select(s => element.Murmur32(s)))
bits.Set((int)(i % (uint)bits.Length), true);
}
+ ///
+ /// Determines whether the contains a specific element.
+ ///
+ /// The object to locate in the .
+ /// if is found in the ; otherwise, .
public bool Check(byte[] element)
{
foreach (uint i in seeds.AsParallel().Select(s => element.Murmur32(s)))
@@ -38,6 +66,10 @@ public bool Check(byte[] element)
return true;
}
+ ///
+ /// Gets the bit array in this .
+ ///
+ /// The byte array to store the bits.
public void GetBits(byte[] newBits)
{
bits.CopyTo(newBits, 0);
diff --git a/src/neo/Cryptography/Crypto.cs b/src/neo/Cryptography/Crypto.cs
index ddd010cc63..aec25ecd09 100644
--- a/src/neo/Cryptography/Crypto.cs
+++ b/src/neo/Cryptography/Crypto.cs
@@ -1,24 +1,43 @@
using System;
-using System.Numerics;
using System.Security.Cryptography;
namespace Neo.Cryptography
{
+ ///
+ /// A cryptographic helper class.
+ ///
public static class Crypto
{
+ ///
+ /// Calculates the 160-bit hash value of the specified message.
+ ///
+ /// The message to be hashed.
+ /// 160-bit hash value.
public static byte[] Hash160(ReadOnlySpan message)
{
return message.Sha256().RIPEMD160();
}
+ ///
+ /// Calculates the 256-bit hash value of the specified message.
+ ///
+ /// The message to be hashed.
+ /// 256-bit hash value.
public static byte[] Hash256(ReadOnlySpan message)
{
return message.Sha256().Sha256();
}
+ ///
+ /// Signs the specified message using the ECDSA algorithm.
+ ///
+ /// The message to be signed.
+ /// The private key to be used.
+ /// The public key to be used.
+ /// The ECDSA signature for the specified message.
public static byte[] Sign(byte[] message, byte[] prikey, byte[] pubkey)
{
- using (var ecdsa = ECDsa.Create(new ECParameters
+ using var ecdsa = ECDsa.Create(new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
D = prikey,
@@ -27,82 +46,47 @@ public static byte[] Sign(byte[] message, byte[] prikey, byte[] pubkey)
X = pubkey[..32],
Y = pubkey[32..]
}
- }))
- {
- return ecdsa.SignData(message, HashAlgorithmName.SHA256);
- }
+ });
+ return ecdsa.SignData(message, HashAlgorithmName.SHA256);
}
+ ///
+ /// Verifies that a digital signature is appropriate for the provided key and message.
+ ///
+ /// The signed message.
+ /// The signature to be verified.
+ /// The public key to be used.
+ /// if the signature is valid; otherwise, .
public static bool VerifySignature(ReadOnlySpan message, ReadOnlySpan signature, ECC.ECPoint pubkey)
{
- if (pubkey.Curve == ECC.ECCurve.Secp256r1)
+ ECCurve curve =
+ pubkey.Curve == ECC.ECCurve.Secp256r1 ? ECCurve.NamedCurves.nistP256 :
+ pubkey.Curve == ECC.ECCurve.Secp256k1 ? ECCurve.CreateFromFriendlyName("secP256k1") :
+ throw new NotSupportedException();
+ byte[] buffer = pubkey.EncodePoint(false);
+ using var ecdsa = ECDsa.Create(new ECParameters
{
- byte[] buffer = pubkey.EncodePoint(false);
- using (var ecdsa = ECDsa.Create(new ECParameters
- {
- Curve = ECCurve.NamedCurves.nistP256,
- Q = new ECPoint
- {
- X = buffer[1..33],
- Y = buffer[33..]
- }
- }))
+ Curve = curve,
+ Q = new ECPoint
{
- return ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
+ X = buffer[1..33],
+ Y = buffer[33..]
}
- }
- else
- {
- var ecdsa = new ECC.ECDsa(pubkey);
- var r = new BigInteger(signature[..32], true, true);
- var s = new BigInteger(signature[32..], true, true);
- return ecdsa.VerifySignature(message.Sha256(), r, s);
- }
+ });
+ return ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
}
+ ///
+ /// Verifies that a digital signature is appropriate for the provided key and message.
+ ///
+ /// The signed message.
+ /// The signature to be verified.
+ /// The public key to be used.
+ /// The curve to be used by the ECDSA algorithm.
+ /// if the signature is valid; otherwise, .
public static bool VerifySignature(ReadOnlySpan message, ReadOnlySpan signature, ReadOnlySpan pubkey, ECC.ECCurve curve)
{
- if (curve == ECC.ECCurve.Secp256r1)
- {
- if (pubkey.Length == 33 && (pubkey[0] == 0x02 || pubkey[0] == 0x03))
- {
- try
- {
- pubkey = ECC.ECPoint.DecodePoint(pubkey, curve).EncodePoint(false).AsSpan(1);
- }
- catch
- {
- return false;
- }
- }
- else if (pubkey.Length == 65 && pubkey[0] == 0x04)
- {
- pubkey = pubkey[1..];
- }
- else
- {
- throw new ArgumentException();
- }
- using (var ecdsa = ECDsa.Create(new ECParameters
- {
- Curve = ECCurve.NamedCurves.nistP256,
- Q = new ECPoint
- {
- X = pubkey[..32].ToArray(),
- Y = pubkey[32..].ToArray()
- }
- }))
- {
- return ecdsa.VerifyData(message, signature, HashAlgorithmName.SHA256);
- }
- }
- else
- {
- var ecdsa = new ECC.ECDsa(ECC.ECPoint.DecodePoint(pubkey, curve));
- var r = new BigInteger(signature[..32], true, true);
- var s = new BigInteger(signature[32..], true, true);
- return ecdsa.VerifySignature(message.Sha256(), r, s);
- }
+ return VerifySignature(message, signature, ECC.ECPoint.DecodePoint(pubkey, curve));
}
}
}
diff --git a/src/neo/Cryptography/ECC/ECCurve.cs b/src/neo/Cryptography/ECC/ECCurve.cs
index 546c794070..ed4f954396 100644
--- a/src/neo/Cryptography/ECC/ECCurve.cs
+++ b/src/neo/Cryptography/ECC/ECCurve.cs
@@ -3,16 +3,25 @@
namespace Neo.Cryptography.ECC
{
+ ///
+ /// Represents an elliptic curve.
+ ///
public class ECCurve
{
internal readonly BigInteger Q;
internal readonly ECFieldElement A;
internal readonly ECFieldElement B;
internal readonly BigInteger N;
+ ///
+ /// The point at infinity.
+ ///
public readonly ECPoint Infinity;
+ ///
+ /// The generator, or base point, for operations on the curve.
+ ///
public readonly ECPoint G;
- public readonly int ExpectedECPointLength;
+ internal readonly int ExpectedECPointLength;
private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G)
{
@@ -25,7 +34,10 @@ private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G
this.G = ECPoint.DecodePoint(G, this);
}
- public static readonly ECCurve Secp256k1 = new ECCurve
+ ///
+ /// Represents a secp256k1 named curve.
+ ///
+ public static readonly ECCurve Secp256k1 = new
(
BigInteger.Parse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", NumberStyles.AllowHexSpecifier),
BigInteger.Zero,
@@ -34,7 +46,10 @@ private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G
("04" + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8").HexToBytes()
);
- public static readonly ECCurve Secp256r1 = new ECCurve
+ ///
+ /// Represents a secp256r1 named curve.
+ ///
+ public static readonly ECCurve Secp256r1 = new
(
BigInteger.Parse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.AllowHexSpecifier),
BigInteger.Parse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", NumberStyles.AllowHexSpecifier),
diff --git a/src/neo/Cryptography/ECC/ECDsa.cs b/src/neo/Cryptography/ECC/ECDsa.cs
deleted file mode 100644
index 1c0a17d7a9..0000000000
--- a/src/neo/Cryptography/ECC/ECDsa.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-using System;
-using System.Numerics;
-using System.Security.Cryptography;
-
-namespace Neo.Cryptography.ECC
-{
- public class ECDsa
- {
- private readonly byte[] privateKey;
- private readonly ECPoint publicKey;
- private readonly ECCurve curve;
-
- public ECDsa(byte[] privateKey, ECCurve curve)
- : this(curve.G * privateKey)
- {
- this.privateKey = privateKey;
- }
-
- public ECDsa(ECPoint publicKey)
- {
- this.publicKey = publicKey;
- this.curve = publicKey.Curve;
- }
-
- private BigInteger CalculateE(BigInteger n, ReadOnlySpan message)
- {
- if (n.GetBitLength() != (message.Length * 8))
- {
- throw new ArgumentException($"Message must be {n.GetBitLength()} bit length");
- }
- return new BigInteger(message, isUnsigned: true, isBigEndian: true);
- }
-
- public BigInteger[] GenerateSignature(ReadOnlySpan message)
- {
- if (privateKey == null) throw new InvalidOperationException();
- BigInteger e = CalculateE(curve.N, message);
- BigInteger d = new BigInteger(privateKey, isUnsigned: true, isBigEndian: true);
- BigInteger r, s;
- using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
- {
- do
- {
- BigInteger k;
- do
- {
- do
- {
- k = rng.NextBigInteger((int)curve.N.GetBitLength());
- }
- while (k.Sign == 0 || k.CompareTo(curve.N) >= 0);
- ECPoint p = ECPoint.Multiply(curve.G, k);
- BigInteger x = p.X.Value;
- r = x.Mod(curve.N);
- }
- while (r.Sign == 0);
- s = (k.ModInverse(curve.N) * (e + d * r)).Mod(curve.N);
- if (s > curve.N / 2)
- {
- s = curve.N - s;
- }
- }
- while (s.Sign == 0);
- }
- return new BigInteger[] { r, s };
- }
-
- private static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger k, ECPoint Q, BigInteger l)
- {
- int m = (int)Math.Max(k.GetBitLength(), l.GetBitLength());
- ECPoint Z = P + Q;
- ECPoint R = P.Curve.Infinity;
- for (int i = m - 1; i >= 0; --i)
- {
- R = R.Twice();
- if (k.TestBit(i))
- {
- if (l.TestBit(i))
- R = R + Z;
- else
- R = R + P;
- }
- else
- {
- if (l.TestBit(i))
- R = R + Q;
- }
- }
- return R;
- }
-
- public bool VerifySignature(ReadOnlySpan message, BigInteger r, BigInteger s)
- {
- if (r.Sign < 1 || s.Sign < 1 || r.CompareTo(curve.N) >= 0 || s.CompareTo(curve.N) >= 0)
- return false;
- BigInteger e = CalculateE(curve.N, message);
- BigInteger c = s.ModInverse(curve.N);
- BigInteger u1 = (e * c).Mod(curve.N);
- BigInteger u2 = (r * c).Mod(curve.N);
- ECPoint point = SumOfTwoMultiplies(curve.G, u1, publicKey, u2);
- BigInteger v = point.X.Value.Mod(curve.N);
- return v.Equals(r);
- }
- }
-}
diff --git a/src/neo/Cryptography/ECC/ECFieldElement.cs b/src/neo/Cryptography/ECC/ECFieldElement.cs
index edfdc497b0..f0cf95430d 100644
--- a/src/neo/Cryptography/ECC/ECFieldElement.cs
+++ b/src/neo/Cryptography/ECC/ECFieldElement.cs
@@ -30,7 +30,7 @@ public override bool Equals(object obj)
if (obj == this)
return true;
- if (!(obj is ECFieldElement other))
+ if (obj is not ECFieldElement other)
return false;
return Equals(other);
@@ -97,7 +97,7 @@ public ECFieldElement Sqrt()
{
if (curve.Q.TestBit(1))
{
- ECFieldElement z = new ECFieldElement(BigInteger.ModPow(Value, (curve.Q >> 2) + 1, curve.Q), curve);
+ ECFieldElement z = new(BigInteger.ModPow(Value, (curve.Q >> 2) + 1, curve.Q), curve);
return z.Square().Equals(this) ? z : null;
}
BigInteger qMinusOne = curve.Q - 1;
@@ -111,7 +111,7 @@ public ECFieldElement Sqrt()
BigInteger U, V;
do
{
- Random rand = new Random();
+ Random rand = new();
BigInteger P;
do
{
diff --git a/src/neo/Cryptography/ECC/ECPoint.cs b/src/neo/Cryptography/ECC/ECPoint.cs
index 49a3c16074..92346376c4 100644
--- a/src/neo/Cryptography/ECC/ECPoint.cs
+++ b/src/neo/Cryptography/ECC/ECPoint.cs
@@ -6,12 +6,18 @@
namespace Neo.Cryptography.ECC
{
+ ///
+ /// Represents a (X,Y) coordinate pair for elliptic curve cryptography (ECC) structures.
+ ///
public class ECPoint : IComparable, IEquatable, ISerializable
{
internal ECFieldElement X, Y;
internal readonly ECCurve Curve;
private byte[] _compressedPoint, _uncompressedPoint;
+ ///
+ /// Indicates whether it is a point at infinity.
+ ///
public bool IsInfinity
{
get { return X == null && Y == null; }
@@ -19,6 +25,9 @@ public bool IsInfinity
public int Size => IsInfinity ? 1 : 33;
+ ///
+ /// Initializes a new instance of the class with the secp256r1 curve.
+ ///
public ECPoint() : this(null, null, ECCurve.Secp256r1) { }
internal ECPoint(ECFieldElement x, ECFieldElement y, ECCurve curve)
@@ -39,6 +48,12 @@ public int CompareTo(ECPoint other)
return Y.CompareTo(other.Y);
}
+ ///
+ /// Decode an object from a sequence of byte.
+ ///
+ /// The sequence of byte to be decoded.
+ /// The object used to construct the .
+ /// The decoded point.
public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve)
{
ECPoint p = null;
@@ -50,7 +65,7 @@ public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve)
if (encoded.Length != (curve.ExpectedECPointLength + 1))
throw new FormatException("Incorrect length for compressed encoding");
int yTilde = encoded[0] & 1;
- BigInteger X1 = new BigInteger(encoded[1..], isUnsigned: true, isBigEndian: true);
+ BigInteger X1 = new(encoded[1..], isUnsigned: true, isBigEndian: true);
p = DecompressPoint(yTilde, X1, curve);
p._compressedPoint = encoded.ToArray();
break;
@@ -59,8 +74,8 @@ public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve)
{
if (encoded.Length != (2 * curve.ExpectedECPointLength + 1))
throw new FormatException("Incorrect length for uncompressed/hybrid encoding");
- BigInteger X1 = new BigInteger(encoded[1..(1 + curve.ExpectedECPointLength)], isUnsigned: true, isBigEndian: true);
- BigInteger Y1 = new BigInteger(encoded[(1 + curve.ExpectedECPointLength)..], isUnsigned: true, isBigEndian: true);
+ BigInteger X1 = new(encoded[1..(1 + curve.ExpectedECPointLength)], isUnsigned: true, isBigEndian: true);
+ BigInteger Y1 = new(encoded[(1 + curve.ExpectedECPointLength)..], isUnsigned: true, isBigEndian: true);
p = new ECPoint(new ECFieldElement(X1, curve), new ECFieldElement(Y1, curve), curve)
{
_uncompressedPoint = encoded.ToArray()
@@ -75,7 +90,7 @@ public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve)
private static ECPoint DecompressPoint(int yTilde, BigInteger X1, ECCurve curve)
{
- ECFieldElement x = new ECFieldElement(X1, curve);
+ ECFieldElement x = new(X1, curve);
ECFieldElement alpha = x * (x.Square() + curve.A) + curve.B;
ECFieldElement beta = alpha.Sqrt();
@@ -105,6 +120,12 @@ void ISerializable.Deserialize(BinaryReader reader)
Y = p.Y;
}
+ ///
+ /// Deserializes an object from a .
+ ///
+ /// The for reading data.
+ /// The object used to construct the .
+ /// The deserialized point.
public static ECPoint DeserializeFrom(BinaryReader reader, ECCurve curve)
{
Span buffer = stackalloc byte[1 + curve.ExpectedECPointLength * 2];
@@ -134,11 +155,11 @@ public static ECPoint DeserializeFrom(BinaryReader reader, ECCurve curve)
}
///
- /// Encode ECPoint to byte array
- /// Note: The return should't be modified because it could be cached
+ /// Encodes an object to a byte array.
///
- /// Compressed
- /// Encoded point
+ /// Indicates whether to encode it in a compressed format.
+ /// The encoded point.
+ /// Note: The return should't be modified because it could be cached.
public byte[] EncodePoint(bool commpressed)
{
if (IsInfinity) return new byte[1];
@@ -166,7 +187,7 @@ public byte[] EncodePoint(bool commpressed)
public bool Equals(ECPoint other)
{
if (ReferenceEquals(this, other)) return true;
- if (ReferenceEquals(null, other)) return false;
+ if (other is null) return false;
if (IsInfinity && other.IsInfinity) return true;
if (IsInfinity || other.IsInfinity) return false;
return X.Equals(other.X) && Y.Equals(other.Y);
@@ -177,22 +198,21 @@ public override bool Equals(object obj)
return Equals(obj as ECPoint);
}
- public static ECPoint FromBytes(byte[] pubkey, ECCurve curve)
+ ///
+ /// Constructs an object from a byte array.
+ ///
+ /// The byte array to be used to construct the object.
+ /// The object used to construct the .
+ /// The decoded point.
+ public static ECPoint FromBytes(byte[] bytes, ECCurve curve)
{
- switch (pubkey.Length)
+ return bytes.Length switch
{
- case 33:
- case 65:
- return DecodePoint(pubkey, curve);
- case 64:
- case 72:
- return DecodePoint(Concat(new byte[] { 0x04 }, pubkey[^64..]), curve);
- case 96:
- case 104:
- return DecodePoint(Concat(new byte[] { 0x04 }, pubkey[^96..^32]), curve);
- default:
- throw new FormatException();
- }
+ 33 or 65 => DecodePoint(bytes, curve),
+ 64 or 72 => DecodePoint(Concat(new byte[] { 0x04 }, bytes[^64..]), curve),
+ 96 or 104 => DecodePoint(Concat(new byte[] { 0x04 }, bytes[^96..^32]), curve),
+ _ => throw new FormatException(),
+ };
}
public override int GetHashCode()
@@ -299,6 +319,12 @@ internal static ECPoint Multiply(ECPoint p, BigInteger k)
return q;
}
+ ///
+ /// Parse the object from a .
+ ///
+ /// The to be parsed.
+ /// The object used to construct the .
+ /// The parsed point.
public static ECPoint Parse(string value, ECCurve curve)
{
return DecodePoint(value.HexToBytes(), curve);
@@ -314,6 +340,13 @@ public override string ToString()
return EncodePoint(true).ToHexString();
}
+ ///
+ /// Try parse the object from a .
+ ///
+ /// The to be parsed.
+ /// The object used to construct the .
+ /// The parsed point.
+ /// if was converted successfully; otherwise, .
public static bool TryParse(string value, ECCurve curve, out ECPoint point)
{
try
@@ -334,8 +367,8 @@ internal ECPoint Twice()
return this;
if (this.Y.Value.Sign == 0)
return Curve.Infinity;
- ECFieldElement TWO = new ECFieldElement(2, Curve);
- ECFieldElement THREE = new ECFieldElement(3, Curve);
+ ECFieldElement TWO = new(2, Curve);
+ ECFieldElement THREE = new(3, Curve);
ECFieldElement gamma = (this.X.Square() * THREE + Curve.A) / (Y * TWO);
ECFieldElement x3 = gamma.Square() - this.X * TWO;
ECFieldElement y3 = gamma * (this.X - x3) - this.Y;
@@ -387,10 +420,10 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k)
if (p == null || n == null)
throw new ArgumentNullException();
if (n.Length != 32)
- throw new ArgumentException();
+ throw new ArgumentException(null, nameof(n));
if (p.IsInfinity)
return p;
- BigInteger k = new BigInteger(n, isUnsigned: true, isBigEndian: true);
+ BigInteger k = new(n, isUnsigned: true, isBigEndian: true);
if (k.Sign == 0)
return p.Curve.Infinity;
return Multiply(p, k);
diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs
index d39236c33d..deb6063186 100644
--- a/src/neo/Cryptography/Helper.cs
+++ b/src/neo/Cryptography/Helper.cs
@@ -11,96 +11,74 @@
namespace Neo.Cryptography
{
+ ///
+ /// A helper class for cryptography
+ ///
public static class Helper
{
- internal static byte[] AES256Decrypt(this byte[] block, byte[] key)
- {
- using (Aes aes = Aes.Create())
- {
- aes.Key = key;
- aes.Mode = CipherMode.ECB;
- aes.Padding = PaddingMode.None;
- using (ICryptoTransform decryptor = aes.CreateDecryptor())
- {
- return decryptor.TransformFinalBlock(block, 0, block.Length);
- }
- }
- }
-
- internal static byte[] AES256Encrypt(this byte[] block, byte[] key)
- {
- using (Aes aes = Aes.Create())
- {
- aes.Key = key;
- aes.Mode = CipherMode.ECB;
- aes.Padding = PaddingMode.None;
- using (ICryptoTransform encryptor = aes.CreateEncryptor())
- {
- return encryptor.TransformFinalBlock(block, 0, block.Length);
- }
- }
- }
-
- internal static byte[] AesDecrypt(this byte[] data, byte[] key, byte[] iv)
- {
- if (data == null || key == null || iv == null) throw new ArgumentNullException();
- if (data.Length % 16 != 0 || key.Length != 32 || iv.Length != 16) throw new ArgumentException();
- using (Aes aes = Aes.Create())
- {
- aes.Padding = PaddingMode.None;
- using (ICryptoTransform decryptor = aes.CreateDecryptor(key, iv))
- {
- return decryptor.TransformFinalBlock(data, 0, data.Length);
- }
- }
- }
-
- internal static byte[] AesEncrypt(this byte[] data, byte[] key, byte[] iv)
- {
- if (data == null || key == null || iv == null) throw new ArgumentNullException();
- if (data.Length % 16 != 0 || key.Length != 32 || iv.Length != 16) throw new ArgumentException();
- using (Aes aes = Aes.Create())
- {
- aes.Padding = PaddingMode.None;
- using (ICryptoTransform encryptor = aes.CreateEncryptor(key, iv))
- {
- return encryptor.TransformFinalBlock(data, 0, data.Length);
- }
- }
- }
-
+ ///
+ /// Computes the hash value for the specified byte array using the ripemd160 algorithm.
+ ///
+ /// The input to compute the hash code for.
+ /// The computed hash code.
public static byte[] RIPEMD160(this byte[] value)
{
using var ripemd160 = new RIPEMD160Managed();
return ripemd160.ComputeHash(value);
}
+ ///
+ /// Computes the hash value for the specified byte array using the ripemd160 algorithm.
+ ///
+ /// The input to compute the hash code for.
+ /// The computed hash code.
public static byte[] RIPEMD160(this ReadOnlySpan value)
{
byte[] source = value.ToArray();
return source.RIPEMD160();
}
+ ///
+ /// Computes the hash value for the specified byte array using the murmur algorithm.
+ ///
+ /// The input to compute the hash code for.
+ /// The seed used by the murmur algorithm.
+ /// The computed hash code.
public static uint Murmur32(this byte[] value, uint seed)
{
- using (Murmur3 murmur = new Murmur3(seed))
- {
- return BinaryPrimitives.ReadUInt32LittleEndian(murmur.ComputeHash(value));
- }
+ using Murmur3 murmur = new(seed);
+ return BinaryPrimitives.ReadUInt32LittleEndian(murmur.ComputeHash(value));
}
+ ///
+ /// Computes the hash value for the specified byte array using the sha256 algorithm.
+ ///
+ /// The input to compute the hash code for.
+ /// The computed hash code.
public static byte[] Sha256(this byte[] value)
{
using var sha256 = SHA256.Create();
return sha256.ComputeHash(value);
}
+ ///
+ /// Computes the hash value for the specified region of the specified byte array using the sha256 algorithm.
+ ///
+ /// The input to compute the hash code for.
+ /// The offset into the byte array from which to begin using data.
+ /// The number of bytes in the array to use as data.
+ /// The computed hash code.
public static byte[] Sha256(this byte[] value, int offset, int count)
{
using var sha256 = SHA256.Create();
return sha256.ComputeHash(value, offset, count);
}
+ ///
+ /// Computes the hash value for the specified byte array using the sha256 algorithm.
+ ///
+ /// The input to compute the hash code for.
+ /// The computed hash code.
public static byte[] Sha256(this ReadOnlySpan value)
{
byte[] buffer = new byte[32];
@@ -109,6 +87,11 @@ public static byte[] Sha256(this ReadOnlySpan value)
return buffer;
}
+ ///
+ /// Computes the hash value for the specified byte array using the sha256 algorithm.
+ ///
+ /// The input to compute the hash code for.
+ /// The computed hash code.
public static byte[] Sha256(this Span value)
{
return Sha256((ReadOnlySpan)value);
@@ -124,28 +107,24 @@ internal static bool Test(this BloomFilter filter, Transaction tx)
internal static byte[] ToAesKey(this string password)
{
- using (SHA256 sha256 = SHA256.Create())
- {
- byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
- byte[] passwordHash = sha256.ComputeHash(passwordBytes);
- byte[] passwordHash2 = sha256.ComputeHash(passwordHash);
- Array.Clear(passwordBytes, 0, passwordBytes.Length);
- Array.Clear(passwordHash, 0, passwordHash.Length);
- return passwordHash2;
- }
+ using SHA256 sha256 = SHA256.Create();
+ byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
+ byte[] passwordHash = sha256.ComputeHash(passwordBytes);
+ byte[] passwordHash2 = sha256.ComputeHash(passwordHash);
+ Array.Clear(passwordBytes, 0, passwordBytes.Length);
+ Array.Clear(passwordHash, 0, passwordHash.Length);
+ return passwordHash2;
}
internal static byte[] ToAesKey(this SecureString password)
{
- using (SHA256 sha256 = SHA256.Create())
- {
- byte[] passwordBytes = password.ToArray();
- byte[] passwordHash = sha256.ComputeHash(passwordBytes);
- byte[] passwordHash2 = sha256.ComputeHash(passwordHash);
- Array.Clear(passwordBytes, 0, passwordBytes.Length);
- Array.Clear(passwordHash, 0, passwordHash.Length);
- return passwordHash2;
- }
+ using SHA256 sha256 = SHA256.Create();
+ byte[] passwordBytes = password.ToArray();
+ byte[] passwordHash = sha256.ComputeHash(passwordBytes);
+ byte[] passwordHash2 = sha256.ComputeHash(passwordHash);
+ Array.Clear(passwordBytes, 0, passwordBytes.Length);
+ Array.Clear(passwordHash, 0, passwordHash.Length);
+ return passwordHash2;
}
internal static byte[] ToArray(this SecureString s)
@@ -154,7 +133,7 @@ internal static byte[] ToArray(this SecureString s)
throw new NullReferenceException();
if (s.Length == 0)
return Array.Empty();
- List result = new List();
+ List result = new();
IntPtr ptr = SecureStringMarshal.SecureStringToGlobalAllocAnsi(s);
try
{
diff --git a/src/neo/Cryptography/MerkleTree.cs b/src/neo/Cryptography/MerkleTree.cs
index 870eaabbb9..d7d1ff8145 100644
--- a/src/neo/Cryptography/MerkleTree.cs
+++ b/src/neo/Cryptography/MerkleTree.cs
@@ -7,16 +7,22 @@
namespace Neo.Cryptography
{
+ ///
+ /// Represents a merkle tree.
+ ///
public class MerkleTree
{
private readonly MerkleTreeNode root;
- public int Depth { get; private set; }
+ ///
+ /// The depth of the tree.
+ ///
+ public int Depth { get; }
internal MerkleTree(UInt256[] hashes)
{
- if (hashes is null || hashes.Length == 0) throw new ArgumentException();
this.root = Build(hashes.Select(p => new MerkleTreeNode { Hash = p }).ToArray());
+ if (root is null) return;
int depth = 1;
for (MerkleTreeNode i = root; i.LeftChild != null; i = i.LeftChild)
depth++;
@@ -25,15 +31,17 @@ internal MerkleTree(UInt256[] hashes)
private static MerkleTreeNode Build(MerkleTreeNode[] leaves)
{
- if (leaves.Length == 0) throw new ArgumentException();
+ if (leaves.Length == 0) return null;
if (leaves.Length == 1) return leaves[0];
Span buffer = stackalloc byte[64];
MerkleTreeNode[] parents = new MerkleTreeNode[(leaves.Length + 1) / 2];
for (int i = 0; i < parents.Length; i++)
{
- parents[i] = new MerkleTreeNode();
- parents[i].LeftChild = leaves[i * 2];
+ parents[i] = new MerkleTreeNode
+ {
+ LeftChild = leaves[i * 2]
+ };
leaves[i * 2].Parent = parents[i];
if (i * 2 + 1 == leaves.Length)
{
@@ -58,11 +66,16 @@ private static UInt256 Concat(Span buffer, UInt256 hash1, UInt256 hash2)
return new UInt256(Crypto.Hash256(buffer));
}
+ ///
+ /// Computes the root of the hash tree.
+ ///
+ /// The leaves of the hash tree.
+ /// The root of the hash tree.
public static UInt256 ComputeRoot(UInt256[] hashes)
{
- if (hashes.Length == 0) throw new ArgumentException();
+ if (hashes.Length == 0) return UInt256.Zero;
if (hashes.Length == 1) return hashes[0];
- MerkleTree tree = new MerkleTree(hashes);
+ MerkleTree tree = new(hashes);
return tree.root.Hash;
}
@@ -80,18 +93,29 @@ private static void DepthFirstSearch(MerkleTreeNode node, IList hashes)
}
}
- // depth-first order
+ ///
+ /// Gets all nodes of the hash tree in depth-first order.
+ ///
+ /// All nodes of the hash tree.
public UInt256[] ToHashArray()
{
- List hashes = new List();
+ if (root is null) return Array.Empty();
+ List hashes = new();
DepthFirstSearch(root, hashes);
return hashes.ToArray();
}
+ ///
+ /// Trims the hash tree using the specified bit array.
+ ///
+ /// The bit array to be used.
public void Trim(BitArray flags)
{
- flags = new BitArray(flags);
- flags.Length = 1 << (Depth - 1);
+ if (root is null) return;
+ flags = new BitArray(flags)
+ {
+ Length = 1 << (Depth - 1)
+ };
Trim(root, 0, Depth, flags);
}
diff --git a/src/neo/Cryptography/Murmur3.cs b/src/neo/Cryptography/Murmur3.cs
index 82642baf7f..08c1e6e6fd 100644
--- a/src/neo/Cryptography/Murmur3.cs
+++ b/src/neo/Cryptography/Murmur3.cs
@@ -5,6 +5,9 @@
namespace Neo.Cryptography
{
+ ///
+ /// Computes the murmur hash for the input data.
+ ///
public sealed class Murmur3 : HashAlgorithm
{
private const uint c1 = 0xcc9e2d51;
@@ -20,6 +23,10 @@ public sealed class Murmur3 : HashAlgorithm
public override int HashSize => 32;
+ ///
+ /// Initializes a new instance of the class with the specified seed.
+ ///
+ /// The seed to be used.
public Murmur3(uint seed)
{
this.seed = seed;
@@ -65,7 +72,10 @@ protected override byte[] HashFinal()
hash ^= hash >> 13;
hash *= 0xc2b2ae35;
hash ^= hash >> 16;
- return BitConverter.GetBytes(hash);
+
+ byte[] buffer = new byte[sizeof(uint)];
+ BinaryPrimitives.WriteUInt32LittleEndian(buffer, hash);
+ return buffer;
}
public override void Initialize()
diff --git a/src/neo/Cryptography/RIPEMD160Managed.cs b/src/neo/Cryptography/RIPEMD160Managed.cs
index 89a4de23c8..9c505ce104 100644
--- a/src/neo/Cryptography/RIPEMD160Managed.cs
+++ b/src/neo/Cryptography/RIPEMD160Managed.cs
@@ -5,20 +5,22 @@
namespace Neo.Cryptography
{
+ ///
+ /// Computes the ripemd160 hash for the input data.
+ ///
[ComVisible(true)]
public class RIPEMD160Managed : HashAlgorithm
{
- private byte[] _buffer;
+ private readonly byte[] _buffer;
private long _count; // Number of bytes in the hashed message
- private uint[] _stateMD160;
- private uint[] _blockDWords;
+ private readonly uint[] _stateMD160;
+ private readonly uint[] _blockDWords;
public override int HashSize => 160;
- //
- // public constructors
- //
-
+ ///
+ /// Initializes a new instance of the class.
+ ///
public RIPEMD160Managed()
{
_stateMD160 = new uint[5];
@@ -28,10 +30,6 @@ public RIPEMD160Managed()
InitializeState();
}
- //
- // public methods
- //
-
public override void Initialize()
{
InitializeState();
@@ -41,22 +39,18 @@ public override void Initialize()
Array.Clear(_buffer, 0, _buffer.Length);
}
- [System.Security.SecuritySafeCritical] // auto-generated
+ [SecuritySafeCritical]
protected override void HashCore(byte[] rgb, int ibStart, int cbSize)
{
- _HashData(rgb, ibStart, cbSize);
+ HashData(rgb, ibStart, cbSize);
}
- [System.Security.SecuritySafeCritical] // auto-generated
+ [SecuritySafeCritical]
protected override byte[] HashFinal()
{
- return _EndHash();
+ return EndHash();
}
- //
- // private methods
- //
-
private void InitializeState()
{
_count = 0;
@@ -70,8 +64,8 @@ private void InitializeState()
_stateMD160[4] = 0xc3d2e1f0;
}
- [System.Security.SecurityCritical] // auto-generated
- private unsafe void _HashData(byte[] partIn, int ibStart, int cbSize)
+ [SecurityCritical]
+ private unsafe void HashData(byte[] partIn, int ibStart, int cbSize)
{
int bufferLen;
int partInLen = cbSize;
@@ -116,8 +110,8 @@ private unsafe void _HashData(byte[] partIn, int ibStart, int cbSize)
}
}
- [SecurityCritical] // auto-generated
- private byte[] _EndHash()
+ [SecurityCritical]
+ private byte[] EndHash()
{
byte[] pad;
int padLen;
@@ -148,7 +142,7 @@ private byte[] _EndHash()
pad[padLen - 8] = (byte)((bitCount >> 0) & 0xff);
/* Digest padding */
- _HashData(pad, 0, pad.Length);
+ HashData(pad, 0, pad.Length);
/* Store digest */
DWORDToLittleEndian(hash, _stateMD160, 5);
@@ -156,7 +150,7 @@ private byte[] _EndHash()
return hash;
}
- [System.Security.SecurityCritical] // auto-generated
+ [SecurityCritical]
private static unsafe void MDTransform(uint* blockDWords, uint* state, byte* block)
{
uint aa = state[0];
@@ -999,7 +993,6 @@ As we don't have macros in C# and we don't want to pay the cost of a function ca
state[0] = ddd;
}
- // The five basic functions
private static uint F(uint x, uint y, uint z)
{
return (x ^ y ^ z);
@@ -1025,7 +1018,7 @@ private static uint J(uint x, uint y, uint z)
return (x ^ (y | ~z));
}
- [SecurityCritical] // auto-generated
+ [SecurityCritical]
private unsafe static void DWORDFromLittleEndian(uint* x, int digits, byte* block)
{
int i;
diff --git a/src/neo/Helper.cs b/src/neo/Helper.cs
index 69fd7ddba4..83560f5a06 100644
--- a/src/neo/Helper.cs
+++ b/src/neo/Helper.cs
@@ -7,14 +7,16 @@
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
-using System.Security.Cryptography;
using System.Text;
namespace Neo
{
+ ///
+ /// A helper class that provides common functions.
+ ///
public static class Helper
{
- private static readonly DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ private static readonly DateTime unixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int BitLen(int w)
@@ -34,6 +36,11 @@ private static int BitLen(int w)
: (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31)))));
}
+ ///
+ /// Concatenates the specified byte arrays.
+ ///
+ /// The byte arrays to concatenate.
+ /// The concatenated byte array.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] Concat(params byte[][] buffers)
{
@@ -50,6 +57,12 @@ public static byte[] Concat(params byte[][] buffers)
return dst;
}
+ ///
+ /// Concatenates two byte arrays.
+ ///
+ /// The first byte array to concatenate.
+ /// The second byte array to concatenate.
+ /// The concatenated byte array.
public static byte[] Concat(ReadOnlySpan a, ReadOnlySpan b)
{
byte[] buffer = new byte[a.Length + b.Length];
@@ -116,6 +129,11 @@ internal static string GetVersion(this Assembly assembly)
return (string)attribute.ConstructorArguments[0].Value;
}
+ ///
+ /// Converts a hex to byte array.
+ ///
+ /// The hex to convert.
+ /// The converted byte array.
public static byte[] HexToBytes(this string value)
{
if (value == null || value.Length == 0)
@@ -163,27 +181,17 @@ internal static BigInteger NextBigInteger(this Random rand, int sizeInBits)
Span b = stackalloc byte[sizeInBits / 8 + 1];
rand.NextBytes(b);
if (sizeInBits % 8 == 0)
- b[b.Length - 1] = 0;
+ b[^1] = 0;
else
- b[b.Length - 1] &= (byte)((1 << sizeInBits % 8) - 1);
- return new BigInteger(b);
- }
-
- internal static BigInteger NextBigInteger(this RandomNumberGenerator rng, int sizeInBits)
- {
- if (sizeInBits < 0)
- throw new ArgumentException("sizeInBits must be non-negative");
- if (sizeInBits == 0)
- return 0;
- Span b = stackalloc byte[sizeInBits / 8 + 1];
- rng.GetBytes(b);
- if (sizeInBits % 8 == 0)
- b[b.Length - 1] = 0;
- else
- b[b.Length - 1] &= (byte)((1 << sizeInBits % 8) - 1);
+ b[^1] &= (byte)((1 << sizeInBits % 8) - 1);
return new BigInteger(b);
}
+ ///
+ /// Finds the sum of the specified integers.
+ ///
+ /// The specified integers.
+ /// The sum of the integers.
public static BigInteger Sum(this IEnumerable source)
{
var sum = BigInteger.Zero;
@@ -197,6 +205,11 @@ internal static bool TestBit(this BigInteger i, int index)
return (i & (BigInteger.One << index)) > BigInteger.Zero;
}
+ ///
+ /// Converts a to byte array and eliminates all the leading zeros.
+ ///
+ /// The to convert.
+ /// The converted byte array.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] ToByteArrayStandard(this BigInteger i)
{
@@ -204,35 +217,61 @@ public static byte[] ToByteArrayStandard(this BigInteger i)
return i.ToByteArray();
}
+ ///
+ /// Converts a byte array to hex .
+ ///
+ /// The byte array to convert.
+ /// The converted hex .
public static string ToHexString(this byte[] value)
{
- StringBuilder sb = new StringBuilder();
+ StringBuilder sb = new();
foreach (byte b in value)
sb.AppendFormat("{0:x2}", b);
return sb.ToString();
}
+ ///
+ /// Converts a byte array to hex .
+ ///
+ /// The byte array to convert.
+ /// Indicates whether it should be converted in the reversed byte order.
+ /// The converted hex .
public static string ToHexString(this byte[] value, bool reverse = false)
{
- StringBuilder sb = new StringBuilder();
+ StringBuilder sb = new();
for (int i = 0; i < value.Length; i++)
sb.AppendFormat("{0:x2}", value[reverse ? value.Length - i - 1 : i]);
return sb.ToString();
}
+ ///
+ /// Converts a byte array to hex .
+ ///
+ /// The byte array to convert.
+ /// The converted hex .
public static string ToHexString(this ReadOnlySpan value)
{
- StringBuilder sb = new StringBuilder();
+ StringBuilder sb = new();
foreach (byte b in value)
sb.AppendFormat("{0:x2}", b);
return sb.ToString();
}
+ ///
+ /// Converts a to timestamp.
+ ///
+ /// The to convert.
+ /// The converted timestamp.
public static uint ToTimestamp(this DateTime time)
{
return (uint)(time.ToUniversalTime() - unixEpoch).TotalSeconds;
}
+ ///
+ /// Converts a to timestamp in milliseconds.
+ ///
+ /// The to convert.
+ /// The converted timestamp.
public static ulong ToTimestampMS(this DateTime time)
{
return (ulong)(time.ToUniversalTime() - unixEpoch).TotalMilliseconds;
diff --git a/src/neo/IO/Actors/PriorityMessageQueue.cs b/src/neo/IO/Actors/PriorityMessageQueue.cs
index b7820b065a..f07d85c8ab 100644
--- a/src/neo/IO/Actors/PriorityMessageQueue.cs
+++ b/src/neo/IO/Actors/PriorityMessageQueue.cs
@@ -11,8 +11,8 @@ namespace Neo.IO.Actors
{
internal class PriorityMessageQueue : IMessageQueue, IUnboundedMessageQueueSemantics
{
- private readonly ConcurrentQueue high = new ConcurrentQueue();
- private readonly ConcurrentQueue low = new ConcurrentQueue();
+ private readonly ConcurrentQueue high = new();
+ private readonly ConcurrentQueue low = new();
private readonly Func