Fixed most of the tests

pull/150/head
obscuren 10 years ago
parent bb5038699e
commit 93fcabd251
  1. 8
      ethchain/state_transition.go
  2. 1
      ethchain/vm_env.go
  3. 1
      ethpipe/vm_env.go
  4. 1
      ethvm/environment.go
  5. 38
      ethvm/execution.go
  6. 58
      ethvm/vm_debug.go
  7. 3
      tests/helper/init.go
  8. 18
      tests/helper/vm.go
  9. 51
      tests/vm/gh_test.go

@ -72,12 +72,6 @@ func (self *StateTransition) Receiver() *ethstate.StateObject {
return self.rec
}
func (self *StateTransition) MakeStateObject(state *ethstate.State, tx *Transaction) *ethstate.StateObject {
contract := MakeContract(tx, state)
return contract
}
func (self *StateTransition) UseGas(amount *big.Int) error {
if self.gas.Cmp(amount) < 0 {
return OutOfGasError()
@ -190,7 +184,7 @@ func (self *StateTransition) TransitionState() (err error) {
snapshot = self.state.Copy()
// Create a new state object for the contract
receiver = self.MakeStateObject(self.state, tx)
receiver := MakeContract(tx, self.state)
self.rec = receiver
if receiver == nil {
return fmt.Errorf("Unable to create contract")

@ -29,3 +29,4 @@ func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) Value() *big.Int { return self.tx.Value }
func (self *VMEnv) State() *ethstate.State { return self.state }
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }

@ -32,3 +32,4 @@ func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty }
func (self *VMEnv) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) State() *ethstate.State { return self.state }
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit }

@ -17,6 +17,7 @@ type Environment interface {
Time() int64
Difficulty() *big.Int
BlockHash() []byte
GasLimit() *big.Int
}
type Object interface {

@ -10,21 +10,27 @@ import (
type Execution struct {
vm VirtualMachine
closure *Closure
address, input []byte
gas, price, value *big.Int
Gas, price, value *big.Int
object *ethstate.StateObject
}
func NewExecution(vm VirtualMachine, address, input []byte, gas, gasPrice, value *big.Int) *Execution {
return &Execution{vm: vm, address: address, input: input, gas: gas, price: gasPrice, value: value}
return &Execution{vm: vm, address: address, input: input, Gas: gas, price: gasPrice, value: value}
}
func (self *Execution) Addr() []byte {
return self.address
}
func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err error) {
func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) ([]byte, error) {
// Retrieve the executing code
code := self.vm.Env().State().GetCode(codeAddr)
return self.exec(code, codeAddr, caller)
}
func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte, err error) {
env := self.vm.Env()
snapshot := env.State().Copy()
@ -44,7 +50,7 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err
object := caller.Object()
if object.Balance.Cmp(self.value) < 0 {
caller.ReturnGas(self.gas, self.price)
caller.ReturnGas(self.Gas, self.price)
err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, object.Balance)
} else {
@ -55,23 +61,23 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err
stateObject.AddAmount(self.value)
// Pre-compiled contracts (address.go) 1, 2 & 3.
naddr := ethutil.BigD(codeAddr).Uint64()
naddr := ethutil.BigD(caddr).Uint64()
if p := Precompiled[naddr]; p != nil {
if self.gas.Cmp(p.Gas) >= 0 {
if self.Gas.Cmp(p.Gas) >= 0 {
ret = p.Call(self.input)
self.vm.Printf("NATIVE_FUNC(%x) => %x", naddr, ret)
}
} else {
// Create a new callable closure
c := NewClosure(msg, caller, stateObject, code, self.Gas, self.price)
c.exe = self
if self.vm.Depth() == MaxCallDepth {
return nil, fmt.Errorf("Max call depth exceeded (%d)", MaxCallDepth)
}
c.UseGas(c.Gas)
// Retrieve the executing code
code := env.State().GetCode(codeAddr)
return c.Return(nil), fmt.Errorf("Max call depth exceeded (%d)", MaxCallDepth)
}
// Create a new callable closure
c := NewClosure(msg, caller, stateObject, code, self.gas, self.price)
c.exe = self
// Executer the closure and get the return value (if any)
ret, _, err = c.Call(self.vm, self.input)
@ -81,3 +87,7 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err
return
}
func (self *Execution) Create(caller ClosureRef) (ret []byte, err error) {
return self.exec(self.input, nil, caller)
}

@ -54,6 +54,25 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m))
}
}
jump = func(pos *big.Int) {
p := int(pos.Int64())
self.Printf(" ~> %v", pos)
// Return to start
if p == 0 {
pc = big.NewInt(0)
} else {
nop := OpCode(closure.GetOp(p - 1))
if nop != JUMPDEST {
panic(fmt.Sprintf("JUMP missed JUMPDEST (%v) %v", nop, p))
}
pc = pos
}
self.Endl()
}
)
if self.Recoverable {
@ -440,14 +459,18 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
case BYTE:
require(2)
val, th := stack.Popn()
if th.Cmp(big.NewInt(32)) < 0 && th.Cmp(big.NewInt(int64(len(val.Bytes())))) < 0 {
if th.Cmp(big.NewInt(32)) < 0 {
byt := big.NewInt(int64(ethutil.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
stack.Push(byt)
self.Printf(" => 0x%x", byt.Bytes())
base.Set(byt)
} else {
stack.Push(ethutil.BigFalse)
base.Set(ethutil.BigFalse)
}
self.Printf(" => 0x%x", base.Bytes())
stack.Push(base)
case ADDMOD:
require(3)
@ -562,7 +585,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
mem.Set(mOff, l, code)
case CODESIZE, EXTCODESIZE:
var code []byte
if op == EXTCODECOPY {
if op == EXTCODESIZE {
addr := stack.Pop().Bytes()
code = state.GetCode(addr)
@ -638,8 +661,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" => 0x%x", difficulty.Bytes())
case GASLIMIT:
// TODO
stack.Push(big.NewInt(0))
stack.Push(self.env.GasLimit())
// 0x50 range
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
@ -713,32 +735,21 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
case JUMP:
require(1)
pc = stack.Pop()
if OpCode(closure.Get(pc).Uint()) != JUMPDEST {
panic(fmt.Sprintf("JUMP missed JUMPDEST %v", pc))
}
// Reduce pc by one because of the increment that's at the end of this for loop
self.Printf(" ~> %v", pc).Endl()
jump(stack.Pop())
continue
case JUMPI:
require(2)
cond, pos := stack.Popn()
if cond.Cmp(ethutil.BigTrue) >= 0 {
pc = pos
if OpCode(closure.Get(pc).Uint()) != JUMPDEST {
panic(fmt.Sprintf("JUMP missed JUMPDEST %v", pc))
}
if cond.Cmp(ethutil.BigTrue) >= 0 {
jump(pos)
continue
} else {
self.Printf(" (f)")
}
case JUMPDEST:
self.Printf(" ~> %v (t)", pc).Endl()
case PC:
stack.Push(pc)
case MSIZE:
@ -771,7 +782,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
closure.UseGas(closure.Gas)
msg := NewExecution(self, addr, input, gas, closure.Price, value)
ret, err := msg.Exec(addr, closure)
ret, err := msg.Create(closure)
if err != nil {
stack.Push(ethutil.BigFalse)
@ -857,6 +868,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
vmlogger.Debugf("(pc) %-3v Invalid opcode %x\n", pc, op)
//panic(fmt.Sprintf("Invalid opcode %x", op))
closure.ReturnGas(big.NewInt(1), nil)
return closure.Return(nil), fmt.Errorf("Invalid opcode %x", op)
}

@ -9,9 +9,10 @@ import (
)
var Logger ethlog.LogSystem
var Log = ethlog.NewLogger("TEST")
func init() {
Logger = ethlog.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlog.LogLevel(4))
Logger = ethlog.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlog.LogLevel(0))
ethlog.AddLogSystem(Logger)
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")

@ -18,6 +18,7 @@ type Env struct {
number *big.Int
time int64
difficulty *big.Int
gasLimit *big.Int
}
func NewEnv(state *ethstate.State) *Env {
@ -33,7 +34,9 @@ func NewEnvFromMap(state *ethstate.State, envValues map[string]string, exeValues
env.parent = ethutil.Hex2Bytes(envValues["previousHash"])
env.coinbase = ethutil.Hex2Bytes(envValues["currentCoinbase"])
env.number = ethutil.Big(envValues["currentNumber"])
env.time = ethutil.Big(envValues["currentTime"]).Int64()
env.time = ethutil.Big(envValues["currentTimestamp"]).Int64()
env.difficulty = ethutil.Big(envValues["currentDifficulty"])
env.gasLimit = ethutil.Big(envValues["currentGasLimit"])
return env
}
@ -46,14 +49,17 @@ func (self *Env) Time() int64 { return self.time }
func (self *Env) Difficulty() *big.Int { return self.difficulty }
func (self *Env) BlockHash() []byte { return nil }
func (self *Env) State() *ethstate.State { return self.state }
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
func RunVm(state *ethstate.State, env, exec map[string]string) ([]byte, *big.Int, error) {
caller := state.GetOrNewStateObject(ethutil.Hex2Bytes(exec["caller"]))
callee := state.GetStateObject(ethutil.Hex2Bytes(exec["address"]))
closure := ethvm.NewClosure(nil, caller, callee, callee.Code, ethutil.Big(exec["gas"]), ethutil.Big(exec["gasPrice"]))
address := FromHex(exec["address"])
caller := state.GetOrNewStateObject(FromHex(exec["caller"]))
caller.Balance = ethutil.Big(exec["value"])
vm := ethvm.New(NewEnvFromMap(state, env, exec), ethvm.DebugVmTy)
ret, _, e := closure.Call(vm, nil)
return ret, closure.Gas, e
execution := ethvm.NewExecution(vm, address, FromHex(exec["data"]), ethutil.Big(exec["gas"]), ethutil.Big(exec["gasPrice"]), ethutil.Big(exec["value"]))
ret, err := execution.Exec(address, caller)
return ret, execution.Gas, err
}

@ -2,7 +2,6 @@ package ethvm
import (
"bytes"
"fmt"
"testing"
"github.com/ethereum/eth-go/ethstate"
@ -55,7 +54,7 @@ func RunVmTest(url string, t *testing.T) {
// When an error is returned it doesn't always mean the tests fails.
// Have to come up with some conditional failing mechanism.
if err != nil {
fmt.Println(err)
helper.Log.Infoln(err)
}
/*
if err != nil {
@ -80,7 +79,7 @@ func RunVmTest(url string, t *testing.T) {
vexp := helper.FromHex(value)
if bytes.Compare(v, vexp) != 0 {
t.Errorf("%s's : (%x: %s) storage failed. Expected %x, got %x\n", name, obj.Address()[0:4], addr, vexp, v)
t.Errorf("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address()[0:4], addr, vexp, v, ethutil.BigD(vexp), ethutil.BigD(v))
}
}
}
@ -88,29 +87,49 @@ func RunVmTest(url string, t *testing.T) {
}
// I've created a new function for each tests so it's easier to identify where the problem lies if any of them fail.
func TestVMSha3(t *testing.T) {
helper.Logger.SetLogLevel(0)
defer helper.Logger.SetLogLevel(4)
const url = "https://raw.githubusercontent.com/ethereum/tests/master/vmtests/vmSha3Test.json"
func TestVMArithmetic(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmArithmeticTest.json"
RunVmTest(url, t)
}
func TestVMArithmetic(t *testing.T) {
helper.Logger.SetLogLevel(0)
defer helper.Logger.SetLogLevel(4)
func TestVMSystemOperation(t *testing.T) {
//helper.Logger.SetLogLevel(5)
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmSystemOperationsTest.json"
RunVmTest(url, t)
}
func TestBitwiseLogicOperation(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmBitwiseLogicOperationTest.json"
RunVmTest(url, t)
}
func TestBlockInfo(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmBlockInfoTest.json"
RunVmTest(url, t)
}
func TestEnvironmentalInfo(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmEnvironmentalInfoTest.json"
RunVmTest(url, t)
}
const url = "https://raw.githubusercontent.com/ethereum/tests/master/vmtests/vmArithmeticTest.json"
func TestFlowOperation(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmIOandFlowOperationsTest.json"
RunVmTest(url, t)
}
func TestVMSystemOperations(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/master/vmtests/vmSystemOperationsTest.json"
func TestPushDupSwap(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmPushDupSwapTest.json"
RunVmTest(url, t)
}
func TestVMSha3(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmSha3Test.json"
RunVmTest(url, t)
}
func TestOperations(t *testing.T) {
t.Skip()
const url = "https://raw.githubusercontent.com/ethereum/tests/master/vmtests/vmSystemOperationsTest.json"
func TestVm(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmtests.json"
RunVmTest(url, t)
}

Loading…
Cancel
Save