Commit 93fcabd2 authored by obscuren's avatar obscuren

Fixed most of the tests

parent bb503869
...@@ -72,12 +72,6 @@ func (self *StateTransition) Receiver() *ethstate.StateObject { ...@@ -72,12 +72,6 @@ func (self *StateTransition) Receiver() *ethstate.StateObject {
return self.rec 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 { func (self *StateTransition) UseGas(amount *big.Int) error {
if self.gas.Cmp(amount) < 0 { if self.gas.Cmp(amount) < 0 {
return OutOfGasError() return OutOfGasError()
...@@ -190,7 +184,7 @@ func (self *StateTransition) TransitionState() (err error) { ...@@ -190,7 +184,7 @@ func (self *StateTransition) TransitionState() (err error) {
snapshot = self.state.Copy() snapshot = self.state.Copy()
// Create a new state object for the contract // Create a new state object for the contract
receiver = self.MakeStateObject(self.state, tx) receiver := MakeContract(tx, self.state)
self.rec = receiver self.rec = receiver
if receiver == nil { if receiver == nil {
return fmt.Errorf("Unable to create contract") return fmt.Errorf("Unable to create contract")
......
...@@ -29,3 +29,4 @@ func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty } ...@@ -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) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) Value() *big.Int { return self.tx.Value } func (self *VMEnv) Value() *big.Int { return self.tx.Value }
func (self *VMEnv) State() *ethstate.State { return self.state } 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 } ...@@ -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) BlockHash() []byte { return self.block.Hash() }
func (self *VMEnv) Value() *big.Int { return self.value } func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) State() *ethstate.State { return self.state } 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 { ...@@ -17,6 +17,7 @@ type Environment interface {
Time() int64 Time() int64
Difficulty() *big.Int Difficulty() *big.Int
BlockHash() []byte BlockHash() []byte
GasLimit() *big.Int
} }
type Object interface { type Object interface {
......
...@@ -10,21 +10,27 @@ import ( ...@@ -10,21 +10,27 @@ import (
type Execution struct { type Execution struct {
vm VirtualMachine vm VirtualMachine
closure *Closure
address, input []byte address, input []byte
gas, price, value *big.Int Gas, price, value *big.Int
object *ethstate.StateObject object *ethstate.StateObject
} }
func NewExecution(vm VirtualMachine, address, input []byte, gas, gasPrice, value *big.Int) *Execution { 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 { func (self *Execution) Addr() []byte {
return self.address 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() env := self.vm.Env()
snapshot := env.State().Copy() snapshot := env.State().Copy()
...@@ -44,7 +50,7 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err ...@@ -44,7 +50,7 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err
object := caller.Object() object := caller.Object()
if object.Balance.Cmp(self.value) < 0 { 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) err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, object.Balance)
} else { } else {
...@@ -55,23 +61,23 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err ...@@ -55,23 +61,23 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err
stateObject.AddAmount(self.value) stateObject.AddAmount(self.value)
// Pre-compiled contracts (address.go) 1, 2 & 3. // 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 p := Precompiled[naddr]; p != nil {
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)
} }
} else { } else {
// Create a new callable closure
c := NewClosure(msg, caller, stateObject, code, self.Gas, self.price)
c.exe = self
if self.vm.Depth() == MaxCallDepth { if self.vm.Depth() == MaxCallDepth {
return nil, fmt.Errorf("Max call depth exceeded (%d)", MaxCallDepth) c.UseGas(c.Gas)
}
// Retrieve the executing code return c.Return(nil), fmt.Errorf("Max call depth exceeded (%d)", MaxCallDepth)
code := env.State().GetCode(codeAddr) }
// 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) // Executer the closure and get the return value (if any)
ret, _, err = c.Call(self.vm, self.input) ret, _, err = c.Call(self.vm, self.input)
...@@ -81,3 +87,7 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err ...@@ -81,3 +87,7 @@ func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err
return 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) { ...@@ -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)) 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 { if self.Recoverable {
...@@ -440,14 +459,18 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { ...@@ -440,14 +459,18 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
case BYTE: case BYTE:
require(2) require(2)
val, th := stack.Popn() 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()])) byt := big.NewInt(int64(ethutil.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
stack.Push(byt)
self.Printf(" => 0x%x", byt.Bytes()) base.Set(byt)
} else { } else {
stack.Push(ethutil.BigFalse) base.Set(ethutil.BigFalse)
} }
self.Printf(" => 0x%x", base.Bytes())
stack.Push(base)
case ADDMOD: case ADDMOD:
require(3) require(3)
...@@ -562,7 +585,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { ...@@ -562,7 +585,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
mem.Set(mOff, l, code) mem.Set(mOff, l, code)
case CODESIZE, EXTCODESIZE: case CODESIZE, EXTCODESIZE:
var code []byte var code []byte
if op == EXTCODECOPY { if op == EXTCODESIZE {
addr := stack.Pop().Bytes() addr := stack.Pop().Bytes()
code = state.GetCode(addr) code = state.GetCode(addr)
...@@ -638,8 +661,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { ...@@ -638,8 +661,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" => 0x%x", difficulty.Bytes()) self.Printf(" => 0x%x", difficulty.Bytes())
case GASLIMIT: case GASLIMIT:
// TODO stack.Push(self.env.GasLimit())
stack.Push(big.NewInt(0))
// 0x50 range // 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: 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) { ...@@ -713,32 +735,21 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes()) self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
case JUMP: case JUMP:
require(1) 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 jump(stack.Pop())
self.Printf(" ~> %v", pc).Endl()
continue continue
case JUMPI: case JUMPI:
require(2) require(2)
cond, pos := stack.Popn() cond, pos := stack.Popn()
if cond.Cmp(ethutil.BigTrue) >= 0 {
pc = pos
if OpCode(closure.Get(pc).Uint()) != JUMPDEST { if cond.Cmp(ethutil.BigTrue) >= 0 {
panic(fmt.Sprintf("JUMP missed JUMPDEST %v", pc)) jump(pos)
}
continue continue
} else {
self.Printf(" (f)")
} }
case JUMPDEST: case JUMPDEST:
self.Printf(" ~> %v (t)", pc).Endl()
case PC: case PC:
stack.Push(pc) stack.Push(pc)
case MSIZE: case MSIZE:
...@@ -771,7 +782,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { ...@@ -771,7 +782,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
closure.UseGas(closure.Gas) closure.UseGas(closure.Gas)
msg := NewExecution(self, addr, input, gas, closure.Price, value) msg := NewExecution(self, addr, input, gas, closure.Price, value)
ret, err := msg.Exec(addr, closure) ret, err := msg.Create(closure)
if err != nil { if err != nil {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
...@@ -857,6 +868,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { ...@@ -857,6 +868,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
vmlogger.Debugf("(pc) %-3v Invalid opcode %x\n", pc, op) vmlogger.Debugf("(pc) %-3v Invalid opcode %x\n", pc, op)
//panic(fmt.Sprintf("Invalid opcode %x", op)) //panic(fmt.Sprintf("Invalid opcode %x", op))
closure.ReturnGas(big.NewInt(1), nil)
return closure.Return(nil), fmt.Errorf("Invalid opcode %x", op) return closure.Return(nil), fmt.Errorf("Invalid opcode %x", op)
} }
......
...@@ -9,9 +9,10 @@ import ( ...@@ -9,9 +9,10 @@ import (
) )
var Logger ethlog.LogSystem var Logger ethlog.LogSystem
var Log = ethlog.NewLogger("TEST")
func init() { 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) ethlog.AddLogSystem(Logger)
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "") ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
......
...@@ -18,6 +18,7 @@ type Env struct { ...@@ -18,6 +18,7 @@ type Env struct {
number *big.Int number *big.Int
time int64 time int64
difficulty *big.Int difficulty *big.Int
gasLimit *big.Int
} }
func NewEnv(state *ethstate.State) *Env { func NewEnv(state *ethstate.State) *Env {
...@@ -33,7 +34,9 @@ func NewEnvFromMap(state *ethstate.State, envValues map[string]string, exeValues ...@@ -33,7 +34,9 @@ func NewEnvFromMap(state *ethstate.State, envValues map[string]string, exeValues
env.parent = ethutil.Hex2Bytes(envValues["previousHash"]) env.parent = ethutil.Hex2Bytes(envValues["previousHash"])
env.coinbase = ethutil.Hex2Bytes(envValues["currentCoinbase"]) env.coinbase = ethutil.Hex2Bytes(envValues["currentCoinbase"])
env.number = ethutil.Big(envValues["currentNumber"]) 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 return env
} }
...@@ -46,14 +49,17 @@ func (self *Env) Time() int64 { return self.time } ...@@ -46,14 +49,17 @@ func (self *Env) Time() int64 { return self.time }
func (self *Env) Difficulty() *big.Int { return self.difficulty } func (self *Env) Difficulty() *big.Int { return self.difficulty }
func (self *Env) BlockHash() []byte { return nil } func (self *Env) BlockHash() []byte { return nil }
func (self *Env) State() *ethstate.State { return self.state } 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) { func RunVm(state *ethstate.State, env, exec map[string]string) ([]byte, *big.Int, error) {
caller := state.GetOrNewStateObject(ethutil.Hex2Bytes(exec["caller"])) address := FromHex(exec["address"])
callee := state.GetStateObject(ethutil.Hex2Bytes(exec["address"])) caller := state.GetOrNewStateObject(FromHex(exec["caller"]))
closure := ethvm.NewClosure(nil, caller, callee, callee.Code, ethutil.Big(exec["gas"]), ethutil.Big(exec["gasPrice"])) caller.Balance = ethutil.Big(exec["value"])
vm := ethvm.New(NewEnvFromMap(state, env, exec), ethvm.DebugVmTy) 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 ...@@ -2,7 +2,6 @@ package ethvm
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/ethereum/eth-go/ethstate" "github.com/ethereum/eth-go/ethstate"
...@@ -55,7 +54,7 @@ func RunVmTest(url string, t *testing.T) { ...@@ -55,7 +54,7 @@ func RunVmTest(url string, t *testing.T) {
// 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 {
fmt.Println(err) helper.Log.Infoln(err)
} }
/* /*
if err != nil { if err != nil {
...@@ -80,7 +79,7 @@ func RunVmTest(url string, t *testing.T) { ...@@ -80,7 +79,7 @@ func RunVmTest(url string, t *testing.T) {
vexp := helper.FromHex(value) vexp := helper.FromHex(value)
if bytes.Compare(v, vexp) != 0 { 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) { ...@@ -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. // 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) RunVmTest(url, t)
} }
func TestVMArithmetic(t *testing.T) { func TestVMSystemOperation(t *testing.T) {
helper.Logger.SetLogLevel(0) //helper.Logger.SetLogLevel(5)
defer helper.Logger.SetLogLevel(4) 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) RunVmTest(url, t)
} }
func TestVMSystemOperations(t *testing.T) { func TestPushDupSwap(t *testing.T) {
const url = "https://raw.githubusercontent.com/ethereum/tests/master/vmtests/vmSystemOperationsTest.json" 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) RunVmTest(url, t)
} }
func TestOperations(t *testing.T) { func TestVm(t *testing.T) {
t.Skip() const url = "https://raw.githubusercontent.com/ethereum/tests/develop/vmtests/vmtests.json"
const url = "https://raw.githubusercontent.com/ethereum/tests/master/vmtests/vmSystemOperationsTest.json"
RunVmTest(url, t) RunVmTest(url, t)
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment