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 1 commit
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
12 changes: 6 additions & 6 deletions src/neo/Cryptography/Crypto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public byte[] Sign(byte[] message, byte[] prikey, byte[] pubkey)
D = prikey,
Q = new ECPoint
{
X = pubkey.Take(32),
Y = pubkey.Skip(32)
X = pubkey[..32],
Y = pubkey[32..]
}
}))
{
Expand All @@ -40,7 +40,7 @@ public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey)
{
try
{
pubkey = ECC.ECPoint.DecodePoint(pubkey, ECC.ECCurve.Secp256r1).EncodePoint(false).Skip(1);
pubkey = ECC.ECPoint.DecodePoint(pubkey, ECC.ECCurve.Secp256r1).EncodePoint(false)[1..];
}
catch
{
Expand All @@ -49,7 +49,7 @@ public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey)
}
else if (pubkey.Length == 65 && pubkey[0] == 0x04)
{
pubkey = pubkey.Skip(1);
pubkey = pubkey[1..];
}
else if (pubkey.Length != 64)
{
Expand All @@ -60,8 +60,8 @@ public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey)
Curve = ECCurve.NamedCurves.nistP256,
Q = new ECPoint
{
X = pubkey.Take(32),
Y = pubkey.Skip(32)
X = pubkey[..32],
Y = pubkey[32..]
}
}))
{
Expand Down
6 changes: 3 additions & 3 deletions src/neo/Cryptography/ECC/ECPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public static ECPoint DeserializeFrom(BinaryReader reader, ECCurve curve)
{
throw new FormatException();
}
return DecodePoint(buffer.Take(1 + curve.ExpectedECPointLength), curve);
return DecodePoint(buffer[..(1 + curve.ExpectedECPointLength)], curve);
}
case 0x04:
{
Expand Down Expand Up @@ -169,10 +169,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)), curve);
return DecodePoint(new byte[] { 0x04 }.Concat(pubkey[^64..]), curve);
case 96:
case 104:
return DecodePoint(new byte[] { 0x04 }.Concat(pubkey.Take(pubkey.Length - 96, 64)), curve);
return DecodePoint(new byte[] { 0x04 }.Concat(pubkey[^96..^32]), curve);
default:
throw new FormatException();
}
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 (!Neo.Helper.MemoryEquals(buffer.Skip(buffer.Length - 4), 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);
var ret = buffer[..^4];
Array.Clear(buffer, 0, buffer.Length);
return ret;
}
Expand Down
96 changes: 18 additions & 78 deletions src/neo/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,82 +17,6 @@ public static class Helper
{
private static readonly DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

#region Avoid Linq

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static bool MemoryEquals(ReadOnlySpan<byte> x, ReadOnlySpan<byte> y)
{
if (x == y) return true;
int len = x.Length;
if (len != y.Length) return false;
if (len == 0) return true;
fixed (byte* xp = x, yp = y)
{
long* xlp = (long*)xp, ylp = (long*)yp;
for (; len >= 8; len -= 8)
{
if (*xlp != *ylp) return false;
xlp++;
ylp++;
}
byte* xbp = (byte*)xlp, ybp = (byte*)ylp;
for (; len > 0; len--)
{
if (*xbp != *ybp) return false;
xbp++;
ybp++;
}
}
return true;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T[] Reverse<T>(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;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
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;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] Take(this byte[] a, int count) => Take(a, 0, count);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
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;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
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;
}

#endregion

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int BitLen(int w)
{
Expand All @@ -111,6 +35,15 @@ 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(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;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int GetBitLength(this BigInteger i)
{
Expand Down Expand Up @@ -257,15 +190,22 @@ 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 IEnumerable<KeyValuePair<TKey, TValue>> Find(byte[] key_prefix = null)
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: 2 additions & 1 deletion src/neo/Network/P2P/Peer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ protected void ConnectToPeer(IPEndPoint endPoint, bool isTrusted = false)

private static bool IsIntranetAddress(IPAddress address)
{
byte[] data = address.MapToIPv4().GetAddressBytes().Reverse();
byte[] data = address.MapToIPv4().GetAddressBytes();
Array.Reverse(data);
uint value = data.ToUInt32(0);
return (value & 0xff000000) == 0x0a000000 || (value & 0xff000000) == 0x7f000000 || (value & 0xfff00000) == 0xac100000 || (value & 0xffff0000) == 0xc0a80000 || (value & 0xffff0000) == 0xa9fe0000;
}
Expand Down
6 changes: 3 additions & 3 deletions src/neo/SmartContract/ContractParametersContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature)
}
while (contract.Script[i++] == 33)
{
points.Add(ECPoint.DecodePoint(contract.Script.Skip(i).Take(33).ToArray(), ECCurve.Secp256r1));
points.Add(ECPoint.DecodePoint(contract.Script[i..^(i + 33)], ECCurve.Secp256r1));
i += 33;
}
}
Expand Down Expand Up @@ -256,9 +256,9 @@ public Witness[] GetWitnesses()
ContextItem item = ContextItems[ScriptHashes[i]];
using (ScriptBuilder sb = new ScriptBuilder())
{
foreach (ContractParameter parameter in item.Parameters.Reverse())
for (int j = item.Parameters.Length - 1; j >= 0; j--)
{
sb.EmitPush(parameter);
sb.EmitPush(item.Parameters[j]);
}
witnesses[i] = new Witness
{
Expand Down
2 changes: 1 addition & 1 deletion src/neo/SmartContract/InteropService.NEO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ private static bool Storage_Find(ApplicationEngine engine)
if (!CheckStorageContext(engine, context)) return false;
byte[] prefix = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray();
byte[] prefix_key = StorageKey.CreateSearchPrefix(context.ScriptHash, prefix);
StorageIterator iterator = engine.AddDisposable(new StorageIterator(engine.Snapshot.Storages.Find(prefix_key).Where(p => p.Key.Key.Take(prefix.Length).SequenceEqual(prefix)).GetEnumerator()));
StorageIterator iterator = engine.AddDisposable(new StorageIterator(engine.Snapshot.Storages.Find(prefix_key).Where(p => p.Key.Key.AsSpan().StartsWith(prefix)).GetEnumerator()));
engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(iterator));
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/neo/SmartContract/Native/Tokens/NeoToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private StackItem GetRegisteredValidators(ApplicationEngine engine, VMArray args
byte[] prefix_key = StorageKey.CreateSearchPrefix(Hash, new[] { Prefix_Validator });
return snapshot.Storages.Find(prefix_key).Select(p =>
(
p.Key.Key.Skip(1).ToArray().AsSerializable<ECPoint>(),
p.Key.Key.AsSerializable<ECPoint>(1),
ValidatorState.FromByteArray(p.Value.Value).Votes
));
}
Expand Down
7 changes: 5 additions & 2 deletions src/neo/UInt160.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ public unsafe bool Equals(UInt160 other)
value = value.Substring(2);
if (value.Length != Length * 2)
throw new FormatException();
return new UInt160(value.HexToBytes().Reverse());
byte[] data = value.HexToBytes();
Array.Reverse(data);
return new UInt160(data);
}

/// <summary>
Expand Down Expand Up @@ -109,7 +111,8 @@ public static bool TryParse(string s, out UInt160 result)
result = null;
return false;
}
result = new UInt160(data.Reverse());
Array.Reverse(data);
result = new UInt160(data);
return true;
}

Expand Down
7 changes: 5 additions & 2 deletions src/neo/UInt256.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ public unsafe bool Equals(UInt256 other)
s = s.Substring(2);
if (s.Length != Length * 2)
throw new FormatException();
return new UInt256(s.HexToBytes().Reverse());
byte[] data = s.HexToBytes();
Array.Reverse(data);
return new UInt256(data);
}

/// <summary>
Expand Down Expand Up @@ -110,7 +112,8 @@ public static bool TryParse(string s, out UInt256 result)
result = null;
return false;
}
result = new UInt256(data.Reverse());
Array.Reverse(data);
result = new UInt256(data);
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions src/neo/UIntBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public bool Equals(UIntBase other)
return true;
if (data_bytes.Length != other.data_bytes.Length)
return false;
return Helper.MemoryEquals(data_bytes, other.data_bytes);
return MemoryExtensions.SequenceEqual<byte>(data_bytes, other.data_bytes);
}

/// <summary>
Expand Down Expand Up @@ -122,7 +122,7 @@ public byte[] ToArray()
/// </summary>
public override string ToString()
{
return "0x" + data_bytes.Reverse().ToHexString();
return "0x" + data_bytes.ToHexString(reverse: true);
}

/// <summary>
Expand Down
5 changes: 2 additions & 3 deletions src/neo/Wallets/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
using Neo.Network.P2P;
using Neo.Network.P2P.Payloads;
using System;
using System.Linq;

namespace Neo.Wallets
{
public static class Helper
{
public static byte[] Sign(this IVerifiable verifiable, KeyPair key)
{
return Crypto.Default.Sign(verifiable.GetHashData(), key.PrivateKey, key.PublicKey.EncodePoint(false).Skip(1).ToArray());
return Crypto.Default.Sign(verifiable.GetHashData(), key.PrivateKey, key.PublicKey.EncodePoint(false)[1..]);
}

public static string ToAddress(this UInt160 scriptHash)
Expand All @@ -28,7 +27,7 @@ public static UInt160 ToScriptHash(this string address)
throw new FormatException();
if (data[0] != ProtocolSettings.Default.AddressVersion)
throw new FormatException();
return new UInt160(data.Skip(1).ToArray());
return new UInt160(data[1..]);
}
}
}
6 changes: 3 additions & 3 deletions src/neo/Wallets/KeyPair.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ public string Export(string passphrase, int N = 16384, int r = 8, int p = 8)
{
UInt160 script_hash = Contract.CreateSignatureRedeemScript(PublicKey).ToScriptHash();
string address = script_hash.ToAddress();
byte[] addresshash = Encoding.ASCII.GetBytes(address).Sha256().Sha256().Take(4).ToArray();
byte[] addresshash = Encoding.ASCII.GetBytes(address).Sha256().Sha256()[..4];
byte[] derivedkey = SCrypt.DeriveKey(Encoding.UTF8.GetBytes(passphrase), addresshash, N, r, p, 64);
byte[] derivedhalf1 = derivedkey.Take(32).ToArray();
byte[] derivedhalf2 = derivedkey.Skip(32).ToArray();
byte[] derivedhalf1 = derivedkey[..32];
byte[] derivedhalf2 = derivedkey[32..];
byte[] encryptedkey = XOR(PrivateKey, derivedhalf1).AES256Encrypt(derivedhalf2);
byte[] buffer = new byte[39];
buffer[0] = 0x01;
Expand Down
6 changes: 3 additions & 3 deletions src/neo/Wallets/Wallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ public static byte[] GetPrivateKeyFromNEP2(string nep2, string passphrase, int N
byte[] datapassphrase = Encoding.UTF8.GetBytes(passphrase);
byte[] derivedkey = SCrypt.DeriveKey(datapassphrase, addresshash, N, r, p, 64);
Array.Clear(datapassphrase, 0, datapassphrase.Length);
byte[] derivedhalf1 = derivedkey.Take(32).ToArray();
byte[] derivedhalf2 = derivedkey.Skip(32).ToArray();
byte[] derivedhalf1 = derivedkey[..32];
byte[] derivedhalf2 = derivedkey[32..];
Array.Clear(derivedkey, 0, derivedkey.Length);
byte[] encryptedkey = new byte[32];
Buffer.BlockCopy(data, 7, encryptedkey, 0, 32);
Expand All @@ -163,7 +163,7 @@ public static byte[] GetPrivateKeyFromNEP2(string nep2, string passphrase, int N
ECPoint pubkey = Cryptography.ECC.ECCurve.Secp256r1.G * prikey;
UInt160 script_hash = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash();
string address = script_hash.ToAddress();
if (!Encoding.ASCII.GetBytes(address).Sha256().Sha256().Take(4).SequenceEqual(addresshash))
if (!Encoding.ASCII.GetBytes(address).Sha256().Sha256().AsSpan(0, 4).SequenceEqual(addresshash))
throw new FormatException();
return prikey;
}
Expand Down