Skip to content
This repository has been archived by the owner on Nov 22, 2023. It is now read-only.

Support .NET Standard 2.1 and .NET 5.0 #498

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
13 changes: 8 additions & 5 deletions src/Neo.VM/Collections/OrderedDictionary.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (C) 2016-2022 The Neo Project.
//
// The neo-vm is free software distributed under the MIT software license,
//
// The neo-vm is free software distributed under the MIT software license,
// see the accompanying file LICENSE in the main directory of the
// project or http://www.opensource.org/licenses/mit-license.php
// project or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

Expand Down Expand Up @@ -39,7 +39,7 @@ protected override TKey GetKeyForItem(TItem item)
}
}

private readonly InternalCollection collection = new();
private readonly InternalCollection collection = new InternalCollection();

public int Count => collection.Count;
public bool IsReadOnly => false;
Expand Down Expand Up @@ -76,7 +76,10 @@ public bool Remove(TKey key)
return collection.Remove(key);
}

// supress warning of value parameter nullability mismatch
#pragma warning disable CS8767
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
#pragma warning restore CS8767
{
if (collection.TryGetValue(key, out var entry))
{
Expand Down
28 changes: 28 additions & 0 deletions src/Neo.VM/Cryptography/BitOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (C) 2015-2022 The Neo Project.
//
// The neo is free software distributed under the MIT software license,
// see the accompanying file LICENSE in the main directory of the
// project or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System.Numerics;
using System.Runtime.CompilerServices;

namespace Neo.VM.Cryptography
{
#if !NET5_0_OR_GREATER
static class BitOperations
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateLeft(uint value, int offset)
=> (value << offset) | (value >> (32 - offset));

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong RotateLeft(ulong value, int offset)
=> (value << offset) | (value >> (64 - offset));
}
#endif
}
10 changes: 5 additions & 5 deletions src/Neo.VM/Debugger.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (C) 2016-2022 The Neo Project.
//
// The neo-vm is free software distributed under the MIT software license,
//
// The neo-vm is free software distributed under the MIT software license,
// see the accompanying file LICENSE in the main directory of the
// project or http://www.opensource.org/licenses/mit-license.php
// project or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

Expand All @@ -18,7 +18,7 @@ namespace Neo.VM
public class Debugger
{
private readonly ExecutionEngine engine;
private readonly Dictionary<Script, HashSet<uint>> break_points = new();
private readonly Dictionary<Script, HashSet<uint>> break_points = new Dictionary<Script, HashSet<uint>>();

/// <summary>
/// Create a debugger on the specified <see cref="ExecutionEngine"/>.
Expand Down
12 changes: 6 additions & 6 deletions src/Neo.VM/EvaluationStack.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (C) 2016-2022 The Neo Project.
//
// The neo-vm is free software distributed under the MIT software license,
//
// The neo-vm is free software distributed under the MIT software license,
// see the accompanying file LICENSE in the main directory of the
// project or http://www.opensource.org/licenses/mit-license.php
// project or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

Expand All @@ -22,7 +22,7 @@ namespace Neo.VM
/// </summary>
public sealed class EvaluationStack : IReadOnlyList<StackItem>
{
private readonly List<StackItem> innerList = new();
private readonly List<StackItem> innerList = new List<StackItem>();
private readonly ReferenceCounter referenceCounter;

internal EvaluationStack(ReferenceCounter referenceCounter)
Expand Down Expand Up @@ -152,7 +152,7 @@ internal T Remove<T>(int index) where T : StackItem
throw new ArgumentOutOfRangeException(nameof(index));
}
index = innerList.Count - index - 1;
if (innerList[index] is not T item)
if (!(innerList[index] is T item))
throw new InvalidCastException($"The item can't be casted to type {typeof(T)}");
innerList.RemoveAt(index);
referenceCounter.RemoveStackReference(item);
Expand Down
28 changes: 14 additions & 14 deletions src/Neo.VM/ExecutionEngine.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (C) 2016-2022 The Neo Project.
//
// The neo-vm is free software distributed under the MIT software license,
//
// The neo-vm is free software distributed under the MIT software license,
// see the accompanying file LICENSE in the main directory of the
// project or http://www.opensource.org/licenses/mit-license.php
// project or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

Expand Down Expand Up @@ -703,7 +703,7 @@ private void ExecuteInstruction(Instruction instruction)
var x1 = Pop().GetSpan();
int length = x1.Length + x2.Length;
Limits.AssertMaxItemSize(length);
Buffer result = new(length, false);
Buffer result = new Buffer(length, false);
x1.CopyTo(result.InnerBuffer.Span);
x2.CopyTo(result.InnerBuffer.Span[x1.Length..]);
Push(result);
Expand All @@ -720,7 +720,7 @@ private void ExecuteInstruction(Instruction instruction)
var x = Pop().GetSpan();
if (index + count > x.Length)
throw new InvalidOperationException($"The value {count} is out of range.");
Buffer result = new(count, false);
Buffer result = new Buffer(count, false);
x.Slice(index, count).CopyTo(result.InnerBuffer.Span);
Push(result);
break;
Expand All @@ -733,7 +733,7 @@ private void ExecuteInstruction(Instruction instruction)
var x = Pop().GetSpan();
if (count > x.Length)
throw new InvalidOperationException($"The value {count} is out of range.");
Buffer result = new(count, false);
Buffer result = new Buffer(count, false);
x[..count].CopyTo(result.InnerBuffer.Span);
Push(result);
break;
Expand All @@ -746,7 +746,7 @@ private void ExecuteInstruction(Instruction instruction)
var x = Pop().GetSpan();
if (count > x.Length)
throw new InvalidOperationException($"The value {count} is out of range.");
Buffer result = new(count, false);
Buffer result = new Buffer(count, false);
x[^count..^0].CopyTo(result.InnerBuffer.Span);
Push(result);
break;
Expand Down Expand Up @@ -1020,7 +1020,7 @@ private void ExecuteInstruction(Instruction instruction)
int size = (int)Pop().GetInteger();
if (size < 0 || size * 2 > CurrentContext!.EvaluationStack.Count)
throw new InvalidOperationException($"The value {size} is out of range.");
Map map = new(ReferenceCounter);
Map map = new Map(ReferenceCounter);
for (int i = 0; i < size; i++)
{
PrimitiveType key = Pop<PrimitiveType>();
Expand All @@ -1035,7 +1035,7 @@ private void ExecuteInstruction(Instruction instruction)
int size = (int)Pop().GetInteger();
if (size < 0 || size > CurrentContext!.EvaluationStack.Count)
throw new InvalidOperationException($"The value {size} is out of range.");
Struct @struct = new(ReferenceCounter);
Struct @struct = new Struct(ReferenceCounter);
for (int i = 0; i < size; i++)
{
StackItem item = Pop();
Expand All @@ -1049,7 +1049,7 @@ private void ExecuteInstruction(Instruction instruction)
int size = (int)Pop().GetInteger();
if (size < 0 || size > CurrentContext!.EvaluationStack.Count)
throw new InvalidOperationException($"The value {size} is out of range.");
VMArray array = new(ReferenceCounter);
VMArray array = new VMArray(ReferenceCounter);
for (int i = 0; i < size; i++)
{
StackItem item = Pop();
Expand Down Expand Up @@ -1124,7 +1124,7 @@ private void ExecuteInstruction(Instruction instruction)
int n = (int)Pop().GetInteger();
if (n < 0 || n > Limits.MaxStackSize)
throw new InvalidOperationException($"MaxStackSize exceed: {n}");
Struct result = new(ReferenceCounter);
Struct result = new Struct(ReferenceCounter);
for (var i = 0; i < n; i++)
result.Add(StackItem.Null);
Push(result);
Expand Down Expand Up @@ -1209,7 +1209,7 @@ private void ExecuteInstruction(Instruction instruction)
Map map => map.Values,
_ => throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"),
};
VMArray newArray = new(ReferenceCounter);
VMArray newArray = new VMArray(ReferenceCounter);
foreach (StackItem item in values)
if (item is Struct s)
newArray.Add(s.Clone(Limits));
Expand Down Expand Up @@ -1295,7 +1295,7 @@ private void ExecuteInstruction(Instruction instruction)
int index = (int)key.GetInteger();
if (index < 0 || index >= buffer.Size)
throw new CatchableException($"The value {index} is out of range.");
if (value is not PrimitiveType p)
if (!(value is PrimitiveType p))
throw new InvalidOperationException($"Value must be a primitive type in {instruction.OpCode}");
int b = (int)p.GetInteger();
if (b < sbyte.MinValue || b > byte.MaxValue)
Expand Down
96 changes: 83 additions & 13 deletions src/Neo.VM/ExecutionEngineLimits.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (C) 2016-2022 The Neo Project.
//
// The neo-vm is free software distributed under the MIT software license,
//
// The neo-vm is free software distributed under the MIT software license,
// see the accompanying file LICENSE in the main directory of the
// project or http://www.opensource.org/licenses/mit-license.php
// project or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

Expand All @@ -16,47 +16,103 @@ namespace Neo.VM
/// <summary>
/// Represents the restrictions on the VM.
/// </summary>
public sealed record ExecutionEngineLimits
public sealed class ExecutionEngineLimits : IEquatable<ExecutionEngineLimits>
{
/// <summary>
/// The default strategy.
/// </summary>
public static readonly ExecutionEngineLimits Default = new();
public static readonly ExecutionEngineLimits Default = new ExecutionEngineLimits();

/// <summary>
/// The maximum number of bits that <see cref="OpCode.SHL"/> and <see cref="OpCode.SHR"/> can shift.
/// </summary>
public int MaxShift { get; init; } = 256;
public int MaxShift
{
get;
#if NET5_0_OR_GREATER
init;
#else
set;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe create a constructor for all of these "else"? otherwise it can be changed after the creation

#endif
} = 256;

/// <summary>
/// The maximum number of items that can be contained in the VM's evaluation stacks and slots.
/// </summary>
public uint MaxStackSize { get; init; } = 2 * 1024;
public uint MaxStackSize
{
get;
#if NET5_0_OR_GREATER
init;
#else
set;
#endif
} = 2 * 1024;

/// <summary>
/// The maximum size of an item in the VM.
/// </summary>
public uint MaxItemSize { get; init; } = 1024 * 1024;
public uint MaxItemSize
{
get;
#if NET5_0_OR_GREATER
init;
#else
set;
#endif
} = 1024 * 1024;

/// <summary>
/// The largest comparable size. If a <see cref="Types.ByteString"/> or <see cref="Types.Struct"/> exceeds this size, comparison operations on it cannot be performed in the VM.
/// </summary>
public uint MaxComparableSize { get; init; } = 65536;
public uint MaxComparableSize
{
get;
#if NET5_0_OR_GREATER
init;
#else
set;
#endif
} = 65536;

/// <summary>
/// The maximum number of frames in the invocation stack of the VM.
/// </summary>
public uint MaxInvocationStackSize { get; init; } = 1024;
public uint MaxInvocationStackSize
{
get;
#if NET5_0_OR_GREATER
init;
#else
set;
#endif
} = 1024;

/// <summary>
/// The maximum nesting depth of <see langword="try"/>-<see langword="catch"/>-<see langword="finally"/> blocks.
/// </summary>
public uint MaxTryNestingDepth { get; init; } = 16;
public uint MaxTryNestingDepth
{
get;
#if NET5_0_OR_GREATER
init;
#else
set;
#endif
} = 16;

/// <summary>
/// Allow to catch the ExecutionEngine Exceptions
/// </summary>
public bool CatchEngineExceptions { get; init; } = true;
public bool CatchEngineExceptions
{
get;
#if NET5_0_OR_GREATER
init;
#else
set;
#endif
} = true;

/// <summary>
/// Assert that the size of the item meets the limit.
Expand All @@ -83,5 +139,19 @@ public void AssertShift(int shift)
throw new InvalidOperationException($"Invalid shift value: {shift}");
}
}

public bool Equals(ExecutionEngineLimits? other)
{
if (ReferenceEquals(this, other)) return true;
if (other is null) return false;
return MaxShift == other.MaxShift
&& MaxStackSize == other.MaxStackSize
&& MaxItemSize == other.MaxItemSize
&& MaxComparableSize == other.MaxComparableSize
&& MaxInvocationStackSize == other.MaxInvocationStackSize
&& MaxInvocationStackSize == other.MaxInvocationStackSize
&& MaxTryNestingDepth == other.MaxTryNestingDepth
&& CatchEngineExceptions == other.CatchEngineExceptions;
}
}
}
10 changes: 5 additions & 5 deletions src/Neo.VM/Instruction.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (C) 2016-2022 The Neo Project.
//
// The neo-vm is free software distributed under the MIT software license,
//
// The neo-vm is free software distributed under the MIT software license,
// see the accompanying file LICENSE in the main directory of the
// project or http://www.opensource.org/licenses/mit-license.php
// project or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

Expand Down Expand Up @@ -191,7 +191,7 @@ static Instruction()
private Instruction(OpCode opcode)
{
this.OpCode = opcode;
if (!Enum.IsDefined(opcode)) throw new BadScriptException();
if (!Enum.IsDefined(typeof(OpCode), opcode)) throw new BadScriptException();
}

internal Instruction(ReadOnlyMemory<byte> script, int ip) : this((OpCode)script.Span[ip++])
Expand Down
Loading