Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Linq from ECDSA and UInt classes #1283

Merged
merged 11 commits into from
Nov 30, 2019
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/neo/Consensus/ConsensusService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion src/neo/Cryptography/Base58.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Numerics;
using System.Text;
using static Neo.Helper;

namespace Neo.Cryptography
{
Expand All @@ -27,7 +28,7 @@ public static byte[] Decode(string input)
var leadingZeros = new byte[leadingZeroCount];
if (bi.IsZero) return leadingZeros;
var bytesWithoutLeadingZeros = bi.ToByteArray(isUnsigned: true, isBigEndian: true);
return leadingZeros.Concat(bytesWithoutLeadingZeros).ToArray();
return Concat(leadingZeros, bytesWithoutLeadingZeros);
}

public static string Encode(byte[] input)
Expand Down
13 changes: 6 additions & 7 deletions src/neo/Cryptography/Crypto.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Security.Cryptography;

namespace Neo.Cryptography
Expand All @@ -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[..32],
Y = pubkey[32..]
}
}))
{
Expand All @@ -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)[1..];
}
catch
{
Expand All @@ -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[1..];
}
else if (pubkey.Length != 64)
{
Expand All @@ -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[..32],
Y = pubkey[32..]
}
}))
{
Expand Down
3 changes: 3 additions & 0 deletions src/neo/Cryptography/ECC/ECCurve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 4 additions & 5 deletions src/neo/Cryptography/ECC/ECFieldElement.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Numerics;

namespace Neo.Cryptography.ECC
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -145,7 +142,9 @@ public byte[] ToByteArray()
byte[] data = Value.ToByteArray(isUnsigned: true, isBigEndian: true);
if (data.Length == 32)
return data;
return Enumerable.Repeat<byte>(0, 32 - data.Length).Concat(data).ToArray();
byte[] buffer = new byte[32];
Buffer.BlockCopy(data, 0, buffer, buffer.Length - data.Length, data.Length);
return buffer;
}

public static ECFieldElement operator -(ECFieldElement x)
Expand Down
31 changes: 13 additions & 18 deletions src/neo/Cryptography/ECC/ECPoint.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Neo.IO;
using System;
using System.IO;
using System.Linq;
using System.Numerics;
using static Neo.Helper;

namespace Neo.Cryptography.ECC
{
Expand All @@ -18,10 +18,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)
{
Expand All @@ -43,13 +40,12 @@ public int CompareTo(ECPoint other)
public static ECPoint DecodePoint(byte[] encoded, ECCurve curve)
{
ECPoint p = null;
int expectedLength = (curve.Q.GetBitLength() + 7) / 8;
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.AsSpan(1), isUnsigned: true, isBigEndian: true);
Expand All @@ -58,10 +54,10 @@ public static ECPoint DecodePoint(byte[] encoded, ECCurve curve)
}
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.AsSpan(1, expectedLength), isUnsigned: true, isBigEndian: true);
BigInteger Y1 = new BigInteger(encoded.AsSpan(1 + expectedLength), isUnsigned: true, isBigEndian: true);
BigInteger X1 = new BigInteger(encoded.AsSpan(1, curve.ExpectedECPointLength), isUnsigned: true, isBigEndian: true);
BigInteger Y1 = new BigInteger(encoded.AsSpan(1 + curve.ExpectedECPointLength), isUnsigned: true, isBigEndian: true);
p = new ECPoint(new ECFieldElement(X1, curve), new ECFieldElement(Y1, curve), curve);
break;
}
Expand Down Expand Up @@ -105,23 +101,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[..(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();
}
Expand Down Expand Up @@ -175,10 +170,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(Concat(new byte[] { 0x04 }, pubkey[^64..]), curve);
case 96:
case 104:
return DecodePoint(new byte[] { 0x04 }.Concat(pubkey.Skip(pubkey.Length - 96).Take(64)).ToArray(), curve);
return DecodePoint(Concat(new byte[] { 0x04 }, pubkey[^96..^32]), curve);
default:
throw new FormatException();
}
Expand Down Expand Up @@ -241,7 +236,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)
Expand Down
4 changes: 2 additions & 2 deletions src/neo/Cryptography/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ public static byte[] Base58CheckDecode(this string input)
byte[] buffer = Base58.Decode(input);
if (buffer.Length < 4) throw new FormatException();
byte[] checksum = buffer.Sha256(0, buffer.Length - 4).Sha256();
if (!buffer.Skip(buffer.Length - 4).SequenceEqual(checksum.Take(4)))
if (!buffer.AsSpan(^4).SequenceEqual(checksum.AsSpan(..4)))
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
throw new FormatException();
var ret = buffer.Take(buffer.Length - 4).ToArray();
var ret = buffer[..^4];
Array.Clear(buffer, 0, buffer.Length);
return ret;
}
Expand Down
28 changes: 26 additions & 2 deletions src/neo/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public static class Helper
{
private static readonly DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int BitLen(int w)
{
return (w < 1 << 15 ? (w < 1 << 7
Expand All @@ -34,6 +35,20 @@ private static int BitLen(int w)
: (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31)))));
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] Concat(params byte[][] buffers)
{
var ret = new byte[buffers.Sum(p => p.Length)];
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
int i = 0;
foreach (byte[] buffer in buffers)
{
Buffer.BlockCopy(buffer, 0, ret, i, buffer.Length);
i += buffer.Length;
}
return ret;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int GetBitLength(this BigInteger i)
{
byte[] b = i.ToByteArray();
Expand Down Expand Up @@ -110,6 +125,7 @@ public static byte[] HexToBytes(this string value)
return result;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static BigInteger Mod(this BigInteger x, BigInteger y)
{
x %= y;
Expand Down Expand Up @@ -172,20 +188,28 @@ public static BigInteger Sum(this IEnumerable<BigInteger> source)
return sum;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TestBit(this BigInteger i, int index)
{
return (i & (BigInteger.One << index)) > BigInteger.Zero;
}


public static string ToHexString(this IEnumerable<byte> value)
public static string ToHexString(this byte[] value)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in value)
sb.AppendFormat("{0:x2}", b);
return sb.ToString();
}

public static string ToHexString(this byte[] value, bool reverse = false)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < value.Length; i++)
sb.AppendFormat("{0:x2}", value[reverse ? value.Length - i - 1 : i]);
return sb.ToString();
}

public static string ToHexString(this ReadOnlySpan<byte> value)
{
StringBuilder sb = new StringBuilder();
Expand Down
2 changes: 1 addition & 1 deletion src/neo/IO/Caching/DataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public void DeleteWhere(Func<TKey, TValue, bool> predicate)
lock (dictionary)
{
cached = dictionary
.Where(p => p.Value.State != TrackState.Deleted && (key_prefix == null || p.Key.ToArray().Take(key_prefix.Length).SequenceEqual(key_prefix)))
.Where(p => p.Value.State != TrackState.Deleted && (key_prefix == null || p.Key.ToArray().AsSpan().StartsWith(key_prefix)))
.Select(p =>
(
KeyBytes: p.Key.ToArray(),
Expand Down
3 changes: 1 addition & 2 deletions src/neo/IO/Data/LevelDB/Helper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Neo.IO.Data.LevelDB
{
Expand All @@ -26,7 +25,7 @@ public static IEnumerable<T> Find<T>(this DB db, ReadOptions options, Slice pref
byte[] x = key.ToArray();
byte[] y = prefix.ToArray();
if (x.Length < y.Length) break;
if (!x.Take(y.Length).SequenceEqual(y)) break;
if (!x.AsSpan().StartsWith(y)) break;
yield return resultSelector(key, it.Value());
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/neo/IO/Data/LevelDB/Slice.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Neo.Cryptography;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

Expand Down Expand Up @@ -29,7 +28,7 @@ public int CompareTo(Slice other)
public bool Equals(Slice other)
{
if (buffer.Length != other.buffer.Length) return false;
return buffer.SequenceEqual(other.buffer);
return MemoryExtensions.SequenceEqual<byte>(buffer, other.buffer);
}

public override bool Equals(object obj)
Expand Down
5 changes: 2 additions & 3 deletions src/neo/Ledger/StorageKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Neo.IO;
using System;
using System.IO;
using System.Linq;

namespace Neo.Ledger
{
Expand All @@ -28,7 +27,7 @@ internal static byte[] CreateSearchPrefix(UInt160 hash, byte[] prefix)
}
if (remain > 0)
ms.Write(prefix, index, remain);
return hash.ToArray().Concat(ms.ToArray()).ToArray();
return Helper.Concat(hash.ToArray(), ms.ToArray());
}
}

Expand All @@ -44,7 +43,7 @@ public bool Equals(StorageKey other)
return false;
if (ReferenceEquals(this, other))
return true;
return ScriptHash.Equals(other.ScriptHash) && Key.SequenceEqual(other.Key);
return ScriptHash.Equals(other.ScriptHash) && MemoryExtensions.SequenceEqual<byte>(Key, other.Key);
}

public override bool Equals(object obj)
Expand Down
3 changes: 1 addition & 2 deletions src/neo/Network/P2P/Payloads/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Neo.IO.Json;
using Neo.Ledger;
using Neo.SmartContract;
using Neo.VM;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -130,7 +129,7 @@ public TrimmedBlock Trim()
Index = Index,
NextConsensus = NextConsensus,
Witness = Witness,
Hashes = new[] { ConsensusData.Hash }.Concat(Transactions.Select(p => p.Hash)).ToArray(),
Hashes = Transactions.Select(p => p.Hash).Prepend(ConsensusData.Hash).ToArray(),
ConsensusData = ConsensusData
};
}
Expand Down
3 changes: 1 addition & 2 deletions src/neo/Network/P2P/Payloads/InvPayload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Neo.Network.P2P.Payloads
{
Expand Down Expand Up @@ -30,7 +29,7 @@ public static IEnumerable<InvPayload> CreateGroup(InventoryType type, UInt256[]
yield return new InvPayload
{
Type = type,
Hashes = hashes.Skip(i).Take(MaxHashesCount).ToArray()
Hashes = hashes[i..(i + MaxHashesCount)]
};
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
Loading