Skip to content

Commit

Permalink
Merge branch 'master' into optimize-vm
Browse files Browse the repository at this point in the history
* master:
  Related to neo-project#3082 (comment) (neo-project#3119)
  [VM UT] update UT name (neo-project#3115)
  Neo as dotnet standard (neo-project#3082)
  Fix ut (neo-project#3113)
  • Loading branch information
Jim8y committed Feb 7, 2024
2 parents 4058940 + e3707fd commit 99e9c5f
Show file tree
Hide file tree
Showing 40 changed files with 300 additions and 163 deletions.
3 changes: 2 additions & 1 deletion benchmarks/Neo.Benchmarks/Benchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// modifications are permitted.

using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.VM;
using System.Diagnostics;
Expand All @@ -19,7 +20,7 @@ namespace Neo;
static class Benchmarks
{
private static readonly ProtocolSettings protocol = ProtocolSettings.Load("config.json");
private static readonly NeoSystem system = new(protocol);
private static readonly NeoSystem system = new(protocol, new MemoryStore());

public static void NeoIssue2725()
{
Expand Down
4 changes: 3 additions & 1 deletion src/Neo.CLI/CLI/MainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Neo.Ledger;
using Neo.Network.P2P;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.Plugins;
using Neo.SmartContract;
using Neo.SmartContract.Manifest;
Expand Down Expand Up @@ -376,7 +377,8 @@ public async void Start(CommandLineOptions options)
ProtocolSettings protocol = ProtocolSettings.Load("config.json");
CustomProtocolSettings(options, protocol);
CustomApplicationSettings(options, Settings.Default);
NeoSystem = new NeoSystem(protocol, Settings.Default.Storage.Engine, string.Format(Settings.Default.Storage.Path, protocol.Network.ToString("X8")));
var store = StoreFactory.GetStore(Settings.Default.Storage.Engine, string.Format(Settings.Default.Storage.Path, protocol.Network.ToString("X8")));
NeoSystem = new NeoSystem(protocol, store);
NeoSystem.AddService(this);

LocalNode = NeoSystem.LocalNode.Ask<LocalNode>(new LocalNode.GetInstance()).Result;
Expand Down
36 changes: 26 additions & 10 deletions src/Neo.VM/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

namespace Neo.VM
{
internal static class Utility
public static class Utility
{
public static Encoding StrictUTF8 { get; }

Expand All @@ -34,11 +34,11 @@ public static BigInteger ModInverse(this BigInteger value, BigInteger modulus)
BigInteger r = value, old_r = modulus, s = 1, old_s = 0;
while (r > 0)
{
BigInteger q = old_r / r;
var q = old_r / r;
(old_r, r) = (r, old_r % r);
(old_s, s) = (s, old_s - q * s);
}
BigInteger result = old_s % modulus;
var result = old_s % modulus;
if (result < 0) result += modulus;
if (!(value * result % modulus).IsOne) throw new InvalidOperationException();
return result;
Expand All @@ -61,17 +61,33 @@ public static BigInteger Sqrt(this BigInteger value)
return z;
}

#if !NET5_0_OR_GREATER
static int GetBitLength(this BigInteger i)
/// <summary>
/// Gets the number of bits required for shortest two's complement representation of the current instance without the sign bit.
/// </summary>
/// <returns>The minimum non-negative number of bits in two's complement notation without the sign bit.</returns>
/// <remarks>This method returns 0 if the value of current object is equal to <see cref="BigInteger.Zero"/> or <see cref="BigInteger.MinusOne"/>. For positive integers the return value is equal to the ordinary binary representation string length.</remarks>
public static long GetBitLength(this BigInteger value)
{
byte[] b = i.ToByteArray();
return (b.Length - 1) * 8 + BitLen(i.Sign > 0 ? b[b.Length - 1] : 255 - b[b.Length - 1]);
#if NET5_0_OR_GREATER
return value.GetBitLength();
#else
if (value == 0 || value == BigInteger.MinusOne) return 0;

// Note: This method is imprecise and might not work as expected with integers larger than 256 bits.
var b = value.ToByteArray();
if (b.Length == 1 || (b.Length == 2 && b[1] == 0))
{
return BitCount(value.Sign > 0 ? b[0] : (byte)(255 - b[0]));
}
return (b.Length - 1) * 8 + BitCount(value.Sign > 0 ? b[^1] : 255 - b[^1]);
#endif
}

#if !NET5_0_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static int BitLen(int w)
private static int BitCount(int w)
{
return (w < 1 << 15 ? (w < 1 << 7
return w < 1 << 15 ? (w < 1 << 7
? (w < 1 << 3 ? (w < 1 << 1
? (w < 1 << 0 ? (w < 0 ? 32 : 0) : 1)
: (w < 1 << 2 ? 2 : 3)) : (w < 1 << 5
Expand All @@ -83,7 +99,7 @@ static int BitLen(int w)
? (w < 1 << 17 ? (w < 1 << 16 ? 16 : 17) : (w < 1 << 18 ? 18 : 19))
: (w < 1 << 21 ? (w < 1 << 20 ? 20 : 21) : (w < 1 << 22 ? 22 : 23))) : (w < 1 << 27
? (w < 1 << 25 ? (w < 1 << 24 ? 24 : 25) : (w < 1 << 26 ? 26 : 27))
: (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31)))));
: (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31))));
}
#endif
}
Expand Down
4 changes: 2 additions & 2 deletions src/Neo/BigDecimal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public BigDecimal(BigInteger value, byte decimals)
public unsafe BigDecimal(decimal value)
{
Span<int> span = stackalloc int[4];
decimal.GetBits(value, span);
span = decimal.GetBits(value);
fixed (int* p = span)
{
ReadOnlySpan<byte> buffer = new(p, 16);
Expand All @@ -73,7 +73,7 @@ public unsafe BigDecimal(decimal value)
public unsafe BigDecimal(decimal value, byte decimals)
{
Span<int> span = stackalloc int[4];
decimal.GetBits(value, span);
span = decimal.GetBits(value);
fixed (int* p = span)
{
ReadOnlySpan<byte> buffer = new(p, 16);
Expand Down
2 changes: 1 addition & 1 deletion src/Neo/Cryptography/ECC/ECCurve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class ECCurve
private ECCurve(BigInteger Q, BigInteger A, BigInteger B, BigInteger N, byte[] G)
{
this.Q = Q;
this.ExpectedECPointLength = ((int)Q.GetBitLength() + 7) / 8;
this.ExpectedECPointLength = ((int)VM.Utility.GetBitLength(Q) + 7) / 8;
this.A = new ECFieldElement(A, this);
this.B = new ECFieldElement(B, this);
this.N = N;
Expand Down
4 changes: 2 additions & 2 deletions src/Neo/Cryptography/ECC/ECFieldElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public bool Equals(ECFieldElement other)

private static BigInteger[] FastLucasSequence(BigInteger p, BigInteger P, BigInteger Q, BigInteger k)
{
int n = (int)k.GetBitLength();
int n = (int)VM.Utility.GetBitLength(k);
int s = k.GetLowestSetBit();

BigInteger Uh = 1;
Expand Down Expand Up @@ -126,7 +126,7 @@ public ECFieldElement Sqrt()
BigInteger P;
do
{
P = rand.NextBigInteger((int)curve.Q.GetBitLength());
P = rand.NextBigInteger((int)VM.Utility.GetBitLength(curve.Q));
}
while (P >= curve.Q || BigInteger.ModPow(P * P - fourQ, legendreExponent, curve.Q) != qMinusOne);
BigInteger[] result = FastLucasSequence(curve.Q, P, Q, k);
Expand Down
4 changes: 2 additions & 2 deletions src/Neo/Cryptography/ECC/ECPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ public override int GetHashCode()
internal static ECPoint Multiply(ECPoint p, BigInteger k)
{
// floor(log2(k))
int m = (int)k.GetBitLength();
int m = (int)VM.Utility.GetBitLength(k);

// width of the Window NAF
sbyte width;
Expand Down Expand Up @@ -391,7 +391,7 @@ internal ECPoint Twice()

private static sbyte[] WindowNaf(sbyte width, BigInteger k)
{
sbyte[] wnaf = new sbyte[k.GetBitLength() + 1];
sbyte[] wnaf = new sbyte[VM.Utility.GetBitLength(k) + 1];
short pow2wB = (short)(1 << width);
int i = 0;
int length = 0;
Expand Down
27 changes: 26 additions & 1 deletion src/Neo/Cryptography/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System;
using System.Buffers.Binary;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using static Neo.Helper;
Expand Down Expand Up @@ -99,7 +100,7 @@ public static byte[] Murmur128(this byte[] value, uint seed)
/// <returns>The computed hash code.</returns>
public static byte[] Murmur128(this ReadOnlySpan<byte> value, uint seed)
{
byte[] buffer = GC.AllocateUninitializedArray<byte>(16);
byte[] buffer = new byte[16];
using Murmur128 murmur = new(seed);
murmur.TryComputeHash(value, buffer, out _);
return buffer;
Expand Down Expand Up @@ -239,5 +240,29 @@ internal static bool Test(this BloomFilter filter, Transaction tx)
return true;
return false;
}

/// <summary>
/// Rotates the specified value left by the specified number of bits.
/// Similar in behavior to the x86 instruction ROL.
/// </summary>
/// <param name="value">The value to rotate.</param>
/// <param name="offset">The number of bits to rotate by.
/// Any value outside the range [0..31] is treated as congruent mod 32.</param>
/// <returns>The rotated value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateLeft(uint value, int offset)
=> (value << offset) | (value >> (32 - offset));

/// <summary>
/// Rotates the specified value left by the specified number of bits.
/// Similar in behavior to the x86 instruction ROL.
/// </summary>
/// <param name="value">The value to rotate.</param>
/// <param name="offset">The number of bits to rotate by.
/// Any value outside the range [0..63] is treated as congruent mod 64.</param>
/// <returns>The rotated value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong RotateLeft(ulong value, int offset)
=> (value << offset) | (value >> (64 - offset));
}
}
14 changes: 7 additions & 7 deletions src/Neo/Cryptography/Murmur128.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,19 @@ protected override void HashCore(ReadOnlySpan<byte> source)
{
ulong k1 = BinaryPrimitives.ReadUInt64LittleEndian(source[i..]);
k1 *= c1;
k1 = BitOperations.RotateLeft(k1, r1);
k1 = Helper.RotateLeft(k1, r1);
k1 *= c2;
H1 ^= k1;
H1 = BitOperations.RotateLeft(H1, 27);
H1 = Helper.RotateLeft(H1, 27);
H1 += H2;
H1 = H1 * m + n1;

ulong k2 = BinaryPrimitives.ReadUInt64LittleEndian(source[(i + 8)..]);
k2 *= c2;
k2 = BitOperations.RotateLeft(k2, r2);
k2 = Helper.RotateLeft(k2, r2);
k2 *= c1;
H2 ^= k2;
H2 = BitOperations.RotateLeft(H2, 31);
H2 = Helper.RotateLeft(H2, 31);
H2 += H1;
H2 = H2 * m + n2;
}
Expand All @@ -102,14 +102,14 @@ protected override void HashCore(ReadOnlySpan<byte> source)
case 1: remainingBytesL ^= (ulong)source[alignedLength] << 0; break;
}

H2 ^= BitOperations.RotateLeft(remainingBytesH * c2, r2) * c1;
H1 ^= BitOperations.RotateLeft(remainingBytesL * c1, r1) * c2;
H2 ^= Helper.RotateLeft(remainingBytesH * c2, r2) * c1;
H1 ^= Helper.RotateLeft(remainingBytesL * c1, r1) * c2;
}
}

protected override byte[] HashFinal()
{
byte[] buffer = GC.AllocateUninitializedArray<byte>(sizeof(ulong) * 2);
byte[] buffer = new byte[sizeof(ulong) * 2];
TryHashFinal(buffer, out _);
return buffer;
}
Expand Down
8 changes: 4 additions & 4 deletions src/Neo/Cryptography/Murmur32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ protected override void HashCore(ReadOnlySpan<byte> source)
{
uint k = BinaryPrimitives.ReadUInt32LittleEndian(source);
k *= c1;
k = BitOperations.RotateLeft(k, r1);
k = Helper.RotateLeft(k, r1);
k *= c2;
hash ^= k;
hash = BitOperations.RotateLeft(hash, r2);
hash = Helper.RotateLeft(hash, r2);
hash = hash * m + n;
}
if (source.Length > 0)
Expand All @@ -72,15 +72,15 @@ protected override void HashCore(ReadOnlySpan<byte> source)
case 1: remainingBytes ^= source[0]; break;
}
remainingBytes *= c1;
remainingBytes = BitOperations.RotateLeft(remainingBytes, r1);
remainingBytes = Helper.RotateLeft(remainingBytes, r1);
remainingBytes *= c2;
hash ^= remainingBytes;
}
}

protected override byte[] HashFinal()
{
byte[] buffer = GC.AllocateUninitializedArray<byte>(sizeof(uint));
byte[] buffer = new byte[sizeof(uint)];
TryHashFinal(buffer, out _);
return buffer;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Neo/IO/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public static ISerializable AsSerializable(this ReadOnlyMemory<byte> value, Type
public static ReadOnlyMemory<byte> CompressLz4(this ReadOnlySpan<byte> data)
{
int maxLength = LZ4Codec.MaximumOutputSize(data.Length);
byte[] buffer = GC.AllocateUninitializedArray<byte>(sizeof(uint) + maxLength);
byte[] buffer = new byte[sizeof(uint) + maxLength];
BinaryPrimitives.WriteInt32LittleEndian(buffer, data.Length);
int length = LZ4Codec.Encode(data, buffer.AsSpan(sizeof(uint)));
return buffer.AsMemory(0, sizeof(uint) + length);
Expand All @@ -118,7 +118,7 @@ public static byte[] DecompressLz4(this ReadOnlySpan<byte> data, int maxOutput)
{
int length = BinaryPrimitives.ReadInt32LittleEndian(data);
if (length < 0 || length > maxOutput) throw new FormatException();
byte[] result = GC.AllocateUninitializedArray<byte>(length);
byte[] result = new byte[length];
if (LZ4Codec.Decode(data[4..], result) != length)
throw new FormatException();
return result;
Expand Down
2 changes: 1 addition & 1 deletion src/Neo/Neo.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net7.0</TargetFrameworks>
<TargetFrameworks>netstandard2.1;net7.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageTags>NEO;AntShares;Blockchain;Smart Contract</PackageTags>
</PropertyGroup>
Expand Down
11 changes: 4 additions & 7 deletions src/Neo/NeoSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ public class NeoSystem : IDisposable
internal RelayCache RelayCache { get; } = new(100);

private ImmutableList<object> services = ImmutableList<object>.Empty;
private readonly string storage_engine;
private readonly IStore store;
private ChannelsConfig start_message = null;
private int suspend = 0;
Expand All @@ -114,14 +113,12 @@ static NeoSystem()
/// Initializes a new instance of the <see cref="NeoSystem"/> class.
/// </summary>
/// <param name="settings">The protocol settings of the <see cref="NeoSystem"/>.</param>
/// <param name="storageEngine">The storage engine used to create the <see cref="IStore"/> objects. If this parameter is <see langword="null"/>, a default in-memory storage engine will be used.</param>
/// <param name="storagePath">The path of the storage. If <paramref name="storageEngine"/> is the default in-memory storage engine, this parameter is ignored.</param>
public NeoSystem(ProtocolSettings settings, string storageEngine = null, string storagePath = null)
/// <param name="storage">The <see cref="IStore"/> to use.</param>
public NeoSystem(ProtocolSettings settings, IStore storage)
{
this.Settings = settings;
this.GenesisBlock = CreateGenesisBlock(settings);
this.storage_engine = storageEngine ?? nameof(MemoryStore);
this.store = LoadStore(storagePath);
this.store = storage;
this.MemPool = new MemoryPool(this);
this.Blockchain = ActorSystem.ActorOf(Ledger.Blockchain.Props(this));
this.LocalNode = ActorSystem.ActorOf(Network.P2P.LocalNode.Props(this));
Expand Down Expand Up @@ -218,7 +215,7 @@ public void EnsureStopped(IActorRef actor)
/// <returns>The loaded <see cref="IStore"/>.</returns>
public IStore LoadStore(string path)
{
return StoreFactory.GetStore(storage_engine, path);
return StoreFactory.GetStore(store.GetType().Name, path);
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Neo/Network/UPnP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ private static XmlDocument SOAPRequest(string url, string soap, string function)
request.Headers.Add("Content-Type", "text/xml; charset=\"utf-8\"");
request.Content = new StringContent(req);
using HttpClient http = new();
using HttpResponseMessage response = http.Send(request);
using Stream stream = response.EnsureSuccessStatusCode().Content.ReadAsStream();
using HttpResponseMessage response = http.SendAsync(request).GetAwaiter().GetResult();
using Stream stream = response.EnsureSuccessStatusCode().Content.ReadAsStreamAsync().GetAwaiter().GetResult();
XmlDocument resp = new() { XmlResolver = null };
resp.Load(stream);
return resp;
Expand Down
Loading

0 comments on commit 99e9c5f

Please sign in to comment.