diff --git a/README.md b/README.md index a34ecec..45ce115 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,6 @@ type IEVM interface { ISHA3Ops IStackOps IMemoryOps - - // Helper methods. - // TODO: Get rid of these methods if possible. - // Push an item to the stack. - HelperPush(*uint256.Int) error - // Pop an item of the stack. - HelperPop() (*uint256.Int, error) - // Write byte slice to memory at the specified offset. - HelperStore(value []byte, offset int) - // Load a chunck of the memory. - HelperLoad(size int) []byte } // EVM represents an Ethereum Virtual Machine. diff --git a/evm.go b/evm.go index 45d4cf3..e441f9c 100644 --- a/evm.go +++ b/evm.go @@ -11,17 +11,6 @@ type IEVM interface { ISHA3Ops IStackOps IMemoryOps - - // Helper methods. - // TODO: Get rid of these methods if possible. - // Push an item to the stack. - HelperPush(*uint256.Int) error - // Pop an item of the stack. - HelperPop() (*uint256.Int, error) - // Write byte slice to memory at the specified offset. - HelperStore(value []byte, offset int) - // Load a chunck of the memory. - HelperLoad(size int) []byte } // EVM represents an Ethereum Virtual Machine. @@ -60,22 +49,6 @@ func NewEVM(code []byte) IEVM { } } -func (e *EVM) HelperPop() (*uint256.Int, error) { - return e.stack.Pop() -} - -func (e *EVM) HelperPush(value *uint256.Int) error { - return e.stack.Push(value) -} - -func (e *EVM) HelperStore(value []byte, offset int) { - e.memory.Store(value, offset) -} - -func (e *EVM) HelperLoad(size int) []byte { - return e.memory.Load(0, size) -} - // Perform an arithmetic or a bitwise operation on the top two elements on the stack. // It pops two values from the stack, applies the operation, and pushes the result back to the stack. func (e *EVM) performBinaryStackOperation(numOperands int, operation func(...*uint256.Int) *uint256.Int) error { diff --git a/evm_test.go b/evm_test.go index a7a2846..efd4782 100644 --- a/evm_test.go +++ b/evm_test.go @@ -7,6 +7,38 @@ import ( "github.com/holiman/uint256" ) +// internalEVM defines the methods that an Ethereum Virtual Machine implementation should have, including helper methods. +// It is only used for testing. +type internalEVM interface { + IEVM + + // Helper methods. + // Push an item to the stack. + HelperPush(*uint256.Int) error + // Pop an item of the stack. + HelperPop() (*uint256.Int, error) + // Write byte slice to memory at the specified offset. + HelperStore(value []byte, offset int) + // Load a chunck of the memory. + HelperLoad(size int) []byte +} + +func (e *EVM) HelperPop() (*uint256.Int, error) { + return e.stack.Pop() +} + +func (e *EVM) HelperPush(value *uint256.Int) error { + return e.stack.Push(value) +} + +func (e *EVM) HelperStore(value []byte, offset int) { + e.memory.Store(value, offset) +} + +func (e *EVM) HelperLoad(size int) []byte { + return e.memory.Load(0, size) +} + func TestNewEVM(t *testing.T) { evm := NewEVM(nil) if evm == nil { @@ -59,15 +91,21 @@ func testStackOperationWithNewEVM(t *testing.T, op func(evm IEVM) error, expecte // Helper function to test stack operations with an existing EVM. func testStackOperationWithExistingEVM(t *testing.T, evm IEVM, op func(evm IEVM) error, expectedErr error, initialStack, expectedStack []uint64, initialMemory, expectedMemory []byte) { + // Extend the capabilities of the EVM using the internal EVM which defines helper methods to access the states of the stack and the memory. + internalEVM, ok := evm.(internalEVM) + if !ok { + t.Fatal("IEVM does not implement internalEVM") + } + // Push initial elements to the stack. for i, v := range initialStack { - if err := evm.HelperPush(uint256.NewInt(v)); err != nil { + if err := internalEVM.HelperPush(uint256.NewInt(v)); err != nil { t.Errorf("Push() returned an unexpected error at iteration %d: %v", i, err) } } // Load initial elements to the memory. - evm.HelperStore(initialMemory, 0) + internalEVM.HelperStore(initialMemory, 0) // Perform the operation. if err := op(evm); err != expectedErr { @@ -76,7 +114,7 @@ func testStackOperationWithExistingEVM(t *testing.T, evm IEVM, op func(evm IEVM) // Check the stack after the operation. for i := len(expectedStack) - 1; i >= 0; i-- { - popped, err := evm.HelperPop() + popped, err := internalEVM.HelperPop() if err != nil { t.Errorf("Pop() returned an unexpected error: %v", err) } @@ -92,7 +130,7 @@ func testStackOperationWithExistingEVM(t *testing.T, evm IEVM, op func(evm IEVM) } // Check the memory after the operation. - actualMemory := evm.HelperLoad(len(expectedMemory)) + actualMemory := internalEVM.HelperLoad(len(expectedMemory)) if !bytes.Equal(actualMemory, expectedMemory) { t.Errorf("Memory mismatch. Expected: %v, got: %v", expectedMemory, actualMemory) } diff --git a/stack_ops_test.go b/stack_ops_test.go index 14e00b0..4638909 100644 --- a/stack_ops_test.go +++ b/stack_ops_test.go @@ -46,16 +46,22 @@ func TestPushOnFullStack(t *testing.T) { code := []byte{0x60, 0x11} evm := NewEVM(code) + // Extend the capabilities of the EVM using the internal EVM which defines helper methods to access the states of the stack and the memory. + internalEVM, ok := evm.(internalEVM) + if !ok { + t.Fatal("IEVM does not implement internalEVM") + } + // Push elements to the stack until its full. for i := 0; i < 1024; i++ { - if err := evm.HelperPush(uint256.NewInt(uint64(i))); err != nil { + if err := internalEVM.HelperPush(uint256.NewInt(uint64(i))); err != nil { t.Errorf("Push() returned an unexpected error at iteration %d: %v", i, err) break } } // Try to push the first element (0x11) from code. - if err := evm.Push1(); err == nil { + if err := internalEVM.Push1(); err == nil { t.Errorf("Operation returned an unexpected error: %v, wanted: %v", err, ErrStackOverflow) } } @@ -119,16 +125,22 @@ func TestDupOnFullStack(t *testing.T) { // Create a new EVM. evm := NewEVM(nil) + // Extend the capabilities of the EVM using the internal EVM which defines helper methods to access the states of the stack and the memory. + internalEVM, ok := evm.(internalEVM) + if !ok { + t.Fatal("IEVM does not implement internalEVM") + } + // Push elements to the stack until its full. for i := 0; i < 1024; i++ { - if err := evm.HelperPush(uint256.NewInt(uint64(i))); err != nil { + if err := internalEVM.HelperPush(uint256.NewInt(uint64(i))); err != nil { t.Errorf("Push() returned an unexpected error at iteration %d: %v", i, err) break } } // Try to duplicate the first element. - if err := evm.Dup1(); err == nil { + if err := internalEVM.Dup1(); err == nil { t.Errorf("Operation returned an unexpected error: %v, wanted: %v", err, ErrStackOverflow) } }