Skip to content

Commit

Permalink
pc fix, sub fix & loop test
Browse files Browse the repository at this point in the history
  • Loading branch information
Scooletz committed Mar 23, 2022
1 parent be8e69b commit 62010c9
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 58 deletions.
47 changes: 27 additions & 20 deletions src/Nethermind/Nethermind.Evm.Test/IlVirtualMachineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void Jump_Invalid()
public void Jump_Valid()
{
byte[] code = Prepare.EvmCode
.PushData(2)
.PushData(3)
.Op(Instruction.JUMP)
.Op(Instruction.JUMPDEST)
.Done;
Expand Down Expand Up @@ -111,7 +111,7 @@ public void Jumpi_ValidCondition_ValidAddress()
{
byte[] code = Prepare.EvmCode
.PushData(1) // valid condition
.PushData(3) // address
.PushData(5) // address
.Op(Instruction.JUMPI)
.Op(Instruction.JUMPDEST)
.Done;
Expand All @@ -127,7 +127,11 @@ public void Sub()
byte[] code = Prepare.EvmCode
.PushData(1)
.PushData(2)
.Op(Instruction.SUB)
.PushData(1)
.PushData(4)
.Op(Instruction.SUB) // 4 - 1 = 3
.Op(Instruction.SUB) // 3 - 2 = 1
.Op(Instruction.SUB) // 1 - 1 = 0
.Done;

TestAllTracerWithOutput result = Execute(code);
Expand All @@ -141,15 +145,15 @@ public void Dup()
byte[] code = Prepare.EvmCode
.PushData(1)
.Op(Instruction.DUP1)
.Op(Instruction.POP)
.Op(Instruction.SUB)
.Op(Instruction.POP)
.Done;

TestAllTracerWithOutput result = Execute(code);

Console.WriteLine(result.Error);
}

[Test]
public void Swap()
{
Expand All @@ -165,21 +169,24 @@ public void Swap()
Console.WriteLine(result.Error);
}

//[Test]
//public void Long_Loop()
//{
// byte[] code = Prepare.EvmCode
// .PushData(1000_000)
// .Op(Instruction.JUMPDEST)
// .

// .Op(Instruction.DUP1)
// .Op(Instruction.POP)
// .Op(Instruction.POP)
// .Done;
[Test]
public void Long_Loop()
{
byte[] code = Prepare.EvmCode
.PushData(5)

.Op(Instruction.JUMPDEST) // counter
.PushData(1) // counter, 1
.Op(Instruction.SWAP1) // 1, counter
.Op(Instruction.SUB) // counter-1
.Op(Instruction.DUP1) // counter-1, counter-1
.PushData(2) // counter-1, counter-1, 2
.Op(Instruction.JUMPI) // counter-1
.Op(Instruction.POP)
.Done;

// TestAllTracerWithOutput result = Execute(code);
TestAllTracerWithOutput result = Execute(code);

// Console.WriteLine(result.Error);
//}
Console.WriteLine(result.Error);
}
}
23 changes: 21 additions & 2 deletions src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
// The Nethermind library is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -60,7 +60,26 @@ public void Trace()
Assert.AreEqual(2, entry.Pc, nameof(entry.Pc));
Assert.AreEqual("PUSH1", entry.Operation, nameof(entry.Operation));
}


[Test]
public void Long_Loop()
{
byte[] code = Prepare.EvmCode
.PushData(5)

.Op(Instruction.JUMPDEST) // counter
.PushData(1) // counter, 1
.Op(Instruction.SWAP1) // 1, counter
.Op(Instruction.SUB) // counter-1
.Op(Instruction.DUP1) // counter-1, counter-1
.PushData(2) // counter-1, counter-1, 1
.Op(Instruction.JUMPI) // counter-1
.Op(Instruction.POP)
.Done;

TestAllTracerWithOutput result = Execute(code);
}

[Test]
public void Trace_vm_errors()
{
Expand Down
68 changes: 32 additions & 36 deletions src/Nethermind/Nethermind.Evm/IlVirtualMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,20 @@ public UInt256 UInt256
}
set
{
ulong u3 = value.u3;
ulong u2 = value.u2;
ulong u1 = value.u1;
ulong u0 = value.u0;

if (BitConverter.IsLittleEndian)
{
u3 = BinaryPrimitives.ReverseEndianness(u3);
u2 = BinaryPrimitives.ReverseEndianness(u2);
u1 = BinaryPrimitives.ReverseEndianness(u1);
u0 = BinaryPrimitives.ReverseEndianness(u0);
Ulong3 = BinaryPrimitives.ReverseEndianness(value.u3);
Ulong2 = BinaryPrimitives.ReverseEndianness(value.u2);
Ulong1 = BinaryPrimitives.ReverseEndianness(value.u1);
Ulong0 = BinaryPrimitives.ReverseEndianness(value.u0);
}
else
{
Ulong3 = value.u3;
Ulong2 = value.u2;
Ulong1 = value.u1;
Ulong0 = value.u0;
}

Ulong3 = u3;
Ulong2 = u2;
Ulong1 = u1;
Ulong0 = u0;
}
}
}
Expand All @@ -140,9 +137,10 @@ public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer

LocalBuilder jmpDestination = il.DeclareLocal(Word.Int0Field.FieldType);
LocalBuilder consumeJumpCondition = il.DeclareLocal(typeof(int));
LocalBuilder uint256a = il.DeclareLocal(typeof(UInt256));
LocalBuilder uint256b = il.DeclareLocal(typeof(UInt256));
LocalBuilder uint256c = il.DeclareLocal(typeof(UInt256));
LocalBuilder word = il.DeclareLocal(typeof(Word));
LocalBuilder uint256A = il.DeclareLocal(typeof(UInt256));
LocalBuilder uint256B = il.DeclareLocal(typeof(UInt256));
LocalBuilder uint256C = il.DeclareLocal(typeof(UInt256));

// TODO: stack check for head
LocalBuilder stack = il.DeclareLocal(typeof(Word*));
Expand All @@ -166,17 +164,15 @@ public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer
il.Load(stack);
il.Store(current); // copy to the current

int pc = 0;

Label ret = il.DefineLabel(); // the label just before return
Label invalidAddress = il.DefineLabel(); // invalid jump address
Label jumpTable = il.DefineLabel(); // jump table

Dictionary<int, Label> jumpDestinations = new();

for (int i = 0; i < code.Length; i++)
for (int pc = 0; pc < code.Length; pc++)
{
Operation op = _operations[(Instruction)code[i]];
Operation op = _operations[(Instruction)code[pc]];

switch (op.Instruction)
{
Expand All @@ -198,21 +194,23 @@ public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer
il.Load(current);
il.Emit(OpCodes.Initobj, typeof(Word));
il.Load(current);
byte push1 = (byte)((i + 1 >= code.Length) ? 0 : code[i + 1]);
byte push1 = (byte)((pc + 1 >= code.Length) ? 0 : code[pc + 1]);
il.Emit(OpCodes.Ldc_I4_S, push1);
il.Emit(OpCodes.Stfld, Word.Byte0Field);
il.StackPush(current);
pc += 1;
break;
case Instruction.PUSH2:
case Instruction.PUSH3:
case Instruction.PUSH4:
il.Load(current);
il.Emit(OpCodes.Initobj, typeof(Word));
il.Load(current);
int push2 = BinaryPrimitives.ReadInt32LittleEndian(code.Slice(i + 1).ToArray().Concat(new byte[4]).ToArray());
int push2 = BinaryPrimitives.ReadInt32LittleEndian(code.Slice(pc + 1).ToArray().Concat(new byte[4]).ToArray());
il.Emit(OpCodes.Ldc_I4, BinaryPrimitives.ReverseEndianness(push2));
il.Emit(OpCodes.Stfld, Word.Int0Field);
il.StackPush(current);
pc += 1 + op.Instruction - Instruction.PUSH1;
break;
case Instruction.DUP1:
il.Load(current);
Expand All @@ -223,7 +221,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer
break;
case Instruction.SWAP1:
// copy to a helper variable the top item
il.LoadAddress(uint256c); // reuse uint as a swap placeholder
il.LoadAddress(word); // reuse uint as a swap placeholder
il.StackLoadPrevious(current, 1);
il.Emit(OpCodes.Ldobj, typeof(Word));
il.Emit(OpCodes.Stobj, typeof(Word));
Expand All @@ -238,7 +236,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer

// write to the more nested one from local variable
il.StackLoadPrevious(current, swapWith);
il.LoadAddress(uint256c);
il.LoadAddress(word);
il.Emit(OpCodes.Ldobj, typeof(Word));
il.Emit(OpCodes.Stobj, typeof(Word));
break;
Expand Down Expand Up @@ -274,32 +272,30 @@ public TransactionSubstate Run(EvmState state, IWorldState worldState, ITxTracer
// a
il.StackLoadPrevious(current, 1);
il.EmitCall(OpCodes.Call, Word.GetUInt256, null);
il.Store(uint256a);
il.Store(uint256A);

// b
il.StackLoadPrevious(current, 2);
il.EmitCall(OpCodes.Call, Word.GetUInt256, null); // stack: uint256, uint256
il.Store(uint256b);
il.Store(uint256B);

// a - b = c
il.LoadAddress(uint256a);
il.LoadAddress(uint256b);
il.LoadAddress(uint256c);
il.LoadAddress(uint256A);
il.LoadAddress(uint256B);
il.LoadAddress(uint256C);

MethodInfo subtract = typeof(UInt256).GetMethod(nameof(UInt256.Subtract), BindingFlags.Public | BindingFlags.Static)!;
il.EmitCall(OpCodes.Call, subtract, null); // stack: _

il.StackPop(current);
il.StackPop(current, 2);
il.Load(current);
il.Load(uint256c); // stack: word*, uint256
il.Load(uint256C); // stack: word*, uint256
il.EmitCall(OpCodes.Call, Word.SetUInt256, null);
il.StackPush(current);
break;
default:
throw new NotImplementedException();
}

i += op.AdditionalBytes;
pc++;
}

// jump to return
Expand Down Expand Up @@ -434,7 +430,7 @@ public void DisableSimdInstructions()
new(Instruction.DUP1, GasCostOf.VeryLow, 0, 1, 2),
new(Instruction.SWAP1, GasCostOf.VeryLow, 0, 2, 2)
}.ToDictionary(op => op.Instruction);

public readonly struct Operation
{
/// <summary>
Expand Down

0 comments on commit 62010c9

Please sign in to comment.