diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs index 9d0bd5a343..77113eafe1 100644 --- a/neo/Consensus/ConsensusService.cs +++ b/neo/Consensus/ConsensusService.cs @@ -573,7 +573,7 @@ private void OnTimer(Timer timer) { var reason = ChangeViewReason.Timeout; - if (context.Block != null && context.TransactionHashes?.Count() > context.Transactions?.Count) + if (context.Block != null && context.TransactionHashes?.Length > context.Transactions?.Count) { reason = ChangeViewReason.TxNotFound; } diff --git a/neo/Cryptography/Base58.cs b/neo/Cryptography/Base58.cs index 9ddbea3dc8..82d2bc0458 100644 --- a/neo/Cryptography/Base58.cs +++ b/neo/Cryptography/Base58.cs @@ -28,13 +28,13 @@ public static byte[] Decode(string input) var bytesWithoutLeadingZeros = bi.ToByteArray() .Reverse()// to big endian .SkipWhile(b => b == 0);//strip sign byte - return leadingZeros.Concat(bytesWithoutLeadingZeros).ToArray(); + return leadingZeros.Concat(bytesWithoutLeadingZeros.ToArray()); } public static string Encode(byte[] input) { // Decode byte[] to BigInteger - BigInteger value = new BigInteger(new byte[1].Concat(input).Reverse().ToArray()); + BigInteger value = new BigInteger(new byte[1].Concat(input).Reverse()); // Encode BigInteger to Base58 string var sb = new StringBuilder(); diff --git a/neo/Cryptography/Crypto.cs b/neo/Cryptography/Crypto.cs index c835e3eebb..6ef43dcb5c 100644 --- a/neo/Cryptography/Crypto.cs +++ b/neo/Cryptography/Crypto.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Security.Cryptography; namespace Neo.Cryptography @@ -26,8 +25,8 @@ public byte[] Sign(byte[] message, byte[] prikey, byte[] pubkey) D = prikey, Q = new ECPoint { - X = pubkey.Take(32).ToArray(), - Y = pubkey.Skip(32).ToArray() + X = pubkey.Take(32), + Y = pubkey.Skip(32) } })) { @@ -41,7 +40,7 @@ public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey) { try { - pubkey = Cryptography.ECC.ECPoint.DecodePoint(pubkey, Cryptography.ECC.ECCurve.Secp256r1).EncodePoint(false).Skip(1).ToArray(); + pubkey = ECC.ECPoint.DecodePoint(pubkey, ECC.ECCurve.Secp256r1).EncodePoint(false).Skip(1); } catch { @@ -50,7 +49,7 @@ public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey) } else if (pubkey.Length == 65 && pubkey[0] == 0x04) { - pubkey = pubkey.Skip(1).ToArray(); + pubkey = pubkey.Skip(1); } else if (pubkey.Length != 64) { @@ -61,8 +60,8 @@ public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey) Curve = ECCurve.NamedCurves.nistP256, Q = new ECPoint { - X = pubkey.Take(32).ToArray(), - Y = pubkey.Skip(32).ToArray() + X = pubkey.Take(32), + Y = pubkey.Skip(32) } })) { diff --git a/neo/Cryptography/ECC/ECCurve.cs b/neo/Cryptography/ECC/ECCurve.cs index 45d70d31f4..9a8d276744 100644 --- a/neo/Cryptography/ECC/ECCurve.cs +++ b/neo/Cryptography/ECC/ECCurve.cs @@ -12,9 +12,12 @@ public class ECCurve public readonly ECPoint Infinity; public readonly ECPoint G; + public readonly int ExpectedECPointLength; + private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G) { this.Q = Q; + this.ExpectedECPointLength = (Q.GetBitLength() + 7) / 8; this.A = new ECFieldElement(A, this); this.B = new ECFieldElement(B, this); this.N = N; @@ -22,6 +25,18 @@ private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G this.G = ECPoint.DecodePoint(G, this); } + public override bool Equals(object obj) + { + if (!(obj is ECCurve curve)) return false; + + return Q.Equals(curve.Q) + && A.Value.Equals(curve.A.Value) + && B.Value.Equals(curve.B.Value) + && N.Equals(curve.N) + && G.X.Value.Equals(curve.G.X.Value) + && G.Y.Value.Equals(curve.G.Y.Value); + } + public static readonly ECCurve Secp256k1 = new ECCurve ( BigInteger.Parse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", NumberStyles.AllowHexSpecifier), diff --git a/neo/Cryptography/ECC/ECDsa.cs b/neo/Cryptography/ECC/ECDsa.cs index 07373a7844..0161dd2339 100644 --- a/neo/Cryptography/ECC/ECDsa.cs +++ b/neo/Cryptography/ECC/ECDsa.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Numerics; using System.Security.Cryptography; @@ -26,7 +25,7 @@ public ECDsa(ECPoint publicKey) private BigInteger CalculateE(BigInteger n, byte[] message) { int messageBitLength = message.Length * 8; - BigInteger trunc = new BigInteger(message.Reverse().Concat(new byte[1]).ToArray()); + BigInteger trunc = new BigInteger(message.Reverse().Concat(new byte[1])); if (n.GetBitLength() < messageBitLength) { trunc >>= messageBitLength - n.GetBitLength(); @@ -38,7 +37,7 @@ public BigInteger[] GenerateSignature(byte[] message) { if (privateKey == null) throw new InvalidOperationException(); BigInteger e = CalculateE(curve.N, message); - BigInteger d = new BigInteger(privateKey.Reverse().Concat(new byte[1]).ToArray()); + BigInteger d = new BigInteger(privateKey.Reverse().Concat(new byte[1])); BigInteger r, s; using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) { diff --git a/neo/Cryptography/ECC/ECFieldElement.cs b/neo/Cryptography/ECC/ECFieldElement.cs index 331e1e4408..0680e76900 100644 --- a/neo/Cryptography/ECC/ECFieldElement.cs +++ b/neo/Cryptography/ECC/ECFieldElement.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Numerics; namespace Neo.Cryptography.ECC @@ -28,9 +27,7 @@ public override bool Equals(object obj) if (obj == this) return true; - ECFieldElement other = obj as ECFieldElement; - - if (other == null) + if (!(obj is ECFieldElement other)) return false; return Equals(other); @@ -38,7 +35,7 @@ public override bool Equals(object obj) public bool Equals(ECFieldElement other) { - return Value.Equals(other.Value); + return Value.Equals(other.Value) && curve.Equals(other.curve); } private static BigInteger[] FastLucasSequence(BigInteger p, BigInteger P, BigInteger Q, BigInteger k) @@ -144,10 +141,11 @@ public byte[] ToByteArray() { byte[] data = Value.ToByteArray(); if (data.Length == 32) - return data.Reverse().ToArray(); + return data.Reverse(); if (data.Length > 32) - return data.Take(32).Reverse().ToArray(); - return Enumerable.Repeat(0, 32 - data.Length).Concat(data.Reverse()).ToArray(); + return data.Take(32).Reverse(); + + return new byte[32 - data.Length].Concat(data.Reverse()); } public static ECFieldElement operator -(ECFieldElement x) diff --git a/neo/Cryptography/ECC/ECPoint.cs b/neo/Cryptography/ECC/ECPoint.cs index 803aab9987..d9dc0dc582 100644 --- a/neo/Cryptography/ECC/ECPoint.cs +++ b/neo/Cryptography/ECC/ECPoint.cs @@ -1,7 +1,6 @@ using Neo.IO; using System; using System.IO; -using System.Linq; using System.Numerics; namespace Neo.Cryptography.ECC @@ -18,10 +17,7 @@ public bool IsInfinity public int Size => IsInfinity ? 1 : 33; - public ECPoint() - : this(null, null, ECCurve.Secp256r1) - { - } + public ECPoint() : this(null, null, ECCurve.Secp256r1) { } internal ECPoint(ECFieldElement x, ECFieldElement y, ECCurve curve) { @@ -42,26 +38,25 @@ public int CompareTo(ECPoint other) public static ECPoint DecodePoint(byte[] encoded, ECCurve curve) { - ECPoint p = null; - int expectedLength = (curve.Q.GetBitLength() + 7) / 8; + ECPoint p; switch (encoded[0]) { case 0x02: // compressed case 0x03: // compressed { - if (encoded.Length != (expectedLength + 1)) + if (encoded.Length != (curve.ExpectedECPointLength + 1)) throw new FormatException("Incorrect length for compressed encoding"); int yTilde = encoded[0] & 1; - BigInteger X1 = new BigInteger(encoded.Skip(1).Reverse().Concat(new byte[1]).ToArray()); + BigInteger X1 = ToUnsignedBigInteger(encoded.Skip(1)); p = DecompressPoint(yTilde, X1, curve); break; } case 0x04: // uncompressed { - if (encoded.Length != (2 * expectedLength + 1)) + if (encoded.Length != (2 * curve.ExpectedECPointLength + 1)) throw new FormatException("Incorrect length for uncompressed/hybrid encoding"); - BigInteger X1 = new BigInteger(encoded.Skip(1).Take(expectedLength).Reverse().Concat(new byte[1]).ToArray()); - BigInteger Y1 = new BigInteger(encoded.Skip(1 + expectedLength).Reverse().Concat(new byte[1]).ToArray()); + BigInteger X1 = ToUnsignedBigInteger(encoded.Take(1, curve.ExpectedECPointLength)); + BigInteger Y1 = ToUnsignedBigInteger(encoded.Skip(1 + curve.ExpectedECPointLength)); p = new ECPoint(new ECFieldElement(X1, curve), new ECFieldElement(Y1, curve), curve); break; } @@ -105,23 +100,22 @@ void ISerializable.Deserialize(BinaryReader reader) public static ECPoint DeserializeFrom(BinaryReader reader, ECCurve curve) { - int expectedLength = (curve.Q.GetBitLength() + 7) / 8; - byte[] buffer = new byte[1 + expectedLength * 2]; + byte[] buffer = new byte[1 + curve.ExpectedECPointLength * 2]; buffer[0] = reader.ReadByte(); switch (buffer[0]) { case 0x02: case 0x03: { - if (reader.Read(buffer, 1, expectedLength) != expectedLength) + if (reader.Read(buffer, 1, curve.ExpectedECPointLength) != curve.ExpectedECPointLength) { throw new FormatException(); } - return DecodePoint(buffer.Take(1 + expectedLength).ToArray(), curve); + return DecodePoint(buffer.Take(1 + curve.ExpectedECPointLength), curve); } case 0x04: { - if (reader.Read(buffer, 1, expectedLength * 2) != expectedLength * 2) + if (reader.Read(buffer, 1, curve.ExpectedECPointLength * 2) != curve.ExpectedECPointLength * 2) { throw new FormatException(); } @@ -132,6 +126,16 @@ public static ECPoint DeserializeFrom(BinaryReader reader, ECCurve curve) } } + private static BigInteger ToUnsignedBigInteger(byte[] data) + { + byte[] ret = new byte[data.Length + 1]; // .Concat(new byte[1]) + for (int x = 0, m = ret.Length - 2; x <= m; x++) + { + ret[x] = data[m - x]; + } + return new BigInteger(ret); + } + public byte[] EncodePoint(bool commpressed) { if (IsInfinity) return new byte[1]; @@ -143,10 +147,10 @@ public byte[] EncodePoint(bool commpressed) else { data = new byte[65]; - byte[] yBytes = Y.Value.ToByteArray().Reverse().ToArray(); + byte[] yBytes = Y.Value.ToByteArray().Reverse(); Buffer.BlockCopy(yBytes, 0, data, 65 - yBytes.Length, yBytes.Length); } - byte[] xBytes = X.Value.ToByteArray().Reverse().ToArray(); + byte[] xBytes = X.Value.ToByteArray().Reverse(); Buffer.BlockCopy(xBytes, 0, data, 33 - xBytes.Length, xBytes.Length); data[0] = commpressed ? Y.Value.IsEven ? (byte)0x02 : (byte)0x03 : (byte)0x04; return data; @@ -158,7 +162,7 @@ public bool Equals(ECPoint other) if (ReferenceEquals(null, other)) return false; if (IsInfinity && other.IsInfinity) return true; if (IsInfinity || other.IsInfinity) return false; - return X.Equals(other.X) && Y.Equals(other.Y); + return X.Equals(other.X) && Y.Equals(other.Y) && Curve.Equals(other.Curve); } public override bool Equals(object obj) @@ -175,10 +179,10 @@ public static ECPoint FromBytes(byte[] pubkey, ECCurve curve) return DecodePoint(pubkey, curve); case 64: case 72: - return DecodePoint(new byte[] { 0x04 }.Concat(pubkey.Skip(pubkey.Length - 64)).ToArray(), curve); + return DecodePoint(new byte[] { 0x04 }.Concat(pubkey.Skip(pubkey.Length - 64)), curve); case 96: case 104: - return DecodePoint(new byte[] { 0x04 }.Concat(pubkey.Skip(pubkey.Length - 96).Take(64)).ToArray(), curve); + return DecodePoint(new byte[] { 0x04 }.Concat(pubkey.Take(pubkey.Length - 96, 64)), curve); default: throw new FormatException(); } @@ -241,7 +245,7 @@ internal static ECPoint Multiply(ECPoint p, BigInteger k) // The length of the precomputation array int preCompLen = 1; - ECPoint[] preComp = preComp = new ECPoint[] { p }; + ECPoint[] preComp = new ECPoint[] { p }; ECPoint twiceP = p.Twice(); if (preCompLen < reqPreCompLen) @@ -379,7 +383,7 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k) throw new ArgumentException(); if (p.IsInfinity) return p; - BigInteger k = new BigInteger(n.Reverse().Concat(new byte[1]).ToArray()); + BigInteger k = ToUnsignedBigInteger(n); if (k.Sign == 0) return p.Curve.Infinity; return Multiply(p, k); diff --git a/neo/Cryptography/Helper.cs b/neo/Cryptography/Helper.cs index 07c9ce74e9..4692f6ad39 100644 --- a/neo/Cryptography/Helper.cs +++ b/neo/Cryptography/Helper.cs @@ -79,7 +79,7 @@ public static byte[] Base58CheckDecode(this string input) byte[] checksum = buffer.Sha256(0, buffer.Length - 4).Sha256(); if (!buffer.Skip(buffer.Length - 4).SequenceEqual(checksum.Take(4))) throw new FormatException(); - var ret = buffer.Take(buffer.Length - 4).ToArray(); + var ret = buffer.Take(buffer.Length - 4); Array.Clear(buffer, 0, buffer.Length); return ret; } diff --git a/neo/Helper.cs b/neo/Helper.cs index 8fa7005f5e..757a72bf28 100644 --- a/neo/Helper.cs +++ b/neo/Helper.cs @@ -34,6 +34,46 @@ private static int BitLen(int w) : (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31))))); } + public static T[] Reverse(this T[] origin) + { + var ret = new T[origin.Length]; + for (int x = 0, m = ret.Length - 1; x <= m; x++) + { + ret[x] = origin[m - x]; + } + return ret; + } + + public static byte[] Skip(this byte[] a, int index) + { + var length = a.Length - index; + + if (length < 0) throw new ArgumentException(nameof(a)); + + var ret = new byte[length]; + Buffer.BlockCopy(a, index, ret, 0, length); + return ret; + } + + public static byte[] Take(this byte[] a, int count) => Take(a, 0, count); + + public static byte[] Take(this byte[] a, int index, int count) + { + if (count < 0) throw new ArgumentException(nameof(count)); + + var ret = new byte[count]; + Buffer.BlockCopy(a, index, ret, 0, count); + return ret; + } + + public static byte[] Concat(this byte[] a, byte[] b) + { + var ret = new byte[a.Length + b.Length]; + Buffer.BlockCopy(a, 0, ret, 0, a.Length); + Buffer.BlockCopy(b, 0, ret, a.Length, b.Length); + return ret; + } + internal static int GetBitLength(this BigInteger i) { byte[] b = i.ToByteArray(); diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index 0665567fc8..e64b3df101 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -90,8 +90,7 @@ protected void ConnectToPeer(IPEndPoint endPoint, bool isTrusted = false) private static bool IsIntranetAddress(IPAddress address) { - byte[] data = address.MapToIPv4().GetAddressBytes(); - Array.Reverse(data); + byte[] data = address.MapToIPv4().GetAddressBytes().Reverse(); uint value = data.ToUInt32(0); return (value & 0xff000000) == 0x0a000000 || (value & 0xff000000) == 0x7f000000 || (value & 0xfff00000) == 0xac100000 || (value & 0xffff0000) == 0xc0a80000 || (value & 0xffff0000) == 0xa9fe0000; } diff --git a/neo/UInt160.cs b/neo/UInt160.cs index 0052d45569..00aa7b7527 100644 --- a/neo/UInt160.cs +++ b/neo/UInt160.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using System.Linq; namespace Neo { @@ -82,7 +81,7 @@ public unsafe bool Equals(UInt160 other) value = value.Substring(2); if (value.Length != Length * 2) throw new FormatException(); - return new UInt160(value.HexToBytes().Reverse().ToArray()); + return new UInt160(value.HexToBytes().Reverse()); } /// @@ -110,7 +109,7 @@ public static bool TryParse(string s, out UInt160 result) result = null; return false; } - result = new UInt160(data.Reverse().ToArray()); + result = new UInt160(data.Reverse()); return true; } diff --git a/neo/UInt256.cs b/neo/UInt256.cs index 72719f0e90..48e6a5d602 100644 --- a/neo/UInt256.cs +++ b/neo/UInt256.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using System.Linq; namespace Neo { @@ -83,7 +82,7 @@ public unsafe bool Equals(UInt256 other) s = s.Substring(2); if (s.Length != Length * 2) throw new FormatException(); - return new UInt256(s.HexToBytes().Reverse().ToArray()); + return new UInt256(s.HexToBytes().Reverse()); } /// @@ -111,7 +110,7 @@ public static bool TryParse(string s, out UInt256 result) result = null; return false; } - result = new UInt256(data.Reverse().ToArray()); + result = new UInt256(data.Reverse()); return true; }