From 5e05c82426e3746b9025401a5c56a48a3e5bb073 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 6 Feb 2024 19:06:56 +0100 Subject: [PATCH 01/34] Jump table --- src/Neo.VM/ExecutionEngine.cs | 1268 +-------------------------- src/Neo.VM/JumpTable.Control.cs | 180 ++++ src/Neo.VM/JumpTable.Push.cs | 98 +++ src/Neo.VM/JumpTable.cs | 406 +++++++++ src/Neo.VM/OpcodeMethodAttribute.cs | 36 + 5 files changed, 728 insertions(+), 1260 deletions(-) create mode 100644 src/Neo.VM/JumpTable.Control.cs create mode 100644 src/Neo.VM/JumpTable.Push.cs create mode 100644 src/Neo.VM/JumpTable.cs create mode 100644 src/Neo.VM/OpcodeMethodAttribute.cs diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index f67cc9caec..f020aa24e5 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -12,21 +12,18 @@ using Neo.VM.Types; using System; using System.Collections.Generic; -using System.Linq; -using System.Numerics; using System.Runtime.CompilerServices; -using Buffer = Neo.VM.Types.Buffer; -using VMArray = Neo.VM.Types.Array; namespace Neo.VM { /// /// Represents the VM used to execute the script. /// - public class ExecutionEngine : IDisposable + public partial class ExecutionEngine : IDisposable { private VMState state = VMState.BREAK; private bool isJumping = false; + private readonly JumpTable JumpTable; /// /// Restrictions on the VM. @@ -85,17 +82,19 @@ protected internal set /// /// Initializes a new instance of the class. /// - public ExecutionEngine() : this(new ReferenceCounter(), ExecutionEngineLimits.Default) + public ExecutionEngine(JumpTable? jumpTable = null) : this(jumpTable, new ReferenceCounter(), ExecutionEngineLimits.Default) { } /// /// Initializes a new instance of the class with the specified and . /// + /// The jump table to be used. /// The reference counter to be used. /// Restrictions on the VM. - protected ExecutionEngine(ReferenceCounter referenceCounter, ExecutionEngineLimits limits) + protected ExecutionEngine(JumpTable? jumpTable, ReferenceCounter referenceCounter, ExecutionEngineLimits limits) { + this.JumpTable = jumpTable ?? new JumpTable(); this.Limits = limits; this.ReferenceCounter = referenceCounter; this.ResultStack = new EvaluationStack(referenceCounter); @@ -148,1257 +147,6 @@ private void ExecuteCall(int position) LoadContext(CurrentContext!.Clone(position)); } - private void ExecuteInstruction(Instruction instruction) - { - switch (instruction.OpCode) - { - //Push - case OpCode.PUSHINT8: - case OpCode.PUSHINT16: - case OpCode.PUSHINT32: - case OpCode.PUSHINT64: - case OpCode.PUSHINT128: - case OpCode.PUSHINT256: - { - Push(new BigInteger(instruction.Operand.Span)); - break; - } - case OpCode.PUSHT: - { - Push(StackItem.True); - break; - } - case OpCode.PUSHF: - { - Push(StackItem.False); - break; - } - case OpCode.PUSHA: - { - int position = checked(CurrentContext!.InstructionPointer + instruction.TokenI32); - if (position < 0 || position > CurrentContext.Script.Length) - throw new InvalidOperationException($"Bad pointer address: {position}"); - Push(new Pointer(CurrentContext.Script, position)); - break; - } - case OpCode.PUSHNULL: - { - Push(StackItem.Null); - break; - } - case OpCode.PUSHDATA1: - case OpCode.PUSHDATA2: - case OpCode.PUSHDATA4: - { - Limits.AssertMaxItemSize(instruction.Operand.Length); - Push(instruction.Operand); - break; - } - case OpCode.PUSHM1: - case OpCode.PUSH0: - case OpCode.PUSH1: - case OpCode.PUSH2: - case OpCode.PUSH3: - case OpCode.PUSH4: - case OpCode.PUSH5: - case OpCode.PUSH6: - case OpCode.PUSH7: - case OpCode.PUSH8: - case OpCode.PUSH9: - case OpCode.PUSH10: - case OpCode.PUSH11: - case OpCode.PUSH12: - case OpCode.PUSH13: - case OpCode.PUSH14: - case OpCode.PUSH15: - case OpCode.PUSH16: - { - Push((int)instruction.OpCode - (int)OpCode.PUSH0); - break; - } - - // Control - case OpCode.NOP: break; - case OpCode.JMP: - { - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMP_L: - { - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.JMPIF: - { - if (Pop().GetBoolean()) - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMPIF_L: - { - if (Pop().GetBoolean()) - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.JMPIFNOT: - { - if (!Pop().GetBoolean()) - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMPIFNOT_L: - { - if (!Pop().GetBoolean()) - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.JMPEQ: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 == x2) - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMPEQ_L: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 == x2) - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.JMPNE: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 != x2) - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMPNE_L: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 != x2) - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.JMPGT: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 > x2) - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMPGT_L: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 > x2) - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.JMPGE: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 >= x2) - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMPGE_L: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 >= x2) - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.JMPLT: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 < x2) - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMPLT_L: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 < x2) - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.JMPLE: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 <= x2) - ExecuteJumpOffset(instruction.TokenI8); - break; - } - case OpCode.JMPLE_L: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - if (x1 <= x2) - ExecuteJumpOffset(instruction.TokenI32); - break; - } - case OpCode.CALL: - { - ExecuteCall(checked(CurrentContext!.InstructionPointer + instruction.TokenI8)); - break; - } - case OpCode.CALL_L: - { - ExecuteCall(checked(CurrentContext!.InstructionPointer + instruction.TokenI32)); - break; - } - case OpCode.CALLA: - { - var x = Pop(); - if (x.Script != CurrentContext!.Script) - throw new InvalidOperationException("Pointers can't be shared between scripts"); - ExecuteCall(x.Position); - break; - } - case OpCode.CALLT: - { - LoadToken(instruction.TokenU16); - break; - } - case OpCode.ABORT: - { - throw new Exception($"{OpCode.ABORT} is executed."); - } - case OpCode.ASSERT: - { - var x = Pop().GetBoolean(); - if (!x) - throw new Exception($"{OpCode.ASSERT} is executed with false result."); - break; - } - case OpCode.THROW: - { - ExecuteThrow(Pop()); - break; - } - case OpCode.TRY: - { - int catchOffset = instruction.TokenI8; - int finallyOffset = instruction.TokenI8_1; - ExecuteTry(catchOffset, finallyOffset); - break; - } - case OpCode.TRY_L: - { - int catchOffset = instruction.TokenI32; - int finallyOffset = instruction.TokenI32_1; - ExecuteTry(catchOffset, finallyOffset); - break; - } - case OpCode.ENDTRY: - { - int endOffset = instruction.TokenI8; - ExecuteEndTry(endOffset); - break; - } - case OpCode.ENDTRY_L: - { - int endOffset = instruction.TokenI32; - ExecuteEndTry(endOffset); - break; - } - case OpCode.ENDFINALLY: - { - if (CurrentContext!.TryStack is null) - throw new InvalidOperationException($"The corresponding TRY block cannot be found."); - if (!CurrentContext.TryStack.TryPop(out ExceptionHandlingContext? currentTry)) - throw new InvalidOperationException($"The corresponding TRY block cannot be found."); - - if (UncaughtException is null) - CurrentContext.InstructionPointer = currentTry.EndPointer; - else - HandleException(); - - isJumping = true; - break; - } - case OpCode.RET: - { - ExecutionContext context_pop = InvocationStack.Pop(); - EvaluationStack stack_eval = InvocationStack.Count == 0 ? ResultStack : InvocationStack.Peek().EvaluationStack; - if (context_pop.EvaluationStack != stack_eval) - { - if (context_pop.RVCount >= 0 && context_pop.EvaluationStack.Count != context_pop.RVCount) - throw new InvalidOperationException("RVCount doesn't match with EvaluationStack"); - context_pop.EvaluationStack.CopyTo(stack_eval); - } - if (InvocationStack.Count == 0) - State = VMState.HALT; - ContextUnloaded(context_pop); - isJumping = true; - break; - } - case OpCode.SYSCALL: - { - OnSysCall(instruction.TokenU32); - break; - } - - // Stack ops - case OpCode.DEPTH: - { - Push(CurrentContext!.EvaluationStack.Count); - break; - } - case OpCode.DROP: - { - Pop(); - break; - } - case OpCode.NIP: - { - CurrentContext!.EvaluationStack.Remove(1); - break; - } - case OpCode.XDROP: - { - int n = (int)Pop().GetInteger(); - if (n < 0) - throw new InvalidOperationException($"The negative value {n} is invalid for OpCode.{instruction.OpCode}."); - CurrentContext!.EvaluationStack.Remove(n); - break; - } - case OpCode.CLEAR: - { - CurrentContext!.EvaluationStack.Clear(); - break; - } - case OpCode.DUP: - { - Push(Peek()); - break; - } - case OpCode.OVER: - { - Push(Peek(1)); - break; - } - case OpCode.PICK: - { - int n = (int)Pop().GetInteger(); - if (n < 0) - throw new InvalidOperationException($"The negative value {n} is invalid for OpCode.{instruction.OpCode}."); - Push(Peek(n)); - break; - } - case OpCode.TUCK: - { - CurrentContext!.EvaluationStack.Insert(2, Peek()); - break; - } - case OpCode.SWAP: - { - var x = CurrentContext!.EvaluationStack.Remove(1); - Push(x); - break; - } - case OpCode.ROT: - { - var x = CurrentContext!.EvaluationStack.Remove(2); - Push(x); - break; - } - case OpCode.ROLL: - { - int n = (int)Pop().GetInteger(); - if (n < 0) - throw new InvalidOperationException($"The negative value {n} is invalid for OpCode.{instruction.OpCode}."); - if (n == 0) break; - var x = CurrentContext!.EvaluationStack.Remove(n); - Push(x); - break; - } - case OpCode.REVERSE3: - { - CurrentContext!.EvaluationStack.Reverse(3); - break; - } - case OpCode.REVERSE4: - { - CurrentContext!.EvaluationStack.Reverse(4); - break; - } - case OpCode.REVERSEN: - { - int n = (int)Pop().GetInteger(); - CurrentContext!.EvaluationStack.Reverse(n); - break; - } - - //Slot - case OpCode.INITSSLOT: - { - if (CurrentContext!.StaticFields != null) - throw new InvalidOperationException($"{instruction.OpCode} cannot be executed twice."); - if (instruction.TokenU8 == 0) - throw new InvalidOperationException($"The operand {instruction.TokenU8} is invalid for OpCode.{instruction.OpCode}."); - CurrentContext.StaticFields = new Slot(instruction.TokenU8, ReferenceCounter); - break; - } - case OpCode.INITSLOT: - { - if (CurrentContext!.LocalVariables != null || CurrentContext.Arguments != null) - throw new InvalidOperationException($"{instruction.OpCode} cannot be executed twice."); - if (instruction.TokenU16 == 0) - throw new InvalidOperationException($"The operand {instruction.TokenU16} is invalid for OpCode.{instruction.OpCode}."); - if (instruction.TokenU8 > 0) - { - CurrentContext.LocalVariables = new Slot(instruction.TokenU8, ReferenceCounter); - } - if (instruction.TokenU8_1 > 0) - { - StackItem[] items = new StackItem[instruction.TokenU8_1]; - for (int i = 0; i < instruction.TokenU8_1; i++) - { - items[i] = Pop(); - } - CurrentContext.Arguments = new Slot(items, ReferenceCounter); - } - break; - } - case OpCode.LDSFLD0: - case OpCode.LDSFLD1: - case OpCode.LDSFLD2: - case OpCode.LDSFLD3: - case OpCode.LDSFLD4: - case OpCode.LDSFLD5: - case OpCode.LDSFLD6: - { - ExecuteLoadFromSlot(CurrentContext!.StaticFields, instruction.OpCode - OpCode.LDSFLD0); - break; - } - case OpCode.LDSFLD: - { - ExecuteLoadFromSlot(CurrentContext!.StaticFields, instruction.TokenU8); - break; - } - case OpCode.STSFLD0: - case OpCode.STSFLD1: - case OpCode.STSFLD2: - case OpCode.STSFLD3: - case OpCode.STSFLD4: - case OpCode.STSFLD5: - case OpCode.STSFLD6: - { - ExecuteStoreToSlot(CurrentContext!.StaticFields, instruction.OpCode - OpCode.STSFLD0); - break; - } - case OpCode.STSFLD: - { - ExecuteStoreToSlot(CurrentContext!.StaticFields, instruction.TokenU8); - break; - } - case OpCode.LDLOC0: - case OpCode.LDLOC1: - case OpCode.LDLOC2: - case OpCode.LDLOC3: - case OpCode.LDLOC4: - case OpCode.LDLOC5: - case OpCode.LDLOC6: - { - ExecuteLoadFromSlot(CurrentContext!.LocalVariables, instruction.OpCode - OpCode.LDLOC0); - break; - } - case OpCode.LDLOC: - { - ExecuteLoadFromSlot(CurrentContext!.LocalVariables, instruction.TokenU8); - break; - } - case OpCode.STLOC0: - case OpCode.STLOC1: - case OpCode.STLOC2: - case OpCode.STLOC3: - case OpCode.STLOC4: - case OpCode.STLOC5: - case OpCode.STLOC6: - { - ExecuteStoreToSlot(CurrentContext!.LocalVariables, instruction.OpCode - OpCode.STLOC0); - break; - } - case OpCode.STLOC: - { - ExecuteStoreToSlot(CurrentContext!.LocalVariables, instruction.TokenU8); - break; - } - case OpCode.LDARG0: - case OpCode.LDARG1: - case OpCode.LDARG2: - case OpCode.LDARG3: - case OpCode.LDARG4: - case OpCode.LDARG5: - case OpCode.LDARG6: - { - ExecuteLoadFromSlot(CurrentContext!.Arguments, instruction.OpCode - OpCode.LDARG0); - break; - } - case OpCode.LDARG: - { - ExecuteLoadFromSlot(CurrentContext!.Arguments, instruction.TokenU8); - break; - } - case OpCode.STARG0: - case OpCode.STARG1: - case OpCode.STARG2: - case OpCode.STARG3: - case OpCode.STARG4: - case OpCode.STARG5: - case OpCode.STARG6: - { - ExecuteStoreToSlot(CurrentContext!.Arguments, instruction.OpCode - OpCode.STARG0); - break; - } - case OpCode.STARG: - { - ExecuteStoreToSlot(CurrentContext!.Arguments, instruction.TokenU8); - break; - } - - // Splice - case OpCode.NEWBUFFER: - { - int length = (int)Pop().GetInteger(); - Limits.AssertMaxItemSize(length); - Push(new Buffer(length)); - break; - } - case OpCode.MEMCPY: - { - int count = (int)Pop().GetInteger(); - if (count < 0) - throw new InvalidOperationException($"The value {count} is out of range."); - int si = (int)Pop().GetInteger(); - if (si < 0) - throw new InvalidOperationException($"The value {si} is out of range."); - ReadOnlySpan src = Pop().GetSpan(); - if (checked(si + count) > src.Length) - throw new InvalidOperationException($"The value {count} is out of range."); - int di = (int)Pop().GetInteger(); - if (di < 0) - throw new InvalidOperationException($"The value {di} is out of range."); - Buffer dst = Pop(); - if (checked(di + count) > dst.Size) - throw new InvalidOperationException($"The value {count} is out of range."); - src.Slice(si, count).CopyTo(dst.InnerBuffer.Span[di..]); - break; - } - case OpCode.CAT: - { - var x2 = Pop().GetSpan(); - var x1 = Pop().GetSpan(); - int length = x1.Length + x2.Length; - Limits.AssertMaxItemSize(length); - Buffer result = new(length, false); - x1.CopyTo(result.InnerBuffer.Span); - x2.CopyTo(result.InnerBuffer.Span[x1.Length..]); - Push(result); - break; - } - case OpCode.SUBSTR: - { - int count = (int)Pop().GetInteger(); - if (count < 0) - throw new InvalidOperationException($"The value {count} is out of range."); - int index = (int)Pop().GetInteger(); - if (index < 0) - throw new InvalidOperationException($"The value {index} is out of range."); - var x = Pop().GetSpan(); - if (index + count > x.Length) - throw new InvalidOperationException($"The value {count} is out of range."); - Buffer result = new(count, false); - x.Slice(index, count).CopyTo(result.InnerBuffer.Span); - Push(result); - break; - } - case OpCode.LEFT: - { - int count = (int)Pop().GetInteger(); - if (count < 0) - throw new InvalidOperationException($"The value {count} is out of range."); - var x = Pop().GetSpan(); - if (count > x.Length) - throw new InvalidOperationException($"The value {count} is out of range."); - Buffer result = new(count, false); - x[..count].CopyTo(result.InnerBuffer.Span); - Push(result); - break; - } - case OpCode.RIGHT: - { - int count = (int)Pop().GetInteger(); - if (count < 0) - throw new InvalidOperationException($"The value {count} is out of range."); - var x = Pop().GetSpan(); - if (count > x.Length) - throw new InvalidOperationException($"The value {count} is out of range."); - Buffer result = new(count, false); - x[^count..^0].CopyTo(result.InnerBuffer.Span); - Push(result); - break; - } - - // Bitwise logic - case OpCode.INVERT: - { - var x = Pop().GetInteger(); - Push(~x); - break; - } - case OpCode.AND: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 & x2); - break; - } - case OpCode.OR: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 | x2); - break; - } - case OpCode.XOR: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 ^ x2); - break; - } - case OpCode.EQUAL: - { - StackItem x2 = Pop(); - StackItem x1 = Pop(); - Push(x1.Equals(x2, Limits)); - break; - } - case OpCode.NOTEQUAL: - { - StackItem x2 = Pop(); - StackItem x1 = Pop(); - Push(!x1.Equals(x2, Limits)); - break; - } - - // Numeric - case OpCode.SIGN: - { - var x = Pop().GetInteger(); - Push(x.Sign); - break; - } - case OpCode.ABS: - { - var x = Pop().GetInteger(); - Push(BigInteger.Abs(x)); - break; - } - case OpCode.NEGATE: - { - var x = Pop().GetInteger(); - Push(-x); - break; - } - case OpCode.INC: - { - var x = Pop().GetInteger(); - Push(x + 1); - break; - } - case OpCode.DEC: - { - var x = Pop().GetInteger(); - Push(x - 1); - break; - } - case OpCode.ADD: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 + x2); - break; - } - case OpCode.SUB: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 - x2); - break; - } - case OpCode.MUL: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 * x2); - break; - } - case OpCode.DIV: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 / x2); - break; - } - case OpCode.MOD: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 % x2); - break; - } - case OpCode.POW: - { - var exponent = (int)Pop().GetInteger(); - Limits.AssertShift(exponent); - var value = Pop().GetInteger(); - Push(BigInteger.Pow(value, exponent)); - break; - } - case OpCode.SQRT: - { - Push(Pop().GetInteger().Sqrt()); - break; - } - case OpCode.MODMUL: - { - var modulus = Pop().GetInteger(); - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 * x2 % modulus); - break; - } - case OpCode.MODPOW: - { - var modulus = Pop().GetInteger(); - var exponent = Pop().GetInteger(); - var value = Pop().GetInteger(); - var result = exponent == -1 - ? value.ModInverse(modulus) - : BigInteger.ModPow(value, exponent, modulus); - Push(result); - break; - } - case OpCode.SHL: - { - int shift = (int)Pop().GetInteger(); - Limits.AssertShift(shift); - if (shift == 0) break; - var x = Pop().GetInteger(); - Push(x << shift); - break; - } - case OpCode.SHR: - { - int shift = (int)Pop().GetInteger(); - Limits.AssertShift(shift); - if (shift == 0) break; - var x = Pop().GetInteger(); - Push(x >> shift); - break; - } - case OpCode.NOT: - { - var x = Pop().GetBoolean(); - Push(!x); - break; - } - case OpCode.BOOLAND: - { - var x2 = Pop().GetBoolean(); - var x1 = Pop().GetBoolean(); - Push(x1 && x2); - break; - } - case OpCode.BOOLOR: - { - var x2 = Pop().GetBoolean(); - var x1 = Pop().GetBoolean(); - Push(x1 || x2); - break; - } - case OpCode.NZ: - { - var x = Pop().GetInteger(); - Push(!x.IsZero); - break; - } - case OpCode.NUMEQUAL: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 == x2); - break; - } - case OpCode.NUMNOTEQUAL: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(x1 != x2); - break; - } - case OpCode.LT: - { - var x2 = Pop(); - var x1 = Pop(); - if (x1.IsNull || x2.IsNull) - Push(false); - else - Push(x1.GetInteger() < x2.GetInteger()); - break; - } - case OpCode.LE: - { - var x2 = Pop(); - var x1 = Pop(); - if (x1.IsNull || x2.IsNull) - Push(false); - else - Push(x1.GetInteger() <= x2.GetInteger()); - break; - } - case OpCode.GT: - { - var x2 = Pop(); - var x1 = Pop(); - if (x1.IsNull || x2.IsNull) - Push(false); - else - Push(x1.GetInteger() > x2.GetInteger()); - break; - } - case OpCode.GE: - { - var x2 = Pop(); - var x1 = Pop(); - if (x1.IsNull || x2.IsNull) - Push(false); - else - Push(x1.GetInteger() >= x2.GetInteger()); - break; - } - case OpCode.MIN: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(BigInteger.Min(x1, x2)); - break; - } - case OpCode.MAX: - { - var x2 = Pop().GetInteger(); - var x1 = Pop().GetInteger(); - Push(BigInteger.Max(x1, x2)); - break; - } - case OpCode.WITHIN: - { - BigInteger b = Pop().GetInteger(); - BigInteger a = Pop().GetInteger(); - var x = Pop().GetInteger(); - Push(a <= x && x < b); - break; - } - - // Compound-type - case OpCode.PACKMAP: - { - 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); - for (int i = 0; i < size; i++) - { - PrimitiveType key = Pop(); - StackItem value = Pop(); - map[key] = value; - } - Push(map); - break; - } - case OpCode.PACKSTRUCT: - { - 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); - for (int i = 0; i < size; i++) - { - StackItem item = Pop(); - @struct.Add(item); - } - Push(@struct); - break; - } - case OpCode.PACK: - { - 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); - for (int i = 0; i < size; i++) - { - StackItem item = Pop(); - array.Add(item); - } - Push(array); - break; - } - case OpCode.UNPACK: - { - CompoundType compound = Pop(); - switch (compound) - { - case Map map: - foreach (var (key, value) in map.Reverse()) - { - Push(value); - Push(key); - } - break; - case VMArray array: - for (int i = array.Count - 1; i >= 0; i--) - { - Push(array[i]); - } - break; - default: - throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {compound.Type}"); - } - Push(compound.Count); - break; - } - case OpCode.NEWARRAY0: - { - Push(new VMArray(ReferenceCounter)); - break; - } - case OpCode.NEWARRAY: - case OpCode.NEWARRAY_T: - { - int n = (int)Pop().GetInteger(); - if (n < 0 || n > Limits.MaxStackSize) - throw new InvalidOperationException($"MaxStackSize exceed: {n}"); - StackItem item; - if (instruction.OpCode == OpCode.NEWARRAY_T) - { - StackItemType type = (StackItemType)instruction.TokenU8; - if (!Enum.IsDefined(typeof(StackItemType), type)) - throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {instruction.TokenU8}"); - item = instruction.TokenU8 switch - { - (byte)StackItemType.Boolean => StackItem.False, - (byte)StackItemType.Integer => Integer.Zero, - (byte)StackItemType.ByteString => ByteString.Empty, - _ => StackItem.Null - }; - } - else - { - item = StackItem.Null; - } - Push(new VMArray(ReferenceCounter, Enumerable.Repeat(item, n))); - break; - } - case OpCode.NEWSTRUCT0: - { - Push(new Struct(ReferenceCounter)); - break; - } - case OpCode.NEWSTRUCT: - { - int n = (int)Pop().GetInteger(); - if (n < 0 || n > Limits.MaxStackSize) - throw new InvalidOperationException($"MaxStackSize exceed: {n}"); - Struct result = new(ReferenceCounter); - for (var i = 0; i < n; i++) - result.Add(StackItem.Null); - Push(result); - break; - } - case OpCode.NEWMAP: - { - Push(new Map(ReferenceCounter)); - break; - } - case OpCode.SIZE: - { - var x = Pop(); - switch (x) - { - case CompoundType compound: - Push(compound.Count); - break; - case PrimitiveType primitive: - Push(primitive.Size); - break; - case Buffer buffer: - Push(buffer.Size); - break; - default: - throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); - } - break; - } - case OpCode.HASKEY: - { - PrimitiveType key = Pop(); - var x = Pop(); - switch (x) - { - case VMArray array: - { - int index = (int)key.GetInteger(); - if (index < 0) - throw new InvalidOperationException($"The negative value {index} is invalid for OpCode.{instruction.OpCode}."); - Push(index < array.Count); - break; - } - case Map map: - { - Push(map.ContainsKey(key)); - break; - } - case Buffer buffer: - { - int index = (int)key.GetInteger(); - if (index < 0) - throw new InvalidOperationException($"The negative value {index} is invalid for OpCode.{instruction.OpCode}."); - Push(index < buffer.Size); - break; - } - case ByteString array: - { - int index = (int)key.GetInteger(); - if (index < 0) - throw new InvalidOperationException($"The negative value {index} is invalid for OpCode.{instruction.OpCode}."); - Push(index < array.Size); - break; - } - default: - throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); - } - break; - } - case OpCode.KEYS: - { - Map map = Pop(); - Push(new VMArray(ReferenceCounter, map.Keys)); - break; - } - case OpCode.VALUES: - { - var x = Pop(); - IEnumerable values = x switch - { - VMArray array => array, - Map map => map.Values, - _ => throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"), - }; - VMArray newArray = new(ReferenceCounter); - foreach (StackItem item in values) - if (item is Struct s) - newArray.Add(s.Clone(Limits)); - else - newArray.Add(item); - Push(newArray); - break; - } - case OpCode.PICKITEM: - { - PrimitiveType key = Pop(); - var x = Pop(); - switch (x) - { - case VMArray array: - { - int index = (int)key.GetInteger(); - if (index < 0 || index >= array.Count) - throw new CatchableException($"The value {index} is out of range."); - Push(array[index]); - break; - } - case Map map: - { - if (!map.TryGetValue(key, out StackItem? value)) - throw new CatchableException($"Key not found in {nameof(Map)}"); - Push(value); - break; - } - case PrimitiveType primitive: - { - ReadOnlySpan byteArray = primitive.GetSpan(); - int index = (int)key.GetInteger(); - if (index < 0 || index >= byteArray.Length) - throw new CatchableException($"The value {index} is out of range."); - Push((BigInteger)byteArray[index]); - break; - } - case Buffer buffer: - { - int index = (int)key.GetInteger(); - if (index < 0 || index >= buffer.Size) - throw new CatchableException($"The value {index} is out of range."); - Push((BigInteger)buffer.InnerBuffer.Span[index]); - break; - } - default: - throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); - } - break; - } - case OpCode.APPEND: - { - StackItem newItem = Pop(); - VMArray array = Pop(); - if (newItem is Struct s) newItem = s.Clone(Limits); - array.Add(newItem); - break; - } - case OpCode.SETITEM: - { - StackItem value = Pop(); - if (value is Struct s) value = s.Clone(Limits); - PrimitiveType key = Pop(); - var x = Pop(); - switch (x) - { - case VMArray array: - { - int index = (int)key.GetInteger(); - if (index < 0 || index >= array.Count) - throw new CatchableException($"The value {index} is out of range."); - array[index] = value; - break; - } - case Map map: - { - map[key] = value; - break; - } - case Buffer buffer: - { - 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) - throw new InvalidOperationException($"Value must be a primitive type in {instruction.OpCode}"); - int b = (int)p.GetInteger(); - if (b < sbyte.MinValue || b > byte.MaxValue) - throw new InvalidOperationException($"Overflow in {instruction.OpCode}, {b} is not a byte type."); - buffer.InnerBuffer.Span[index] = (byte)b; - break; - } - default: - throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); - } - break; - } - case OpCode.REVERSEITEMS: - { - var x = Pop(); - switch (x) - { - case VMArray array: - array.Reverse(); - break; - case Buffer buffer: - buffer.InnerBuffer.Span.Reverse(); - break; - default: - throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); - } - break; - } - case OpCode.REMOVE: - { - PrimitiveType key = Pop(); - var x = Pop(); - switch (x) - { - case VMArray array: - int index = (int)key.GetInteger(); - if (index < 0 || index >= array.Count) - throw new InvalidOperationException($"The value {index} is out of range."); - array.RemoveAt(index); - break; - case Map map: - map.Remove(key); - break; - default: - throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); - } - break; - } - case OpCode.CLEARITEMS: - { - CompoundType x = Pop(); - x.Clear(); - break; - } - case OpCode.POPITEM: - { - VMArray x = Pop(); - int index = x.Count - 1; - Push(x[index]); - x.RemoveAt(index); - break; - } - - //Types - case OpCode.ISNULL: - { - var x = Pop(); - Push(x.IsNull); - break; - } - case OpCode.ISTYPE: - { - var x = Pop(); - StackItemType type = (StackItemType)instruction.TokenU8; - if (type == StackItemType.Any || !Enum.IsDefined(typeof(StackItemType), type)) - throw new InvalidOperationException($"Invalid type: {type}"); - Push(x.Type == type); - break; - } - case OpCode.CONVERT: - { - var x = Pop(); - Push(x.ConvertTo((StackItemType)instruction.TokenU8)); - break; - } - case OpCode.ABORTMSG: - { - var msg = Pop().GetString(); - throw new Exception($"{OpCode.ABORTMSG} is executed. Reason: {msg}"); - } - case OpCode.ASSERTMSG: - { - var msg = Pop().GetString(); - var x = Pop().GetBoolean(); - if (!x) - throw new Exception($"{OpCode.ASSERTMSG} is executed with false result. Reason: {msg}"); - break; - } - default: throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ExecuteEndTry(int endOffset) { @@ -1442,7 +190,7 @@ protected void ExecuteJump(int position) /// /// The offset from the current position to jump to. [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void ExecuteJumpOffset(int offset) + public void ExecuteJumpOffset(int offset) { ExecuteJump(checked(CurrentContext!.InstructionPointer + offset)); } @@ -1474,7 +222,7 @@ protected internal void ExecuteNext() PreExecuteInstruction(instruction); try { - ExecuteInstruction(instruction); + JumpTable.GetMethod(instruction.OpCode)(this, instruction); } catch (CatchableException ex) when (Limits.CatchEngineExceptions) { diff --git a/src/Neo.VM/JumpTable.Control.cs b/src/Neo.VM/JumpTable.Control.cs new file mode 100644 index 0000000000..0c2a2aa694 --- /dev/null +++ b/src/Neo.VM/JumpTable.Control.cs @@ -0,0 +1,180 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Control.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Runtime.CompilerServices; + +namespace Neo.VM +{ + public partial class JumpTable + { + /* TODO + case OpCode.JMPGT: + JmpGt(instruction); + break; + case OpCode.JMPGT_L: + JmpGt_L(instruction); + break; + case OpCode.JMPGE: + JmpGe(instruction); + break; + case OpCode.JMPGE_L: + JmpGe_L(instruction); + break; + case OpCode.JMPLT: + JmpLt(instruction); + break; + case OpCode.JMPLT_L: + JmpLt_L(instruction); + break; + case OpCode.JMPLE: + JmpLe(instruction); + break; + case OpCode.JMPLE_L: + JmpLe_L(instruction); + break; + case OpCode.CALL: + Call(instruction); + break; + case OpCode.CALL_L: + Call_L(instruction); + break; + case OpCode.CALLA: + CallA(instruction); + break; + case OpCode.CALLT: + CallT(instruction); + break; + case OpCode.ABORT: + Abort(instruction); + break; + case OpCode.ASSERT: + Assert(instruction); + break; + case OpCode.THROW: + Throw(instruction); + break; + case OpCode.TRY: + Try(instruction); + break; + case OpCode.TRY_L: + Try_L(instruction); + break; + case OpCode.ENDTRY: + EndTry(instruction); + break; + case OpCode.ENDTRY_L: + EndTry_L(instruction); + break; + case OpCode.ENDFINALLY: + EndFinally(instruction); + break; + case OpCode.RET: + Ret(instruction); + break; + case OpCode.SYSCALL: + Syscall(instruction); + break; + + */ + + [OpcodeMethod(OpCode.NOP)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Nop(ExecutionEngine engine, Instruction instruction) + { + } + + [OpcodeMethod(OpCode.JMP)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Jmp(ExecutionEngine engine, Instruction instruction) + { + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMP_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpL(ExecutionEngine engine, Instruction instruction) + { + engine.ExecuteJumpOffset(instruction.TokenI32); + } + + [OpcodeMethod(OpCode.JMPIF)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpIf(ExecutionEngine engine, Instruction instruction) + { + if (engine.Pop().GetBoolean()) + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMPIF_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpIfL(ExecutionEngine engine, Instruction instruction) + { + if (engine.Pop().GetBoolean()) + engine.ExecuteJumpOffset(instruction.TokenI32); + } + + [OpcodeMethod(OpCode.JMPIFNOT)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpIfNot(ExecutionEngine engine, Instruction instruction) + { + if (!engine.Pop().GetBoolean()) + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMPIFNOT_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpIfNotL(ExecutionEngine engine, Instruction instruction) + { + if (!engine.Pop().GetBoolean()) + engine.ExecuteJumpOffset(instruction.TokenI32); + } + + [OpcodeMethod(OpCode.JMPEQ)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpEq(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 == x2) + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMPEQ_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpEqL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 == x2) + engine.ExecuteJumpOffset(instruction.TokenI32); + } + + [OpcodeMethod(OpCode.JMPNE)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpNe(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 != x2) + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMPNE_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpNeL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 != x2) + engine.ExecuteJumpOffset(instruction.TokenI32); + } + } +} diff --git a/src/Neo.VM/JumpTable.Push.cs b/src/Neo.VM/JumpTable.Push.cs new file mode 100644 index 0000000000..e15910778a --- /dev/null +++ b/src/Neo.VM/JumpTable.Push.cs @@ -0,0 +1,98 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Push.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo.VM.Types; +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace Neo.VM +{ + public partial class JumpTable + { + [OpcodeMethod(OpCode.PUSHINT8)] + [OpcodeMethod(OpCode.PUSHINT16)] + [OpcodeMethod(OpCode.PUSHINT32)] + [OpcodeMethod(OpCode.PUSHINT64)] + [OpcodeMethod(OpCode.PUSHINT128)] + [OpcodeMethod(OpCode.PUSHINT256)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PushInt(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new BigInteger(instruction.Operand.Span)); + } + + [OpcodeMethod(OpCode.PUSHT)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PushT(ExecutionEngine engine, Instruction instruction) + { + engine.Push(StackItem.True); + } + + [OpcodeMethod(OpCode.PUSHF)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PushF(ExecutionEngine engine, Instruction instruction) + { + engine.Push(StackItem.False); + } + + [OpcodeMethod(OpCode.PUSHA)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PushA(ExecutionEngine engine, Instruction instruction) + { + var position = checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI32); + if (position < 0 || position > engine.CurrentContext.Script.Length) + throw new InvalidOperationException($"Bad pointer address(Instruction instruction) {position}"); + engine.Push(new Pointer(engine.CurrentContext.Script, position)); + } + + [OpcodeMethod(OpCode.PUSHNULL)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PushNull(ExecutionEngine engine, Instruction instruction) + { + engine.Push(StackItem.Null); + } + + [OpcodeMethod(OpCode.PUSHDATA1)] + [OpcodeMethod(OpCode.PUSHDATA2)] + [OpcodeMethod(OpCode.PUSHDATA4)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PushData(ExecutionEngine engine, Instruction instruction) + { + engine.Limits.AssertMaxItemSize(instruction.Operand.Length); + engine.Push(instruction.Operand); + } + + [OpcodeMethod(OpCode.PUSHM1)] + [OpcodeMethod(OpCode.PUSH0)] + [OpcodeMethod(OpCode.PUSH1)] + [OpcodeMethod(OpCode.PUSH2)] + [OpcodeMethod(OpCode.PUSH3)] + [OpcodeMethod(OpCode.PUSH4)] + [OpcodeMethod(OpCode.PUSH5)] + [OpcodeMethod(OpCode.PUSH6)] + [OpcodeMethod(OpCode.PUSH7)] + [OpcodeMethod(OpCode.PUSH8)] + [OpcodeMethod(OpCode.PUSH9)] + [OpcodeMethod(OpCode.PUSH10)] + [OpcodeMethod(OpCode.PUSH11)] + [OpcodeMethod(OpCode.PUSH12)] + [OpcodeMethod(OpCode.PUSH13)] + [OpcodeMethod(OpCode.PUSH14)] + [OpcodeMethod(OpCode.PUSH15)] + [OpcodeMethod(OpCode.PUSH16)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Push(ExecutionEngine engine, Instruction instruction) + { + engine.Push((int)instruction.OpCode - (int)OpCode.PUSH0); + } + } +} diff --git a/src/Neo.VM/JumpTable.cs b/src/Neo.VM/JumpTable.cs new file mode 100644 index 0000000000..0a352567a0 --- /dev/null +++ b/src/Neo.VM/JumpTable.cs @@ -0,0 +1,406 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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; +using System.Reflection; + +namespace Neo.VM +{ + public partial class JumpTable + { + public delegate void delAction(ExecutionEngine engine, Instruction instruction); + public readonly delAction[] Table = new delAction[byte.MaxValue]; + + /// + /// Get Method + /// + /// OpCode + /// Action + public delAction GetMethod(OpCode opCode) + { + return Table[(byte)opCode]; + } + + public JumpTable() + { + // Fill defined + + foreach (var mi in GetType().GetMethods()) + { + foreach (var attr in mi.GetCustomAttributes(true)) + { + if (Table[(byte)attr.OpCode] is not null) + { + throw new InvalidOperationException($"Opcode {attr.OpCode} is already defined."); + } + + Table[(byte)attr.OpCode] = (delAction)mi.CreateDelegate(typeof(delAction), this); + } + } + + // Fill with undefined + + for (int x = 0; x < Table.Length; x++) + { + if (Table[x] is not null) continue; + + Table[x] = (engine, instruction) => + { + throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); + }; + } + + /* + switch (instruction.OpCode) + { + // Stack ops + case OpCode.DEPTH: + Depth(instruction); + break; + case OpCode.DROP: + Drop(instruction); + break; + case OpCode.NIP: + Nip(instruction); + break; + case OpCode.XDROP: + XDrop(instruction); + break; + case OpCode.CLEAR: + Clear(instruction); + break; + case OpCode.DUP: + Dup(instruction); + break; + case OpCode.OVER: + Over(instruction); + break; + case OpCode.PICK: + Pick(instruction); + break; + case OpCode.TUCK: + Tuck(instruction); + break; + case OpCode.SWAP: + Swap(instruction); + break; + case OpCode.ROT: + Rot(instruction); + break; + case OpCode.ROLL: + Roll(instruction); + break; + case OpCode.REVERSE3: + Reverse3(instruction); + break; + case OpCode.REVERSE4: + Reverse4(instruction); + break; + case OpCode.REVERSEN: + ReverseN(instruction); + break; + + //Slot + case OpCode.INITSSLOT: + InitSSlot(instruction); + break; + case OpCode.INITSLOT: + InitSlot(instruction); + break; + case OpCode.LDSFLD0: + case OpCode.LDSFLD1: + case OpCode.LDSFLD2: + case OpCode.LDSFLD3: + case OpCode.LDSFLD4: + case OpCode.LDSFLD5: + case OpCode.LDSFLD6: + LdSFldM(instruction); + break; + case OpCode.LDSFLD: + LdSFld(instruction); + break; + case OpCode.STSFLD0: + case OpCode.STSFLD1: + case OpCode.STSFLD2: + case OpCode.STSFLD3: + case OpCode.STSFLD4: + case OpCode.STSFLD5: + case OpCode.STSFLD6: + StSFldM(instruction); + break; + case OpCode.STSFLD: + StSFld(instruction); + break; + case OpCode.LDLOC0: + case OpCode.LDLOC1: + case OpCode.LDLOC2: + case OpCode.LDLOC3: + case OpCode.LDLOC4: + case OpCode.LDLOC5: + case OpCode.LDLOC6: + LdLocM(instruction); + break; + case OpCode.LDLOC: + LdLoc(instruction); + break; + case OpCode.STLOC0: + case OpCode.STLOC1: + case OpCode.STLOC2: + case OpCode.STLOC3: + case OpCode.STLOC4: + case OpCode.STLOC5: + case OpCode.STLOC6: + StLocM(instruction); + break; + case OpCode.STLOC: + StLoc(instruction); + break; + case OpCode.LDARG0: + case OpCode.LDARG1: + case OpCode.LDARG2: + case OpCode.LDARG3: + case OpCode.LDARG4: + case OpCode.LDARG5: + case OpCode.LDARG6: + LdArgM(instruction); + break; + case OpCode.LDARG: + LdArg(instruction); + break; + case OpCode.STARG0: + case OpCode.STARG1: + case OpCode.STARG2: + case OpCode.STARG3: + case OpCode.STARG4: + case OpCode.STARG5: + case OpCode.STARG6: + StArgM(instruction); + break; + case OpCode.STARG: + StArg(instruction); + break; + + // Splice + case OpCode.NEWBUFFER: + NewBuffer(instruction); + break; + case OpCode.MEMCPY: + Memcpy(instruction); + break; + case OpCode.CAT: + Cat(instruction); + break; + case OpCode.SUBSTR: + Substr(instruction); + break; + case OpCode.LEFT: + Left(instruction); + break; + case OpCode.RIGHT: + Right(instruction); + break; + + // Bitwise logic + case OpCode.INVERT: + Invert(instruction); + break; + case OpCode.AND: + And(instruction); + break; + case OpCode.OR: + Or(instruction); + break; + case OpCode.XOR: + Xor(instruction); + break; + case OpCode.EQUAL: + Equal(instruction); + break; + case OpCode.NOTEQUAL: + NotEqual(instruction); + break; + + // Numeric + case OpCode.SIGN: + Sign(instruction); + break; + case OpCode.ABS: + Abs(instruction); + break; + case OpCode.NEGATE: + Negate(instruction); + break; + case OpCode.INC: + Inc(instruction); + break; + case OpCode.DEC: + Dec(instruction); + break; + case OpCode.ADD: + Add(instruction); + break; + case OpCode.SUB: + Sub(instruction); + break; + case OpCode.MUL: + Mul(instruction); + break; + case OpCode.DIV: + Div(instruction); + break; + case OpCode.MOD: + Mod(instruction); + break; + case OpCode.POW: + Pow(instruction); + break; + case OpCode.SQRT: + Sqrt(instruction); + break; + case OpCode.MODMUL: + ModMul(instruction); + break; + case OpCode.MODPOW: + ModPow(instruction); + break; + case OpCode.SHL: + Shl(instruction); + break; + case OpCode.SHR: + Shr(instruction); + break; + case OpCode.NOT: + Not(instruction); + break; + case OpCode.BOOLAND: + BoolAnd(instruction); + break; + case OpCode.BOOLOR: + BoolOr(instruction); + break; + case OpCode.NZ: + Nz(instruction); + break; + case OpCode.NUMEQUAL: + NumEqual(instruction); + break; + case OpCode.NUMNOTEQUAL: + NumNotEqual(instruction); + break; + case OpCode.LT: + Lt(instruction); + break; + case OpCode.LE: + Le(instruction); + break; + case OpCode.GT: + Gt(instruction); + break; + case OpCode.GE: + Ge(instruction); + break; + case OpCode.MIN: + Min(instruction); + break; + case OpCode.MAX: + Max(instruction); + break; + case OpCode.WITHIN: + Within(instruction); + break; + + // Compound-type + case OpCode.PACKMAP: + PackMap(instruction); + break; + case OpCode.PACKSTRUCT: + PackStruct(instruction); + break; + case OpCode.PACK: + Pack(instruction); + break; + case OpCode.UNPACK: + Unpack(instruction); + break; + case OpCode.NEWARRAY0: + NewArray0(instruction); + break; + case OpCode.NEWARRAY: + case OpCode.NEWARRAY_T: + NewArray_T(instruction); + break; + case OpCode.NEWSTRUCT0: + NewStruct0(instruction); + break; + case OpCode.NEWSTRUCT: + NewStruct(instruction); + break; + case OpCode.NEWMAP: + NewMap(instruction); + break; + case OpCode.SIZE: + Size(instruction); + break; + case OpCode.HASKEY: + HasKey(instruction); + break; + case OpCode.KEYS: + Keys(instruction); + break; + case OpCode.VALUES: + Values(instruction); + break; + case OpCode.PICKITEM: + PickItem(instruction); + break; + case OpCode.APPEND: + Append(instruction); + break; + case OpCode.SETITEM: + SetItem(instruction); + break; + case OpCode.REVERSEITEMS: + ReverseItems(instruction); + break; + case OpCode.REMOVE: + Remove(instruction); + break; + case OpCode.CLEARITEMS: + ClearItems(instruction); + break; + case OpCode.POPITEM: + PopItem(instruction); + break; + + //Types + case OpCode.ISNULL: + IsNull(instruction); + break; + case OpCode.ISTYPE: + IsType(instruction); + break; + case OpCode.CONVERT: + Convert(instruction); + break; + case OpCode.ABORTMSG: + AbortMsg(instruction); + break; + case OpCode.ASSERTMSG: + AssertMsg(instruction); + break; + default: + throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); + } + */ + } + + } +} diff --git a/src/Neo.VM/OpcodeMethodAttribute.cs b/src/Neo.VM/OpcodeMethodAttribute.cs new file mode 100644 index 0000000000..3a91233728 --- /dev/null +++ b/src/Neo.VM/OpcodeMethodAttribute.cs @@ -0,0 +1,36 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// OpcodeMethodAttribute.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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; + +namespace Neo.VM +{ + /// + /// Indicates the . + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public class OpcodeMethodAttribute : Attribute + { + /// + /// The method is for this Opcode + /// + public OpCode OpCode { get; set; } + + /// + /// Constructor + /// + /// OpCode + public OpcodeMethodAttribute(OpCode opCode) + { + OpCode = opCode; + } + } +} From 4537325c8f9236e2816db58750747c8145fd629c Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 6 Feb 2024 19:12:27 +0100 Subject: [PATCH 02/34] Types --- src/Neo.VM/JumpTable.Control.cs | 45 ----------------------- src/Neo.VM/JumpTable.Types.cs | 65 +++++++++++++++++++++++++++++++++ src/Neo.VM/JumpTable.cs | 40 ++++++-------------- 3 files changed, 76 insertions(+), 74 deletions(-) create mode 100644 src/Neo.VM/JumpTable.Types.cs diff --git a/src/Neo.VM/JumpTable.Control.cs b/src/Neo.VM/JumpTable.Control.cs index 0c2a2aa694..4015ef426c 100644 --- a/src/Neo.VM/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable.Control.cs @@ -17,72 +17,27 @@ public partial class JumpTable { /* TODO case OpCode.JMPGT: - JmpGt(instruction); - break; case OpCode.JMPGT_L: - JmpGt_L(instruction); - break; case OpCode.JMPGE: - JmpGe(instruction); - break; case OpCode.JMPGE_L: - JmpGe_L(instruction); - break; case OpCode.JMPLT: - JmpLt(instruction); - break; case OpCode.JMPLT_L: - JmpLt_L(instruction); - break; case OpCode.JMPLE: - JmpLe(instruction); - break; case OpCode.JMPLE_L: - JmpLe_L(instruction); - break; case OpCode.CALL: - Call(instruction); - break; case OpCode.CALL_L: - Call_L(instruction); - break; case OpCode.CALLA: - CallA(instruction); - break; case OpCode.CALLT: - CallT(instruction); - break; case OpCode.ABORT: - Abort(instruction); - break; case OpCode.ASSERT: - Assert(instruction); - break; case OpCode.THROW: - Throw(instruction); - break; case OpCode.TRY: - Try(instruction); - break; case OpCode.TRY_L: - Try_L(instruction); - break; case OpCode.ENDTRY: - EndTry(instruction); - break; case OpCode.ENDTRY_L: - EndTry_L(instruction); - break; case OpCode.ENDFINALLY: - EndFinally(instruction); - break; case OpCode.RET: - Ret(instruction); - break; case OpCode.SYSCALL: - Syscall(instruction); - break; - */ [OpcodeMethod(OpCode.NOP)] diff --git a/src/Neo.VM/JumpTable.Types.cs b/src/Neo.VM/JumpTable.Types.cs new file mode 100644 index 0000000000..b8c1da6cf3 --- /dev/null +++ b/src/Neo.VM/JumpTable.Types.cs @@ -0,0 +1,65 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Types.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo.VM.Types; +using System; +using System.Runtime.CompilerServices; + +namespace Neo.VM +{ + public partial class JumpTable + { + [OpcodeMethod(OpCode.ISNULL)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void IsNull(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + engine.Push(x.IsNull); + } + + [OpcodeMethod(OpCode.ISTYPE)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void IsType(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + var type = (StackItemType)instruction.TokenU8; + if (type == StackItemType.Any || !Enum.IsDefined(typeof(StackItemType), type)) + throw new InvalidOperationException($"Invalid type: {type}"); + engine.Push(x.Type == type); + } + + [OpcodeMethod(OpCode.CONVERT)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Convert(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + engine.Push(x.ConvertTo((StackItemType)instruction.TokenU8)); + } + + [OpcodeMethod(OpCode.ABORTMSG)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void AbortMsg(ExecutionEngine engine, Instruction instruction) + { + var msg = engine.Pop().GetString(); + throw new Exception($"{OpCode.ABORTMSG} is executed. Reason: {msg}"); + } + + [OpcodeMethod(OpCode.ASSERTMSG)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void AssertMsg(ExecutionEngine engine, Instruction instruction) + { + var msg = engine.Pop().GetString(); + var x = engine.Pop().GetBoolean(); + if (!x) + throw new Exception($"{OpCode.ASSERTMSG} is executed with false result. Reason: {msg}"); + } + } +} diff --git a/src/Neo.VM/JumpTable.cs b/src/Neo.VM/JumpTable.cs index 0a352567a0..2f89161d61 100644 --- a/src/Neo.VM/JumpTable.cs +++ b/src/Neo.VM/JumpTable.cs @@ -16,17 +16,17 @@ namespace Neo.VM { public partial class JumpTable { - public delegate void delAction(ExecutionEngine engine, Instruction instruction); - public readonly delAction[] Table = new delAction[byte.MaxValue]; + public delegate void DelAction(ExecutionEngine engine, Instruction instruction); + private readonly DelAction[] _table = new DelAction[byte.MaxValue]; /// /// Get Method /// /// OpCode /// Action - public delAction GetMethod(OpCode opCode) + public DelAction GetMethod(OpCode opCode) { - return Table[(byte)opCode]; + return _table[(byte)opCode]; } public JumpTable() @@ -37,28 +37,29 @@ public JumpTable() { foreach (var attr in mi.GetCustomAttributes(true)) { - if (Table[(byte)attr.OpCode] is not null) + if (_table[(byte)attr.OpCode] is not null) { throw new InvalidOperationException($"Opcode {attr.OpCode} is already defined."); } - Table[(byte)attr.OpCode] = (delAction)mi.CreateDelegate(typeof(delAction), this); + _table[(byte)attr.OpCode] = (DelAction)mi.CreateDelegate(typeof(DelAction), this); } } // Fill with undefined - for (int x = 0; x < Table.Length; x++) + for (int x = 0; x < _table.Length; x++) { - if (Table[x] is not null) continue; + if (_table[x] is not null) continue; - Table[x] = (engine, instruction) => + _table[x] = (engine, instruction) => { throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); }; } - /* + /* TODO: + switch (instruction.OpCode) { // Stack ops @@ -379,25 +380,6 @@ public JumpTable() case OpCode.POPITEM: PopItem(instruction); break; - - //Types - case OpCode.ISNULL: - IsNull(instruction); - break; - case OpCode.ISTYPE: - IsType(instruction); - break; - case OpCode.CONVERT: - Convert(instruction); - break; - case OpCode.ABORTMSG: - AbortMsg(instruction); - break; - case OpCode.ASSERTMSG: - AssertMsg(instruction); - break; - default: - throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); } */ } From d12b011a20b2672adec604f4710a466ebfe533fe Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 6 Feb 2024 19:20:40 +0100 Subject: [PATCH 03/34] Splice --- src/Neo.VM/JumpTable.Splice.cs | 112 +++++++++++++++++++++++++++++++++ src/Neo.VM/JumpTable.cs | 22 +------ 2 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 src/Neo.VM/JumpTable.Splice.cs diff --git a/src/Neo.VM/JumpTable.Splice.cs b/src/Neo.VM/JumpTable.Splice.cs new file mode 100644 index 0000000000..9ab770df51 --- /dev/null +++ b/src/Neo.VM/JumpTable.Splice.cs @@ -0,0 +1,112 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Splice.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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; +using System.Runtime.CompilerServices; + +namespace Neo.VM +{ + public partial class JumpTable + { + [OpcodeMethod(OpCode.NEWBUFFER)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NewBuffer(ExecutionEngine engine, Instruction instruction) + { + int length = (int)engine.Pop().GetInteger(); + engine.Limits.AssertMaxItemSize(length); + engine.Push(new Types.Buffer(length)); + } + + [OpcodeMethod(OpCode.MEMCPY)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Memcpy(ExecutionEngine engine, Instruction instruction) + { + int count = (int)engine.Pop().GetInteger(); + if (count < 0) + throw new InvalidOperationException($"The value {count} is out of range."); + int si = (int)engine.Pop().GetInteger(); + if (si < 0) + throw new InvalidOperationException($"The value {si} is out of range."); + ReadOnlySpan src = engine.Pop().GetSpan(); + if (checked(si + count) > src.Length) + throw new InvalidOperationException($"The value {count} is out of range."); + int di = (int)engine.Pop().GetInteger(); + if (di < 0) + throw new InvalidOperationException($"The value {di} is out of range."); + Types.Buffer dst = engine.Pop(); + if (checked(di + count) > dst.Size) + throw new InvalidOperationException($"The value {count} is out of range."); + src.Slice(si, count).CopyTo(dst.InnerBuffer.Span[di..]); + } + + [OpcodeMethod(OpCode.CAT)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Cat(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetSpan(); + var x1 = engine.Pop().GetSpan(); + int length = x1.Length + x2.Length; + engine.Limits.AssertMaxItemSize(length); + Types.Buffer result = new(length, false); + x1.CopyTo(result.InnerBuffer.Span); + x2.CopyTo(result.InnerBuffer.Span[x1.Length..]); + engine.Push(result); + } + + [OpcodeMethod(OpCode.SUBSTR)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Substr(ExecutionEngine engine, Instruction instruction) + { + int count = (int)engine.Pop().GetInteger(); + if (count < 0) + throw new InvalidOperationException($"The value {count} is out of range."); + int index = (int)engine.Pop().GetInteger(); + if (index < 0) + throw new InvalidOperationException($"The value {index} is out of range."); + var x = engine.Pop().GetSpan(); + if (index + count > x.Length) + throw new InvalidOperationException($"The value {count} is out of range."); + Types.Buffer result = new(count, false); + x.Slice(index, count).CopyTo(result.InnerBuffer.Span); + engine.Push(result); + } + + [OpcodeMethod(OpCode.LEFT)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Left(ExecutionEngine engine, Instruction instruction) + { + int count = (int)engine.Pop().GetInteger(); + if (count < 0) + throw new InvalidOperationException($"The value {count} is out of range."); + var x = engine.Pop().GetSpan(); + if (count > x.Length) + throw new InvalidOperationException($"The value {count} is out of range."); + Types.Buffer result = new(count, false); + x[..count].CopyTo(result.InnerBuffer.Span); + engine.Push(result); + } + + [OpcodeMethod(OpCode.RIGHT)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Right(ExecutionEngine engine, Instruction instruction) + { + int count = (int)engine.Pop().GetInteger(); + if (count < 0) + throw new InvalidOperationException($"The value {count} is out of range."); + var x = engine.Pop().GetSpan(); + if (count > x.Length) + throw new InvalidOperationException($"The value {count} is out of range."); + Types.Buffer result = new(count, false); + x[^count..^0].CopyTo(result.InnerBuffer.Span); + engine.Push(result); + } + } +} diff --git a/src/Neo.VM/JumpTable.cs b/src/Neo.VM/JumpTable.cs index 2f89161d61..ca0e0e9a50 100644 --- a/src/Neo.VM/JumpTable.cs +++ b/src/Neo.VM/JumpTable.cs @@ -17,7 +17,7 @@ namespace Neo.VM public partial class JumpTable { public delegate void DelAction(ExecutionEngine engine, Instruction instruction); - private readonly DelAction[] _table = new DelAction[byte.MaxValue]; + protected readonly DelAction[] _table = new DelAction[byte.MaxValue]; /// /// Get Method @@ -189,26 +189,6 @@ public JumpTable() StArg(instruction); break; - // Splice - case OpCode.NEWBUFFER: - NewBuffer(instruction); - break; - case OpCode.MEMCPY: - Memcpy(instruction); - break; - case OpCode.CAT: - Cat(instruction); - break; - case OpCode.SUBSTR: - Substr(instruction); - break; - case OpCode.LEFT: - Left(instruction); - break; - case OpCode.RIGHT: - Right(instruction); - break; - // Bitwise logic case OpCode.INVERT: Invert(instruction); From 23d4be4589e5dbfa1c9bcf3c099933d577efe44a Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 6 Feb 2024 19:22:42 +0100 Subject: [PATCH 04/34] revert partial --- src/Neo.VM/ExecutionEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index f020aa24e5..02507de608 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -19,7 +19,7 @@ namespace Neo.VM /// /// Represents the VM used to execute the script. /// - public partial class ExecutionEngine : IDisposable + public class ExecutionEngine : IDisposable { private VMState state = VMState.BREAK; private bool isJumping = false; From 2e41b1ebca56a8c0f1d7376f3eb0d98806af2135 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 6 Feb 2024 19:30:03 +0100 Subject: [PATCH 05/34] More control --- src/Neo.VM/ExecutionEngine.cs | 2 +- src/Neo.VM/JumpTable.Control.cs | 134 ++++++++++++++++++++++++++------ 2 files changed, 110 insertions(+), 26 deletions(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index 02507de608..67fe4bb5d7 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -142,7 +142,7 @@ public virtual VMState Execute() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ExecuteCall(int position) + public void ExecuteCall(int position) { LoadContext(CurrentContext!.Clone(position)); } diff --git a/src/Neo.VM/JumpTable.Control.cs b/src/Neo.VM/JumpTable.Control.cs index 4015ef426c..eef9b09659 100644 --- a/src/Neo.VM/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable.Control.cs @@ -15,31 +15,6 @@ namespace Neo.VM { public partial class JumpTable { - /* TODO - case OpCode.JMPGT: - case OpCode.JMPGT_L: - case OpCode.JMPGE: - case OpCode.JMPGE_L: - case OpCode.JMPLT: - case OpCode.JMPLT_L: - case OpCode.JMPLE: - case OpCode.JMPLE_L: - case OpCode.CALL: - case OpCode.CALL_L: - case OpCode.CALLA: - case OpCode.CALLT: - case OpCode.ABORT: - case OpCode.ASSERT: - case OpCode.THROW: - case OpCode.TRY: - case OpCode.TRY_L: - case OpCode.ENDTRY: - case OpCode.ENDTRY_L: - case OpCode.ENDFINALLY: - case OpCode.RET: - case OpCode.SYSCALL: - */ - [OpcodeMethod(OpCode.NOP)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void Nop(ExecutionEngine engine, Instruction instruction) @@ -131,5 +106,114 @@ public virtual void JmpNeL(ExecutionEngine engine, Instruction instruction) if (x1 != x2) engine.ExecuteJumpOffset(instruction.TokenI32); } + + [OpcodeMethod(OpCode.JMPGT)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpGt(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 > x2) + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMPGT_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpGtL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 > x2) + engine.ExecuteJumpOffset(instruction.TokenI32); + } + + [OpcodeMethod(OpCode.JMPGE)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpGe(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 >= x2) + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMPGE_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpGeL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 >= x2) + engine.ExecuteJumpOffset(instruction.TokenI32); + } + + [OpcodeMethod(OpCode.JMPLT)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpLt(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 < x2) + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMPLT_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpLtL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 < x2) + engine.ExecuteJumpOffset(instruction.TokenI32); + } + + [OpcodeMethod(OpCode.JMPLE)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpLe(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 <= x2) + engine.ExecuteJumpOffset(instruction.TokenI8); + } + + [OpcodeMethod(OpCode.JMPLE_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void JmpLeL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + if (x1 <= x2) + engine.ExecuteJumpOffset(instruction.TokenI32); + } + + [OpcodeMethod(OpCode.CALL)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void Call(ExecutionEngine engine, Instruction instruction) + { + engine.ExecuteCall(checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI8)); + } + + [OpcodeMethod(OpCode.CALL_L)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void CallL(ExecutionEngine engine, Instruction instruction) + { + engine.ExecuteCall(checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI32)); + } + + /* TODO + case OpCode.CALLA: + case OpCode.CALLT: + case OpCode.ABORT: + case OpCode.ASSERT: + case OpCode.THROW: + case OpCode.TRY: + case OpCode.TRY_L: + case OpCode.ENDTRY: + case OpCode.ENDTRY_L: + case OpCode.ENDFINALLY: + case OpCode.RET: + case OpCode.SYSCALL: + */ } } From 8f7809bd85811868bcede2aa122f09391ea06a26 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 6 Feb 2024 19:39:35 +0100 Subject: [PATCH 06/34] Remove attribute --- src/Neo.VM/JumpTable.Control.cs | 63 +++------ src/Neo.VM/JumpTable.Push.cs | 197 ++++++++++++++++++++++------ src/Neo.VM/JumpTable.Splice.cs | 18 +-- src/Neo.VM/JumpTable.Types.cs | 16 +-- src/Neo.VM/JumpTable.cs | 9 +- src/Neo.VM/OpcodeMethodAttribute.cs | 36 ----- 6 files changed, 192 insertions(+), 147 deletions(-) delete mode 100644 src/Neo.VM/OpcodeMethodAttribute.cs diff --git a/src/Neo.VM/JumpTable.Control.cs b/src/Neo.VM/JumpTable.Control.cs index eef9b09659..5d5d172c3c 100644 --- a/src/Neo.VM/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable.Control.cs @@ -15,61 +15,53 @@ namespace Neo.VM { public partial class JumpTable { - [OpcodeMethod(OpCode.NOP)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Nop(ExecutionEngine engine, Instruction instruction) + public virtual void NOP(ExecutionEngine engine, Instruction instruction) { } - [OpcodeMethod(OpCode.JMP)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Jmp(ExecutionEngine engine, Instruction instruction) + public virtual void JMP(ExecutionEngine engine, Instruction instruction) { engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMP_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpL(ExecutionEngine engine, Instruction instruction) + public virtual void JMP_L(ExecutionEngine engine, Instruction instruction) { engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.JMPIF)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpIf(ExecutionEngine engine, Instruction instruction) + public virtual void JMPIF(ExecutionEngine engine, Instruction instruction) { if (engine.Pop().GetBoolean()) engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMPIF_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpIfL(ExecutionEngine engine, Instruction instruction) + public virtual void JMPIF_L(ExecutionEngine engine, Instruction instruction) { if (engine.Pop().GetBoolean()) engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.JMPIFNOT)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpIfNot(ExecutionEngine engine, Instruction instruction) + public virtual void JMPIFNOT(ExecutionEngine engine, Instruction instruction) { if (!engine.Pop().GetBoolean()) engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMPIFNOT_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpIfNotL(ExecutionEngine engine, Instruction instruction) + public virtual void JMPIFNOT_L(ExecutionEngine engine, Instruction instruction) { if (!engine.Pop().GetBoolean()) engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.JMPEQ)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpEq(ExecutionEngine engine, Instruction instruction) + public virtual void JMPEQ(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -77,9 +69,8 @@ public virtual void JmpEq(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMPEQ_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpEqL(ExecutionEngine engine, Instruction instruction) + public virtual void JMPEQ_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -87,9 +78,8 @@ public virtual void JmpEqL(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.JMPNE)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpNe(ExecutionEngine engine, Instruction instruction) + public virtual void JMPNE(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -97,9 +87,8 @@ public virtual void JmpNe(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMPNE_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpNeL(ExecutionEngine engine, Instruction instruction) + public virtual void JMPNE_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -107,9 +96,8 @@ public virtual void JmpNeL(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.JMPGT)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpGt(ExecutionEngine engine, Instruction instruction) + public virtual void JMPGT(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -117,9 +105,8 @@ public virtual void JmpGt(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMPGT_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpGtL(ExecutionEngine engine, Instruction instruction) + public virtual void JMPGT_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -127,9 +114,8 @@ public virtual void JmpGtL(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.JMPGE)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpGe(ExecutionEngine engine, Instruction instruction) + public virtual void JMPGE(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -137,9 +123,8 @@ public virtual void JmpGe(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMPGE_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpGeL(ExecutionEngine engine, Instruction instruction) + public virtual void JMPGE_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -147,9 +132,8 @@ public virtual void JmpGeL(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.JMPLT)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpLt(ExecutionEngine engine, Instruction instruction) + public virtual void JMPLT(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -157,9 +141,8 @@ public virtual void JmpLt(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMPLT_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpLtL(ExecutionEngine engine, Instruction instruction) + public virtual void JMPLT_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -167,9 +150,8 @@ public virtual void JmpLtL(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.JMPLE)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpLe(ExecutionEngine engine, Instruction instruction) + public virtual void JMPLE(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -177,9 +159,8 @@ public virtual void JmpLe(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI8); } - [OpcodeMethod(OpCode.JMPLE_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JmpLeL(ExecutionEngine engine, Instruction instruction) + public virtual void JMPLE_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -187,16 +168,14 @@ public virtual void JmpLeL(ExecutionEngine engine, Instruction instruction) engine.ExecuteJumpOffset(instruction.TokenI32); } - [OpcodeMethod(OpCode.CALL)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Call(ExecutionEngine engine, Instruction instruction) + public virtual void CALL(ExecutionEngine engine, Instruction instruction) { engine.ExecuteCall(checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI8)); } - [OpcodeMethod(OpCode.CALL_L)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CallL(ExecutionEngine engine, Instruction instruction) + public virtual void CALL_L(ExecutionEngine engine, Instruction instruction) { engine.ExecuteCall(checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI32)); } diff --git a/src/Neo.VM/JumpTable.Push.cs b/src/Neo.VM/JumpTable.Push.cs index e15910778a..66b9f64c51 100644 --- a/src/Neo.VM/JumpTable.Push.cs +++ b/src/Neo.VM/JumpTable.Push.cs @@ -18,35 +18,56 @@ namespace Neo.VM { public partial class JumpTable { - [OpcodeMethod(OpCode.PUSHINT8)] - [OpcodeMethod(OpCode.PUSHINT16)] - [OpcodeMethod(OpCode.PUSHINT32)] - [OpcodeMethod(OpCode.PUSHINT64)] - [OpcodeMethod(OpCode.PUSHINT128)] - [OpcodeMethod(OpCode.PUSHINT256)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PushInt(ExecutionEngine engine, Instruction instruction) + public virtual void PUSHINT8(ExecutionEngine engine, Instruction instruction) { engine.Push(new BigInteger(instruction.Operand.Span)); } - [OpcodeMethod(OpCode.PUSHT)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PushT(ExecutionEngine engine, Instruction instruction) + public virtual void PUSHINT16(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new BigInteger(instruction.Operand.Span)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSHINT32(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new BigInteger(instruction.Operand.Span)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSHINT64(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new BigInteger(instruction.Operand.Span)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSHINT128(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new BigInteger(instruction.Operand.Span)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSHINT256(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new BigInteger(instruction.Operand.Span)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSHT(ExecutionEngine engine, Instruction instruction) { engine.Push(StackItem.True); } - [OpcodeMethod(OpCode.PUSHF)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PushF(ExecutionEngine engine, Instruction instruction) + public virtual void PUSHF(ExecutionEngine engine, Instruction instruction) { engine.Push(StackItem.False); } - [OpcodeMethod(OpCode.PUSHA)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PushA(ExecutionEngine engine, Instruction instruction) + public virtual void PUSHA(ExecutionEngine engine, Instruction instruction) { var position = checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI32); if (position < 0 || position > engine.CurrentContext.Script.Length) @@ -54,45 +75,139 @@ public virtual void PushA(ExecutionEngine engine, Instruction instruction) engine.Push(new Pointer(engine.CurrentContext.Script, position)); } - [OpcodeMethod(OpCode.PUSHNULL)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PushNull(ExecutionEngine engine, Instruction instruction) + public virtual void PUSHNULL(ExecutionEngine engine, Instruction instruction) { engine.Push(StackItem.Null); } - [OpcodeMethod(OpCode.PUSHDATA1)] - [OpcodeMethod(OpCode.PUSHDATA2)] - [OpcodeMethod(OpCode.PUSHDATA4)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PushData(ExecutionEngine engine, Instruction instruction) + public virtual void PUSHDATA1(ExecutionEngine engine, Instruction instruction) + { + engine.Limits.AssertMaxItemSize(instruction.Operand.Length); + engine.Push(instruction.Operand); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSHDATA2(ExecutionEngine engine, Instruction instruction) + { + engine.Limits.AssertMaxItemSize(instruction.Operand.Length); + engine.Push(instruction.Operand); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSHDATA4(ExecutionEngine engine, Instruction instruction) { engine.Limits.AssertMaxItemSize(instruction.Operand.Length); engine.Push(instruction.Operand); } - [OpcodeMethod(OpCode.PUSHM1)] - [OpcodeMethod(OpCode.PUSH0)] - [OpcodeMethod(OpCode.PUSH1)] - [OpcodeMethod(OpCode.PUSH2)] - [OpcodeMethod(OpCode.PUSH3)] - [OpcodeMethod(OpCode.PUSH4)] - [OpcodeMethod(OpCode.PUSH5)] - [OpcodeMethod(OpCode.PUSH6)] - [OpcodeMethod(OpCode.PUSH7)] - [OpcodeMethod(OpCode.PUSH8)] - [OpcodeMethod(OpCode.PUSH9)] - [OpcodeMethod(OpCode.PUSH10)] - [OpcodeMethod(OpCode.PUSH11)] - [OpcodeMethod(OpCode.PUSH12)] - [OpcodeMethod(OpCode.PUSH13)] - [OpcodeMethod(OpCode.PUSH14)] - [OpcodeMethod(OpCode.PUSH15)] - [OpcodeMethod(OpCode.PUSH16)] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Push(ExecutionEngine engine, Instruction instruction) - { - engine.Push((int)instruction.OpCode - (int)OpCode.PUSH0); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSHM1(ExecutionEngine engine, Instruction instruction) + { + engine.Push(-1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH0(ExecutionEngine engine, Instruction instruction) + { + engine.Push(0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH1(ExecutionEngine engine, Instruction instruction) + { + engine.Push(1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH2(ExecutionEngine engine, Instruction instruction) + { + engine.Push(2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH3(ExecutionEngine engine, Instruction instruction) + { + engine.Push(3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH4(ExecutionEngine engine, Instruction instruction) + { + engine.Push(4); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH5(ExecutionEngine engine, Instruction instruction) + { + engine.Push(5); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH6(ExecutionEngine engine, Instruction instruction) + { + engine.Push(6); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH7(ExecutionEngine engine, Instruction instruction) + { + engine.Push(7); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH8(ExecutionEngine engine, Instruction instruction) + { + engine.Push(8); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH9(ExecutionEngine engine, Instruction instruction) + { + engine.Push(9); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH10(ExecutionEngine engine, Instruction instruction) + { + engine.Push(10); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH11(ExecutionEngine engine, Instruction instruction) + { + engine.Push(11); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH12(ExecutionEngine engine, Instruction instruction) + { + engine.Push(12); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH13(ExecutionEngine engine, Instruction instruction) + { + engine.Push(13); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH14(ExecutionEngine engine, Instruction instruction) + { + engine.Push(14); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH15(ExecutionEngine engine, Instruction instruction) + { + engine.Push(15); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PUSH16(ExecutionEngine engine, Instruction instruction) + { + engine.Push(16); } } } diff --git a/src/Neo.VM/JumpTable.Splice.cs b/src/Neo.VM/JumpTable.Splice.cs index 9ab770df51..f5aec89352 100644 --- a/src/Neo.VM/JumpTable.Splice.cs +++ b/src/Neo.VM/JumpTable.Splice.cs @@ -16,18 +16,16 @@ namespace Neo.VM { public partial class JumpTable { - [OpcodeMethod(OpCode.NEWBUFFER)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NewBuffer(ExecutionEngine engine, Instruction instruction) + public virtual void NEWBUFFER(ExecutionEngine engine, Instruction instruction) { int length = (int)engine.Pop().GetInteger(); engine.Limits.AssertMaxItemSize(length); engine.Push(new Types.Buffer(length)); } - [OpcodeMethod(OpCode.MEMCPY)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Memcpy(ExecutionEngine engine, Instruction instruction) + public virtual void MEMCPY(ExecutionEngine engine, Instruction instruction) { int count = (int)engine.Pop().GetInteger(); if (count < 0) @@ -47,9 +45,8 @@ public virtual void Memcpy(ExecutionEngine engine, Instruction instruction) src.Slice(si, count).CopyTo(dst.InnerBuffer.Span[di..]); } - [OpcodeMethod(OpCode.CAT)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Cat(ExecutionEngine engine, Instruction instruction) + public virtual void CAT(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetSpan(); var x1 = engine.Pop().GetSpan(); @@ -61,9 +58,8 @@ public virtual void Cat(ExecutionEngine engine, Instruction instruction) engine.Push(result); } - [OpcodeMethod(OpCode.SUBSTR)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Substr(ExecutionEngine engine, Instruction instruction) + public virtual void SUBSTR(ExecutionEngine engine, Instruction instruction) { int count = (int)engine.Pop().GetInteger(); if (count < 0) @@ -79,9 +75,8 @@ public virtual void Substr(ExecutionEngine engine, Instruction instruction) engine.Push(result); } - [OpcodeMethod(OpCode.LEFT)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Left(ExecutionEngine engine, Instruction instruction) + public virtual void LEFT(ExecutionEngine engine, Instruction instruction) { int count = (int)engine.Pop().GetInteger(); if (count < 0) @@ -94,9 +89,8 @@ public virtual void Left(ExecutionEngine engine, Instruction instruction) engine.Push(result); } - [OpcodeMethod(OpCode.RIGHT)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Right(ExecutionEngine engine, Instruction instruction) + public virtual void RIGHT(ExecutionEngine engine, Instruction instruction) { int count = (int)engine.Pop().GetInteger(); if (count < 0) diff --git a/src/Neo.VM/JumpTable.Types.cs b/src/Neo.VM/JumpTable.Types.cs index b8c1da6cf3..46fd50749d 100644 --- a/src/Neo.VM/JumpTable.Types.cs +++ b/src/Neo.VM/JumpTable.Types.cs @@ -17,17 +17,14 @@ namespace Neo.VM { public partial class JumpTable { - [OpcodeMethod(OpCode.ISNULL)] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void IsNull(ExecutionEngine engine, Instruction instruction) + public virtual void ISNULL(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); engine.Push(x.IsNull); } - [OpcodeMethod(OpCode.ISTYPE)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void IsType(ExecutionEngine engine, Instruction instruction) + public virtual void ISTYPE(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); var type = (StackItemType)instruction.TokenU8; @@ -36,25 +33,22 @@ public virtual void IsType(ExecutionEngine engine, Instruction instruction) engine.Push(x.Type == type); } - [OpcodeMethod(OpCode.CONVERT)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void Convert(ExecutionEngine engine, Instruction instruction) + public virtual void CONVERT(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); engine.Push(x.ConvertTo((StackItemType)instruction.TokenU8)); } - [OpcodeMethod(OpCode.ABORTMSG)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void AbortMsg(ExecutionEngine engine, Instruction instruction) + public virtual void ABORTMSG(ExecutionEngine engine, Instruction instruction) { var msg = engine.Pop().GetString(); throw new Exception($"{OpCode.ABORTMSG} is executed. Reason: {msg}"); } - [OpcodeMethod(OpCode.ASSERTMSG)] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void AssertMsg(ExecutionEngine engine, Instruction instruction) + public virtual void ASSERTMSG(ExecutionEngine engine, Instruction instruction) { var msg = engine.Pop().GetString(); var x = engine.Pop().GetBoolean(); diff --git a/src/Neo.VM/JumpTable.cs b/src/Neo.VM/JumpTable.cs index ca0e0e9a50..db68fe71c8 100644 --- a/src/Neo.VM/JumpTable.cs +++ b/src/Neo.VM/JumpTable.cs @@ -10,7 +10,6 @@ // modifications are permitted. using System; -using System.Reflection; namespace Neo.VM { @@ -35,14 +34,14 @@ public JumpTable() foreach (var mi in GetType().GetMethods()) { - foreach (var attr in mi.GetCustomAttributes(true)) + if (Enum.TryParse(mi.Name, false, out var opCode)) { - if (_table[(byte)attr.OpCode] is not null) + if (_table[(byte)opCode] is not null) { - throw new InvalidOperationException($"Opcode {attr.OpCode} is already defined."); + throw new InvalidOperationException($"Opcode {opCode} is already defined."); } - _table[(byte)attr.OpCode] = (DelAction)mi.CreateDelegate(typeof(DelAction), this); + _table[(byte)opCode] = (DelAction)mi.CreateDelegate(typeof(DelAction), this); } } diff --git a/src/Neo.VM/OpcodeMethodAttribute.cs b/src/Neo.VM/OpcodeMethodAttribute.cs deleted file mode 100644 index 3a91233728..0000000000 --- a/src/Neo.VM/OpcodeMethodAttribute.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2015-2024 The Neo Project. -// -// OpcodeMethodAttribute.cs file belongs to the neo project and is free -// software distributed under the MIT software license, see the -// accompanying file LICENSE in the main directory of the -// repository 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; - -namespace Neo.VM -{ - /// - /// Indicates the . - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public class OpcodeMethodAttribute : Attribute - { - /// - /// The method is for this Opcode - /// - public OpCode OpCode { get; set; } - - /// - /// Constructor - /// - /// OpCode - public OpcodeMethodAttribute(OpCode opCode) - { - OpCode = opCode; - } - } -} From 957e1d2482074aaf829f2eeccae1d43ada0cfe1f Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Wed, 7 Feb 2024 10:43:31 +0100 Subject: [PATCH 07/34] ApplicationEngine logic --- src/Neo.VM/ExecutionEngine.cs | 198 +++------------ src/Neo.VM/JumpTable.Control.cs | 270 ++++++++++++++++++--- src/Neo.VM/JumpTable.cs | 16 +- src/Neo/SmartContract/ApplicationEngine.cs | 81 +++++-- tests/Neo.VM.Tests/Types/TestEngine.cs | 19 +- 5 files changed, 346 insertions(+), 238 deletions(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index 67fe4bb5d7..043b095ef0 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -22,8 +22,9 @@ namespace Neo.VM public class ExecutionEngine : IDisposable { private VMState state = VMState.BREAK; - private bool isJumping = false; - private readonly JumpTable JumpTable; + internal bool isJumping = false; + + public JumpTable JumpTable { get; } /// /// Restrictions on the VM. @@ -58,7 +59,7 @@ public class ExecutionEngine : IDisposable /// /// The VM object representing the uncaught exception. /// - public StackItem? UncaughtException { get; private set; } + public StackItem? UncaughtException { get; internal set; } /// /// The current state of the VM. @@ -100,29 +101,6 @@ protected ExecutionEngine(JumpTable? jumpTable, ReferenceCounter referenceCounte this.ResultStack = new EvaluationStack(referenceCounter); } - /// - /// Called when a context is unloaded. - /// - /// The context being unloaded. - protected virtual void ContextUnloaded(ExecutionContext context) - { - if (InvocationStack.Count == 0) - { - CurrentContext = null; - EntryContext = null; - } - else - { - CurrentContext = InvocationStack.Peek(); - } - if (context.StaticFields != null && context.StaticFields != CurrentContext?.StaticFields) - { - context.StaticFields.ClearReferences(); - } - context.LocalVariables?.ClearReferences(); - context.Arguments?.ClearReferences(); - } - public virtual void Dispose() { InvocationStack.Clear(); @@ -141,60 +119,6 @@ public virtual VMState Execute() return State; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ExecuteCall(int position) - { - LoadContext(CurrentContext!.Clone(position)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ExecuteEndTry(int endOffset) - { - if (CurrentContext!.TryStack is null) - throw new InvalidOperationException($"The corresponding TRY block cannot be found."); - if (!CurrentContext.TryStack.TryPeek(out ExceptionHandlingContext? currentTry)) - throw new InvalidOperationException($"The corresponding TRY block cannot be found."); - if (currentTry.State == ExceptionHandlingState.Finally) - throw new InvalidOperationException($"The opcode {OpCode.ENDTRY} can't be executed in a FINALLY block."); - - int endPointer = checked(CurrentContext.InstructionPointer + endOffset); - if (currentTry.HasFinally) - { - currentTry.State = ExceptionHandlingState.Finally; - currentTry.EndPointer = endPointer; - CurrentContext.InstructionPointer = currentTry.FinallyPointer; - } - else - { - CurrentContext.TryStack.Pop(); - CurrentContext.InstructionPointer = endPointer; - } - isJumping = true; - } - - /// - /// Jump to the specified position. - /// - /// The position to jump to. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void ExecuteJump(int position) - { - if (position < 0 || position >= CurrentContext!.Script.Length) - throw new ArgumentOutOfRangeException($"Jump out of range for position: {position}"); - CurrentContext.InstructionPointer = position; - isJumping = true; - } - - /// - /// Jump to the specified offset from the current position. - /// - /// The offset from the current position to jump to. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ExecuteJumpOffset(int offset) - { - ExecuteJump(checked(CurrentContext!.InstructionPointer + offset)); - } - private void ExecuteLoadFromSlot(Slot? slot, int index) { if (slot is null) @@ -222,11 +146,11 @@ protected internal void ExecuteNext() PreExecuteInstruction(instruction); try { - JumpTable.GetMethod(instruction.OpCode)(this, instruction); + JumpTable[instruction.OpCode](this, instruction); } catch (CatchableException ex) when (Limits.CatchEngineExceptions) { - ExecuteThrow(ex.Message); + JumpTable.ExecuteThrow(this, ex.Message); } PostExecuteInstruction(instruction); if (!isJumping) context.MoveNext(); @@ -248,75 +172,11 @@ private void ExecuteStoreToSlot(Slot? slot, int index) slot[index] = Pop(); } - /// - /// Throws a specified exception in the VM. - /// - /// The exception to be thrown. - protected void ExecuteThrow(StackItem ex) - { - UncaughtException = ex; - HandleException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ExecuteTry(int catchOffset, int finallyOffset) - { - if (catchOffset == 0 && finallyOffset == 0) - throw new InvalidOperationException($"catchOffset and finallyOffset can't be 0 in a TRY block"); - if (CurrentContext!.TryStack is null) - CurrentContext.TryStack = new Stack(); - else if (CurrentContext.TryStack.Count >= Limits.MaxTryNestingDepth) - throw new InvalidOperationException("MaxTryNestingDepth exceed."); - int catchPointer = catchOffset == 0 ? -1 : checked(CurrentContext.InstructionPointer + catchOffset); - int finallyPointer = finallyOffset == 0 ? -1 : checked(CurrentContext.InstructionPointer + finallyOffset); - CurrentContext.TryStack.Push(new ExceptionHandlingContext(catchPointer, finallyPointer)); - } - - private void HandleException() - { - int pop = 0; - foreach (var executionContext in InvocationStack) - { - if (executionContext.TryStack != null) - { - while (executionContext.TryStack.TryPeek(out var tryContext)) - { - if (tryContext.State == ExceptionHandlingState.Finally || (tryContext.State == ExceptionHandlingState.Catch && !tryContext.HasFinally)) - { - executionContext.TryStack.Pop(); - continue; - } - for (int i = 0; i < pop; i++) - { - ContextUnloaded(InvocationStack.Pop()); - } - if (tryContext.State == ExceptionHandlingState.Try && tryContext.HasCatch) - { - tryContext.State = ExceptionHandlingState.Catch; - Push(UncaughtException!); - executionContext.InstructionPointer = tryContext.CatchPointer; - UncaughtException = null; - } - else - { - tryContext.State = ExceptionHandlingState.Finally; - executionContext.InstructionPointer = tryContext.FinallyPointer; - } - isJumping = true; - return; - } - } - ++pop; - } - - throw new VMUnhandledException(UncaughtException!); - } - /// /// Loads the specified context into the invocation stack. /// /// The context to load. - protected virtual void LoadContext(ExecutionContext context) + public virtual void LoadContext(ExecutionContext context) { if (InvocationStack.Count >= Limits.MaxInvocationStackSize) throw new InvalidOperationException($"MaxInvocationStackSize exceed: {InvocationStack.Count}"); @@ -325,6 +185,29 @@ protected virtual void LoadContext(ExecutionContext context) CurrentContext = context; } + /// + /// Called when a context is unloaded. + /// + /// The context being unloaded. + public virtual void UnloadedContext(ExecutionContext context) + { + if (InvocationStack.Count == 0) + { + CurrentContext = null; + EntryContext = null; + } + else + { + CurrentContext = InvocationStack.Peek(); + } + if (context.StaticFields != null && context.StaticFields != CurrentContext?.StaticFields) + { + context.StaticFields.ClearReferences(); + } + context.LocalVariables?.ClearReferences(); + context.Arguments?.ClearReferences(); + } + /// /// Create a new context with the specified script without loading. /// @@ -355,17 +238,6 @@ public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialP return context; } - /// - /// When overridden in a derived class, loads the specified method token. - /// Called when is executed. - /// - /// The method token to be loaded. - /// The created context. - protected virtual ExecutionContext LoadToken(ushort token) - { - throw new InvalidOperationException($"Token not found: {token}"); - } - /// /// Called when an exception that cannot be caught by the VM is thrown. /// @@ -382,16 +254,6 @@ protected virtual void OnStateChanged() { } - /// - /// When overridden in a derived class, invokes the specified system call. - /// Called when is executed. - /// - /// The system call to be invoked. - protected virtual void OnSysCall(uint method) - { - throw new InvalidOperationException($"Syscall not found: {method}"); - } - /// /// Returns the item at the specified index from the top of the current stack without removing it. /// diff --git a/src/Neo.VM/JumpTable.Control.cs b/src/Neo.VM/JumpTable.Control.cs index 5d5d172c3c..7d1b9f9542 100644 --- a/src/Neo.VM/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable.Control.cs @@ -9,6 +9,9 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.VM.Types; +using System; +using System.Collections.Generic; using System.Runtime.CompilerServices; namespace Neo.VM @@ -23,41 +26,41 @@ public virtual void NOP(ExecutionEngine engine, Instruction instruction) [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void JMP(ExecutionEngine engine, Instruction instruction) { - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void JMP_L(ExecutionEngine engine, Instruction instruction) { - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void JMPIF(ExecutionEngine engine, Instruction instruction) { if (engine.Pop().GetBoolean()) - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void JMPIF_L(ExecutionEngine engine, Instruction instruction) { if (engine.Pop().GetBoolean()) - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void JMPIFNOT(ExecutionEngine engine, Instruction instruction) { if (!engine.Pop().GetBoolean()) - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void JMPIFNOT_L(ExecutionEngine engine, Instruction instruction) { if (!engine.Pop().GetBoolean()) - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -66,7 +69,7 @@ public virtual void JMPEQ(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 == x2) - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -75,7 +78,7 @@ public virtual void JMPEQ_L(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 == x2) - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -84,7 +87,7 @@ public virtual void JMPNE(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 != x2) - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -93,7 +96,7 @@ public virtual void JMPNE_L(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 != x2) - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -102,7 +105,7 @@ public virtual void JMPGT(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 > x2) - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -111,7 +114,7 @@ public virtual void JMPGT_L(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 > x2) - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -120,7 +123,7 @@ public virtual void JMPGE(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 >= x2) - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -129,7 +132,7 @@ public virtual void JMPGE_L(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 >= x2) - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -138,7 +141,7 @@ public virtual void JMPLT(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 < x2) - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -147,7 +150,7 @@ public virtual void JMPLT_L(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 < x2) - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -156,7 +159,7 @@ public virtual void JMPLE(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 <= x2) - engine.ExecuteJumpOffset(instruction.TokenI8); + ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -165,34 +168,229 @@ public virtual void JMPLE_L(ExecutionEngine engine, Instruction instruction) var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); if (x1 <= x2) - engine.ExecuteJumpOffset(instruction.TokenI32); + ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void CALL(ExecutionEngine engine, Instruction instruction) { - engine.ExecuteCall(checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI8)); + ExecuteCall(engine, checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI8)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void CALL_L(ExecutionEngine engine, Instruction instruction) { - engine.ExecuteCall(checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI32)); - } - - /* TODO - case OpCode.CALLA: - case OpCode.CALLT: - case OpCode.ABORT: - case OpCode.ASSERT: - case OpCode.THROW: - case OpCode.TRY: - case OpCode.TRY_L: - case OpCode.ENDTRY: - case OpCode.ENDTRY_L: - case OpCode.ENDFINALLY: - case OpCode.RET: - case OpCode.SYSCALL: - */ + ExecuteCall(engine, checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI32)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void CALLA(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + if (x.Script != engine.CurrentContext!.Script) + throw new InvalidOperationException("Pointers can't be shared between scripts"); + ExecuteCall(engine, x.Position); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void CALLT(ExecutionEngine engine, Instruction instruction) + { + throw new InvalidOperationException($"Token not found: {instruction.TokenU16}"); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ABORT(ExecutionEngine engine, Instruction instruction) + { + throw new Exception($"{OpCode.ABORT} is executed."); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ASSERT(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetBoolean(); + if (!x) + throw new Exception($"{OpCode.ASSERT} is executed with false result."); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void THROW(ExecutionEngine engine, Instruction instruction) + { + ExecuteThrow(engine, engine.Pop()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void TRY(ExecutionEngine engine, Instruction instruction) + { + int catchOffset = instruction.TokenI8; + int finallyOffset = instruction.TokenI8_1; + ExecuteTry(engine, catchOffset, finallyOffset); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void TRY_L(ExecutionEngine engine, Instruction instruction) + { + int catchOffset = instruction.TokenI32; + int finallyOffset = instruction.TokenI32_1; + ExecuteTry(engine, catchOffset, finallyOffset); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ENDTRY(ExecutionEngine engine, Instruction instruction) + { + int endOffset = instruction.TokenI8; + ExecuteEndTry(engine, endOffset); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ENDTRY_L(ExecutionEngine engine, Instruction instruction) + { + int endOffset = instruction.TokenI32; + ExecuteEndTry(engine, endOffset); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ENDFINALLY(ExecutionEngine engine, Instruction instruction) + { + if (engine.CurrentContext!.TryStack is null) + throw new InvalidOperationException($"The corresponding TRY block cannot be found."); + if (!engine.CurrentContext.TryStack.TryPop(out ExceptionHandlingContext? currentTry)) + throw new InvalidOperationException($"The corresponding TRY block cannot be found."); + + if (engine.UncaughtException is null) + engine.CurrentContext.InstructionPointer = currentTry.EndPointer; + else + ExecuteThrow(engine, engine.UncaughtException); + + engine.isJumping = true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void RET(ExecutionEngine engine, Instruction instruction) + { + ExecutionContext context_pop = engine.InvocationStack.Pop(); + EvaluationStack stack_eval = engine.InvocationStack.Count == 0 ? engine.ResultStack : engine.InvocationStack.Peek().EvaluationStack; + if (context_pop.EvaluationStack != stack_eval) + { + if (context_pop.RVCount >= 0 && context_pop.EvaluationStack.Count != context_pop.RVCount) + throw new InvalidOperationException("RVCount doesn't match with EvaluationStack"); + context_pop.EvaluationStack.CopyTo(stack_eval); + } + if (engine.InvocationStack.Count == 0) + engine.State = VMState.HALT; + engine.UnloadedContext(context_pop); + engine.isJumping = true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SYSCALL(ExecutionEngine engine, Instruction instruction) + { + throw new InvalidOperationException($"Syscall not found: {instruction.TokenU32}"); + } + + #region Execute methods + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteCall(ExecutionEngine engine, int position) + { + engine.LoadContext(engine.CurrentContext!.Clone(position)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteEndTry(ExecutionEngine engine, int endOffset) + { + if (engine.CurrentContext!.TryStack is null) + throw new InvalidOperationException($"The corresponding TRY block cannot be found."); + if (!engine.CurrentContext.TryStack.TryPeek(out ExceptionHandlingContext? currentTry)) + throw new InvalidOperationException($"The corresponding TRY block cannot be found."); + if (currentTry.State == ExceptionHandlingState.Finally) + throw new InvalidOperationException($"The opcode {OpCode.ENDTRY} can't be executed in a FINALLY block."); + + int endPointer = checked(engine.CurrentContext.InstructionPointer + endOffset); + if (currentTry.HasFinally) + { + currentTry.State = ExceptionHandlingState.Finally; + currentTry.EndPointer = endPointer; + engine.CurrentContext.InstructionPointer = currentTry.FinallyPointer; + } + else + { + engine.CurrentContext.TryStack.Pop(); + engine.CurrentContext.InstructionPointer = endPointer; + } + engine.isJumping = true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteJump(ExecutionEngine engine, int position) + { + if (position < 0 || position >= engine.CurrentContext!.Script.Length) + throw new ArgumentOutOfRangeException($"Jump out of range for position: {position}"); + engine.CurrentContext.InstructionPointer = position; + engine.isJumping = true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteJumpOffset(ExecutionEngine engine, int offset) + { + ExecuteJump(engine, checked(engine.CurrentContext!.InstructionPointer + offset)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ExecuteTry(ExecutionEngine engine, int catchOffset, int finallyOffset) + { + if (catchOffset == 0 && finallyOffset == 0) + throw new InvalidOperationException($"catchOffset and finallyOffset can't be 0 in a TRY block"); + if (engine.CurrentContext!.TryStack is null) + engine.CurrentContext.TryStack = new Stack(); + else if (engine.CurrentContext.TryStack.Count >= engine.Limits.MaxTryNestingDepth) + throw new InvalidOperationException("MaxTryNestingDepth exceed."); + int catchPointer = catchOffset == 0 ? -1 : checked(engine.CurrentContext.InstructionPointer + catchOffset); + int finallyPointer = finallyOffset == 0 ? -1 : checked(engine.CurrentContext.InstructionPointer + finallyOffset); + engine.CurrentContext.TryStack.Push(new ExceptionHandlingContext(catchPointer, finallyPointer)); + } + + public void ExecuteThrow(ExecutionEngine engine, StackItem? ex) + { + engine.UncaughtException = ex; + + int pop = 0; + foreach (var executionContext in engine.InvocationStack) + { + if (executionContext.TryStack != null) + { + while (executionContext.TryStack.TryPeek(out var tryContext)) + { + if (tryContext.State == ExceptionHandlingState.Finally || (tryContext.State == ExceptionHandlingState.Catch && !tryContext.HasFinally)) + { + executionContext.TryStack.Pop(); + continue; + } + for (int i = 0; i < pop; i++) + { + engine.UnloadedContext(engine.InvocationStack.Pop()); + } + if (tryContext.State == ExceptionHandlingState.Try && tryContext.HasCatch) + { + tryContext.State = ExceptionHandlingState.Catch; + engine.Push(engine.UncaughtException!); + executionContext.InstructionPointer = tryContext.CatchPointer; + engine.UncaughtException = null; + } + else + { + tryContext.State = ExceptionHandlingState.Finally; + executionContext.InstructionPointer = tryContext.FinallyPointer; + } + engine.isJumping = true; + return; + } + } + ++pop; + } + + throw new VMUnhandledException(engine.UncaughtException!); + } + + #endregion } } diff --git a/src/Neo.VM/JumpTable.cs b/src/Neo.VM/JumpTable.cs index db68fe71c8..e78ce5d606 100644 --- a/src/Neo.VM/JumpTable.cs +++ b/src/Neo.VM/JumpTable.cs @@ -18,14 +18,16 @@ public partial class JumpTable public delegate void DelAction(ExecutionEngine engine, Instruction instruction); protected readonly DelAction[] _table = new DelAction[byte.MaxValue]; - /// - /// Get Method - /// - /// OpCode - /// Action - public DelAction GetMethod(OpCode opCode) + public DelAction this[OpCode opCode] { - return _table[(byte)opCode]; + get + { + return _table[(byte)opCode]; + } + set + { + _table[(byte)opCode] = value; + } } public JumpTable() diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index ba161e6951..02b7691f87 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Akka.Configuration.Hocon; using Neo.IO; using Neo.Json; using Neo.Network.P2P.Payloads; @@ -32,6 +33,8 @@ namespace Neo.SmartContract /// public partial class ApplicationEngine : ExecutionEngine { + private static readonly JumpTable JumpTable = ComposeJumpTable(); + /// /// The maximum cost that can be spent when a contract is executed in test mode. /// @@ -177,6 +180,58 @@ protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, D diagnostic?.Initialized(this); } + #region JumpTable + + private static JumpTable ComposeJumpTable() + { + var table = new JumpTable(); + + table[OpCode.SYSCALL] = OnSysCall; + table[OpCode.CALLT] = OnCallT; + + return table; + } + + private static void OnCallT(ExecutionEngine engine, Instruction instruction) + { + if (engine is ApplicationEngine app) + { + uint tokenId = instruction.TokenU16; + + app.ValidateCallFlags(CallFlags.ReadStates | CallFlags.AllowCall); + ContractState contract = app.CurrentContext.GetState().Contract; + if (contract is null || tokenId >= contract.Nef.Tokens.Length) + throw new InvalidOperationException(); + MethodToken token = contract.Nef.Tokens[tokenId]; + if (token.ParametersCount > app.CurrentContext.EvaluationStack.Count) + throw new InvalidOperationException(); + StackItem[] args = new StackItem[token.ParametersCount]; + for (int i = 0; i < token.ParametersCount; i++) + args[i] = app.Pop(); + app.CallContractInternal(token.Hash, token.Method, token.CallFlags, token.HasReturnValue, args); + } + else + { + throw new InvalidOperationException(); + } + } + + private static void OnSysCall(ExecutionEngine engine, Instruction instruction) + { + if (engine is ApplicationEngine app) + { + uint method = instruction.TokenU16; + + app.OnSysCall(services[method]); + } + else + { + throw new InvalidOperationException(); + } + } + + #endregion + /// /// Adds GAS to and checks if it has exceeded the maximum limit. /// @@ -270,9 +325,9 @@ internal ContractTask CallFromNativeContract(UInt160 callingScriptHash, UI return task; } - protected override void ContextUnloaded(ExecutionContext context) + public override void UnloadedContext(ExecutionContext context) { - base.ContextUnloaded(context); + base.UnloadedContext(context); if (context.Script != CurrentContext?.Script) { ExecutionContextState state = context.GetState(); @@ -324,7 +379,7 @@ public static ApplicationEngine Create(TriggerType trigger, IVerifiable containe ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); } - protected override void LoadContext(ExecutionContext context) + public override void LoadContext(ExecutionContext context) { // Set default execution context state var state = context.GetState(); @@ -391,21 +446,6 @@ public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialP return context; } - protected override ExecutionContext LoadToken(ushort tokenId) - { - ValidateCallFlags(CallFlags.ReadStates | CallFlags.AllowCall); - ContractState contract = CurrentContext.GetState().Contract; - if (contract is null || tokenId >= contract.Nef.Tokens.Length) - throw new InvalidOperationException(); - MethodToken token = contract.Nef.Tokens[tokenId]; - if (token.ParametersCount > CurrentContext.EvaluationStack.Count) - throw new InvalidOperationException(); - StackItem[] args = new StackItem[token.ParametersCount]; - for (int i = 0; i < token.ParametersCount; i++) - args[i] = Pop(); - return CallContractInternal(token.Hash, token.Method, token.CallFlags, token.HasReturnValue, args); - } - /// /// Converts an to a that used in the virtual machine. /// @@ -503,11 +543,6 @@ internal protected void ValidateCallFlags(CallFlags requiredCallFlags) throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state.CallFlags}."); } - protected override void OnSysCall(uint method) - { - OnSysCall(services[method]); - } - /// /// Invokes the specified interoperable service. /// diff --git a/tests/Neo.VM.Tests/Types/TestEngine.cs b/tests/Neo.VM.Tests/Types/TestEngine.cs index 07aa89a09f..cf99314892 100644 --- a/tests/Neo.VM.Tests/Types/TestEngine.cs +++ b/tests/Neo.VM.Tests/Types/TestEngine.cs @@ -19,21 +19,32 @@ class TestEngine : ExecutionEngine { public Exception FaultException { get; private set; } - protected override void OnSysCall(uint method) + public TestEngine() : base(ComposeJumpTable()) { } + + private static JumpTable ComposeJumpTable() { + JumpTable jumpTable = new JumpTable(); + jumpTable[OpCode.SYSCALL] = OnSysCall; + return jumpTable; + } + + private static void OnSysCall(ExecutionEngine engine, Instruction instruction) + { + uint method = instruction.TokenU32; + if (method == 0x77777777) { - CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new object())); + engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(new object())); return; } if (method == 0xaddeadde) { - ExecuteThrow("error"); + engine.JumpTable.ExecuteThrow(engine, "error"); return; } - throw new System.Exception(); + throw new Exception(); } protected override void OnFault(Exception ex) From 6c2a9d1d7b50854f26a4aa2c816fa282f82c063d Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 09:43:43 +0100 Subject: [PATCH 08/34] Stack --- .../{ => JumpTable}/JumpTable.Control.cs | 0 src/Neo.VM/{ => JumpTable}/JumpTable.Push.cs | 0 .../{ => JumpTable}/JumpTable.Splice.cs | 0 src/Neo.VM/JumpTable/JumpTable.Stack.cs | 124 ++++++++++++++++++ src/Neo.VM/{ => JumpTable}/JumpTable.Types.cs | 0 src/Neo.VM/{ => JumpTable}/JumpTable.cs | 64 ++------- 6 files changed, 132 insertions(+), 56 deletions(-) rename src/Neo.VM/{ => JumpTable}/JumpTable.Control.cs (100%) rename src/Neo.VM/{ => JumpTable}/JumpTable.Push.cs (100%) rename src/Neo.VM/{ => JumpTable}/JumpTable.Splice.cs (100%) create mode 100644 src/Neo.VM/JumpTable/JumpTable.Stack.cs rename src/Neo.VM/{ => JumpTable}/JumpTable.Types.cs (100%) rename src/Neo.VM/{ => JumpTable}/JumpTable.cs (82%) diff --git a/src/Neo.VM/JumpTable.Control.cs b/src/Neo.VM/JumpTable/JumpTable.Control.cs similarity index 100% rename from src/Neo.VM/JumpTable.Control.cs rename to src/Neo.VM/JumpTable/JumpTable.Control.cs diff --git a/src/Neo.VM/JumpTable.Push.cs b/src/Neo.VM/JumpTable/JumpTable.Push.cs similarity index 100% rename from src/Neo.VM/JumpTable.Push.cs rename to src/Neo.VM/JumpTable/JumpTable.Push.cs diff --git a/src/Neo.VM/JumpTable.Splice.cs b/src/Neo.VM/JumpTable/JumpTable.Splice.cs similarity index 100% rename from src/Neo.VM/JumpTable.Splice.cs rename to src/Neo.VM/JumpTable/JumpTable.Splice.cs diff --git a/src/Neo.VM/JumpTable/JumpTable.Stack.cs b/src/Neo.VM/JumpTable/JumpTable.Stack.cs new file mode 100644 index 0000000000..a068a114d6 --- /dev/null +++ b/src/Neo.VM/JumpTable/JumpTable.Stack.cs @@ -0,0 +1,124 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Push.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo.VM.Types; +using System; +using System.Runtime.CompilerServices; + +namespace Neo.VM +{ + public partial class JumpTable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void DEPTH(ExecutionEngine engine, Instruction instruction) + { + engine.Push(engine.CurrentContext!.EvaluationStack.Count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void DROP(ExecutionEngine engine, Instruction instruction) + { + engine.Pop(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NIP(ExecutionEngine engine, Instruction instruction) + { + engine.CurrentContext!.EvaluationStack.Remove(1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void XDROP(ExecutionEngine engine, Instruction instruction) + { + var n = (int)engine.Pop().GetInteger(); + if (n < 0) + throw new InvalidOperationException($"The negative value {n} is invalid for OpCode.{instruction.OpCode}."); + engine.CurrentContext!.EvaluationStack.Remove(n); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void CLEAR(ExecutionEngine engine, Instruction instruction) + { + engine.CurrentContext!.EvaluationStack.Clear(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void DUP(ExecutionEngine engine, Instruction instruction) + { + engine.Push(engine.Peek()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void OVER(ExecutionEngine engine, Instruction instruction) + { + engine.Push(engine.Peek(1)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PICK(ExecutionEngine engine, Instruction instruction) + { + var n = (int)engine.Pop().GetInteger(); + if (n < 0) + throw new InvalidOperationException($"The negative value {n} is invalid for OpCode.{instruction.OpCode}."); + engine.Push(engine.Peek(n)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void TUCK(ExecutionEngine engine, Instruction instruction) + { + engine.CurrentContext!.EvaluationStack.Insert(2, engine.Peek()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SWAP(ExecutionEngine engine, Instruction instruction) + { + var x = engine.CurrentContext!.EvaluationStack.Remove(1); + engine.Push(x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ROT(ExecutionEngine engine, Instruction instruction) + { + var x = engine.CurrentContext!.EvaluationStack.Remove(2); + engine.Push(x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ROLL(ExecutionEngine engine, Instruction instruction) + { + var n = (int)engine.Pop().GetInteger(); + if (n < 0) + throw new InvalidOperationException($"The negative value {n} is invalid for OpCode.{instruction.OpCode}."); + if (n == 0) return; + var x = engine.CurrentContext!.EvaluationStack.Remove(n); + engine.Push(x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void REVERSE3(ExecutionEngine engine, Instruction instruction) + { + engine.CurrentContext!.EvaluationStack.Reverse(3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void REVERSE4(ExecutionEngine engine, Instruction instruction) + { + engine.CurrentContext!.EvaluationStack.Reverse(4); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void REVERSEN(ExecutionEngine engine, Instruction instruction) + { + var n = (int)engine.Pop().GetInteger(); + engine.CurrentContext!.EvaluationStack.Reverse(n); + } + } +} diff --git a/src/Neo.VM/JumpTable.Types.cs b/src/Neo.VM/JumpTable/JumpTable.Types.cs similarity index 100% rename from src/Neo.VM/JumpTable.Types.cs rename to src/Neo.VM/JumpTable/JumpTable.Types.cs diff --git a/src/Neo.VM/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs similarity index 82% rename from src/Neo.VM/JumpTable.cs rename to src/Neo.VM/JumpTable/JumpTable.cs index e78ce5d606..a1ba2408df 100644 --- a/src/Neo.VM/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -16,17 +16,17 @@ namespace Neo.VM public partial class JumpTable { public delegate void DelAction(ExecutionEngine engine, Instruction instruction); - protected readonly DelAction[] _table = new DelAction[byte.MaxValue]; + protected readonly DelAction[] Table = new DelAction[byte.MaxValue]; public DelAction this[OpCode opCode] { get { - return _table[(byte)opCode]; + return Table[(byte)opCode]; } set { - _table[(byte)opCode] = value; + Table[(byte)opCode] = value; } } @@ -38,22 +38,22 @@ public JumpTable() { if (Enum.TryParse(mi.Name, false, out var opCode)) { - if (_table[(byte)opCode] is not null) + if (Table[(byte)opCode] is not null) { throw new InvalidOperationException($"Opcode {opCode} is already defined."); } - _table[(byte)opCode] = (DelAction)mi.CreateDelegate(typeof(DelAction), this); + Table[(byte)opCode] = (DelAction)mi.CreateDelegate(typeof(DelAction), this); } } // Fill with undefined - for (int x = 0; x < _table.Length; x++) + for (var x = 0; x < Table.Length; x++) { - if (_table[x] is not null) continue; + if (Table[x] is not null) continue; - _table[x] = (engine, instruction) => + Table[x] = (engine, instruction) => { throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); }; @@ -63,56 +63,8 @@ public JumpTable() switch (instruction.OpCode) { - // Stack ops - case OpCode.DEPTH: - Depth(instruction); - break; - case OpCode.DROP: - Drop(instruction); - break; - case OpCode.NIP: - Nip(instruction); - break; - case OpCode.XDROP: - XDrop(instruction); - break; - case OpCode.CLEAR: - Clear(instruction); - break; - case OpCode.DUP: - Dup(instruction); - break; - case OpCode.OVER: - Over(instruction); - break; - case OpCode.PICK: - Pick(instruction); - break; - case OpCode.TUCK: - Tuck(instruction); - break; - case OpCode.SWAP: - Swap(instruction); - break; - case OpCode.ROT: - Rot(instruction); - break; - case OpCode.ROLL: - Roll(instruction); - break; - case OpCode.REVERSE3: - Reverse3(instruction); - break; - case OpCode.REVERSE4: - Reverse4(instruction); - break; - case OpCode.REVERSEN: - ReverseN(instruction); - break; - //Slot case OpCode.INITSSLOT: - InitSSlot(instruction); break; case OpCode.INITSLOT: InitSlot(instruction); From e0dd24b2d8d4f56a71a897bc3ab2f5f64d26cb12 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 09:46:11 +0100 Subject: [PATCH 09/34] Bitwisee --- src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs | 65 ++++++++++++++++++++++ src/Neo.VM/JumpTable/JumpTable.Stack.cs | 2 +- src/Neo.VM/JumpTable/JumpTable.cs | 20 ------- 3 files changed, 66 insertions(+), 21 deletions(-) create mode 100644 src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs diff --git a/src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs b/src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs new file mode 100644 index 0000000000..b502e6b686 --- /dev/null +++ b/src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs @@ -0,0 +1,65 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Bitwisee.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Runtime.CompilerServices; + +namespace Neo.VM +{ + public partial class JumpTable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void INVERT(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetInteger(); + engine.Push(~x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void AND(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 & x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void OR(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 | x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void XOR(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 ^ x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void EQUAL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop(); + var x1 = engine.Pop(); + engine.Push(x1.Equals(x2, engine.Limits)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NOTEQUAL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop(); + var x1 = engine.Pop(); + engine.Push(!x1.Equals(x2, engine.Limits)); + } + } +} diff --git a/src/Neo.VM/JumpTable/JumpTable.Stack.cs b/src/Neo.VM/JumpTable/JumpTable.Stack.cs index a068a114d6..281388d0a0 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Stack.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Stack.cs @@ -1,6 +1,6 @@ // Copyright (C) 2015-2024 The Neo Project. // -// JumpTable.Push.cs file belongs to the neo project and is free +// JumpTable.Stack.cs file belongs to the neo project and is free // software distributed under the MIT software license, see the // accompanying file LICENSE in the main directory of the // repository or http://www.opensource.org/licenses/mit-license.php diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index a1ba2408df..6884adef9b 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -142,26 +142,6 @@ public JumpTable() StArg(instruction); break; - // Bitwise logic - case OpCode.INVERT: - Invert(instruction); - break; - case OpCode.AND: - And(instruction); - break; - case OpCode.OR: - Or(instruction); - break; - case OpCode.XOR: - Xor(instruction); - break; - case OpCode.EQUAL: - Equal(instruction); - break; - case OpCode.NOTEQUAL: - NotEqual(instruction); - break; - // Numeric case OpCode.SIGN: Sign(instruction); From 8f9b1608040da13cff22e262569e4d46b199901d Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 09:48:26 +0100 Subject: [PATCH 10/34] clean using --- src/Neo.VM/JumpTable/JumpTable.cs | 1 - src/Neo/SmartContract/ApplicationEngine.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index 6884adef9b..fa5d8d0c98 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -296,6 +296,5 @@ public JumpTable() } */ } - } } diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 02b7691f87..6a73005c5b 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -9,7 +9,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Akka.Configuration.Hocon; using Neo.IO; using Neo.Json; using Neo.Network.P2P.Payloads; From b72cb14485fa1730336f18dc37768208f58849d5 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 09:58:50 +0100 Subject: [PATCH 11/34] Numeric --- src/Neo.VM/JumpTable/JumpTable.Numeric.cs | 265 ++++++++++++++++++++++ src/Neo.VM/JumpTable/JumpTable.cs | 89 -------- 2 files changed, 265 insertions(+), 89 deletions(-) create mode 100644 src/Neo.VM/JumpTable/JumpTable.Numeric.cs diff --git a/src/Neo.VM/JumpTable/JumpTable.Numeric.cs b/src/Neo.VM/JumpTable/JumpTable.Numeric.cs new file mode 100644 index 0000000000..aa9ec742e7 --- /dev/null +++ b/src/Neo.VM/JumpTable/JumpTable.Numeric.cs @@ -0,0 +1,265 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Numeric.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 +{ + public partial class JumpTable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SIGN(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetInteger(); + engine.Push(x.Sign); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ABS(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetInteger(); + engine.Push(BigInteger.Abs(x)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NEGATE(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetInteger(); + engine.Push(-x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void INC(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetInteger(); + engine.Push(x + 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void DEC(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetInteger(); + engine.Push(x - 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void ADD(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 + x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SUB(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 - x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void MUL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 * x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void DIV(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 / x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void MOD(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 % x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void POW(ExecutionEngine engine, Instruction instruction) + { + var exponent = (int)engine.Pop().GetInteger(); + engine.Limits.AssertShift(exponent); + var value = engine.Pop().GetInteger(); + engine.Push(BigInteger.Pow(value, exponent)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SQRT(ExecutionEngine engine, Instruction instruction) + { + engine.Push(engine.Pop().GetInteger().Sqrt()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void MODMUL(ExecutionEngine engine, Instruction instruction) + { + var modulus = engine.Pop().GetInteger(); + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 * x2 % modulus); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void MODPOW(ExecutionEngine engine, Instruction instruction) + { + var modulus = engine.Pop().GetInteger(); + var exponent = engine.Pop().GetInteger(); + var value = engine.Pop().GetInteger(); + var result = exponent == -1 + ? value.ModInverse(modulus) + : BigInteger.ModPow(value, exponent, modulus); + engine.Push(result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SHL(ExecutionEngine engine, Instruction instruction) + { + var shift = (int)engine.Pop().GetInteger(); + engine.Limits.AssertShift(shift); + if (shift == 0) return; + var x = engine.Pop().GetInteger(); + engine.Push(x << shift); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SHR(ExecutionEngine engine, Instruction instruction) + { + var shift = (int)engine.Pop().GetInteger(); + engine.Limits.AssertShift(shift); + if (shift == 0) return; + var x = engine.Pop().GetInteger(); + engine.Push(x >> shift); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NOT(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetBoolean(); + engine.Push(!x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void BOOLAND(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetBoolean(); + var x1 = engine.Pop().GetBoolean(); + engine.Push(x1 && x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void BOOLOR(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetBoolean(); + var x1 = engine.Pop().GetBoolean(); + engine.Push(x1 || x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NZ(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop().GetInteger(); + engine.Push(!x.IsZero); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NUMEQUAL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 == x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NUMNOTEQUAL(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(x1 != x2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LT(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop(); + var x1 = engine.Pop(); + if (x1.IsNull || x2.IsNull) + engine.Push(false); + else + engine.Push(x1.GetInteger() < x2.GetInteger()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LE(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop(); + var x1 = engine.Pop(); + if (x1.IsNull || x2.IsNull) + engine.Push(false); + else + engine.Push(x1.GetInteger() <= x2.GetInteger()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void GT(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop(); + var x1 = engine.Pop(); + if (x1.IsNull || x2.IsNull) + engine.Push(false); + else + engine.Push(x1.GetInteger() > x2.GetInteger()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void GE(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop(); + var x1 = engine.Pop(); + if (x1.IsNull || x2.IsNull) + engine.Push(false); + else + engine.Push(x1.GetInteger() >= x2.GetInteger()); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void MIN(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(BigInteger.Min(x1, x2)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void MAX(ExecutionEngine engine, Instruction instruction) + { + var x2 = engine.Pop().GetInteger(); + var x1 = engine.Pop().GetInteger(); + engine.Push(BigInteger.Max(x1, x2)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void WITHIN(ExecutionEngine engine, Instruction instruction) + { + var b = engine.Pop().GetInteger(); + var a = engine.Pop().GetInteger(); + var x = engine.Pop().GetInteger(); + engine.Push(a <= x && x < b); + } + } +} diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index fa5d8d0c98..3cf6096bac 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -142,95 +142,6 @@ public JumpTable() StArg(instruction); break; - // Numeric - case OpCode.SIGN: - Sign(instruction); - break; - case OpCode.ABS: - Abs(instruction); - break; - case OpCode.NEGATE: - Negate(instruction); - break; - case OpCode.INC: - Inc(instruction); - break; - case OpCode.DEC: - Dec(instruction); - break; - case OpCode.ADD: - Add(instruction); - break; - case OpCode.SUB: - Sub(instruction); - break; - case OpCode.MUL: - Mul(instruction); - break; - case OpCode.DIV: - Div(instruction); - break; - case OpCode.MOD: - Mod(instruction); - break; - case OpCode.POW: - Pow(instruction); - break; - case OpCode.SQRT: - Sqrt(instruction); - break; - case OpCode.MODMUL: - ModMul(instruction); - break; - case OpCode.MODPOW: - ModPow(instruction); - break; - case OpCode.SHL: - Shl(instruction); - break; - case OpCode.SHR: - Shr(instruction); - break; - case OpCode.NOT: - Not(instruction); - break; - case OpCode.BOOLAND: - BoolAnd(instruction); - break; - case OpCode.BOOLOR: - BoolOr(instruction); - break; - case OpCode.NZ: - Nz(instruction); - break; - case OpCode.NUMEQUAL: - NumEqual(instruction); - break; - case OpCode.NUMNOTEQUAL: - NumNotEqual(instruction); - break; - case OpCode.LT: - Lt(instruction); - break; - case OpCode.LE: - Le(instruction); - break; - case OpCode.GT: - Gt(instruction); - break; - case OpCode.GE: - Ge(instruction); - break; - case OpCode.MIN: - Min(instruction); - break; - case OpCode.MAX: - Max(instruction); - break; - case OpCode.WITHIN: - Within(instruction); - break; - // Compound-type case OpCode.PACKMAP: PackMap(instruction); From c8e69c3fa7e4bda5617ce4c62a38d8d0359f5f67 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 10:05:35 +0100 Subject: [PATCH 12/34] Prepare --- src/Neo.VM/ExecutionEngine.cs | 18 --- src/Neo.VM/JumpTable/JumpTable.Compound.cs | 84 ++++++++++++ src/Neo.VM/JumpTable/JumpTable.Control.cs | 38 +++--- src/Neo.VM/JumpTable/JumpTable.Slot.cs | 121 +++++++++++++++++ src/Neo.VM/JumpTable/JumpTable.cs | 148 +-------------------- 5 files changed, 225 insertions(+), 184 deletions(-) create mode 100644 src/Neo.VM/JumpTable/JumpTable.Compound.cs create mode 100644 src/Neo.VM/JumpTable/JumpTable.Slot.cs diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index a6d1423f70..141540fdc8 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -119,15 +119,6 @@ public virtual VMState Execute() return State; } - private void ExecuteLoadFromSlot(Slot? slot, int index) - { - if (slot is null) - throw new InvalidOperationException("Slot has not been initialized."); - if (index < 0 || index >= slot.Count) - throw new InvalidOperationException($"Index out of range when loading from slot: {index}"); - Push(slot[index]); - } - /// /// Execute the next instruction. /// @@ -163,15 +154,6 @@ protected internal void ExecuteNext() } } - private void ExecuteStoreToSlot(Slot? slot, int index) - { - if (slot is null) - throw new InvalidOperationException("Slot has not been initialized."); - if (index < 0 || index >= slot.Count) - throw new InvalidOperationException($"Index out of range when storing to slot: {index}"); - slot[index] = Pop(); - } - /// /// Loads the specified context into the invocation stack. /// diff --git a/src/Neo.VM/JumpTable/JumpTable.Compound.cs b/src/Neo.VM/JumpTable/JumpTable.Compound.cs new file mode 100644 index 0000000000..c1e66efd31 --- /dev/null +++ b/src/Neo.VM/JumpTable/JumpTable.Compound.cs @@ -0,0 +1,84 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Compound.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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. + +namespace Neo.VM +{ + public partial class JumpTable + { + /* TODO: + switch (instruction.OpCode) + { + // Compound-type + case OpCode.PACKMAP: + PackMap(instruction); + break; + case OpCode.PACKSTRUCT: + PackStruct(instruction); + break; + case OpCode.PACK: + Pack(instruction); + break; + case OpCode.UNPACK: + Unpack(instruction); + break; + case OpCode.NEWARRAY0: + NewArray0(instruction); + break; + case OpCode.NEWARRAY: + case OpCode.NEWARRAY_T: + NewArray_T(instruction); + break; + case OpCode.NEWSTRUCT0: + NewStruct0(instruction); + break; + case OpCode.NEWSTRUCT: + NewStruct(instruction); + break; + case OpCode.NEWMAP: + NewMap(instruction); + break; + case OpCode.SIZE: + Size(instruction); + break; + case OpCode.HASKEY: + HasKey(instruction); + break; + case OpCode.KEYS: + Keys(instruction); + break; + case OpCode.VALUES: + Values(instruction); + break; + case OpCode.PICKITEM: + PickItem(instruction); + break; + case OpCode.APPEND: + Append(instruction); + break; + case OpCode.SETITEM: + SetItem(instruction); + break; + case OpCode.REVERSEITEMS: + ReverseItems(instruction); + break; + case OpCode.REMOVE: + Remove(instruction); + break; + case OpCode.CLEARITEMS: + ClearItems(instruction); + break; + case OpCode.POPITEM: + PopItem(instruction); + break; + } + */ + } +} diff --git a/src/Neo.VM/JumpTable/JumpTable.Control.cs b/src/Neo.VM/JumpTable/JumpTable.Control.cs index 7d1b9f9542..8e631fbf3d 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Control.cs @@ -229,22 +229,22 @@ public virtual void TRY(ExecutionEngine engine, Instruction instruction) [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void TRY_L(ExecutionEngine engine, Instruction instruction) { - int catchOffset = instruction.TokenI32; - int finallyOffset = instruction.TokenI32_1; + var catchOffset = instruction.TokenI32; + var finallyOffset = instruction.TokenI32_1; ExecuteTry(engine, catchOffset, finallyOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void ENDTRY(ExecutionEngine engine, Instruction instruction) { - int endOffset = instruction.TokenI8; + var endOffset = instruction.TokenI8; ExecuteEndTry(engine, endOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void ENDTRY_L(ExecutionEngine engine, Instruction instruction) { - int endOffset = instruction.TokenI32; + var endOffset = instruction.TokenI32; ExecuteEndTry(engine, endOffset); } @@ -253,7 +253,7 @@ public virtual void ENDFINALLY(ExecutionEngine engine, Instruction instruction) { if (engine.CurrentContext!.TryStack is null) throw new InvalidOperationException($"The corresponding TRY block cannot be found."); - if (!engine.CurrentContext.TryStack.TryPop(out ExceptionHandlingContext? currentTry)) + if (!engine.CurrentContext.TryStack.TryPop(out var currentTry)) throw new InvalidOperationException($"The corresponding TRY block cannot be found."); if (engine.UncaughtException is null) @@ -267,8 +267,8 @@ public virtual void ENDFINALLY(ExecutionEngine engine, Instruction instruction) [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void RET(ExecutionEngine engine, Instruction instruction) { - ExecutionContext context_pop = engine.InvocationStack.Pop(); - EvaluationStack stack_eval = engine.InvocationStack.Count == 0 ? engine.ResultStack : engine.InvocationStack.Peek().EvaluationStack; + var context_pop = engine.InvocationStack.Pop(); + var stack_eval = engine.InvocationStack.Count == 0 ? engine.ResultStack : engine.InvocationStack.Peek().EvaluationStack; if (context_pop.EvaluationStack != stack_eval) { if (context_pop.RVCount >= 0 && context_pop.EvaluationStack.Count != context_pop.RVCount) @@ -290,22 +290,22 @@ public virtual void SYSCALL(ExecutionEngine engine, Instruction instruction) #region Execute methods [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ExecuteCall(ExecutionEngine engine, int position) + public virtual void ExecuteCall(ExecutionEngine engine, int position) { engine.LoadContext(engine.CurrentContext!.Clone(position)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ExecuteEndTry(ExecutionEngine engine, int endOffset) + public virtual void ExecuteEndTry(ExecutionEngine engine, int endOffset) { if (engine.CurrentContext!.TryStack is null) throw new InvalidOperationException($"The corresponding TRY block cannot be found."); - if (!engine.CurrentContext.TryStack.TryPeek(out ExceptionHandlingContext? currentTry)) + if (!engine.CurrentContext.TryStack.TryPeek(out var currentTry)) throw new InvalidOperationException($"The corresponding TRY block cannot be found."); if (currentTry.State == ExceptionHandlingState.Finally) throw new InvalidOperationException($"The opcode {OpCode.ENDTRY} can't be executed in a FINALLY block."); - int endPointer = checked(engine.CurrentContext.InstructionPointer + endOffset); + var endPointer = checked(engine.CurrentContext.InstructionPointer + endOffset); if (currentTry.HasFinally) { currentTry.State = ExceptionHandlingState.Finally; @@ -321,7 +321,7 @@ public void ExecuteEndTry(ExecutionEngine engine, int endOffset) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ExecuteJump(ExecutionEngine engine, int position) + public virtual void ExecuteJump(ExecutionEngine engine, int position) { if (position < 0 || position >= engine.CurrentContext!.Script.Length) throw new ArgumentOutOfRangeException($"Jump out of range for position: {position}"); @@ -330,13 +330,13 @@ public void ExecuteJump(ExecutionEngine engine, int position) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ExecuteJumpOffset(ExecutionEngine engine, int offset) + public virtual void ExecuteJumpOffset(ExecutionEngine engine, int offset) { ExecuteJump(engine, checked(engine.CurrentContext!.InstructionPointer + offset)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ExecuteTry(ExecutionEngine engine, int catchOffset, int finallyOffset) + public virtual void ExecuteTry(ExecutionEngine engine, int catchOffset, int finallyOffset) { if (catchOffset == 0 && finallyOffset == 0) throw new InvalidOperationException($"catchOffset and finallyOffset can't be 0 in a TRY block"); @@ -344,16 +344,16 @@ public void ExecuteTry(ExecutionEngine engine, int catchOffset, int finallyOffse engine.CurrentContext.TryStack = new Stack(); else if (engine.CurrentContext.TryStack.Count >= engine.Limits.MaxTryNestingDepth) throw new InvalidOperationException("MaxTryNestingDepth exceed."); - int catchPointer = catchOffset == 0 ? -1 : checked(engine.CurrentContext.InstructionPointer + catchOffset); - int finallyPointer = finallyOffset == 0 ? -1 : checked(engine.CurrentContext.InstructionPointer + finallyOffset); + var catchPointer = catchOffset == 0 ? -1 : checked(engine.CurrentContext.InstructionPointer + catchOffset); + var finallyPointer = finallyOffset == 0 ? -1 : checked(engine.CurrentContext.InstructionPointer + finallyOffset); engine.CurrentContext.TryStack.Push(new ExceptionHandlingContext(catchPointer, finallyPointer)); } - public void ExecuteThrow(ExecutionEngine engine, StackItem? ex) + public virtual void ExecuteThrow(ExecutionEngine engine, StackItem? ex) { engine.UncaughtException = ex; - int pop = 0; + var pop = 0; foreach (var executionContext in engine.InvocationStack) { if (executionContext.TryStack != null) @@ -365,7 +365,7 @@ public void ExecuteThrow(ExecutionEngine engine, StackItem? ex) executionContext.TryStack.Pop(); continue; } - for (int i = 0; i < pop; i++) + for (var i = 0; i < pop; i++) { engine.UnloadedContext(engine.InvocationStack.Pop()); } diff --git a/src/Neo.VM/JumpTable/JumpTable.Slot.cs b/src/Neo.VM/JumpTable/JumpTable.Slot.cs new file mode 100644 index 0000000000..6035d6570f --- /dev/null +++ b/src/Neo.VM/JumpTable/JumpTable.Slot.cs @@ -0,0 +1,121 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// JumpTable.Slot.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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; + +namespace Neo.VM +{ + public partial class JumpTable + { + /* TODO: + case OpCode.INITSSLOT: + break; + case OpCode.INITSLOT: + InitSlot(instruction); + break; + case OpCode.LDSFLD0: + case OpCode.LDSFLD1: + case OpCode.LDSFLD2: + case OpCode.LDSFLD3: + case OpCode.LDSFLD4: + case OpCode.LDSFLD5: + case OpCode.LDSFLD6: + LdSFldM(instruction); + break; + case OpCode.LDSFLD: + LdSFld(instruction); + break; + case OpCode.STSFLD0: + case OpCode.STSFLD1: + case OpCode.STSFLD2: + case OpCode.STSFLD3: + case OpCode.STSFLD4: + case OpCode.STSFLD5: + case OpCode.STSFLD6: + StSFldM(instruction); + break; + case OpCode.STSFLD: + StSFld(instruction); + break; + case OpCode.LDLOC0: + case OpCode.LDLOC1: + case OpCode.LDLOC2: + case OpCode.LDLOC3: + case OpCode.LDLOC4: + case OpCode.LDLOC5: + case OpCode.LDLOC6: + LdLocM(instruction); + break; + case OpCode.LDLOC: + LdLoc(instruction); + break; + case OpCode.STLOC0: + case OpCode.STLOC1: + case OpCode.STLOC2: + case OpCode.STLOC3: + case OpCode.STLOC4: + case OpCode.STLOC5: + case OpCode.STLOC6: + StLocM(instruction); + break; + case OpCode.STLOC: + StLoc(instruction); + break; + case OpCode.LDARG0: + case OpCode.LDARG1: + case OpCode.LDARG2: + case OpCode.LDARG3: + case OpCode.LDARG4: + case OpCode.LDARG5: + case OpCode.LDARG6: + LdArgM(instruction); + break; + case OpCode.LDARG: + LdArg(instruction); + break; + case OpCode.STARG0: + case OpCode.STARG1: + case OpCode.STARG2: + case OpCode.STARG3: + case OpCode.STARG4: + case OpCode.STARG5: + case OpCode.STARG6: + StArgM(instruction); + break; + case OpCode.STARG: + StArg(instruction); + break; + */ + + + #region Execute methods + + private void ExecuteStoreToSlot(ExecutionEngine engine, Slot? slot, int index) + { + if (slot is null) + throw new InvalidOperationException("Slot has not been initialized."); + if (index < 0 || index >= slot.Count) + throw new InvalidOperationException($"Index out of range when storing to slot: {index}"); + slot[index] = engine.Pop(); + } + + private void ExecuteLoadFromSlot(ExecutionEngine engine, Slot? slot, int index) + { + if (slot is null) + throw new InvalidOperationException("Slot has not been initialized."); + if (index < 0 || index >= slot.Count) + throw new InvalidOperationException($"Index out of range when loading from slot: {index}"); + engine.Push(slot[index]); + } + + #endregion + } +} diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index 3cf6096bac..61a83eeaff 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -59,153 +59,7 @@ public JumpTable() }; } - /* TODO: - - switch (instruction.OpCode) - { - //Slot - case OpCode.INITSSLOT: - break; - case OpCode.INITSLOT: - InitSlot(instruction); - break; - case OpCode.LDSFLD0: - case OpCode.LDSFLD1: - case OpCode.LDSFLD2: - case OpCode.LDSFLD3: - case OpCode.LDSFLD4: - case OpCode.LDSFLD5: - case OpCode.LDSFLD6: - LdSFldM(instruction); - break; - case OpCode.LDSFLD: - LdSFld(instruction); - break; - case OpCode.STSFLD0: - case OpCode.STSFLD1: - case OpCode.STSFLD2: - case OpCode.STSFLD3: - case OpCode.STSFLD4: - case OpCode.STSFLD5: - case OpCode.STSFLD6: - StSFldM(instruction); - break; - case OpCode.STSFLD: - StSFld(instruction); - break; - case OpCode.LDLOC0: - case OpCode.LDLOC1: - case OpCode.LDLOC2: - case OpCode.LDLOC3: - case OpCode.LDLOC4: - case OpCode.LDLOC5: - case OpCode.LDLOC6: - LdLocM(instruction); - break; - case OpCode.LDLOC: - LdLoc(instruction); - break; - case OpCode.STLOC0: - case OpCode.STLOC1: - case OpCode.STLOC2: - case OpCode.STLOC3: - case OpCode.STLOC4: - case OpCode.STLOC5: - case OpCode.STLOC6: - StLocM(instruction); - break; - case OpCode.STLOC: - StLoc(instruction); - break; - case OpCode.LDARG0: - case OpCode.LDARG1: - case OpCode.LDARG2: - case OpCode.LDARG3: - case OpCode.LDARG4: - case OpCode.LDARG5: - case OpCode.LDARG6: - LdArgM(instruction); - break; - case OpCode.LDARG: - LdArg(instruction); - break; - case OpCode.STARG0: - case OpCode.STARG1: - case OpCode.STARG2: - case OpCode.STARG3: - case OpCode.STARG4: - case OpCode.STARG5: - case OpCode.STARG6: - StArgM(instruction); - break; - case OpCode.STARG: - StArg(instruction); - break; - - // Compound-type - case OpCode.PACKMAP: - PackMap(instruction); - break; - case OpCode.PACKSTRUCT: - PackStruct(instruction); - break; - case OpCode.PACK: - Pack(instruction); - break; - case OpCode.UNPACK: - Unpack(instruction); - break; - case OpCode.NEWARRAY0: - NewArray0(instruction); - break; - case OpCode.NEWARRAY: - case OpCode.NEWARRAY_T: - NewArray_T(instruction); - break; - case OpCode.NEWSTRUCT0: - NewStruct0(instruction); - break; - case OpCode.NEWSTRUCT: - NewStruct(instruction); - break; - case OpCode.NEWMAP: - NewMap(instruction); - break; - case OpCode.SIZE: - Size(instruction); - break; - case OpCode.HASKEY: - HasKey(instruction); - break; - case OpCode.KEYS: - Keys(instruction); - break; - case OpCode.VALUES: - Values(instruction); - break; - case OpCode.PICKITEM: - PickItem(instruction); - break; - case OpCode.APPEND: - Append(instruction); - break; - case OpCode.SETITEM: - SetItem(instruction); - break; - case OpCode.REVERSEITEMS: - ReverseItems(instruction); - break; - case OpCode.REMOVE: - Remove(instruction); - break; - case OpCode.CLEARITEMS: - ClearItems(instruction); - break; - case OpCode.POPITEM: - PopItem(instruction); - break; - } - */ + } } } From f218d2a2c4d08cfa46185b1a522640023ec524f5 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 10:06:53 +0100 Subject: [PATCH 13/34] AggressiveInlining --- src/Neo.VM/JumpTable/JumpTable.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index 61a83eeaff..f215c814a0 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -10,6 +10,7 @@ // modifications are permitted. using System; +using System.Runtime.CompilerServices; namespace Neo.VM { @@ -20,14 +21,10 @@ public partial class JumpTable public DelAction this[OpCode opCode] { - get - { - return Table[(byte)opCode]; - } - set - { - Table[(byte)opCode] = value; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => Table[(byte)opCode]; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set { Table[(byte)opCode] = value; } } public JumpTable() @@ -58,8 +55,6 @@ public JumpTable() throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); }; } - - } } } From d495868530085d99467f12bebaf4dceed88673d8 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 10:08:48 +0100 Subject: [PATCH 14/34] one left --- src/Neo.VM/JumpTable/JumpTable.Types.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Neo.VM/JumpTable/JumpTable.Types.cs b/src/Neo.VM/JumpTable/JumpTable.Types.cs index 46fd50749d..6b0107e97f 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Types.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Types.cs @@ -17,6 +17,7 @@ namespace Neo.VM { public partial class JumpTable { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual void ISNULL(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); From c4fd26b45f322cb12742090c9886e4c34e38156b Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 10:24:19 +0100 Subject: [PATCH 15/34] Compound --- src/Neo.VM/JumpTable/JumpTable.Compound.cs | 418 ++++++++++++++++++--- 1 file changed, 362 insertions(+), 56 deletions(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.Compound.cs b/src/Neo.VM/JumpTable/JumpTable.Compound.cs index c1e66efd31..5414a47c3b 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Compound.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Compound.cs @@ -9,76 +9,382 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.VM.Types; +using System; +using System.Linq; +using System.Numerics; +using System.Runtime.CompilerServices; +using VMArray = Neo.VM.Types.Array; + namespace Neo.VM { public partial class JumpTable { - /* TODO: - switch (instruction.OpCode) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PACKMAP(ExecutionEngine engine, Instruction instruction) + { + var size = (int)engine.Pop().GetInteger(); + if (size < 0 || size * 2 > engine.CurrentContext!.EvaluationStack.Count) + throw new InvalidOperationException($"The value {size} is out of range."); + Map map = new(engine.ReferenceCounter); + for (var i = 0; i < size; i++) { - // Compound-type - case OpCode.PACKMAP: - PackMap(instruction); - break; - case OpCode.PACKSTRUCT: - PackStruct(instruction); - break; - case OpCode.PACK: - Pack(instruction); - break; - case OpCode.UNPACK: - Unpack(instruction); - break; - case OpCode.NEWARRAY0: - NewArray0(instruction); - break; - case OpCode.NEWARRAY: - case OpCode.NEWARRAY_T: - NewArray_T(instruction); - break; - case OpCode.NEWSTRUCT0: - NewStruct0(instruction); - break; - case OpCode.NEWSTRUCT: - NewStruct(instruction); - break; - case OpCode.NEWMAP: - NewMap(instruction); - break; - case OpCode.SIZE: - Size(instruction); - break; - case OpCode.HASKEY: - HasKey(instruction); - break; - case OpCode.KEYS: - Keys(instruction); + var key = engine.Pop(); + var value = engine.Pop(); + map[key] = value; + } + engine.Push(map); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PACKSTRUCT(ExecutionEngine engine, Instruction instruction) + { + var size = (int)engine.Pop().GetInteger(); + if (size < 0 || size > engine.CurrentContext!.EvaluationStack.Count) + throw new InvalidOperationException($"The value {size} is out of range."); + Struct @struct = new(engine.ReferenceCounter); + for (var i = 0; i < size; i++) + { + var item = engine.Pop(); + @struct.Add(item); + } + engine.Push(@struct); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PACK(ExecutionEngine engine, Instruction instruction) + { + var size = (int)engine.Pop().GetInteger(); + if (size < 0 || size > engine.CurrentContext!.EvaluationStack.Count) + throw new InvalidOperationException($"The value {size} is out of range."); + VMArray array = new(engine.ReferenceCounter); + for (var i = 0; i < size; i++) + { + var item = engine.Pop(); + array.Add(item); + } + engine.Push(array); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void UNPACK(ExecutionEngine engine, Instruction instruction) + { + var compound = engine.Pop(); + switch (compound) + { + case Map map: + foreach (var (key, value) in map.Reverse()) + { + engine.Push(value); + engine.Push(key); + } break; - case OpCode.VALUES: - Values(instruction); + case VMArray array: + for (var i = array.Count - 1; i >= 0; i--) + { + engine.Push(array[i]); + } break; - case OpCode.PICKITEM: - PickItem(instruction); + default: + throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {compound.Type}"); + } + engine.Push(compound.Count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NEWARRAY0(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new VMArray(engine.ReferenceCounter)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NEWARRAY(ExecutionEngine engine, Instruction instruction) + { + var n = (int)engine.Pop().GetInteger(); + if (n < 0 || n > engine.Limits.MaxStackSize) + throw new InvalidOperationException($"MaxStackSize exceed: {n}"); + + engine.Push(new VMArray(engine.ReferenceCounter, Enumerable.Repeat(StackItem.Null, n))); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NEWARRAY_T(ExecutionEngine engine, Instruction instruction) + { + var n = (int)engine.Pop().GetInteger(); + if (n < 0 || n > engine.Limits.MaxStackSize) + throw new InvalidOperationException($"MaxStackSize exceed: {n}"); + + var type = (StackItemType)instruction.TokenU8; + if (!Enum.IsDefined(typeof(StackItemType), type)) + throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {instruction.TokenU8}"); + + var item = instruction.TokenU8 switch + { + (byte)StackItemType.Boolean => StackItem.False, + (byte)StackItemType.Integer => Integer.Zero, + (byte)StackItemType.ByteString => ByteString.Empty, + _ => StackItem.Null + }; + + engine.Push(new VMArray(engine.ReferenceCounter, Enumerable.Repeat(item, n))); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NEWSTRUCT0(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new Struct(engine.ReferenceCounter)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NEWSTRUCT(ExecutionEngine engine, Instruction instruction) + { + var n = (int)engine.Pop().GetInteger(); + if (n < 0 || n > engine.Limits.MaxStackSize) + throw new InvalidOperationException($"MaxStackSize exceed: {n}"); + Struct result = new(engine.ReferenceCounter); + for (var i = 0; i < n; i++) + result.Add(StackItem.Null); + engine.Push(result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void NEWMAP(ExecutionEngine engine, Instruction instruction) + { + engine.Push(new Map(engine.ReferenceCounter)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SIZE(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + switch (x) + { + case CompoundType compound: + engine.Push(compound.Count); break; - case OpCode.APPEND: - Append(instruction); + case PrimitiveType primitive: + engine.Push(primitive.Size); break; - case OpCode.SETITEM: - SetItem(instruction); + case Types.Buffer buffer: + engine.Push(buffer.Size); break; - case OpCode.REVERSEITEMS: - ReverseItems(instruction); + default: + throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void HASKEY(ExecutionEngine engine, Instruction instruction) + { + var key = engine.Pop(); + var x = engine.Pop(); + switch (x) + { + case VMArray array: + { + var index = (int)key.GetInteger(); + if (index < 0) + throw new InvalidOperationException($"The negative value {index} is invalid for OpCode.{instruction.OpCode}."); + engine.Push(index < array.Count); + break; + } + case Map map: + { + engine.Push(map.ContainsKey(key)); + break; + } + case Types.Buffer buffer: + { + var index = (int)key.GetInteger(); + if (index < 0) + throw new InvalidOperationException($"The negative value {index} is invalid for OpCode.{instruction.OpCode}."); + engine.Push(index < buffer.Size); + break; + } + case ByteString array: + { + var index = (int)key.GetInteger(); + if (index < 0) + throw new InvalidOperationException($"The negative value {index} is invalid for OpCode.{instruction.OpCode}."); + engine.Push(index < array.Size); + break; + } + default: + throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void KEYS(ExecutionEngine engine, Instruction instruction) + { + var map = engine.Pop(); + engine.Push(new VMArray(engine.ReferenceCounter, map.Keys)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void VALUES(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + var values = x switch + { + VMArray array => array, + Map map => map.Values, + _ => throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"), + }; + VMArray newArray = new(engine.ReferenceCounter); + foreach (var item in values) + if (item is Struct s) + newArray.Add(s.Clone(engine.Limits)); + else + newArray.Add(item); + engine.Push(newArray); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void PICKITEM(ExecutionEngine engine, Instruction instruction) + { + var key = engine.Pop(); + var x = engine.Pop(); + switch (x) + { + case VMArray array: + { + var index = (int)key.GetInteger(); + if (index < 0 || index >= array.Count) + throw new CatchableException($"The value {index} is out of range."); + engine.Push(array[index]); + break; + } + case Map map: + { + if (!map.TryGetValue(key, out var value)) + throw new CatchableException($"Key not found in {nameof(Map)}"); + engine.Push(value); + break; + } + case PrimitiveType primitive: + { + var byteArray = primitive.GetSpan(); + var index = (int)key.GetInteger(); + if (index < 0 || index >= byteArray.Length) + throw new CatchableException($"The value {index} is out of range."); + engine.Push((BigInteger)byteArray[index]); + break; + } + case Types.Buffer buffer: + { + var index = (int)key.GetInteger(); + if (index < 0 || index >= buffer.Size) + throw new CatchableException($"The value {index} is out of range."); + engine.Push((BigInteger)buffer.InnerBuffer.Span[index]); + break; + } + default: + throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void APPEND(ExecutionEngine engine, Instruction instruction) + { + var newItem = engine.Pop(); + var array = engine.Pop(); + if (newItem is Struct s) newItem = s.Clone(engine.Limits); + array.Add(newItem); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void SETITEM(ExecutionEngine engine, Instruction instruction) + { + var value = engine.Pop(); + if (value is Struct s) value = s.Clone(engine.Limits); + var key = engine.Pop(); + var x = engine.Pop(); + switch (x) + { + case VMArray array: + { + var index = (int)key.GetInteger(); + if (index < 0 || index >= array.Count) + throw new CatchableException($"The value {index} is out of range."); + array[index] = value; + break; + } + case Map map: + { + map[key] = value; + break; + } + case Types.Buffer buffer: + { + var 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) + throw new InvalidOperationException($"Value must be a primitive type in {instruction.OpCode}"); + var b = (int)p.GetInteger(); + if (b < sbyte.MinValue || b > byte.MaxValue) + throw new InvalidOperationException($"Overflow in {instruction.OpCode}, {b} is not a byte type."); + buffer.InnerBuffer.Span[index] = (byte)b; + break; + } + default: + throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void REVERSEITEMS(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + switch (x) + { + case VMArray array: + array.Reverse(); break; - case OpCode.REMOVE: - Remove(instruction); + case Types.Buffer buffer: + buffer.InnerBuffer.Span.Reverse(); break; - case OpCode.CLEARITEMS: - ClearItems(instruction); + default: + throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void REMOVE(ExecutionEngine engine, Instruction instruction) + { + var key = engine.Pop(); + var x = engine.Pop(); + switch (x) + { + case VMArray array: + var index = (int)key.GetInteger(); + if (index < 0 || index >= array.Count) + throw new InvalidOperationException($"The value {index} is out of range."); + array.RemoveAt(index); break; - case OpCode.POPITEM: - PopItem(instruction); + case Map map: + map.Remove(key); break; + default: + throw new InvalidOperationException($"Invalid type for {instruction.OpCode}: {x.Type}"); } - */ + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void CLEARITEMS(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + x.Clear(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void POPITEM(ExecutionEngine engine, Instruction instruction) + { + var x = engine.Pop(); + var index = x.Count - 1; + engine.Push(x[index]); + x.RemoveAt(index); + } } } From 101d1586549ec5efa77e34b83b3217988e451339 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 10:42:04 +0100 Subject: [PATCH 16/34] Slot --- src/Neo.VM/JumpTable/JumpTable.Slot.cs | 404 ++++++++++++++++++++----- src/Neo.VM/JumpTable/JumpTable.cs | 10 +- 2 files changed, 329 insertions(+), 85 deletions(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.Slot.cs b/src/Neo.VM/JumpTable/JumpTable.Slot.cs index 6035d6570f..f1f377dca7 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Slot.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Slot.cs @@ -9,96 +9,338 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.VM; +using Neo.VM.Types; using System; +using System.Runtime.CompilerServices; namespace Neo.VM { public partial class JumpTable { - /* TODO: - case OpCode.INITSSLOT: - break; - case OpCode.INITSLOT: - InitSlot(instruction); - break; - case OpCode.LDSFLD0: - case OpCode.LDSFLD1: - case OpCode.LDSFLD2: - case OpCode.LDSFLD3: - case OpCode.LDSFLD4: - case OpCode.LDSFLD5: - case OpCode.LDSFLD6: - LdSFldM(instruction); - break; - case OpCode.LDSFLD: - LdSFld(instruction); - break; - case OpCode.STSFLD0: - case OpCode.STSFLD1: - case OpCode.STSFLD2: - case OpCode.STSFLD3: - case OpCode.STSFLD4: - case OpCode.STSFLD5: - case OpCode.STSFLD6: - StSFldM(instruction); - break; - case OpCode.STSFLD: - StSFld(instruction); - break; - case OpCode.LDLOC0: - case OpCode.LDLOC1: - case OpCode.LDLOC2: - case OpCode.LDLOC3: - case OpCode.LDLOC4: - case OpCode.LDLOC5: - case OpCode.LDLOC6: - LdLocM(instruction); - break; - case OpCode.LDLOC: - LdLoc(instruction); - break; - case OpCode.STLOC0: - case OpCode.STLOC1: - case OpCode.STLOC2: - case OpCode.STLOC3: - case OpCode.STLOC4: - case OpCode.STLOC5: - case OpCode.STLOC6: - StLocM(instruction); - break; - case OpCode.STLOC: - StLoc(instruction); - break; - case OpCode.LDARG0: - case OpCode.LDARG1: - case OpCode.LDARG2: - case OpCode.LDARG3: - case OpCode.LDARG4: - case OpCode.LDARG5: - case OpCode.LDARG6: - LdArgM(instruction); - break; - case OpCode.LDARG: - LdArg(instruction); - break; - case OpCode.STARG0: - case OpCode.STARG1: - case OpCode.STARG2: - case OpCode.STARG3: - case OpCode.STARG4: - case OpCode.STARG5: - case OpCode.STARG6: - StArgM(instruction); - break; - case OpCode.STARG: - StArg(instruction); - break; - */ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void INITSSLOT(ExecutionEngine engine, Instruction instruction) + { + if (engine.CurrentContext!.StaticFields != null) + throw new InvalidOperationException($"{instruction.OpCode} cannot be executed twice."); + if (instruction.TokenU8 == 0) + throw new InvalidOperationException($"The operand {instruction.TokenU8} is invalid for OpCode.{instruction.OpCode}."); + engine.CurrentContext.StaticFields = new Slot(instruction.TokenU8, engine.ReferenceCounter); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void INITSLOT(ExecutionEngine engine, Instruction instruction) + { + if (engine.CurrentContext!.LocalVariables != null || engine.CurrentContext.Arguments != null) + throw new InvalidOperationException($"{instruction.OpCode} cannot be executed twice."); + if (instruction.TokenU16 == 0) + throw new InvalidOperationException($"The operand {instruction.TokenU16} is invalid for OpCode.{instruction.OpCode}."); + if (instruction.TokenU8 > 0) + { + engine.CurrentContext.LocalVariables = new Slot(instruction.TokenU8, engine.ReferenceCounter); + } + if (instruction.TokenU8_1 > 0) + { + var items = new StackItem[instruction.TokenU8_1]; + for (var i = 0; i < instruction.TokenU8_1; i++) + { + items[i] = engine.Pop(); + } + engine.CurrentContext.Arguments = new Slot(items, engine.ReferenceCounter); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDSFLD0(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDSFLD1(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDSFLD2(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDSFLD3(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDSFLD4(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 4); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDSFLD5(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 5); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDSFLD6(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 6); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDSFLD(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, instruction.TokenU8); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STSFLD0(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STSFLD1(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STSFLD2(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STSFLD3(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STSFLD4(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 4); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STSFLD5(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 5); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STSFLD6(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 6); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STSFLD(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, instruction.TokenU8); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDLOC0(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDLOC1(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDLOC2(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDLOC3(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDLOC4(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 4); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDLOC5(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 5); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDLOC6(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 6); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDLOC(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, instruction.TokenU8); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STLOC0(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STLOC1(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STLOC2(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STLOC3(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STLOC4(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 4); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STLOC5(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 5); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STLOC6(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 6); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STLOC(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, instruction.TokenU8); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDARG0(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDARG1(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDARG2(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDARG3(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDARG4(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 4); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDARG5(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 5); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDARG6(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 6); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void LDARG(ExecutionEngine engine, Instruction instruction) + { + ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, instruction.TokenU8); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STARG0(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STARG1(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STARG2(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STARG3(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 3); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STARG4(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 4); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STARG5(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 5); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STARG6(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 6); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public virtual void STARG(ExecutionEngine engine, Instruction instruction) + { + ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, instruction.TokenU8); + } #region Execute methods - private void ExecuteStoreToSlot(ExecutionEngine engine, Slot? slot, int index) + public virtual void ExecuteStoreToSlot(ExecutionEngine engine, Slot? slot, int index) { if (slot is null) throw new InvalidOperationException("Slot has not been initialized."); @@ -107,7 +349,7 @@ private void ExecuteStoreToSlot(ExecutionEngine engine, Slot? slot, int index) slot[index] = engine.Pop(); } - private void ExecuteLoadFromSlot(ExecutionEngine engine, Slot? slot, int index) + public virtual void ExecuteLoadFromSlot(ExecutionEngine engine, Slot? slot, int index) { if (slot is null) throw new InvalidOperationException("Slot has not been initialized."); diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index f215c814a0..2752394a93 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -50,11 +50,13 @@ public JumpTable() { if (Table[x] is not null) continue; - Table[x] = (engine, instruction) => - { - throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); - }; + Table[x] = InvalidOpcode; } } + + private static void InvalidOpcode(ExecutionEngine engine, Instruction instruction) + { + throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); + } } } From 31d8246622b83f890878b6c60f44fe494a28fc25 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 10:42:54 +0100 Subject: [PATCH 17/34] Allow to override invalid opcode --- src/Neo.VM/JumpTable/JumpTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index 2752394a93..a6318ddbc0 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -54,7 +54,7 @@ public JumpTable() } } - private static void InvalidOpcode(ExecutionEngine engine, Instruction instruction) + public virtual void InvalidOpcode(ExecutionEngine engine, Instruction instruction) { throw new InvalidOperationException($"Opcode {instruction.OpCode} is undefined."); } From e3d79e151006b5d1518d1cb2c7faf6398d4a27a7 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 10:52:39 +0100 Subject: [PATCH 18/34] Specify jumpTable according to block --- src/Neo/SmartContract/ApplicationEngine.cs | 15 ++++++++++----- .../SmartContract/IApplicationEngineProvider.cs | 4 +++- .../SmartContract/UT_ApplicationEngineProvider.cs | 9 +++++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 6a73005c5b..0ea6bd6ebe 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -32,7 +32,7 @@ namespace Neo.SmartContract /// public partial class ApplicationEngine : ExecutionEngine { - private static readonly JumpTable JumpTable = ComposeJumpTable(); + private static readonly JumpTable DefaultJumpTable = ComposeDefaultJumpTable(); /// /// The maximum cost that can be spent when a contract is executed in test mode. @@ -157,7 +157,9 @@ public UInt160 CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) + /// The jump table to be used by the . + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic, JumpTable jumpTable) + : base(jumpTable) { this.Trigger = trigger; this.ScriptContainer = container; @@ -181,7 +183,7 @@ protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, D #region JumpTable - private static JumpTable ComposeJumpTable() + private static JumpTable ComposeDefaultJumpTable() { var table = new JumpTable(); @@ -374,8 +376,11 @@ public override void UnloadedContext(ExecutionContext context) /// The engine instance created. public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) { - return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) - ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); + // Adjust jump table according persistingBlock + var jumpTable = ApplicationEngine.DefaultJumpTable; + + return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable) + ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable); } public override void LoadContext(ExecutionContext context) diff --git a/src/Neo/SmartContract/IApplicationEngineProvider.cs b/src/Neo/SmartContract/IApplicationEngineProvider.cs index ef06c6b92c..ba7866739c 100644 --- a/src/Neo/SmartContract/IApplicationEngineProvider.cs +++ b/src/Neo/SmartContract/IApplicationEngineProvider.cs @@ -11,6 +11,7 @@ using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.VM; namespace Neo.SmartContract { @@ -29,7 +30,8 @@ public interface IApplicationEngineProvider /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . + /// The jump table to be used by the . /// The engine instance created. - ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic); + ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic, JumpTable jumpTable); } } diff --git a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs index f4e99e6936..75fc558669 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs @@ -14,6 +14,7 @@ using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract; +using Neo.VM; namespace Neo.UnitTests.SmartContract { @@ -50,16 +51,16 @@ public void TestDefaultAppEngineProvider() class TestProvider : IApplicationEngineProvider { - public ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) + public ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic, JumpTable jumpTable) { - return new TestEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); + return new TestEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable); } } class TestEngine : ApplicationEngine { - public TestEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) - : base(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) + public TestEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic, JumpTable jumpTable) + : base(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable) { } } From b0e8199dfcdc53f75bf2b1031fc37a864effc4d8 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 11:04:15 +0100 Subject: [PATCH 19/34] Fix syscall --- src/Neo/SmartContract/ApplicationEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 0ea6bd6ebe..2f5adc741d 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -221,7 +221,7 @@ private static void OnSysCall(ExecutionEngine engine, Instruction instruction) { if (engine is ApplicationEngine app) { - uint method = instruction.TokenU16; + uint method = instruction.TokenU32; app.OnSysCall(services[method]); } From 5a551da79897b6377473755c50f048925d1b87ff Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 11:27:00 +0100 Subject: [PATCH 20/34] Rename to UnloadContext --- src/Neo.VM/ExecutionEngine.cs | 11 +++++++---- src/Neo.VM/JumpTable/JumpTable.Control.cs | 4 ++-- src/Neo/SmartContract/ApplicationEngine.cs | 6 +++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index 141540fdc8..fa92eb9c45 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -22,7 +22,7 @@ namespace Neo.VM public class ExecutionEngine : IDisposable { private VMState state = VMState.BREAK; - internal bool isJumping = false; + private bool isJumping = false; public JumpTable JumpTable { get; } @@ -137,7 +137,10 @@ protected internal void ExecuteNext() PreExecuteInstruction(instruction); try { - JumpTable[instruction.OpCode](this, instruction); + if (JumpTable[instruction.OpCode](this, instruction)) + { + isJumping = true; + } } catch (CatchableException ex) when (Limits.CatchEngineExceptions) { @@ -158,7 +161,7 @@ protected internal void ExecuteNext() /// Loads the specified context into the invocation stack. /// /// The context to load. - public virtual void LoadContext(ExecutionContext context) + protected virtual void LoadContext(ExecutionContext context) { if (InvocationStack.Count >= Limits.MaxInvocationStackSize) throw new InvalidOperationException($"MaxInvocationStackSize exceed: {InvocationStack.Count}"); @@ -171,7 +174,7 @@ public virtual void LoadContext(ExecutionContext context) /// Called when a context is unloaded. /// /// The context being unloaded. - public virtual void UnloadedContext(ExecutionContext context) + protected virtual void UnloadContext(ExecutionContext context) { if (InvocationStack.Count == 0) { diff --git a/src/Neo.VM/JumpTable/JumpTable.Control.cs b/src/Neo.VM/JumpTable/JumpTable.Control.cs index 8e631fbf3d..ff2a386d88 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Control.cs @@ -277,7 +277,7 @@ public virtual void RET(ExecutionEngine engine, Instruction instruction) } if (engine.InvocationStack.Count == 0) engine.State = VMState.HALT; - engine.UnloadedContext(context_pop); + engine.UnloadContext(context_pop); engine.isJumping = true; } @@ -367,7 +367,7 @@ public virtual void ExecuteThrow(ExecutionEngine engine, StackItem? ex) } for (var i = 0; i < pop; i++) { - engine.UnloadedContext(engine.InvocationStack.Pop()); + engine.UnloadContext(engine.InvocationStack.Pop()); } if (tryContext.State == ExceptionHandlingState.Try && tryContext.HasCatch) { diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 2f5adc741d..5c2f89d2ea 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -326,9 +326,9 @@ internal ContractTask CallFromNativeContract(UInt160 callingScriptHash, UI return task; } - public override void UnloadedContext(ExecutionContext context) + protected override void UnloadContext(ExecutionContext context) { - base.UnloadedContext(context); + base.UnloadContext(context); if (context.Script != CurrentContext?.Script) { ExecutionContextState state = context.GetState(); @@ -383,7 +383,7 @@ public static ApplicationEngine Create(TriggerType trigger, IVerifiable containe ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable); } - public override void LoadContext(ExecutionContext context) + protected override void LoadContext(ExecutionContext context) { // Set default execution context state var state = context.GetState(); From 87a1aeec43e1d4652bc1abe03ab78a0446152b9b Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 11:30:18 +0100 Subject: [PATCH 21/34] Revert "Rename to UnloadContext" This reverts commit 5a551da79897b6377473755c50f048925d1b87ff. --- src/Neo.VM/ExecutionEngine.cs | 11 ++++------- src/Neo.VM/JumpTable/JumpTable.Control.cs | 4 ++-- src/Neo/SmartContract/ApplicationEngine.cs | 6 +++--- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index fa92eb9c45..141540fdc8 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -22,7 +22,7 @@ namespace Neo.VM public class ExecutionEngine : IDisposable { private VMState state = VMState.BREAK; - private bool isJumping = false; + internal bool isJumping = false; public JumpTable JumpTable { get; } @@ -137,10 +137,7 @@ protected internal void ExecuteNext() PreExecuteInstruction(instruction); try { - if (JumpTable[instruction.OpCode](this, instruction)) - { - isJumping = true; - } + JumpTable[instruction.OpCode](this, instruction); } catch (CatchableException ex) when (Limits.CatchEngineExceptions) { @@ -161,7 +158,7 @@ protected internal void ExecuteNext() /// Loads the specified context into the invocation stack. /// /// The context to load. - protected virtual void LoadContext(ExecutionContext context) + public virtual void LoadContext(ExecutionContext context) { if (InvocationStack.Count >= Limits.MaxInvocationStackSize) throw new InvalidOperationException($"MaxInvocationStackSize exceed: {InvocationStack.Count}"); @@ -174,7 +171,7 @@ protected virtual void LoadContext(ExecutionContext context) /// Called when a context is unloaded. /// /// The context being unloaded. - protected virtual void UnloadContext(ExecutionContext context) + public virtual void UnloadedContext(ExecutionContext context) { if (InvocationStack.Count == 0) { diff --git a/src/Neo.VM/JumpTable/JumpTable.Control.cs b/src/Neo.VM/JumpTable/JumpTable.Control.cs index ff2a386d88..8e631fbf3d 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Control.cs @@ -277,7 +277,7 @@ public virtual void RET(ExecutionEngine engine, Instruction instruction) } if (engine.InvocationStack.Count == 0) engine.State = VMState.HALT; - engine.UnloadContext(context_pop); + engine.UnloadedContext(context_pop); engine.isJumping = true; } @@ -367,7 +367,7 @@ public virtual void ExecuteThrow(ExecutionEngine engine, StackItem? ex) } for (var i = 0; i < pop; i++) { - engine.UnloadContext(engine.InvocationStack.Pop()); + engine.UnloadedContext(engine.InvocationStack.Pop()); } if (tryContext.State == ExceptionHandlingState.Try && tryContext.HasCatch) { diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 5c2f89d2ea..2f5adc741d 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -326,9 +326,9 @@ internal ContractTask CallFromNativeContract(UInt160 callingScriptHash, UI return task; } - protected override void UnloadContext(ExecutionContext context) + public override void UnloadedContext(ExecutionContext context) { - base.UnloadContext(context); + base.UnloadedContext(context); if (context.Script != CurrentContext?.Script) { ExecutionContextState state = context.GetState(); @@ -383,7 +383,7 @@ public static ApplicationEngine Create(TriggerType trigger, IVerifiable containe ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable); } - protected override void LoadContext(ExecutionContext context) + public override void LoadContext(ExecutionContext context) { // Set default execution context state var state = context.GetState(); From 9f78ef1261ebf0d40961cf0e058ed2449794bd95 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 8 Feb 2024 11:31:29 +0100 Subject: [PATCH 22/34] Rename --- src/Neo.VM/ExecutionEngine.cs | 2 +- src/Neo.VM/JumpTable/JumpTable.Control.cs | 4 ++-- src/Neo/SmartContract/ApplicationEngine.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index 141540fdc8..ada560c1c8 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -171,7 +171,7 @@ public virtual void LoadContext(ExecutionContext context) /// Called when a context is unloaded. /// /// The context being unloaded. - public virtual void UnloadedContext(ExecutionContext context) + public virtual void UnloadContext(ExecutionContext context) { if (InvocationStack.Count == 0) { diff --git a/src/Neo.VM/JumpTable/JumpTable.Control.cs b/src/Neo.VM/JumpTable/JumpTable.Control.cs index 8e631fbf3d..ff2a386d88 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Control.cs @@ -277,7 +277,7 @@ public virtual void RET(ExecutionEngine engine, Instruction instruction) } if (engine.InvocationStack.Count == 0) engine.State = VMState.HALT; - engine.UnloadedContext(context_pop); + engine.UnloadContext(context_pop); engine.isJumping = true; } @@ -367,7 +367,7 @@ public virtual void ExecuteThrow(ExecutionEngine engine, StackItem? ex) } for (var i = 0; i < pop; i++) { - engine.UnloadedContext(engine.InvocationStack.Pop()); + engine.UnloadContext(engine.InvocationStack.Pop()); } if (tryContext.State == ExceptionHandlingState.Try && tryContext.HasCatch) { diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 2f5adc741d..0280191250 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -326,9 +326,9 @@ internal ContractTask CallFromNativeContract(UInt160 callingScriptHash, UI return task; } - public override void UnloadedContext(ExecutionContext context) + public override void UnloadContext(ExecutionContext context) { - base.UnloadedContext(context); + base.UnloadContext(context); if (context.Script != CurrentContext?.Script) { ExecutionContextState state = context.GetState(); From d5da406da2dfde923f60dec6b8ac8d9c6332443c Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 17:59:31 +0800 Subject: [PATCH 23/34] Update JumpTable.Control.cs --- src/Neo.VM/JumpTable/JumpTable.Control.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.Control.cs b/src/Neo.VM/JumpTable/JumpTable.Control.cs index ff2a386d88..551f8c5a69 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Control.cs @@ -19,7 +19,7 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NOP(ExecutionEngine engine, Instruction instruction) + public virtual void Nop(ExecutionEngine engine, Instruction instruction) { } From ecc1e351a4595d037c9db59af2e7b7cd4b4ce154 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 9 Feb 2024 02:01:56 -0800 Subject: [PATCH 24/34] Update src/Neo.VM/JumpTable/JumpTable.cs --- src/Neo.VM/JumpTable/JumpTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index a6318ddbc0..a2267f9dd1 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -33,7 +33,7 @@ public JumpTable() foreach (var mi in GetType().GetMethods()) { - if (Enum.TryParse(mi.Name, false, out var opCode)) + if (Enum.TryParse(mi.Name, true, out var opCode)) { if (Table[(byte)opCode] is not null) { From 50fc4a2b0583298060a0a938074de00cbe1ae83e Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Fri, 9 Feb 2024 14:30:48 +0100 Subject: [PATCH 25/34] Rename methods --- src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs | 12 +-- src/Neo.VM/JumpTable/JumpTable.Compound.cs | 42 ++++----- src/Neo.VM/JumpTable/JumpTable.Control.cs | 62 ++++++------- src/Neo.VM/JumpTable/JumpTable.Numeric.cs | 58 ++++++------ src/Neo.VM/JumpTable/JumpTable.Push.cs | 60 ++++++------- src/Neo.VM/JumpTable/JumpTable.Slot.cs | 100 ++++++++++----------- src/Neo.VM/JumpTable/JumpTable.Splice.cs | 12 +-- src/Neo.VM/JumpTable/JumpTable.Stack.cs | 30 +++---- src/Neo.VM/JumpTable/JumpTable.Types.cs | 10 +-- src/Neo.VM/JumpTable/JumpTable.cs | 4 + 10 files changed, 197 insertions(+), 193 deletions(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs b/src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs index b502e6b686..65a8e490d1 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Bitwisee.cs @@ -16,14 +16,14 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void INVERT(ExecutionEngine engine, Instruction instruction) + public virtual void Invert(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetInteger(); engine.Push(~x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void AND(ExecutionEngine engine, Instruction instruction) + public virtual void And(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -31,7 +31,7 @@ public virtual void AND(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void OR(ExecutionEngine engine, Instruction instruction) + public virtual void Or(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -39,7 +39,7 @@ public virtual void OR(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void XOR(ExecutionEngine engine, Instruction instruction) + public virtual void XOr(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -47,7 +47,7 @@ public virtual void XOR(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void EQUAL(ExecutionEngine engine, Instruction instruction) + public virtual void Equal(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop(); var x1 = engine.Pop(); @@ -55,7 +55,7 @@ public virtual void EQUAL(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NOTEQUAL(ExecutionEngine engine, Instruction instruction) + public virtual void NotEqual(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop(); var x1 = engine.Pop(); diff --git a/src/Neo.VM/JumpTable/JumpTable.Compound.cs b/src/Neo.VM/JumpTable/JumpTable.Compound.cs index 5414a47c3b..916caf02b8 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Compound.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Compound.cs @@ -21,7 +21,7 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PACKMAP(ExecutionEngine engine, Instruction instruction) + public virtual void PackMap(ExecutionEngine engine, Instruction instruction) { var size = (int)engine.Pop().GetInteger(); if (size < 0 || size * 2 > engine.CurrentContext!.EvaluationStack.Count) @@ -37,7 +37,7 @@ public virtual void PACKMAP(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PACKSTRUCT(ExecutionEngine engine, Instruction instruction) + public virtual void PackStruct(ExecutionEngine engine, Instruction instruction) { var size = (int)engine.Pop().GetInteger(); if (size < 0 || size > engine.CurrentContext!.EvaluationStack.Count) @@ -52,7 +52,7 @@ public virtual void PACKSTRUCT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PACK(ExecutionEngine engine, Instruction instruction) + public virtual void Pack(ExecutionEngine engine, Instruction instruction) { var size = (int)engine.Pop().GetInteger(); if (size < 0 || size > engine.CurrentContext!.EvaluationStack.Count) @@ -67,7 +67,7 @@ public virtual void PACK(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void UNPACK(ExecutionEngine engine, Instruction instruction) + public virtual void Unpack(ExecutionEngine engine, Instruction instruction) { var compound = engine.Pop(); switch (compound) @@ -92,13 +92,13 @@ public virtual void UNPACK(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NEWARRAY0(ExecutionEngine engine, Instruction instruction) + public virtual void NewArray0(ExecutionEngine engine, Instruction instruction) { engine.Push(new VMArray(engine.ReferenceCounter)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NEWARRAY(ExecutionEngine engine, Instruction instruction) + public virtual void NewArray(ExecutionEngine engine, Instruction instruction) { var n = (int)engine.Pop().GetInteger(); if (n < 0 || n > engine.Limits.MaxStackSize) @@ -108,7 +108,7 @@ public virtual void NEWARRAY(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NEWARRAY_T(ExecutionEngine engine, Instruction instruction) + public virtual void NewArray_T(ExecutionEngine engine, Instruction instruction) { var n = (int)engine.Pop().GetInteger(); if (n < 0 || n > engine.Limits.MaxStackSize) @@ -130,13 +130,13 @@ public virtual void NEWARRAY_T(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NEWSTRUCT0(ExecutionEngine engine, Instruction instruction) + public virtual void NewStruct0(ExecutionEngine engine, Instruction instruction) { engine.Push(new Struct(engine.ReferenceCounter)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NEWSTRUCT(ExecutionEngine engine, Instruction instruction) + public virtual void NewStruct(ExecutionEngine engine, Instruction instruction) { var n = (int)engine.Pop().GetInteger(); if (n < 0 || n > engine.Limits.MaxStackSize) @@ -148,13 +148,13 @@ public virtual void NEWSTRUCT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NEWMAP(ExecutionEngine engine, Instruction instruction) + public virtual void NewMap(ExecutionEngine engine, Instruction instruction) { engine.Push(new Map(engine.ReferenceCounter)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SIZE(ExecutionEngine engine, Instruction instruction) + public virtual void Size(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); switch (x) @@ -174,7 +174,7 @@ public virtual void SIZE(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void HASKEY(ExecutionEngine engine, Instruction instruction) + public virtual void HasKey(ExecutionEngine engine, Instruction instruction) { var key = engine.Pop(); var x = engine.Pop(); @@ -215,14 +215,14 @@ public virtual void HASKEY(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void KEYS(ExecutionEngine engine, Instruction instruction) + public virtual void Keys(ExecutionEngine engine, Instruction instruction) { var map = engine.Pop(); engine.Push(new VMArray(engine.ReferenceCounter, map.Keys)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void VALUES(ExecutionEngine engine, Instruction instruction) + public virtual void Values(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); var values = x switch @@ -241,7 +241,7 @@ public virtual void VALUES(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PICKITEM(ExecutionEngine engine, Instruction instruction) + public virtual void PickItem(ExecutionEngine engine, Instruction instruction) { var key = engine.Pop(); var x = engine.Pop(); @@ -285,7 +285,7 @@ public virtual void PICKITEM(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void APPEND(ExecutionEngine engine, Instruction instruction) + public virtual void Append(ExecutionEngine engine, Instruction instruction) { var newItem = engine.Pop(); var array = engine.Pop(); @@ -294,7 +294,7 @@ public virtual void APPEND(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SETITEM(ExecutionEngine engine, Instruction instruction) + public virtual void SetItem(ExecutionEngine engine, Instruction instruction) { var value = engine.Pop(); if (value is Struct s) value = s.Clone(engine.Limits); @@ -334,7 +334,7 @@ public virtual void SETITEM(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void REVERSEITEMS(ExecutionEngine engine, Instruction instruction) + public virtual void ReverseItems(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); switch (x) @@ -351,7 +351,7 @@ public virtual void REVERSEITEMS(ExecutionEngine engine, Instruction instruction } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void REMOVE(ExecutionEngine engine, Instruction instruction) + public virtual void Remove(ExecutionEngine engine, Instruction instruction) { var key = engine.Pop(); var x = engine.Pop(); @@ -372,14 +372,14 @@ public virtual void REMOVE(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CLEARITEMS(ExecutionEngine engine, Instruction instruction) + public virtual void ClearItems(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); x.Clear(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void POPITEM(ExecutionEngine engine, Instruction instruction) + public virtual void PopItem(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); var index = x.Count - 1; diff --git a/src/Neo.VM/JumpTable/JumpTable.Control.cs b/src/Neo.VM/JumpTable/JumpTable.Control.cs index 551f8c5a69..2415f1e614 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Control.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Control.cs @@ -24,47 +24,47 @@ public virtual void Nop(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMP(ExecutionEngine engine, Instruction instruction) + public virtual void Jmp(ExecutionEngine engine, Instruction instruction) { ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMP_L(ExecutionEngine engine, Instruction instruction) + public virtual void Jmp_L(ExecutionEngine engine, Instruction instruction) { ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPIF(ExecutionEngine engine, Instruction instruction) + public virtual void JmpIf(ExecutionEngine engine, Instruction instruction) { if (engine.Pop().GetBoolean()) ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPIF_L(ExecutionEngine engine, Instruction instruction) + public virtual void JmpIf_L(ExecutionEngine engine, Instruction instruction) { if (engine.Pop().GetBoolean()) ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPIFNOT(ExecutionEngine engine, Instruction instruction) + public virtual void JmpIfNot(ExecutionEngine engine, Instruction instruction) { if (!engine.Pop().GetBoolean()) ExecuteJumpOffset(engine, instruction.TokenI8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPIFNOT_L(ExecutionEngine engine, Instruction instruction) + public virtual void JmpIfNot_L(ExecutionEngine engine, Instruction instruction) { if (!engine.Pop().GetBoolean()) ExecuteJumpOffset(engine, instruction.TokenI32); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPEQ(ExecutionEngine engine, Instruction instruction) + public virtual void JmpEq(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -73,7 +73,7 @@ public virtual void JMPEQ(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPEQ_L(ExecutionEngine engine, Instruction instruction) + public virtual void JmpEq_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -82,7 +82,7 @@ public virtual void JMPEQ_L(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPNE(ExecutionEngine engine, Instruction instruction) + public virtual void JmpNe(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -91,7 +91,7 @@ public virtual void JMPNE(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPNE_L(ExecutionEngine engine, Instruction instruction) + public virtual void JmpNe_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -100,7 +100,7 @@ public virtual void JMPNE_L(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPGT(ExecutionEngine engine, Instruction instruction) + public virtual void JmpGt(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -109,7 +109,7 @@ public virtual void JMPGT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPGT_L(ExecutionEngine engine, Instruction instruction) + public virtual void JmpGt_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -118,7 +118,7 @@ public virtual void JMPGT_L(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPGE(ExecutionEngine engine, Instruction instruction) + public virtual void JmpGe(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -127,7 +127,7 @@ public virtual void JMPGE(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPGE_L(ExecutionEngine engine, Instruction instruction) + public virtual void JmpGe_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -136,7 +136,7 @@ public virtual void JMPGE_L(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPLT(ExecutionEngine engine, Instruction instruction) + public virtual void JmpLt(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -145,7 +145,7 @@ public virtual void JMPLT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPLT_L(ExecutionEngine engine, Instruction instruction) + public virtual void JmpLt_L(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -154,7 +154,7 @@ public virtual void JMPLT_L(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void JMPLE(ExecutionEngine engine, Instruction instruction) + public virtual void JmpLe(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -172,19 +172,19 @@ public virtual void JMPLE_L(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CALL(ExecutionEngine engine, Instruction instruction) + public virtual void Call(ExecutionEngine engine, Instruction instruction) { ExecuteCall(engine, checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI8)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CALL_L(ExecutionEngine engine, Instruction instruction) + public virtual void Call_L(ExecutionEngine engine, Instruction instruction) { ExecuteCall(engine, checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI32)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CALLA(ExecutionEngine engine, Instruction instruction) + public virtual void CallA(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); if (x.Script != engine.CurrentContext!.Script) @@ -193,19 +193,19 @@ public virtual void CALLA(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CALLT(ExecutionEngine engine, Instruction instruction) + public virtual void CallT(ExecutionEngine engine, Instruction instruction) { throw new InvalidOperationException($"Token not found: {instruction.TokenU16}"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ABORT(ExecutionEngine engine, Instruction instruction) + public virtual void Abort(ExecutionEngine engine, Instruction instruction) { throw new Exception($"{OpCode.ABORT} is executed."); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ASSERT(ExecutionEngine engine, Instruction instruction) + public virtual void Assert(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetBoolean(); if (!x) @@ -213,13 +213,13 @@ public virtual void ASSERT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void THROW(ExecutionEngine engine, Instruction instruction) + public virtual void Throw(ExecutionEngine engine, Instruction instruction) { ExecuteThrow(engine, engine.Pop()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void TRY(ExecutionEngine engine, Instruction instruction) + public virtual void Try(ExecutionEngine engine, Instruction instruction) { int catchOffset = instruction.TokenI8; int finallyOffset = instruction.TokenI8_1; @@ -227,7 +227,7 @@ public virtual void TRY(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void TRY_L(ExecutionEngine engine, Instruction instruction) + public virtual void Try_L(ExecutionEngine engine, Instruction instruction) { var catchOffset = instruction.TokenI32; var finallyOffset = instruction.TokenI32_1; @@ -235,21 +235,21 @@ public virtual void TRY_L(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ENDTRY(ExecutionEngine engine, Instruction instruction) + public virtual void EndTry(ExecutionEngine engine, Instruction instruction) { var endOffset = instruction.TokenI8; ExecuteEndTry(engine, endOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ENDTRY_L(ExecutionEngine engine, Instruction instruction) + public virtual void EndTry_L(ExecutionEngine engine, Instruction instruction) { var endOffset = instruction.TokenI32; ExecuteEndTry(engine, endOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ENDFINALLY(ExecutionEngine engine, Instruction instruction) + public virtual void EndFinally(ExecutionEngine engine, Instruction instruction) { if (engine.CurrentContext!.TryStack is null) throw new InvalidOperationException($"The corresponding TRY block cannot be found."); @@ -265,7 +265,7 @@ public virtual void ENDFINALLY(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void RET(ExecutionEngine engine, Instruction instruction) + public virtual void Ret(ExecutionEngine engine, Instruction instruction) { var context_pop = engine.InvocationStack.Pop(); var stack_eval = engine.InvocationStack.Count == 0 ? engine.ResultStack : engine.InvocationStack.Peek().EvaluationStack; @@ -282,7 +282,7 @@ public virtual void RET(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SYSCALL(ExecutionEngine engine, Instruction instruction) + public virtual void Syscall(ExecutionEngine engine, Instruction instruction) { throw new InvalidOperationException($"Syscall not found: {instruction.TokenU32}"); } diff --git a/src/Neo.VM/JumpTable/JumpTable.Numeric.cs b/src/Neo.VM/JumpTable/JumpTable.Numeric.cs index aa9ec742e7..60586cb77e 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Numeric.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Numeric.cs @@ -17,42 +17,42 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SIGN(ExecutionEngine engine, Instruction instruction) + public virtual void Sign(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetInteger(); engine.Push(x.Sign); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ABS(ExecutionEngine engine, Instruction instruction) + public virtual void Abs(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetInteger(); engine.Push(BigInteger.Abs(x)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NEGATE(ExecutionEngine engine, Instruction instruction) + public virtual void Negate(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetInteger(); engine.Push(-x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void INC(ExecutionEngine engine, Instruction instruction) + public virtual void Inc(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetInteger(); engine.Push(x + 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void DEC(ExecutionEngine engine, Instruction instruction) + public virtual void Dec(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetInteger(); engine.Push(x - 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ADD(ExecutionEngine engine, Instruction instruction) + public virtual void Add(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -60,7 +60,7 @@ public virtual void ADD(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SUB(ExecutionEngine engine, Instruction instruction) + public virtual void Sub(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -68,7 +68,7 @@ public virtual void SUB(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void MUL(ExecutionEngine engine, Instruction instruction) + public virtual void Mul(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -76,7 +76,7 @@ public virtual void MUL(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void DIV(ExecutionEngine engine, Instruction instruction) + public virtual void Div(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -84,7 +84,7 @@ public virtual void DIV(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void MOD(ExecutionEngine engine, Instruction instruction) + public virtual void Mod(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -92,7 +92,7 @@ public virtual void MOD(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void POW(ExecutionEngine engine, Instruction instruction) + public virtual void Pow(ExecutionEngine engine, Instruction instruction) { var exponent = (int)engine.Pop().GetInteger(); engine.Limits.AssertShift(exponent); @@ -101,13 +101,13 @@ public virtual void POW(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SQRT(ExecutionEngine engine, Instruction instruction) + public virtual void Sqrt(ExecutionEngine engine, Instruction instruction) { engine.Push(engine.Pop().GetInteger().Sqrt()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void MODMUL(ExecutionEngine engine, Instruction instruction) + public virtual void ModMul(ExecutionEngine engine, Instruction instruction) { var modulus = engine.Pop().GetInteger(); var x2 = engine.Pop().GetInteger(); @@ -116,7 +116,7 @@ public virtual void MODMUL(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void MODPOW(ExecutionEngine engine, Instruction instruction) + public virtual void ModPow(ExecutionEngine engine, Instruction instruction) { var modulus = engine.Pop().GetInteger(); var exponent = engine.Pop().GetInteger(); @@ -128,7 +128,7 @@ public virtual void MODPOW(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SHL(ExecutionEngine engine, Instruction instruction) + public virtual void Shl(ExecutionEngine engine, Instruction instruction) { var shift = (int)engine.Pop().GetInteger(); engine.Limits.AssertShift(shift); @@ -138,7 +138,7 @@ public virtual void SHL(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SHR(ExecutionEngine engine, Instruction instruction) + public virtual void Shr(ExecutionEngine engine, Instruction instruction) { var shift = (int)engine.Pop().GetInteger(); engine.Limits.AssertShift(shift); @@ -148,14 +148,14 @@ public virtual void SHR(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NOT(ExecutionEngine engine, Instruction instruction) + public virtual void Not(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetBoolean(); engine.Push(!x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void BOOLAND(ExecutionEngine engine, Instruction instruction) + public virtual void BoolAnd(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetBoolean(); var x1 = engine.Pop().GetBoolean(); @@ -163,7 +163,7 @@ public virtual void BOOLAND(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void BOOLOR(ExecutionEngine engine, Instruction instruction) + public virtual void BoolOr(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetBoolean(); var x1 = engine.Pop().GetBoolean(); @@ -171,14 +171,14 @@ public virtual void BOOLOR(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NZ(ExecutionEngine engine, Instruction instruction) + public virtual void Nz(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop().GetInteger(); engine.Push(!x.IsZero); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NUMEQUAL(ExecutionEngine engine, Instruction instruction) + public virtual void NumEqual(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -186,7 +186,7 @@ public virtual void NUMEQUAL(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NUMNOTEQUAL(ExecutionEngine engine, Instruction instruction) + public virtual void NumNotEqual(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -194,7 +194,7 @@ public virtual void NUMNOTEQUAL(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LT(ExecutionEngine engine, Instruction instruction) + public virtual void Lt(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop(); var x1 = engine.Pop(); @@ -205,7 +205,7 @@ public virtual void LT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LE(ExecutionEngine engine, Instruction instruction) + public virtual void Le(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop(); var x1 = engine.Pop(); @@ -216,7 +216,7 @@ public virtual void LE(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void GT(ExecutionEngine engine, Instruction instruction) + public virtual void Gt(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop(); var x1 = engine.Pop(); @@ -227,7 +227,7 @@ public virtual void GT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void GE(ExecutionEngine engine, Instruction instruction) + public virtual void Ge(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop(); var x1 = engine.Pop(); @@ -238,7 +238,7 @@ public virtual void GE(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void MIN(ExecutionEngine engine, Instruction instruction) + public virtual void Min(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -246,7 +246,7 @@ public virtual void MIN(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void MAX(ExecutionEngine engine, Instruction instruction) + public virtual void Max(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetInteger(); var x1 = engine.Pop().GetInteger(); @@ -254,7 +254,7 @@ public virtual void MAX(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void WITHIN(ExecutionEngine engine, Instruction instruction) + public virtual void Within(ExecutionEngine engine, Instruction instruction) { var b = engine.Pop().GetInteger(); var a = engine.Pop().GetInteger(); diff --git a/src/Neo.VM/JumpTable/JumpTable.Push.cs b/src/Neo.VM/JumpTable/JumpTable.Push.cs index 66b9f64c51..361fb8814a 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Push.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Push.cs @@ -19,43 +19,43 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHINT8(ExecutionEngine engine, Instruction instruction) + public virtual void PushInt8(ExecutionEngine engine, Instruction instruction) { engine.Push(new BigInteger(instruction.Operand.Span)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHINT16(ExecutionEngine engine, Instruction instruction) + public virtual void PushInt16(ExecutionEngine engine, Instruction instruction) { engine.Push(new BigInteger(instruction.Operand.Span)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHINT32(ExecutionEngine engine, Instruction instruction) + public virtual void PushInt32(ExecutionEngine engine, Instruction instruction) { engine.Push(new BigInteger(instruction.Operand.Span)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHINT64(ExecutionEngine engine, Instruction instruction) + public virtual void PushInt64(ExecutionEngine engine, Instruction instruction) { engine.Push(new BigInteger(instruction.Operand.Span)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHINT128(ExecutionEngine engine, Instruction instruction) + public virtual void PushInt128(ExecutionEngine engine, Instruction instruction) { engine.Push(new BigInteger(instruction.Operand.Span)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHINT256(ExecutionEngine engine, Instruction instruction) + public virtual void PushInt256(ExecutionEngine engine, Instruction instruction) { engine.Push(new BigInteger(instruction.Operand.Span)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHT(ExecutionEngine engine, Instruction instruction) + public virtual void PushT(ExecutionEngine engine, Instruction instruction) { engine.Push(StackItem.True); } @@ -67,7 +67,7 @@ public virtual void PUSHF(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHA(ExecutionEngine engine, Instruction instruction) + public virtual void PushA(ExecutionEngine engine, Instruction instruction) { var position = checked(engine.CurrentContext!.InstructionPointer + instruction.TokenI32); if (position < 0 || position > engine.CurrentContext.Script.Length) @@ -76,136 +76,136 @@ public virtual void PUSHA(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHNULL(ExecutionEngine engine, Instruction instruction) + public virtual void PushNull(ExecutionEngine engine, Instruction instruction) { engine.Push(StackItem.Null); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHDATA1(ExecutionEngine engine, Instruction instruction) + public virtual void PushData1(ExecutionEngine engine, Instruction instruction) { engine.Limits.AssertMaxItemSize(instruction.Operand.Length); engine.Push(instruction.Operand); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHDATA2(ExecutionEngine engine, Instruction instruction) + public virtual void PushData2(ExecutionEngine engine, Instruction instruction) { engine.Limits.AssertMaxItemSize(instruction.Operand.Length); engine.Push(instruction.Operand); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHDATA4(ExecutionEngine engine, Instruction instruction) + public virtual void PushData4(ExecutionEngine engine, Instruction instruction) { engine.Limits.AssertMaxItemSize(instruction.Operand.Length); engine.Push(instruction.Operand); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHM1(ExecutionEngine engine, Instruction instruction) + public virtual void PushM1(ExecutionEngine engine, Instruction instruction) { engine.Push(-1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH0(ExecutionEngine engine, Instruction instruction) + public virtual void Push0(ExecutionEngine engine, Instruction instruction) { engine.Push(0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH1(ExecutionEngine engine, Instruction instruction) + public virtual void Push1(ExecutionEngine engine, Instruction instruction) { engine.Push(1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH2(ExecutionEngine engine, Instruction instruction) + public virtual void Push2(ExecutionEngine engine, Instruction instruction) { engine.Push(2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH3(ExecutionEngine engine, Instruction instruction) + public virtual void Push3(ExecutionEngine engine, Instruction instruction) { engine.Push(3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH4(ExecutionEngine engine, Instruction instruction) + public virtual void Push4(ExecutionEngine engine, Instruction instruction) { engine.Push(4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH5(ExecutionEngine engine, Instruction instruction) + public virtual void Push5(ExecutionEngine engine, Instruction instruction) { engine.Push(5); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH6(ExecutionEngine engine, Instruction instruction) + public virtual void Push6(ExecutionEngine engine, Instruction instruction) { engine.Push(6); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH7(ExecutionEngine engine, Instruction instruction) + public virtual void Push7(ExecutionEngine engine, Instruction instruction) { engine.Push(7); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH8(ExecutionEngine engine, Instruction instruction) + public virtual void Push8(ExecutionEngine engine, Instruction instruction) { engine.Push(8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH9(ExecutionEngine engine, Instruction instruction) + public virtual void Push9(ExecutionEngine engine, Instruction instruction) { engine.Push(9); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH10(ExecutionEngine engine, Instruction instruction) + public virtual void Push10(ExecutionEngine engine, Instruction instruction) { engine.Push(10); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH11(ExecutionEngine engine, Instruction instruction) + public virtual void Push11(ExecutionEngine engine, Instruction instruction) { engine.Push(11); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH12(ExecutionEngine engine, Instruction instruction) + public virtual void Push12(ExecutionEngine engine, Instruction instruction) { engine.Push(12); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH13(ExecutionEngine engine, Instruction instruction) + public virtual void Push13(ExecutionEngine engine, Instruction instruction) { engine.Push(13); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH14(ExecutionEngine engine, Instruction instruction) + public virtual void Push14(ExecutionEngine engine, Instruction instruction) { engine.Push(14); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH15(ExecutionEngine engine, Instruction instruction) + public virtual void Push15(ExecutionEngine engine, Instruction instruction) { engine.Push(15); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSH16(ExecutionEngine engine, Instruction instruction) + public virtual void Push16(ExecutionEngine engine, Instruction instruction) { engine.Push(16); } diff --git a/src/Neo.VM/JumpTable/JumpTable.Slot.cs b/src/Neo.VM/JumpTable/JumpTable.Slot.cs index f1f377dca7..1305701e98 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Slot.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Slot.cs @@ -19,7 +19,7 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void INITSSLOT(ExecutionEngine engine, Instruction instruction) + public virtual void InitSSlot(ExecutionEngine engine, Instruction instruction) { if (engine.CurrentContext!.StaticFields != null) throw new InvalidOperationException($"{instruction.OpCode} cannot be executed twice."); @@ -29,7 +29,7 @@ public virtual void INITSSLOT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void INITSLOT(ExecutionEngine engine, Instruction instruction) + public virtual void InitSlot(ExecutionEngine engine, Instruction instruction) { if (engine.CurrentContext!.LocalVariables != null || engine.CurrentContext.Arguments != null) throw new InvalidOperationException($"{instruction.OpCode} cannot be executed twice."); @@ -51,289 +51,289 @@ public virtual void INITSLOT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDSFLD0(ExecutionEngine engine, Instruction instruction) + public virtual void LdSFld0(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDSFLD1(ExecutionEngine engine, Instruction instruction) + public virtual void LdSFld1(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDSFLD2(ExecutionEngine engine, Instruction instruction) + public virtual void LdSFld2(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDSFLD3(ExecutionEngine engine, Instruction instruction) + public virtual void LdSFld3(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDSFLD4(ExecutionEngine engine, Instruction instruction) + public virtual void LdSFld4(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDSFLD5(ExecutionEngine engine, Instruction instruction) + public virtual void LdSFld5(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 5); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDSFLD6(ExecutionEngine engine, Instruction instruction) + public virtual void LdSFld6(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, 6); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDSFLD(ExecutionEngine engine, Instruction instruction) + public virtual void LdSFld(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.StaticFields, instruction.TokenU8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STSFLD0(ExecutionEngine engine, Instruction instruction) + public virtual void StSFld0(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STSFLD1(ExecutionEngine engine, Instruction instruction) + public virtual void StSFld1(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STSFLD2(ExecutionEngine engine, Instruction instruction) + public virtual void StSFld2(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STSFLD3(ExecutionEngine engine, Instruction instruction) + public virtual void StSFld3(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STSFLD4(ExecutionEngine engine, Instruction instruction) + public virtual void StSFld4(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STSFLD5(ExecutionEngine engine, Instruction instruction) + public virtual void StSFld5(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 5); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STSFLD6(ExecutionEngine engine, Instruction instruction) + public virtual void StSFld6(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, 6); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STSFLD(ExecutionEngine engine, Instruction instruction) + public virtual void StSFld(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.StaticFields, instruction.TokenU8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDLOC0(ExecutionEngine engine, Instruction instruction) + public virtual void LdLoc0(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDLOC1(ExecutionEngine engine, Instruction instruction) + public virtual void LdLoc1(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDLOC2(ExecutionEngine engine, Instruction instruction) + public virtual void LdLoc2(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDLOC3(ExecutionEngine engine, Instruction instruction) + public virtual void LdLoc3(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDLOC4(ExecutionEngine engine, Instruction instruction) + public virtual void LdLoc4(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDLOC5(ExecutionEngine engine, Instruction instruction) + public virtual void LdLoc5(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 5); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDLOC6(ExecutionEngine engine, Instruction instruction) + public virtual void LdLoc6(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, 6); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDLOC(ExecutionEngine engine, Instruction instruction) + public virtual void LdLoc(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.LocalVariables, instruction.TokenU8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STLOC0(ExecutionEngine engine, Instruction instruction) + public virtual void StLoc0(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STLOC1(ExecutionEngine engine, Instruction instruction) + public virtual void StLoc1(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STLOC2(ExecutionEngine engine, Instruction instruction) + public virtual void StLoc2(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STLOC3(ExecutionEngine engine, Instruction instruction) + public virtual void StLoc3(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STLOC4(ExecutionEngine engine, Instruction instruction) + public virtual void StLoc4(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STLOC5(ExecutionEngine engine, Instruction instruction) + public virtual void StLoc5(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 5); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STLOC6(ExecutionEngine engine, Instruction instruction) + public virtual void StLoc6(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, 6); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STLOC(ExecutionEngine engine, Instruction instruction) + public virtual void StLoc(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.LocalVariables, instruction.TokenU8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDARG0(ExecutionEngine engine, Instruction instruction) + public virtual void LdArg0(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDARG1(ExecutionEngine engine, Instruction instruction) + public virtual void LdArg1(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDARG2(ExecutionEngine engine, Instruction instruction) + public virtual void LdArg2(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDARG3(ExecutionEngine engine, Instruction instruction) + public virtual void LdArg3(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDARG4(ExecutionEngine engine, Instruction instruction) + public virtual void LdArg4(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDARG5(ExecutionEngine engine, Instruction instruction) + public virtual void LdArg5(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 5); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDARG6(ExecutionEngine engine, Instruction instruction) + public virtual void LdArg6(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, 6); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LDARG(ExecutionEngine engine, Instruction instruction) + public virtual void LdArg(ExecutionEngine engine, Instruction instruction) { ExecuteLoadFromSlot(engine, engine.CurrentContext!.Arguments, instruction.TokenU8); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STARG0(ExecutionEngine engine, Instruction instruction) + public virtual void StArg0(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STARG1(ExecutionEngine engine, Instruction instruction) + public virtual void StArg1(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STARG2(ExecutionEngine engine, Instruction instruction) + public virtual void StArg2(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STARG3(ExecutionEngine engine, Instruction instruction) + public virtual void StArg3(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STARG4(ExecutionEngine engine, Instruction instruction) + public virtual void StArg4(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STARG5(ExecutionEngine engine, Instruction instruction) + public virtual void StArg5(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 5); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STARG6(ExecutionEngine engine, Instruction instruction) + public virtual void StArg6(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, 6); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void STARG(ExecutionEngine engine, Instruction instruction) + public virtual void StArg(ExecutionEngine engine, Instruction instruction) { ExecuteStoreToSlot(engine, engine.CurrentContext!.Arguments, instruction.TokenU8); } diff --git a/src/Neo.VM/JumpTable/JumpTable.Splice.cs b/src/Neo.VM/JumpTable/JumpTable.Splice.cs index f5aec89352..95bad5314f 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Splice.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Splice.cs @@ -17,7 +17,7 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NEWBUFFER(ExecutionEngine engine, Instruction instruction) + public virtual void NewBuffer(ExecutionEngine engine, Instruction instruction) { int length = (int)engine.Pop().GetInteger(); engine.Limits.AssertMaxItemSize(length); @@ -25,7 +25,7 @@ public virtual void NEWBUFFER(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void MEMCPY(ExecutionEngine engine, Instruction instruction) + public virtual void Memcpy(ExecutionEngine engine, Instruction instruction) { int count = (int)engine.Pop().GetInteger(); if (count < 0) @@ -46,7 +46,7 @@ public virtual void MEMCPY(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CAT(ExecutionEngine engine, Instruction instruction) + public virtual void Cat(ExecutionEngine engine, Instruction instruction) { var x2 = engine.Pop().GetSpan(); var x1 = engine.Pop().GetSpan(); @@ -59,7 +59,7 @@ public virtual void CAT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SUBSTR(ExecutionEngine engine, Instruction instruction) + public virtual void SubStr(ExecutionEngine engine, Instruction instruction) { int count = (int)engine.Pop().GetInteger(); if (count < 0) @@ -76,7 +76,7 @@ public virtual void SUBSTR(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void LEFT(ExecutionEngine engine, Instruction instruction) + public virtual void Left(ExecutionEngine engine, Instruction instruction) { int count = (int)engine.Pop().GetInteger(); if (count < 0) @@ -90,7 +90,7 @@ public virtual void LEFT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void RIGHT(ExecutionEngine engine, Instruction instruction) + public virtual void Right(ExecutionEngine engine, Instruction instruction) { int count = (int)engine.Pop().GetInteger(); if (count < 0) diff --git a/src/Neo.VM/JumpTable/JumpTable.Stack.cs b/src/Neo.VM/JumpTable/JumpTable.Stack.cs index 281388d0a0..0f623c26ce 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Stack.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Stack.cs @@ -18,25 +18,25 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void DEPTH(ExecutionEngine engine, Instruction instruction) + public virtual void Depth(ExecutionEngine engine, Instruction instruction) { engine.Push(engine.CurrentContext!.EvaluationStack.Count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void DROP(ExecutionEngine engine, Instruction instruction) + public virtual void Drop(ExecutionEngine engine, Instruction instruction) { engine.Pop(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void NIP(ExecutionEngine engine, Instruction instruction) + public virtual void Nip(ExecutionEngine engine, Instruction instruction) { engine.CurrentContext!.EvaluationStack.Remove(1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void XDROP(ExecutionEngine engine, Instruction instruction) + public virtual void XDrop(ExecutionEngine engine, Instruction instruction) { var n = (int)engine.Pop().GetInteger(); if (n < 0) @@ -45,25 +45,25 @@ public virtual void XDROP(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CLEAR(ExecutionEngine engine, Instruction instruction) + public virtual void Clear(ExecutionEngine engine, Instruction instruction) { engine.CurrentContext!.EvaluationStack.Clear(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void DUP(ExecutionEngine engine, Instruction instruction) + public virtual void Dup(ExecutionEngine engine, Instruction instruction) { engine.Push(engine.Peek()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void OVER(ExecutionEngine engine, Instruction instruction) + public virtual void Over(ExecutionEngine engine, Instruction instruction) { engine.Push(engine.Peek(1)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PICK(ExecutionEngine engine, Instruction instruction) + public virtual void Pick(ExecutionEngine engine, Instruction instruction) { var n = (int)engine.Pop().GetInteger(); if (n < 0) @@ -72,27 +72,27 @@ public virtual void PICK(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void TUCK(ExecutionEngine engine, Instruction instruction) + public virtual void Tuck(ExecutionEngine engine, Instruction instruction) { engine.CurrentContext!.EvaluationStack.Insert(2, engine.Peek()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void SWAP(ExecutionEngine engine, Instruction instruction) + public virtual void Swap(ExecutionEngine engine, Instruction instruction) { var x = engine.CurrentContext!.EvaluationStack.Remove(1); engine.Push(x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ROT(ExecutionEngine engine, Instruction instruction) + public virtual void Rot(ExecutionEngine engine, Instruction instruction) { var x = engine.CurrentContext!.EvaluationStack.Remove(2); engine.Push(x); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ROLL(ExecutionEngine engine, Instruction instruction) + public virtual void Roll(ExecutionEngine engine, Instruction instruction) { var n = (int)engine.Pop().GetInteger(); if (n < 0) @@ -103,19 +103,19 @@ public virtual void ROLL(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void REVERSE3(ExecutionEngine engine, Instruction instruction) + public virtual void Reverse3(ExecutionEngine engine, Instruction instruction) { engine.CurrentContext!.EvaluationStack.Reverse(3); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void REVERSE4(ExecutionEngine engine, Instruction instruction) + public virtual void Reverse4(ExecutionEngine engine, Instruction instruction) { engine.CurrentContext!.EvaluationStack.Reverse(4); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void REVERSEN(ExecutionEngine engine, Instruction instruction) + public virtual void ReverseN(ExecutionEngine engine, Instruction instruction) { var n = (int)engine.Pop().GetInteger(); engine.CurrentContext!.EvaluationStack.Reverse(n); diff --git a/src/Neo.VM/JumpTable/JumpTable.Types.cs b/src/Neo.VM/JumpTable/JumpTable.Types.cs index 6b0107e97f..6c3b1cbb61 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Types.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Types.cs @@ -18,14 +18,14 @@ namespace Neo.VM public partial class JumpTable { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ISNULL(ExecutionEngine engine, Instruction instruction) + public virtual void IsNull(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); engine.Push(x.IsNull); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ISTYPE(ExecutionEngine engine, Instruction instruction) + public virtual void IsType(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); var type = (StackItemType)instruction.TokenU8; @@ -35,21 +35,21 @@ public virtual void ISTYPE(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void CONVERT(ExecutionEngine engine, Instruction instruction) + public virtual void Convert(ExecutionEngine engine, Instruction instruction) { var x = engine.Pop(); engine.Push(x.ConvertTo((StackItemType)instruction.TokenU8)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ABORTMSG(ExecutionEngine engine, Instruction instruction) + public virtual void AbortMsg(ExecutionEngine engine, Instruction instruction) { var msg = engine.Pop().GetString(); throw new Exception($"{OpCode.ABORTMSG} is executed. Reason: {msg}"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void ASSERTMSG(ExecutionEngine engine, Instruction instruction) + public virtual void AssertMsg(ExecutionEngine engine, Instruction instruction) { var msg = engine.Pop().GetString(); var x = engine.Pop().GetBoolean(); diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index a2267f9dd1..d32712ff59 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -27,6 +27,10 @@ public DelAction this[OpCode opCode] set { Table[(byte)opCode] = value; } } + /// + /// Jump table constructor + /// + /// Throw an exception if the opcode was already set public JumpTable() { // Fill defined From 4cbb548967600c0e5155337cd754e637faf8d608 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 11 Feb 2024 06:29:18 -0800 Subject: [PATCH 26/34] Update src/Neo.VM/JumpTable/JumpTable.Push.cs Co-authored-by: Jimmy --- src/Neo.VM/JumpTable/JumpTable.Push.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.Push.cs b/src/Neo.VM/JumpTable/JumpTable.Push.cs index 361fb8814a..066330f5bb 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Push.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Push.cs @@ -61,7 +61,7 @@ public virtual void PushT(ExecutionEngine engine, Instruction instruction) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void PUSHF(ExecutionEngine engine, Instruction instruction) + public virtual void PushF(ExecutionEngine engine, Instruction instruction) { engine.Push(StackItem.False); } From 24356666c6d181be2010015949c8611558c9f8ee Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 12 Feb 2024 23:07:43 +0100 Subject: [PATCH 27/34] Update src/Neo.VM/ExecutionEngine.cs Co-authored-by: Christopher Schuchardt --- src/Neo.VM/ExecutionEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index ada560c1c8..5771f8d278 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -95,7 +95,7 @@ protected internal set /// Restrictions on the VM. protected ExecutionEngine(JumpTable? jumpTable, ReferenceCounter referenceCounter, ExecutionEngineLimits limits) { - this.JumpTable = jumpTable ?? new JumpTable(); + this.JumpTable = jumpTable ?? new(); this.Limits = limits; this.ReferenceCounter = referenceCounter; this.ResultStack = new EvaluationStack(referenceCounter); From fea8fac676854c01c6cbe22a7cc82d05e5fb48a6 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 12 Feb 2024 23:08:00 +0100 Subject: [PATCH 28/34] Update src/Neo.VM/ExecutionEngine.cs Co-authored-by: Christopher Schuchardt --- src/Neo.VM/ExecutionEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index 5771f8d278..502377e785 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -158,7 +158,7 @@ protected internal void ExecuteNext() /// Loads the specified context into the invocation stack. /// /// The context to load. - public virtual void LoadContext(ExecutionContext context) + internal virtual void LoadContext(ExecutionContext context) { if (InvocationStack.Count >= Limits.MaxInvocationStackSize) throw new InvalidOperationException($"MaxInvocationStackSize exceed: {InvocationStack.Count}"); From ff7445578b942a5d215133583874ce33eb5cc236 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 12 Feb 2024 23:08:11 +0100 Subject: [PATCH 29/34] Update src/Neo.VM/ExecutionEngine.cs Co-authored-by: Christopher Schuchardt --- src/Neo.VM/ExecutionEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index 502377e785..b3d23bef04 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -171,7 +171,7 @@ internal virtual void LoadContext(ExecutionContext context) /// Called when a context is unloaded. /// /// The context being unloaded. - public virtual void UnloadContext(ExecutionContext context) + internal virtual void UnloadContext(ExecutionContext context) { if (InvocationStack.Count == 0) { From 68a936750e65bc8af5f017d6c0146d8d7257e8fb Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 12 Feb 2024 23:09:22 +0100 Subject: [PATCH 30/34] Update src/Neo/SmartContract/ApplicationEngine.cs Co-authored-by: Christopher Schuchardt --- src/Neo/SmartContract/ApplicationEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 0280191250..a67cffb9a1 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -326,7 +326,7 @@ internal ContractTask CallFromNativeContract(UInt160 callingScriptHash, UI return task; } - public override void UnloadContext(ExecutionContext context) + internal override void UnloadContext(ExecutionContext context) { base.UnloadContext(context); if (context.Script != CurrentContext?.Script) From 1e86bf4f04913c74da59592f6f29c912b901bcb8 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 13 Feb 2024 10:13:37 +0100 Subject: [PATCH 31/34] use internal --- src/Neo.VM/Neo.VM.csproj | 4 ++++ src/Neo/SmartContract/ApplicationEngine.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Neo.VM/Neo.VM.csproj b/src/Neo.VM/Neo.VM.csproj index 5e7e071b22..8798e704d6 100644 --- a/src/Neo.VM/Neo.VM.csproj +++ b/src/Neo.VM/Neo.VM.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index a67cffb9a1..56a1fe193e 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -383,7 +383,7 @@ public static ApplicationEngine Create(TriggerType trigger, IVerifiable containe ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable); } - public override void LoadContext(ExecutionContext context) + internal override void LoadContext(ExecutionContext context) { // Set default execution context state var state = context.GetState(); From cffab437114eae777fe27ecafd4ef73a75565f7c Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 13 Feb 2024 10:16:25 +0100 Subject: [PATCH 32/34] Allow previous constructor --- src/Neo/SmartContract/ApplicationEngine.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 56a1fe193e..8f30723d48 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -158,8 +158,10 @@ public UInt160 CallingScriptHash /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The jump table to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic, JumpTable jumpTable) - : base(jumpTable) + protected unsafe ApplicationEngine( + TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, + ProtocolSettings settings, long gas, IDiagnostic diagnostic, JumpTable jumpTable = null) + : base(jumpTable ?? DefaultJumpTable) { this.Trigger = trigger; this.ScriptContainer = container; From 7d4836e27d20c1c7594fc6eeb75978bf7758f399 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 13 Feb 2024 10:18:55 +0100 Subject: [PATCH 33/34] prevent new jumptTable if default --- src/Neo.VM/ExecutionEngine.cs | 2 +- src/Neo.VM/JumpTable/JumpTable.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Neo.VM/ExecutionEngine.cs b/src/Neo.VM/ExecutionEngine.cs index b3d23bef04..de268d1030 100644 --- a/src/Neo.VM/ExecutionEngine.cs +++ b/src/Neo.VM/ExecutionEngine.cs @@ -95,7 +95,7 @@ protected internal set /// Restrictions on the VM. protected ExecutionEngine(JumpTable? jumpTable, ReferenceCounter referenceCounter, ExecutionEngineLimits limits) { - this.JumpTable = jumpTable ?? new(); + this.JumpTable = jumpTable ?? JumpTable.Default; this.Limits = limits; this.ReferenceCounter = referenceCounter; this.ResultStack = new EvaluationStack(referenceCounter); diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index d32712ff59..d9a366596d 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -16,6 +16,11 @@ namespace Neo.VM { public partial class JumpTable { + /// + /// Default JumpTable + /// + public static JumpTable Default = new(); + public delegate void DelAction(ExecutionEngine engine, Instruction instruction); protected readonly DelAction[] Table = new DelAction[byte.MaxValue]; From d445a8dcefc083c045193879722ea7a635bf2df0 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 13 Feb 2024 01:20:27 -0800 Subject: [PATCH 34/34] Update src/Neo.VM/JumpTable/JumpTable.cs --- src/Neo.VM/JumpTable/JumpTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.cs b/src/Neo.VM/JumpTable/JumpTable.cs index d9a366596d..0c387e7c9b 100644 --- a/src/Neo.VM/JumpTable/JumpTable.cs +++ b/src/Neo.VM/JumpTable/JumpTable.cs @@ -19,7 +19,7 @@ public partial class JumpTable /// /// Default JumpTable /// - public static JumpTable Default = new(); + public static readonly JumpTable Default = new(); public delegate void DelAction(ExecutionEngine engine, Instruction instruction); protected readonly DelAction[] Table = new DelAction[byte.MaxValue];