Skip to content
Merged
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
144 changes: 144 additions & 0 deletions src/Neo.Core/Extensions/TryCatchExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// BSD 2-Clause License
//
// Copyright (c) 2026, Rapid Loop
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES

using System;

namespace Neo.Core.Extensions
{
public static class TryCatchExtensions
{
public static TResult? TryCatch<TSource, TResult>(this TSource obj, Func<TSource?, TResult?> func)
{
try
{
return func(obj);
}
catch
{
return default;
}
}

public static TSource TryCatch<TSource, TException>(this TSource obj, Action<TSource> action, Action<TSource?, TException>? onError = default)
where TException : Exception
{
try
{
action(obj);
}
catch (TException ex)
{
onError?.Invoke(obj, ex);
}

return obj;
}

public static TResult TryCatch<TSource, TException, TResult>(this TSource obj, Func<TSource, TResult> func, Func<TSource, TException, TResult>? onError = default)
where TException : Exception
{
try
{
return func(obj);
}
catch (TException ex)
{
if (onError == null) throw;
return onError(obj, ex);
}
}

public static TSource TryCatchThrow<TSource, TException>(this TSource obj, Action<TSource?> action)
where TException : Exception
{
try
{
action(obj);

return obj;
}
catch (TException)
{
throw;
}
}

public static TResult TryCatchThrow<TSource, TException, TResult>(this TSource obj, Func<TSource, TResult> func)
where TException : Exception
{
try
{
return func(obj);
}
catch (TException)
{
throw;
}
}

public static TSource TryCatchThrow<TSource, TException>(this TSource obj, Action<TSource?> action, string? errorMessage = default)
where TException : Exception, new()
{
try
{
action(obj);

return obj;
}
catch (TException innerException)
{
if (string.IsNullOrEmpty(errorMessage))
throw;
else
{
if (Activator.CreateInstance(typeof(TException), errorMessage, innerException) is not TException ex)
throw;
else
throw ex;
}

}
}

public static TResult? TryCatchThrow<TSource, TException, TResult>(this TSource obj, Func<TSource?, TResult?> func, string? errorMessage = default)
where TException : Exception
{
try
{
return func(obj);
}
catch (TException innerException)
{
if (string.IsNullOrEmpty(errorMessage))
throw;
else
{
if (Activator.CreateInstance(typeof(TException), errorMessage, innerException) is not TException ex)
throw;
else
throw ex;
}

}
}
}
}
32 changes: 32 additions & 0 deletions src/Neo.Core/Json/LowerCaseNamingPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// BSD 2-Clause License
//
// Copyright (c) 2026, Rapid Loop
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES

using System.Text.Json;

namespace Neo.Core.Json
{
public class LowerCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name) =>
name.ToLowerInvariant();
}
}
17 changes: 9 additions & 8 deletions src/Neo.Core/VM/OpCodeInst.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// SERVICES

using Neo.Core.VM.Attributes;
using Neo.Core.VM.Type;
using System;
using System.Buffers.Binary;
using System.Collections;
Expand Down Expand Up @@ -176,7 +177,7 @@ OpCode.JMPNE or
OpCode.JMPGT or
OpCode.JMPLT or
OpCode.CALL or
OpCode.ENDTRY => $"[{checked(Position + AsToken<byte>()):x8}]",
OpCode.ENDTRY => $"[0x{checked(Position + AsToken<byte>()):x8}]",
OpCode.JMP_L or
OpCode.JMPIF_L or
OpCode.PUSHA or
Expand All @@ -186,14 +187,14 @@ OpCode.JMPNE_L or
OpCode.JMPGT_L or
OpCode.JMPLT_L or
OpCode.CALL_L or
OpCode.ENDTRY_L => $"[{checked(Position + AsToken<int>()):x8}]",
OpCode.TRY => $"[{AsToken<byte>():x2}, {AsToken<byte>(1):x2}]",
OpCode.INITSLOT => $"{AsToken<byte>()}, {AsToken<byte>(1)}",
OpCode.TRY_L => $"[{checked(Position + AsToken<int>()):x8}, {checked(Position + AsToken<int>()):x8}]",
OpCode.CALLT => $"[{checked(Position + AsToken<ushort>()):x8}]",
OpCode.ENDTRY_L => $"[0x{checked(Position + AsToken<int>()):x8}]",
OpCode.TRY => $"[0x{AsToken<byte>():x2}, 0x{AsToken<byte>(1):x2}]",
OpCode.INITSLOT => $"[{AsToken<byte>()}, {AsToken<byte>(1)}]",
OpCode.TRY_L => $"[0x{checked(Position + AsToken<int>()):x8}, 0x{checked(Position + AsToken<int>()):x8}]",
OpCode.CALLT => $"[0x{checked(Position + AsToken<ushort>()):x8}]",
OpCode.NEWARRAY_T or
OpCode.ISTYPE or
OpCode.CONVERT => $"{AsToken<byte>():x2}",
OpCode.CONVERT => $"0x{AsToken<byte>():x2} // \"{AsToken<VMObjectType>():G}\"",
OpCode.STLOC or
OpCode.LDLOC or
OpCode.LDSFLD or
Expand All @@ -207,7 +208,7 @@ OpCode.STARG or
OpCode.PUSHINT64 => $"{AsToken<long>()}",
OpCode.PUSHINT128 or
OpCode.PUSHINT256 => $"{new BigInteger(operand)}",
OpCode.SYSCALL => $"[{Unsafe.As<byte, uint>(ref operand[0])}]",
OpCode.SYSCALL => $"[0x{Unsafe.As<byte, uint>(ref operand[0]):x8}]",
OpCode.PUSHDATA1 or
OpCode.PUSHDATA2 or
OpCode.PUSHDATA4 => operand.Length == 0 ? string.Empty : readable ? $"0x{Convert.ToHexStringLower(operand)} // \"{asStr}\"" : $"0x{Convert.ToHexStringLower(operand)}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES

namespace Neo.VM.Types
namespace Neo.Core.VM.Type
{
/// <summary>
/// An enumeration representing the types in the VM.
Expand Down Expand Up @@ -75,6 +75,6 @@ public enum VMObjectType : byte
/// <summary>
/// Represents an interface used to interoperate with the outside of the the VM.
/// </summary>
InteropInterface = 0x60,
Interop = 0x60,
}
}
14 changes: 8 additions & 6 deletions src/Neo.VM/Core/ExecutionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ public class ExecutionContext
/// <summary>
/// Returns the current <see cref="OpCodeInst"/>.
/// </summary>
public OpCodeInst CurrentInstruction => new(_script.Slice(InstructionPointer));
public OpCodeInst CurrentInstruction => new(_script[InstructionPointer..]);

/// <summary>
/// Returns the next <see cref="OpCodeInst"/>.
/// </summary>
public OpCodeInst NextInstruction => new(_script.Slice(InstructionPointer + CurrentInstruction.Size));
public OpCodeInst NextInstruction => new(_script[(InstructionPointer + CurrentInstruction.Size)..]);

/// <summary>
/// Current stack frame
Expand Down Expand Up @@ -96,6 +96,8 @@ public class ExecutionContext

public ExecutionContext(byte[] script, HardFork fork = HardFork.Genesis, uint blockHeight = 0, long initialGas = 1_000000L, int depth = 0, ExecutionContext? parent = null)
{
script = [.. script, (byte)OpCode.RET];

_script = script.Clone() as byte[] ?? throw new ArgumentNullException(nameof(script));
_blockHeight = blockHeight;
_fork = fork;
Expand Down Expand Up @@ -136,17 +138,17 @@ public bool ConsumeGas(OpCode opcode)
/// <summary>
/// Push value onto current frame's evaluation stack
/// </summary>
public void Push(VMObject item)
public void Push(VMObject item, bool addReferenceItem = true, bool addReferenceChildren = true)
{
Frame.Push(item);
Frame.Push(item, addReferenceItem, addReferenceChildren);
}

/// <summary>
/// Pop value from current frame's evaluation stack
/// </summary>
public VMObject Pop()
public VMObject Pop(bool releaseReferenceItem = true, bool releaseReferenceChildren = true)
{
return Frame.Pop();
return Frame.Pop(releaseReferenceItem, releaseReferenceChildren);
}

/// <summary>
Expand Down
Loading
Loading