diff options
Diffstat (limited to 'ethvm/vm.go')
-rw-r--r-- | ethvm/vm.go | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/ethvm/vm.go b/ethvm/vm.go index 924a861ca..9518540e0 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -197,7 +197,11 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { require(3) newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64() - case CALL: + case EXTCODECOPY: + require(4) + + newMemSize = stack.data[stack.Len()-1].Uint64() + stack.data[stack.Len()-4].Uint64() + case CALL, CALLSTATELESS: require(7) gas.Set(GasCall) addStepGasUsage(stack.data[stack.Len()-1]) @@ -550,14 +554,32 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { code := closure.Args[cOff : cOff+l] mem.Set(mOff, l, code) - case CODESIZE: - l := big.NewInt(int64(len(closure.Code))) + case CODESIZE, EXTCODESIZE: + var code []byte + if op == EXTCODECOPY { + addr := stack.Pop().Bytes() + + code = self.env.State().GetCode(addr) + } else { + code = closure.Code + } + + l := big.NewInt(int64(len(code))) stack.Push(l) self.Printf(" => %d", l) - case CODECOPY: + case CODECOPY, EXTCODECOPY: + var code []byte + if op == EXTCODECOPY { + addr := stack.Pop().Bytes() + + code = self.env.State().GetCode(addr) + } else { + code = closure.Code + } + var ( - size = int64(len(closure.Code)) + size = int64(len(code)) mOff = stack.Pop().Int64() cOff = stack.Pop().Int64() l = stack.Pop().Int64() @@ -570,9 +592,9 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { l = 0 } - code := closure.Code[cOff : cOff+l] + codeCopy := code[cOff : cOff+l] - mem.Set(mOff, l, code) + mem.Set(mOff, l, codeCopy) case GASPRICE: stack.Push(closure.Price) @@ -730,7 +752,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { closure.UseGas(closure.Gas) msg := NewMessage(self, addr, input, gas, closure.Price, value) - ret, err := msg.Exec(closure) + ret, err := msg.Exec(addr, closure) if err != nil { stack.Push(ethutil.BigFalse) @@ -794,7 +816,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { if self.Dbg != nil { self.Dbg.SetCode(closure.Code) } - case CALL: + case CALL, CALLSTATELESS: require(7) self.Endl() @@ -812,8 +834,15 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { snapshot := self.env.State().Copy() - msg := NewMessage(self, addr.Bytes(), args, gas, closure.Price, value) - ret, err := msg.Exec(closure) + var executeAddr []byte + if op == CALLSTATELESS { + executeAddr = closure.Address() + } else { + executeAddr = addr.Bytes() + } + + msg := NewMessage(self, executeAddr, args, gas, closure.Price, value) + ret, err := msg.Exec(addr.Bytes(), closure) if err != nil { stack.Push(ethutil.BigFalse) @@ -995,7 +1024,11 @@ func (self *Message) Postpone() { self.vm.queue.PushBack(self) } -func (self *Message) Exec(caller ClosureRef) (ret []byte, err error) { +func (self *Message) Addr() []byte { + return self.address +} + +func (self *Message) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err error) { queue := self.vm.queue self.vm.queue = list.New() @@ -1027,8 +1060,11 @@ func (self *Message) Exec(caller ClosureRef) (ret []byte, err error) { caller.Object().SubAmount(self.value) stateObject.AddAmount(self.value) + // Retrieve the executing code + code := self.vm.env.State().GetCode(codeAddr) + // Create a new callable closure - c := NewClosure(msg, caller, object, object.Code, self.gas, self.price) + c := NewClosure(msg, caller, object, code, self.gas, self.price) // Executer the closure and get the return value (if any) ret, _, err = c.Call(self.vm, self.input) |