From 7455b903d61ca827c8e4d34a1d06cd4992d984a8 Mon Sep 17 00:00:00 2001 From: leovct Date: Tue, 16 Jul 2024 10:28:55 +0200 Subject: [PATCH] feat: implement add operation on EVM and its related tests --- evm.go | 42 ++++++++++++++++++++++ evm_test.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 14 -------- 3 files changed, 142 insertions(+), 14 deletions(-) create mode 100644 evm.go create mode 100644 evm_test.go diff --git a/evm.go b/evm.go new file mode 100644 index 0000000..703ccef --- /dev/null +++ b/evm.go @@ -0,0 +1,42 @@ +package main + +import "github.com/holiman/uint256" + +// IEVM defines the methods that an Ethereum Virtual Machine implementation should have. +type IEVM interface{} + +// EVM represents an Ethereum Virtual Machine. +type EVM struct { + stack IStack + memory IMemory + storage IStorage +} + +// NewEVM creates and returns a new EVM instance. +func NewEVM() *EVM { + return &EVM{ + stack: NewStack(), + memory: NewMemory(), + storage: NewStorage(), + } +} + +// Add performs addition of the top two elements on the stack. +// It pops two values from the stack, adds them, and pushes the result back to the stack. +func (e *EVM) Add() error { + a, err := e.stack.Pop() + if err != nil { + return err + } + + b, err := e.stack.Pop() + if err != nil { + return err + } + + result := new(uint256.Int).Add(a, b) + // This step should never fail because of an overflow. + // Indeed, two elements are popped from the stack and only one is pushed back. + _ = e.stack.Push(result) + return nil +} diff --git a/evm_test.go b/evm_test.go new file mode 100644 index 0000000..132b834 --- /dev/null +++ b/evm_test.go @@ -0,0 +1,100 @@ +package main + +import ( + "testing" + + "github.com/holiman/uint256" +) + +func TestNewEVM(t *testing.T) { + evm := NewEVM() + if evm == nil { + t.Error("NewEVM() returned nil") + } +} + +func TestAdd(t *testing.T) { + // Create a new EVM. + evm := NewEVM() + + // Push some elements to the stack. + // The stack should be equal to [0x1, 0x2, 0x3]. + evm.stack.Push(uint256.NewInt(1)) + evm.stack.Push(uint256.NewInt(2)) + evm.stack.Push(uint256.NewInt(3)) + + // Add the two elements at the top of the stack. + // The stack should be equal to [0x1, 0x5]. + err := evm.Add() + if err != nil { + t.Errorf("Add() returned an unexpected error: %v", err) + } + + // Pop the element from the stack to check the result. + result, err := evm.stack.Pop() + expectedResult := uint256.NewInt(5) + if err != nil { + t.Errorf("Pop() returned an unexpected error: %v", err) + } + if !result.Eq(expectedResult) { + t.Errorf("Expected %v, got %v", expectedResult, result) + } +} + +func TestAddOnEmptyStack(t *testing.T) { + // Create a new EVM. + evm := NewEVM() + + // Try to add the two elements at the top of the stack. + err := evm.Add() + if err == nil { + t.Error("Add() should return an error because there are no elements in the stack") + } +} + +func TestAddOnOneElementStack(t *testing.T) { + // Create a new EVM. + evm := NewEVM() + + // Add one element to the stack. + // The stack should be equal to [0x1]. + evm.stack.Push(uint256.NewInt(1)) + + // Try to add the two elements at the top of the stack. + err := evm.Add() + if err == nil { + t.Error("Add() should return an error because there is only one element in the stack") + } +} + +func TestAddOnFullStack(t *testing.T) { + // Create a new EVM. + evm := NewEVM() + + // Push 1024 elements to the stack. + // The stack should contain 1024 0x1 elements. + for i := 0; i < MAX_STACK_SIZE; i++ { + err := evm.stack.Push(uint256.NewInt(1)) + if err != nil { + t.Errorf("Push() returned an unexpected error on iteration %d: %v", i, err) + } + } + + // Try to add the two elements at the top of the stack. + err := evm.Add() + if err != nil { + t.Error("Add() should return an error because the stack is full") + } +} + +func TestMul(t *testing.T) { + // TODO +} + +func TestSub(t *testing.T) { + // TODO +} + +func TestDiv(t *testing.T) { + // TODO +} diff --git a/main.go b/main.go index 1e28fad..c56831f 100644 --- a/main.go +++ b/main.go @@ -6,17 +6,3 @@ func main() { evm := NewEVM() fmt.Println("EVM:", evm) } - -type EVM struct { - Stack IStack - Memory IMemory - Storage IStorage -} - -func NewEVM() *EVM { - return &EVM{ - Stack: NewStack(), - Memory: NewMemory(), - Storage: NewStorage(), - } -}