From 91a36760840b498c2b4f3b5cec2d447c61dc1e3b Mon Sep 17 00:00:00 2001
From: Silas Davis <silas@erisindustries.com>
Date: Wed, 5 Oct 2016 10:43:55 +0100
Subject: [PATCH] Fix state/* tests that were not allocating sufficient gas and
 so broke with fixed gasLimit implementation

---
 .../eris-mint/evm/{ => opcodes}/opcodes.go    | 50 +++++++++-
 manager/eris-mint/evm/test/log_event_test.go  |  1 +
 manager/eris-mint/evm/test/vm_test.go         | 97 ++++---------------
 manager/eris-mint/evm/vm.go                   |  1 +
 manager/eris-mint/state/permissions_test.go   | 15 +--
 manager/eris-mint/state/state_test.go         |  5 +-
 6 files changed, 83 insertions(+), 86 deletions(-)
 rename manager/eris-mint/evm/{ => opcodes}/opcodes.go (81%)

diff --git a/manager/eris-mint/evm/opcodes.go b/manager/eris-mint/evm/opcodes/opcodes.go
similarity index 81%
rename from manager/eris-mint/evm/opcodes.go
rename to manager/eris-mint/evm/opcodes/opcodes.go
index ee125eaa..b4205f2f 100644
--- a/manager/eris-mint/evm/opcodes.go
+++ b/manager/eris-mint/evm/opcodes/opcodes.go
@@ -1,4 +1,4 @@
-package vm
+package opcodes
 
 import (
 	"fmt"
@@ -355,3 +355,51 @@ func AnalyzeJumpDests(code []byte) (dests *set.Set) {
 	}
 	return
 }
+
+// Convenience function to allow us to mix bytes, ints, and OpCodes that
+// represent bytes in an EVM assembly code to make assembly more readable.
+// Also allows us to splice together assembly
+// fragments because any []byte arguments are flattened in the result.
+func Bytecode(bytelikes ...interface{}) []byte {
+	bytes := make([]byte, len(bytelikes))
+	for i, bytelike := range bytelikes {
+		switch b := bytelike.(type) {
+		case byte:
+			bytes[i] = b
+		case OpCode:
+			bytes[i] = byte(b)
+		case int:
+			bytes[i] = byte(b)
+			if int(bytes[i]) != b {
+				panic(fmt.Sprintf("The int %v does not fit inside a byte", b))
+			}
+		case int64:
+			bytes[i] = byte(b)
+			if int64(bytes[i]) != b {
+				panic(fmt.Sprintf("The int64 %v does not fit inside a byte", b))
+			}
+		case []byte:
+			// splice
+			return Concat(bytes[:i], b, Bytecode(bytelikes[i+1:]...))
+		default:
+			panic("Only byte-like codes (and []byte sequences) can be used to form bytecode")
+		}
+	}
+	return bytes
+}
+
+func Concat(bss ...[]byte) []byte {
+	offset := 0
+	for _, bs := range bss {
+		offset += len(bs)
+	}
+	bytes := make([]byte, offset)
+	offset = 0
+	for _, bs := range bss {
+		for i, b := range bs {
+			bytes[offset+i] = b
+		}
+		offset += len(bs)
+	}
+	return bytes
+}
diff --git a/manager/eris-mint/evm/test/log_event_test.go b/manager/eris-mint/evm/test/log_event_test.go
index 302f2912..5f1eb2f4 100644
--- a/manager/eris-mint/evm/test/log_event_test.go
+++ b/manager/eris-mint/evm/test/log_event_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
+	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
 	"github.com/eris-ltd/eris-db/txs"
 	. "github.com/tendermint/go-common"
 	"github.com/tendermint/go-events"
diff --git a/manager/eris-mint/evm/test/vm_test.go b/manager/eris-mint/evm/test/vm_test.go
index e9e10a65..53895c0d 100644
--- a/manager/eris-mint/evm/test/vm_test.go
+++ b/manager/eris-mint/evm/test/vm_test.go
@@ -9,12 +9,14 @@ import (
 	"time"
 
 	"errors"
+
 	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
+	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
 	ptypes "github.com/eris-ltd/eris-db/permission/types"
 	"github.com/eris-ltd/eris-db/txs"
+	"github.com/stretchr/testify/assert"
 	. "github.com/tendermint/go-common"
 	"github.com/tendermint/go-events"
-	"github.com/stretchr/testify/assert"
 )
 
 func init() {
@@ -206,20 +208,20 @@ func TestDelegateCallGas(t *testing.T) {
 
 	// Do a simple operation using 1 gas unit
 	calleeAccount, calleeAddress := makeAccountWithCode(appState, "callee",
-		bytecode(PUSH1, calleeReturnValue, return1()))
+		Bytecode(PUSH1, calleeReturnValue, return1()))
 
 	// Here we split up the caller code so we can make a DELEGATE call with
 	// different amounts of gas. The value we sandwich in the middle is the amount
 	// we subtract from the available gas (that the caller has available), so:
-	// code := bytecode(callerCodePrefix, <amount to subtract from GAS> , callerCodeSuffix)
+	// code := Bytecode(callerCodePrefix, <amount to subtract from GAS> , callerCodeSuffix)
 	// gives us the code to make the call
-	callerCodePrefix := bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize,
+	callerCodePrefix := Bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize,
 		PUSH1, inOff, PUSH20, calleeAddress, PUSH1)
-	callerCodeSuffix := bytecode(GAS, SUB, DELEGATECALL, returnWord())
+	callerCodeSuffix := Bytecode(GAS, SUB, DELEGATECALL, returnWord())
 
 	// Perform a delegate call
 	callerAccount, _ := makeAccountWithCode(appState, "caller",
-		bytecode(callerCodePrefix,
+		Bytecode(callerCodePrefix,
 			// Give just enough gas to make the DELEGATECALL
 			costBetweenGasAndDelegateCall,
 			callerCodeSuffix))
@@ -230,7 +232,7 @@ func TestDelegateCallGas(t *testing.T) {
 	assert.NoError(t, err, "Should have sufficient funds for call")
 	assert.Equal(t, Int64ToWord256(calleeReturnValue).Bytes(), output)
 
-	callerAccount.Code = bytecode(callerCodePrefix,
+	callerAccount.Code = Bytecode(callerCodePrefix,
 		// Shouldn't be enough gas to make call
 		costBetweenGasAndDelegateCall-1,
 		callerCodeSuffix)
@@ -244,12 +246,12 @@ func TestDelegateCallGas(t *testing.T) {
 // Store the top element of the stack (which is a 32-byte word) in memory
 // and return it. Useful for a simple return value.
 func return1() []byte {
-	return bytecode(PUSH1, 0, MSTORE, returnWord())
+	return Bytecode(PUSH1, 0, MSTORE, returnWord())
 }
 
 func returnWord() []byte {
 	// PUSH1 => return size, PUSH1 => return offset, RETURN
-	return bytecode(PUSH1, 32, PUSH1, 0, RETURN)
+	return Bytecode(PUSH1, 32, PUSH1, 0, RETURN)
 }
 
 func makeAccountWithCode(appState AppState, name string,
@@ -327,24 +329,24 @@ func callContractCode(addr []byte) []byte {
 	inOff, inSize := byte(0x0), byte(0x0) // no call data
 	retOff, retSize := byte(0x0), byte(0x20)
 	// this is the code we want to run (send funds to an account and return)
-	return bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
+	return Bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
 		inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize,
 		PUSH1, retOff, RETURN)
 }
 
 func TestBytecode(t *testing.T) {
 	assert.Equal(t,
-		bytecode(1, 2, 3, 4, 5, 6),
-		bytecode(1, 2, 3, bytecode(4, 5, 6)))
+		Bytecode(1, 2, 3, 4, 5, 6),
+		Bytecode(1, 2, 3, Bytecode(4, 5, 6)))
 	assert.Equal(t,
-		bytecode(1, 2, 3, 4, 5, 6, 7, 8),
-		bytecode(1, 2, 3, bytecode(4, bytecode(5), 6), 7, 8))
+		Bytecode(1, 2, 3, 4, 5, 6, 7, 8),
+		Bytecode(1, 2, 3, Bytecode(4, Bytecode(5), 6), 7, 8))
 	assert.Equal(t,
-		bytecode(PUSH1, 2),
-		bytecode(byte(PUSH1), 0x02))
+		Bytecode(PUSH1, 2),
+		Bytecode(byte(PUSH1), 0x02))
 	assert.Equal(t,
 		[]byte{},
-		bytecode(bytecode(bytecode())))
+		Bytecode(Bytecode(Bytecode())))
 
 	contractAccount := &Account{Address: Int64ToWord256(102)}
 	addr := contractAccount.Address.Postfix(20)
@@ -352,7 +354,7 @@ func TestBytecode(t *testing.T) {
 	value := byte(0x69)
 	inOff, inSize := byte(0x0), byte(0x0) // no call data
 	retOff, retSize := byte(0x0), byte(0x20)
-	contractCodeBytecode := bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
+	contractCodeBytecode := Bytecode(PUSH1, retSize, PUSH1, retOff, PUSH1, inSize, PUSH1,
 		inOff, PUSH1, value, PUSH20, addr, PUSH2, gas1, gas2, CALL, PUSH1, retSize,
 		PUSH1, retOff, RETURN)
 	contractCode := []byte{0x60, retSize, 0x60, retOff, 0x60, inSize, 0x60, inOff, 0x60, value, 0x73}
@@ -364,62 +366,5 @@ func TestBytecode(t *testing.T) {
 func TestConcat(t *testing.T) {
 	assert.Equal(t,
 		[]byte{0x01, 0x02, 0x03, 0x04},
-		concat([]byte{0x01, 0x02}, []byte{0x03, 0x04}))
-}
-
-// Convenience function to allow us to mix bytes, ints, and OpCodes that
-// represent bytes in an EVM assembly code to make assembly more readable.
-// Also allows us to splice together assembly
-// fragments because any []byte arguments are flattened in the result.
-func bytecode(bytelikes ...interface{}) []byte {
-	bytes := make([]byte, len(bytelikes))
-	for i, bytelike := range bytelikes {
-		switch b := bytelike.(type) {
-		case byte:
-			bytes[i] = b
-		case OpCode:
-			bytes[i] = byte(b)
-		case int:
-			bytes[i] = byte(b)
-			if int(bytes[i]) != b {
-				panic(fmt.Sprintf("The int %v does not fit inside a byte", b))
-			}
-		case int64:
-			bytes[i] = byte(b)
-			if int64(bytes[i]) != b {
-				panic(fmt.Sprintf("The int64 %v does not fit inside a byte", b))
-			}
-		case []byte:
-			// splice
-			return concat(bytes[:i], b, bytecode(bytelikes[i+1:]...))
-		default:
-			panic("Only byte-like codes (and []byte sequences) can be used to form bytecode")
-		}
-	}
-	return bytes
+		Concat([]byte{0x01, 0x02}, []byte{0x03, 0x04}))
 }
-
-func concat(bss ...[]byte) []byte {
-	offset := 0
-	for _, bs := range bss {
-		offset += len(bs)
-	}
-	bytes := make([]byte, offset)
-	offset = 0
-	for _, bs := range bss {
-		for i, b := range bs {
-			bytes[offset+i] = b
-		}
-		offset += len(bs)
-	}
-	return bytes
-}
-
-/*
-	// infinite loop
-	code := []byte{0x5B, 0x60, 0x00, 0x56}
-	// mstore
-	code := []byte{0x60, 0x00, 0x60, 0x20}
-	// mstore, mload
-	code := []byte{0x60, 0x01, 0x60, 0x20, 0x52, 0x60, 0x20, 0x51}
-*/
diff --git a/manager/eris-mint/evm/vm.go b/manager/eris-mint/evm/vm.go
index 590b1cfa..a3f4d51e 100644
--- a/manager/eris-mint/evm/vm.go
+++ b/manager/eris-mint/evm/vm.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"math/big"
 
+	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
 	"github.com/eris-ltd/eris-db/manager/eris-mint/evm/sha3"
 	ptypes "github.com/eris-ltd/eris-db/permission/types"
 	"github.com/eris-ltd/eris-db/txs"
diff --git a/manager/eris-mint/state/permissions_test.go b/manager/eris-mint/state/permissions_test.go
index 5c311405..523a5ffc 100644
--- a/manager/eris-mint/state/permissions_test.go
+++ b/manager/eris-mint/state/permissions_test.go
@@ -14,6 +14,7 @@ import (
 	ptypes "github.com/eris-ltd/eris-db/permission/types"
 	"github.com/eris-ltd/eris-db/txs"
 
+	. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
 	. "github.com/tendermint/go-common"
 	"github.com/tendermint/go-crypto"
 	dbm "github.com/tendermint/go-db"
@@ -1257,17 +1258,17 @@ func snativeRoleTestInputTx(name string, user *acm.PrivAccount, role string) (sn
 func callContractCode(contractAddr []byte) []byte {
 	// calldatacopy into mem and use as input to call
 	memOff, inputOff := byte(0x0), byte(0x0)
-	contractCode := []byte{0x36, 0x60, inputOff, 0x60, memOff, 0x37}
-
-	gas1, gas2 := byte(0x1), byte(0x1)
 	value := byte(0x1)
 	inOff := byte(0x0)
 	retOff, retSize := byte(0x0), byte(0x20)
+
 	// this is the code we want to run (call a contract and return)
-	contractCode = append(contractCode, []byte{0x60, retSize, 0x60, retOff, 0x36, 0x60, inOff, 0x60, value, 0x73}...)
-	contractCode = append(contractCode, contractAddr...)
-	contractCode = append(contractCode, []byte{0x61, gas1, gas2, 0xf1, 0x60, 0x20, 0x60, 0x0, 0xf3}...)
-	return contractCode
+	return Bytecode(CALLDATASIZE, PUSH1, inputOff, PUSH1, memOff,
+		CALLDATACOPY, PUSH1, retSize, PUSH1, retOff, CALLDATASIZE, PUSH1, inOff,
+		PUSH1, value, PUSH20, contractAddr,
+		// Zeno loves us - call with half of the available gas each time we CALL
+		PUSH1, 2, GAS, DIV, CALL,
+		PUSH1, 32, PUSH1, 0, RETURN)
 }
 
 // convenience function for contract that is a factory for the code that comes as call data
diff --git a/manager/eris-mint/state/state_test.go b/manager/eris-mint/state/state_test.go
index 7f8cb8f1..be619f33 100644
--- a/manager/eris-mint/state/state_test.go
+++ b/manager/eris-mint/state/state_test.go
@@ -11,12 +11,13 @@ import (
 	// tmtypes "github.com/tendermint/tendermint/types"
 
 	core_types "github.com/eris-ltd/eris-db/core/types"
-	//evm "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
 	"github.com/eris-ltd/eris-db/txs"
+	evm "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
 )
 
 func init() {
 	tendermint_test.ResetConfig("state_test")
+	evm.SetDebug(true)
 }
 
 func execTxWithState(state *State, tx txs.Tx, runCall bool) error {
@@ -463,7 +464,7 @@ func TestCreates(t *testing.T) {
 			PubKey:   acc0PubKey,
 		},
 		Address:  acc1.Address,
-		GasLimit: 10000,
+		GasLimit: 100000,
 		Data:     createData,
 	}
 
-- 
GitLab