Added state tests

This commit is contained in:
obscuren 2014-12-02 00:03:53 +01:00
parent a052357872
commit 2df8ad6307
4 changed files with 86 additions and 7 deletions

View File

@ -3,6 +3,7 @@ package helper
import ( import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/vm" "github.com/ethereum/go-ethereum/vm"
@ -66,3 +67,17 @@ func RunVm(state *state.State, env, exec map[string]string) ([]byte, *big.Int, e
return ret, execution.Gas, err return ret, execution.Gas, err
} }
func RunState(state *state.State, env, tx map[string]string) ([]byte, *big.Int, error) {
address := FromHex(tx["to"])
keyPair, _ := crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(tx["secretKey"])))
caller := state.GetOrNewStateObject(keyPair.Address())
vmenv := NewEnvFromMap(state, env, tx)
vmenv.origin = caller.Address()
evm := vm.New(vmenv, vm.DebugVmTy)
execution := vm.NewExecution(evm, address, FromHex(tx["data"]), ethutil.Big(tx["gasLimit"]), ethutil.Big(tx["gasPrice"]), ethutil.Big(tx["value"]))
ret, err := execution.Exec(address, caller)
return ret, execution.Gas, err
}

View File

@ -2,6 +2,8 @@ package vm
import ( import (
"bytes" "bytes"
"math/big"
"strconv"
"testing" "testing"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
@ -29,10 +31,21 @@ func StateObjectFromAccount(addr string, account Account) *state.StateObject {
return obj return obj
} }
type Env struct {
CurrentCoinbase string
CurrentDifficulty string
CurrentGasLimit string
CurrentNumber string
CurrentTimestamp interface{}
PreviousHash string
}
type VmTest struct { type VmTest struct {
Callcreates interface{} Callcreates interface{}
Env map[string]string //Env map[string]string
Env Env
Exec map[string]string Exec map[string]string
Transaction map[string]string
Gas string Gas string
Out string Out string
Post map[string]Account Post map[string]Account
@ -50,7 +63,31 @@ func RunVmTest(p string, t *testing.T) {
state.SetStateObject(obj) state.SetStateObject(obj)
} }
ret, gas, err := helper.RunVm(state, test.Env, test.Exec) // XXX Yeah, yeah...
env := make(map[string]string)
env["currentCoinbase"] = test.Env.CurrentCoinbase
env["currentDifficulty"] = test.Env.CurrentDifficulty
env["currentGasLimit"] = test.Env.CurrentGasLimit
env["currentNumber"] = test.Env.CurrentNumber
env["previousHash"] = test.Env.PreviousHash
if n, ok := test.Env.CurrentTimestamp.(float64); ok {
env["currentTimestamp"] = strconv.Itoa(int(n))
} else {
env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
}
var (
ret []byte
gas *big.Int
err error
)
if len(test.Exec) > 0 {
ret, gas, err = helper.RunVm(state, env, test.Exec)
} else {
ret, gas, err = helper.RunState(state, env, test.Transaction)
}
// When an error is returned it doesn't always mean the tests fails. // When an error is returned it doesn't always mean the tests fails.
// Have to come up with some conditional failing mechanism. // Have to come up with some conditional failing mechanism.
if err != nil { if err != nil {
@ -62,10 +99,12 @@ func RunVmTest(p string, t *testing.T) {
t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret) t.Errorf("%s's return failed. Expected %x, got %x\n", name, rexp, ret)
} }
if len(test.Gas) > 0 {
gexp := ethutil.Big(test.Gas) gexp := ethutil.Big(test.Gas)
if gexp.Cmp(gas) != 0 { if gexp.Cmp(gas) != 0 {
t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas) t.Errorf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas)
} }
}
for addr, account := range test.Post { for addr, account := range test.Post {
obj := state.GetStateObject(helper.FromHex(addr)) obj := state.GetStateObject(helper.FromHex(addr))
@ -123,3 +162,23 @@ func TestVm(t *testing.T) {
const fn = "../files/vmtests/vmtests.json" const fn = "../files/vmtests/vmtests.json"
RunVmTest(fn, t) RunVmTest(fn, t)
} }
func TestStateSystemOperations(t *testing.T) {
const fn = "../files/StateTests/stSystemOperationsTest.json"
RunVmTest(fn, t)
}
func TestStatePreCompiledContracts(t *testing.T) {
const fn = "../files/StateTests/stPreCompiledContracts.json"
RunVmTest(fn, t)
}
func TestStateRecursiveCreate(t *testing.T) {
const fn = "../files/StateTests/stRecursiveCreate.json"
RunVmTest(fn, t)
}
func TestStateSpecialTest(t *testing.T) {
const fn = "../files/StateTests/stSpecialTest.json"
RunVmTest(fn, t)
}

View File

@ -31,12 +31,16 @@ func sha256Func(in []byte) []byte {
} }
func ripemd160Func(in []byte) []byte { func ripemd160Func(in []byte) []byte {
return ethutil.RightPadBytes(crypto.Ripemd160(in), 32) return ethutil.LeftPadBytes(crypto.Ripemd160(in), 32)
} }
func ecrecoverFunc(in []byte) []byte { func ecrecoverFunc(in []byte) []byte {
// In case of an invalid sig. Defaults to return nil // In case of an invalid sig. Defaults to return nil
defer func() { recover() }() defer func() { recover() }()
return crypto.Ecrecover(in) hash := in[:32]
v := ethutil.BigD(in[32:64]).Bytes()[0] - 27
sig := append(in[64:], v)
return crypto.Sha3(crypto.Ecrecover(append(hash, sig...))[1:])
} }

View File

@ -69,6 +69,7 @@ func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte,
if self.Gas.Cmp(p.Gas) >= 0 { if self.Gas.Cmp(p.Gas) >= 0 {
ret = p.Call(self.input) ret = p.Call(self.input)
self.vm.Printf("NATIVE_FUNC(%x) => %x", naddr, ret) self.vm.Printf("NATIVE_FUNC(%x) => %x", naddr, ret)
self.vm.Endl()
} }
} else { } else {
// Create a new callable closure // Create a new callable closure