diff --git a/core/execution.go b/core/execution.go index 8f2b5bee12..be45eeeb46 100644 --- a/core/execution.go +++ b/core/execution.go @@ -59,7 +59,11 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret snapshot := env.State().Copy() start := time.Now() - ret, err = evm.Run(to, caller, code, self.value, self.Gas, self.price, self.input) + + context := vm.NewContext(caller, to, self.value, self.Gas, self.price) + context.SetCallCode(contextAddr, code) + + ret, err = evm.Run(context, self.input) //self.value, self.Gas, self.price, self.input) chainlogger.Debugf("vm took %v\n", time.Since(start)) if err != nil { env.State().Set(snapshot) diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go index 959f204630..1e8cd5b51c 100644 --- a/tests/vm/gh_test.go +++ b/tests/vm/gh_test.go @@ -116,7 +116,6 @@ func RunVmTest(p string, t *testing.T) { } else { ret, logs, gas, err = helper.RunState(statedb, env, test.Transaction) } - statedb.Sync() rexp := helper.FromHex(test.Out) if bytes.Compare(rexp, ret) != 0 { @@ -157,6 +156,7 @@ func RunVmTest(p string, t *testing.T) { } if !isVmTest { + statedb.Sync() if !bytes.Equal(ethutil.Hex2Bytes(test.PostStateRoot), statedb.Root()) { t.Errorf("%s's : Post state root error. Expected %s, got %x", name, test.PostStateRoot, statedb.Root()) } diff --git a/vm/common.go b/vm/common.go index b391bb8c25..1cb549228f 100644 --- a/vm/common.go +++ b/vm/common.go @@ -1,6 +1,7 @@ package vm import ( + "math" "math/big" "github.com/ethereum/go-ethereum/ethutil" @@ -117,3 +118,10 @@ func toValue(val *big.Int) interface{} { return val } + +func getCode(code []byte, start, size uint64) []byte { + x := uint64(math.Min(float64(start), float64(len(code)))) + y := uint64(math.Min(float64(x+size), float64(len(code)))) + + return ethutil.RightPadBytes(code[x:y], int(size)) +} diff --git a/vm/context.go b/vm/context.go index 9ce07bc4a4..78712f5619 100644 --- a/vm/context.go +++ b/vm/context.go @@ -15,21 +15,24 @@ type ContextRef interface { type Context struct { caller ContextRef - object ContextRef - Code []byte + self ContextRef - Gas, UsedGas, Price *big.Int + Code []byte + CodeAddr []byte + + value, Gas, UsedGas, Price *big.Int Args []byte } // Create a new context for the given data items -func NewContext(caller ContextRef, object ContextRef, code []byte, gas, price *big.Int) *Context { - c := &Context{caller: caller, object: object, Code: code, Args: nil} +func NewContext(caller ContextRef, object ContextRef, value, gas, price *big.Int) *Context { + c := &Context{caller: caller, self: object, Args: nil} // Gas should be a pointer so it can safely be reduced through the run // This pointer will be off the state transition c.Gas = gas //new(big.Int).Set(gas) + c.value = new(big.Int).Set(value) // In most cases price and value are pointers to transaction objects // and we don't want the transaction's values to change. c.Price = new(big.Int).Set(price) @@ -62,10 +65,7 @@ func (c *Context) GetRangeValue(x, size uint64) []byte { } func (c *Context) GetCode(x, size uint64) []byte { - x = uint64(math.Min(float64(x), float64(len(c.Code)))) - y := uint64(math.Min(float64(x+size), float64(len(c.Code)))) - - return ethutil.RightPadBytes(c.Code[x:y], int(size)) + return getCode(c.Code, x, size) } func (c *Context) Return(ret []byte) []byte { @@ -101,9 +101,14 @@ func (c *Context) ReturnGas(gas, price *big.Int) { * Set / Get */ func (c *Context) Address() []byte { - return c.object.Address() + return c.self.Address() } func (self *Context) SetCode(code []byte) { self.Code = code } + +func (self *Context) SetCallCode(addr, code []byte) { + self.Code = code + self.CodeAddr = addr +} diff --git a/vm/virtual_machine.go b/vm/virtual_machine.go index 23ac4878f6..6db284f425 100644 --- a/vm/virtual_machine.go +++ b/vm/virtual_machine.go @@ -1,10 +1,8 @@ package vm -import "math/big" - type VirtualMachine interface { Env() Environment - Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, data []byte) ([]byte, error) + Run(context *Context, data []byte) ([]byte, error) Printf(string, ...interface{}) VirtualMachine Endl() VirtualMachine } diff --git a/vm/vm.go b/vm/vm.go index a818ac47df..58aebeedb2 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -32,10 +32,17 @@ func New(env Environment) *Vm { return &Vm{debug: Debug, env: env, logTy: lt, Recoverable: true} } -func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) { +func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) { + //func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) { self.env.SetDepth(self.env.Depth() + 1) - context := NewContext(caller, me, code, gas, price) + //context := NewContext(caller, me, code, gas, price) + var ( + caller = context.caller + code = context.Code + value = context.value + price = context.Price + ) self.Printf("(%d) (%x) %x (code=%d) gas: %v (d) %x", self.env.Depth(), caller.Address()[:4], context.Address(), len(code), context.Gas, callData).Endl() @@ -55,7 +62,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I }() } - if p := Precompiled[string(me.Address())]; p != nil { + if p := Precompiled[string(context.CodeAddr)]; p != nil { return self.RunPrecompiled(p, callData, context) } @@ -352,7 +359,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I z := stack.pop() if z.Cmp(Zero) > 0 { - add := U256(new(big.Int).Add(x, y)) + add := new(big.Int).Add(x, y) base.Mod(add, z) base = U256(base) @@ -362,13 +369,12 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I stack.push(base) case MULMOD: - x := stack.pop() y := stack.pop() z := stack.pop() - mul := new(big.Int).Mul(x, y) - if len(z.Bytes()) > 0 { // NOT 0x0 + if z.Cmp(Zero) > 0 { + mul := new(big.Int).Mul(x, y) base.Mod(mul, z) U256(base) @@ -476,13 +482,12 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I } else { code = context.Code } - context := NewContext(nil, nil, code, ethutil.Big0, ethutil.Big0) var ( mOff = stack.pop().Uint64() cOff = stack.pop().Uint64() l = stack.pop().Uint64() ) - codeCopy := context.GetCode(cOff, l) + codeCopy := getCode(code, cOff, l) mem.Set(mOff, l, codeCopy)