Skip to content

Commit

Permalink
Remove Linq from ECDSA and UInt classes (neo-project#1283)
Browse files Browse the repository at this point in the history
  • Loading branch information
shargon authored and Luchuan committed Jan 10, 2020
1 parent 104fc74 commit 12ec257
Show file tree
Hide file tree
Showing 30 changed files with 104 additions and 84 deletions.
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)))
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
31 changes: 29 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,23 @@ 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)
{
int length = 0;
for (int i = 0; i < buffers.Length; i++)
length += buffers[i].Length;
byte[] dst = new byte[length];
int p = 0;
foreach (byte[] src in buffers)
{
Buffer.BlockCopy(src, 0, dst, p, src.Length);
p += src.Length;
}
return dst;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int GetBitLength(this BigInteger i)
{
byte[] b = i.ToByteArray();
Expand Down Expand Up @@ -110,6 +128,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 +191,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)]
};
}

Expand Down
Loading

0 comments on commit 12ec257

Please sign in to comment.