From d9d4f63cd4e3c9388ea8425e9d41f63af030c77c Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Fri, 22 Aug 2014 17:57:33 +0200 Subject: Don't add ... --- ethvm/vm.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index 873a80c44..347ebcfe6 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -631,12 +631,12 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { require(1) stack.Pop() case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: - n := int(op - DUP1 + 1) + n := int(op - DUP1) stack.Dupn(n) self.Printf(" => [%d] 0x%x", n, stack.Peek().Bytes()) case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: - n := int(op - SWAP1 + 1) + n := int(op - SWAP1) x, y := stack.Swapn(n) self.Printf(" => [%d] %x [0] %x", n, x.Bytes(), y.Bytes()) -- cgit v1.2.3 From 3f904bf3acb5779f68834ebca95825ea1990f85b Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Mon, 25 Aug 2014 11:29:42 +0200 Subject: Implemented POST --- ethvm/vm.go | 261 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 191 insertions(+), 70 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index 347ebcfe6..924a861ca 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -1,6 +1,7 @@ package ethvm import ( + "container/list" "fmt" "math" "math/big" @@ -18,11 +19,6 @@ type Debugger interface { } type Vm struct { - // Stack for processing contracts - stack *Stack - // non-persistent key/value memory storage - mem map[string]*big.Int - env Environment Verbose bool @@ -40,6 +36,8 @@ type Vm struct { Fn string Recoverable bool + + queue *list.List } type Environment interface { @@ -66,7 +64,7 @@ func New(env Environment) *Vm { lt = LogTyDiff } - return &Vm{env: env, logTy: lt, Recoverable: true} + return &Vm{env: env, logTy: lt, Recoverable: true, queue: list.New()} } func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { @@ -215,6 +213,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { newMemSize = stack.data[stack.Len()-2].Uint64() + stack.data[stack.Len()-3].Uint64() } + // BUG This will break on overflows. https://github.com/ethereum/eth-go/issues/47 newMemSize = (newMemSize + 31) / 32 * 32 if newMemSize > uint64(mem.Len()) { m := GasMemory.Uint64() * (newMemSize - uint64(mem.Len())) / 32 @@ -711,6 +710,8 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { err error value = stack.Pop() size, offset = stack.Popn() + input = mem.Get(offset.Int64(), size.Int64()) + gas = new(big.Int).Set(closure.Gas) // Snapshot the current stack so we are able to // revert back to it later. @@ -726,37 +727,10 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { self.Printf(" (*) %x", addr).Endl() - msg := self.env.State().Manifest().AddMessage(ðstate.Message{ - To: addr, From: closure.Address(), - Origin: self.env.Origin(), - Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(), - Value: value, - }) - - // Create a new contract - contract := self.env.State().NewStateObject(addr) - if contract.Balance.Cmp(value) >= 0 { - closure.object.SubAmount(value) - contract.AddAmount(value) - - // Set the init script - initCode := mem.Get(offset.Int64(), size.Int64()) - msg.Input = initCode - - // Transfer all remaining gas to the new - // contract so it may run the init script - gas := new(big.Int).Set(closure.Gas) - closure.UseGas(closure.Gas) - - // Create the closure - c := NewClosure(msg, closure, contract, initCode, gas, closure.Price) - // Call the closure and set the return value as - // main script. - contract.Code, _, err = c.Call(self, nil) - } else { - err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Balance) - } + closure.UseGas(closure.Gas) + msg := NewMessage(self, addr, input, gas, closure.Price, value) + ret, err := msg.Exec(closure) if err != nil { stack.Push(ethutil.BigFalse) @@ -765,10 +739,55 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { self.Printf("CREATE err %v", err) } else { - stack.Push(ethutil.BigD(addr)) + msg.object.Code = ret - msg.Output = contract.Code + stack.Push(ethutil.BigD(addr)) } + /* + msg := self.env.State().Manifest().AddMessage(ðstate.Message{ + To: addr, From: closure.Address(), + Origin: self.env.Origin(), + Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(), + Value: value, + }) + + // Create a new contract + contract := self.env.State().NewStateObject(addr) + if contract.Balance.Cmp(value) >= 0 { + closure.object.SubAmount(value) + contract.AddAmount(value) + + // Set the init script + initCode := mem.Get(offset.Int64(), size.Int64()) + msg.Input = initCode + + // Transfer all remaining gas to the new + // contract so it may run the init script + gas := new(big.Int).Set(closure.Gas) + closure.UseGas(closure.Gas) + + // Create the closure + c := NewClosure(msg, closure, contract, initCode, gas, closure.Price) + // Call the closure and set the return value as + // main script. + contract.Code, _, err = c.Call(self, nil) + } else { + err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Balance) + } + + if err != nil { + stack.Push(ethutil.BigFalse) + + // Revert the state as it was before. + self.env.State().Set(snapshot) + + self.Printf("CREATE err %v", err) + } else { + stack.Push(ethutil.BigD(addr)) + + msg.Output = contract.Code + } + */ self.Endl() // Debug hook @@ -791,51 +810,88 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { // Get the arguments from the memory args := mem.Get(inOffset.Int64(), inSize.Int64()) - msg := self.env.State().Manifest().AddMessage(ðstate.Message{ - To: addr.Bytes(), From: closure.Address(), - Input: args, - Origin: self.env.Origin(), - Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(), - Value: value, - }) - - if closure.object.Balance.Cmp(value) < 0 { - vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Balance) - - closure.ReturnGas(gas, nil) + snapshot := self.env.State().Copy() + msg := NewMessage(self, addr.Bytes(), args, gas, closure.Price, value) + ret, err := msg.Exec(closure) + if err != nil { stack.Push(ethutil.BigFalse) + + self.env.State().Set(snapshot) } else { - snapshot := self.env.State().Copy() + stack.Push(ethutil.BigTrue) + + mem.Set(retOffset.Int64(), retSize.Int64(), ret) + } + + // Debug hook + if self.Dbg != nil { + self.Dbg.SetCode(closure.Code) + } - stateObject := self.env.State().GetOrNewStateObject(addr.Bytes()) + /* + msg := self.env.State().Manifest().AddMessage(ðstate.Message{ + To: addr.Bytes(), From: closure.Address(), + Input: args, + Origin: self.env.Origin(), + Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(), + Value: value, + }) - closure.object.SubAmount(value) - stateObject.AddAmount(value) + if closure.object.Balance.Cmp(value) < 0 { + vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Balance) + + closure.ReturnGas(gas, nil) - // Create a new callable closure - c := NewClosure(msg, closure, stateObject, stateObject.Code, gas, closure.Price) - // Executer the closure and get the return value (if any) - ret, _, err := c.Call(self, args) - if err != nil { stack.Push(ethutil.BigFalse) + } else { + snapshot := self.env.State().Copy() - vmlogger.Debugf("Closure execution failed. %v\n", err) + stateObject := self.env.State().GetOrNewStateObject(addr.Bytes()) - self.env.State().Set(snapshot) - } else { - stack.Push(ethutil.BigTrue) + closure.object.SubAmount(value) + stateObject.AddAmount(value) - mem.Set(retOffset.Int64(), retSize.Int64(), ret) - } + // Create a new callable closure + c := NewClosure(msg, closure, stateObject, stateObject.Code, gas, closure.Price) + // Executer the closure and get the return value (if any) + ret, _, err := c.Call(self, args) + if err != nil { + stack.Push(ethutil.BigFalse) - msg.Output = ret + vmlogger.Debugf("Closure execution failed. %v\n", err) - // Debug hook - if self.Dbg != nil { - self.Dbg.SetCode(closure.Code) + self.env.State().Set(snapshot) + } else { + stack.Push(ethutil.BigTrue) + + mem.Set(retOffset.Int64(), retSize.Int64(), ret) + } + + msg.Output = ret + + // Debug hook + if self.Dbg != nil { + self.Dbg.SetCode(closure.Code) + } } - } + */ + case POST: + require(6) + + self.Endl() + + gas := stack.Pop() + // Pop gas and value of the stack. + value, addr := stack.Popn() + // Pop input size and offset + inSize, inOffset := stack.Popn() + // Get the arguments from the memory + args := mem.Get(inOffset.Int64(), inSize.Int64()) + + msg := NewMessage(self, addr.Bytes(), args, gas, closure.Price, value) + + msg.Postpone() case RETURN: require(2) size, offset := stack.Popn() @@ -887,6 +943,10 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { } } +func (self *Vm) Queue() *list.List { + return self.queue +} + func (self *Vm) Printf(format string, v ...interface{}) *Vm { if self.Verbose && self.logTy == LogTyPretty { self.logStr += fmt.Sprintf(format, v...) @@ -918,3 +978,64 @@ func ensure256(x *big.Int) { x.SetInt64(0) } } + +type Message struct { + vm *Vm + closure *Closure + address, input []byte + gas, price, value *big.Int + object *ethstate.StateObject +} + +func NewMessage(vm *Vm, address, input []byte, gas, gasPrice, value *big.Int) *Message { + return &Message{vm: vm, address: address, input: input, gas: gas, price: gasPrice, value: value} +} + +func (self *Message) Postpone() { + self.vm.queue.PushBack(self) +} + +func (self *Message) Exec(caller ClosureRef) (ret []byte, err error) { + queue := self.vm.queue + self.vm.queue = list.New() + + defer func() { + if err == nil { + queue.PushBackList(self.vm.queue) + } + + self.vm.queue = queue + }() + + msg := self.vm.env.State().Manifest().AddMessage(ðstate.Message{ + To: self.address, From: caller.Address(), + Input: self.input, + Origin: self.vm.env.Origin(), + Block: self.vm.env.BlockHash(), Timestamp: self.vm.env.Time(), Coinbase: self.vm.env.Coinbase(), Number: self.vm.env.BlockNumber(), + Value: self.value, + }) + + object := caller.Object() + if object.Balance.Cmp(self.value) < 0 { + caller.ReturnGas(self.gas, self.price) + + err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, object.Balance) + } else { + stateObject := self.vm.env.State().GetOrNewStateObject(self.address) + self.object = stateObject + + caller.Object().SubAmount(self.value) + stateObject.AddAmount(self.value) + + // Create a new callable closure + c := NewClosure(msg, caller, object, object.Code, self.gas, self.price) + // Executer the closure and get the return value (if any) + ret, _, err = c.Call(self.vm, self.input) + + msg.Output = ret + + return ret, err + } + + return +} -- cgit v1.2.3 From a63b74e345e83d08b7a85b0602c5087ca4b06075 Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Mon, 8 Sep 2014 00:49:25 +0200 Subject: New OPCODES * EXT- CODECOPY, CODESIZE --- ethvm/vm.go | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index 924a861ca..2acf52f92 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -197,6 +197,10 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { require(3) newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64() + case EXTCODECOPY: + require(4) + + newMemSize = stack.data[stack.Len()-1].Uint64() + stack.data[stack.Len()-4].Uint64() case CALL: require(7) gas.Set(GasCall) @@ -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) -- cgit v1.2.3 From 29499900160cc2ee88968b74035f0a5c2d4c5af6 Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Wed, 10 Sep 2014 00:19:20 +0200 Subject: Added CALLSTATELESS --- ethvm/vm.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index 2acf52f92..9518540e0 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -201,7 +201,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { require(4) newMemSize = stack.data[stack.Len()-1].Uint64() + stack.data[stack.Len()-4].Uint64() - case CALL: + case CALL, CALLSTATELESS: require(7) gas.Set(GasCall) addStepGasUsage(stack.data[stack.Len()-1]) @@ -752,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) @@ -816,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() @@ -834,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) @@ -1017,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() @@ -1049,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) -- cgit v1.2.3 From c0187930dc352c645c223e17364623a68413cb74 Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Wed, 10 Sep 2014 11:39:11 +0200 Subject: Removed some commented code --- ethvm/vm.go | 91 ------------------------------------------------------------- 1 file changed, 91 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index 9518540e0..fba8c4a0e 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -765,51 +765,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { stack.Push(ethutil.BigD(addr)) } - /* - msg := self.env.State().Manifest().AddMessage(ðstate.Message{ - To: addr, From: closure.Address(), - Origin: self.env.Origin(), - Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(), - Value: value, - }) - - // Create a new contract - contract := self.env.State().NewStateObject(addr) - if contract.Balance.Cmp(value) >= 0 { - closure.object.SubAmount(value) - contract.AddAmount(value) - - // Set the init script - initCode := mem.Get(offset.Int64(), size.Int64()) - msg.Input = initCode - - // Transfer all remaining gas to the new - // contract so it may run the init script - gas := new(big.Int).Set(closure.Gas) - closure.UseGas(closure.Gas) - - // Create the closure - c := NewClosure(msg, closure, contract, initCode, gas, closure.Price) - // Call the closure and set the return value as - // main script. - contract.Code, _, err = c.Call(self, nil) - } else { - err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Balance) - } - - if err != nil { - stack.Push(ethutil.BigFalse) - - // Revert the state as it was before. - self.env.State().Set(snapshot) - - self.Printf("CREATE err %v", err) - } else { - stack.Push(ethutil.BigD(addr)) - msg.Output = contract.Code - } - */ self.Endl() // Debug hook @@ -858,53 +814,6 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { self.Dbg.SetCode(closure.Code) } - /* - msg := self.env.State().Manifest().AddMessage(ðstate.Message{ - To: addr.Bytes(), From: closure.Address(), - Input: args, - Origin: self.env.Origin(), - Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(), - Value: value, - }) - - if closure.object.Balance.Cmp(value) < 0 { - vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Balance) - - closure.ReturnGas(gas, nil) - - stack.Push(ethutil.BigFalse) - } else { - snapshot := self.env.State().Copy() - - stateObject := self.env.State().GetOrNewStateObject(addr.Bytes()) - - closure.object.SubAmount(value) - stateObject.AddAmount(value) - - // Create a new callable closure - c := NewClosure(msg, closure, stateObject, stateObject.Code, gas, closure.Price) - // Executer the closure and get the return value (if any) - ret, _, err := c.Call(self, args) - if err != nil { - stack.Push(ethutil.BigFalse) - - vmlogger.Debugf("Closure execution failed. %v\n", err) - - self.env.State().Set(snapshot) - } else { - stack.Push(ethutil.BigTrue) - - mem.Set(retOffset.Int64(), retSize.Int64(), ret) - } - - msg.Output = ret - - // Debug hook - if self.Dbg != nil { - self.Dbg.SetCode(closure.Code) - } - } - */ case POST: require(6) -- cgit v1.2.3 From 2f614900e82036e3e8f6f6a714efc43e09aca830 Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Mon, 15 Sep 2014 01:11:01 +0200 Subject: Updated GHOST --- ethvm/vm.go | 57 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 20 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index fba8c4a0e..2c516f4f8 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -3,7 +3,6 @@ package ethvm import ( "container/list" "fmt" - "math" "math/big" "github.com/ethereum/eth-go/ethcrypto" @@ -67,6 +66,19 @@ func New(env Environment) *Vm { return &Vm{env: env, logTy: lt, Recoverable: true, queue: list.New()} } +func calcMemSize(off, l *big.Int) *big.Int { + if l.Cmp(ethutil.Big0) == 0 { + return ethutil.Big0 + } + + return new(big.Int).Add(off, l) +} + +// Simple helper +func u256(n int64) *big.Int { + return big.NewInt(n) +} + func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { if self.Recoverable { // Recover from any require exception @@ -147,7 +159,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { addStepGasUsage(GasStep) - var newMemSize uint64 = 0 + var newMemSize *big.Int = ethutil.Big0 switch op { case STOP: gas.Set(ethutil.Big0) @@ -171,57 +183,62 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { gas.Set(GasBalance) case MSTORE: require(2) - newMemSize = stack.Peek().Uint64() + 32 + newMemSize = calcMemSize(stack.Peek(), u256(32)) case MLOAD: require(1) - newMemSize = stack.Peek().Uint64() + 32 + newMemSize = calcMemSize(stack.Peek(), u256(32)) case MSTORE8: require(2) - newMemSize = stack.Peek().Uint64() + 1 + newMemSize = calcMemSize(stack.Peek(), u256(1)) case RETURN: require(2) - newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-2].Uint64() + newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) case SHA3: require(2) gas.Set(GasSha) - newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-2].Uint64() + newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) case CALLDATACOPY: require(3) - newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64() + newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) case CODECOPY: require(3) - newMemSize = stack.Peek().Uint64() + stack.data[stack.Len()-3].Uint64() + newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) case EXTCODECOPY: require(4) - newMemSize = stack.data[stack.Len()-1].Uint64() + stack.data[stack.Len()-4].Uint64() + newMemSize = calcMemSize(stack.data[stack.Len()-1], stack.data[stack.Len()-4]) case CALL, CALLSTATELESS: require(7) gas.Set(GasCall) addStepGasUsage(stack.data[stack.Len()-1]) - x := stack.data[stack.Len()-6].Uint64() + stack.data[stack.Len()-7].Uint64() - y := stack.data[stack.Len()-4].Uint64() + stack.data[stack.Len()-5].Uint64() + x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7]) + y := calcMemSize(stack.data[stack.Len()-4], stack.data[stack.Len()-5]) - newMemSize = uint64(math.Max(float64(x), float64(y))) + newMemSize = ethutil.BigMax(x, y) case CREATE: require(3) gas.Set(GasCreate) - newMemSize = stack.data[stack.Len()-2].Uint64() + stack.data[stack.Len()-3].Uint64() + newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3]) } - // BUG This will break on overflows. https://github.com/ethereum/eth-go/issues/47 - newMemSize = (newMemSize + 31) / 32 * 32 - if newMemSize > uint64(mem.Len()) { - m := GasMemory.Uint64() * (newMemSize - uint64(mem.Len())) / 32 - addStepGasUsage(big.NewInt(int64(m))) + if newMemSize.Cmp(ethutil.Big0) > 0 { + //newMemSize = (newMemSize + 31) / 32 * 32 + newMemSize = newMemSize.Add(newMemSize, u256(31)).Div(newMemSize, u256(32)).Mul(newMemSize, u256(32)) + //if newMemSize > uint64(mem.Len()) { + if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { + newMemSize = newMemSize.Sub(newMemSize, u256(int64(mem.Len()))) + memGasUsage := newMemSize.Mul(GasMemory, newMemSize).Div(newMemSize, u256(32)) + //m := GasMemory.Uint64() * (newMemSize - uint64(mem.Len())) / 32 + addStepGasUsage(memGasUsage) + } } if !closure.UseGas(gas) { @@ -235,7 +252,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { self.Printf("(pc) %-3d -o- %-14s", pc, op.String()) self.Printf(" (g) %-3v (%v)", gas, closure.Gas) - mem.Resize(newMemSize) + mem.Resize(newMemSize.Uint64()) switch op { case LOG: -- cgit v1.2.3 From 399256b38403f2e95312250d49fca3cada8956b8 Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Mon, 15 Sep 2014 22:11:05 +0200 Subject: VM execution fixes Refactoring caused executing issues --- ethvm/vm.go | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index 2c516f4f8..cfba3820b 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -63,7 +63,7 @@ func New(env Environment) *Vm { lt = LogTyDiff } - return &Vm{env: env, logTy: lt, Recoverable: true, queue: list.New()} + return &Vm{env: env, logTy: lt, Recoverable: false, queue: list.New()} } func calcMemSize(off, l *big.Int) *big.Int { @@ -132,15 +132,13 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { // XXX Leave this Println intact. Don't change this to the log system. // Used for creating diffs between implementations if self.logTy == LogTyDiff { - /* - switch op { - case STOP, RETURN, SUICIDE: - closure.object.EachStorage(func(key string, value *ethutil.Value) { - value.Decode() - fmt.Printf("%x %x\n", new(big.Int).SetBytes([]byte(key)).Bytes(), value.Bytes()) - }) - } - */ + switch op { + case STOP, RETURN, SUICIDE: + closure.object.EachStorage(func(key string, value *ethutil.Value) { + value.Decode() + fmt.Printf("%x %x\n", new(big.Int).SetBytes([]byte(key)).Bytes(), value.Bytes()) + }) + } b := pc.Bytes() if len(b) == 0 { @@ -230,13 +228,15 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { } if newMemSize.Cmp(ethutil.Big0) > 0 { - //newMemSize = (newMemSize + 31) / 32 * 32 - newMemSize = newMemSize.Add(newMemSize, u256(31)).Div(newMemSize, u256(32)).Mul(newMemSize, u256(32)) - //if newMemSize > uint64(mem.Len()) { + newMemSize.Add(newMemSize, u256(31)) + newMemSize.Div(newMemSize, u256(32)) + newMemSize.Mul(newMemSize, u256(32)) + if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { - newMemSize = newMemSize.Sub(newMemSize, u256(int64(mem.Len()))) - memGasUsage := newMemSize.Mul(GasMemory, newMemSize).Div(newMemSize, u256(32)) - //m := GasMemory.Uint64() * (newMemSize - uint64(mem.Len())) / 32 + memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len()))) + memGasUsage.Mul(GasMemory, memGasUsage) + memGasUsage.Div(memGasUsage, u256(32)) + addStepGasUsage(memGasUsage) } } @@ -669,12 +669,12 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { require(1) stack.Pop() case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: - n := int(op - DUP1) + n := int(op - DUP1 + 1) stack.Dupn(n) self.Printf(" => [%d] 0x%x", n, stack.Peek().Bytes()) case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: - n := int(op - SWAP1) + n := int(op - SWAP1 + 2) x, y := stack.Swapn(n) self.Printf(" => [%d] %x [0] %x", n, x.Bytes(), y.Bytes()) @@ -694,12 +694,12 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { self.Printf(" => 0x%x", val) case MSTORE8: require(2) - val, mStart := stack.Popn() - //base.And(val, new(big.Int).SetInt64(0xff)) - //mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(base, 256)) - mem.store[mStart.Int64()] = byte(val.Int64() & 0xff) + off := stack.Pop() + val := stack.Pop() - self.Printf(" => 0x%x", val) + mem.store[off.Int64()] = byte(val.Int64() & 0xff) + + self.Printf(" => [%v] 0x%x", off, val) case SLOAD: require(1) loc := stack.Pop() @@ -955,6 +955,7 @@ func (self *Message) Addr() []byte { } func (self *Message) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err error) { + fmt.Printf("%x %x\n", codeAddr[0:4], self.address[0:4]) queue := self.vm.queue self.vm.queue = list.New() @@ -990,7 +991,7 @@ func (self *Message) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err e code := self.vm.env.State().GetCode(codeAddr) // Create a new callable closure - c := NewClosure(msg, caller, object, code, self.gas, self.price) + c := NewClosure(msg, caller, stateObject, code, self.gas, self.price) // Executer the closure and get the return value (if any) ret, _, err = c.Call(self.vm, self.input) -- cgit v1.2.3 From d02024929a3e617c16c5b33e1d245f23fa4f6c7b Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Tue, 16 Sep 2014 11:35:26 +0200 Subject: require 5 for post --- ethvm/vm.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index cfba3820b..2a4fddbc5 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -63,7 +63,7 @@ func New(env Environment) *Vm { lt = LogTyDiff } - return &Vm{env: env, logTy: lt, Recoverable: false, queue: list.New()} + return &Vm{env: env, logTy: lt, Recoverable: true, queue: list.New()} } func calcMemSize(off, l *big.Int) *big.Int { @@ -200,7 +200,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) case CALLDATACOPY: - require(3) + require(2) newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) case CODECOPY: @@ -210,7 +210,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { case EXTCODECOPY: require(4) - newMemSize = calcMemSize(stack.data[stack.Len()-1], stack.data[stack.Len()-4]) + newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4]) case CALL, CALLSTATELESS: require(7) gas.Set(GasCall) @@ -832,7 +832,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { } case POST: - require(6) + require(5) self.Endl() @@ -872,6 +872,9 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { default: vmlogger.Debugf("(pc) %-3v Invalid opcode %x\n", pc, op) + // XXX Really? + closure.UseGas(closure.Gas) + return closure.Return(nil), fmt.Errorf("Invalid opcode %x", op) } -- cgit v1.2.3 From f3a93b046e45a293b673a955959666ec5389c4eb Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Thu, 18 Sep 2014 01:02:15 +0200 Subject: Upped protocol version for VM change --- ethvm/vm.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index 2a4fddbc5..f1c23b370 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -872,8 +872,7 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { default: vmlogger.Debugf("(pc) %-3v Invalid opcode %x\n", pc, op) - // XXX Really? - closure.UseGas(closure.Gas) + //panic(fmt.Sprintf("Invalid opcode %x", op)) return closure.Return(nil), fmt.Errorf("Invalid opcode %x", op) } -- cgit v1.2.3 From 80261c803a82e51413608a3dc5273c982844d135 Mon Sep 17 00:00:00 2001 From: obscuren <geffobscura@gmail.com> Date: Fri, 19 Sep 2014 13:19:19 +0200 Subject: Fixed deref ptr --- ethvm/vm.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'ethvm/vm.go') diff --git a/ethvm/vm.go b/ethvm/vm.go index f1c23b370..7aff320f9 100644 --- a/ethvm/vm.go +++ b/ethvm/vm.go @@ -670,9 +670,13 @@ func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { stack.Pop() case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: n := int(op - DUP1 + 1) - stack.Dupn(n) + v := stack.Dupn(n) self.Printf(" => [%d] 0x%x", n, stack.Peek().Bytes()) + + if OpCode(closure.Get(new(big.Int).Add(pc, ethutil.Big1)).Uint()) == POP && OpCode(closure.Get(new(big.Int).Add(pc, big.NewInt(2))).Uint()) == POP { + fmt.Println(toValue(v)) + } case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: n := int(op - SWAP1 + 2) x, y := stack.Swapn(n) @@ -1004,3 +1008,14 @@ func (self *Message) Exec(codeAddr []byte, caller ClosureRef) (ret []byte, err e return } + +// Mainly used for print variables and passing to Print* +func toValue(val *big.Int) interface{} { + // Let's assume a string on right padded zero's + b := val.Bytes() + if b[0] != 0 && b[len(b)-1] == 0x0 && b[len(b)-2] == 0x0 { + return string(b) + } + + return val +} -- cgit v1.2.3