aboutsummaryrefslogtreecommitdiffstats
path: root/ethvm/vm.go
diff options
context:
space:
mode:
Diffstat (limited to 'ethvm/vm.go')
-rw-r--r--ethvm/vm.go62
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)