All Stack requirements are now checked prior to reduring gas.

This commit is contained in:
obscuren 2014-10-23 10:14:55 +02:00
parent 29b8a0bc5f
commit 06aa74e7df

View File

@ -138,13 +138,31 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
addStepGasUsage(GasStep) addStepGasUsage(GasStep)
var newMemSize *big.Int = ethutil.Big0 var newMemSize *big.Int = ethutil.Big0
// Stack Check, memory resize & gas phase
switch op { switch op {
// Stack checks only
case NOT, CALLDATALOAD, POP, JUMP, NEG: // 1
require(1)
case ADD, SUB, DIV, SDIV, MOD, SMOD, EXP, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 2
require(2)
case ADDMOD, MULMOD: // 3
require(3)
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
n := int(op - SWAP1 + 2)
require(n)
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
n := int(op - DUP1 + 1)
require(n)
// Gas only
case STOP: case STOP:
gas.Set(ethutil.Big0) gas.Set(ethutil.Big0)
case SUICIDE: case SUICIDE:
require(1)
gas.Set(ethutil.Big0) gas.Set(ethutil.Big0)
case SLOAD: case SLOAD:
gas.Set(GasSLoad) gas.Set(GasSLoad)
// Memory resize & Gas
case SSTORE: case SSTORE:
var mult *big.Int var mult *big.Int
y, x := stack.Peekn() y, x := stack.Peekn()
@ -158,6 +176,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
} }
gas = new(big.Int).Mul(mult, GasSStore) gas = new(big.Int).Mul(mult, GasSStore)
case BALANCE: case BALANCE:
require(1)
gas.Set(GasBalance) gas.Set(GasBalance)
case MSTORE: case MSTORE:
require(2) require(2)
@ -239,7 +258,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
switch op { switch op {
// 0x20 range // 0x20 range
case ADD: case ADD:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v + %v", y, x) self.Printf(" %v + %v", y, x)
@ -251,7 +269,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// Pop result back on the stack // Pop result back on the stack
stack.Push(base) stack.Push(base)
case SUB: case SUB:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v - %v", y, x) self.Printf(" %v - %v", y, x)
@ -263,7 +280,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// Pop result back on the stack // Pop result back on the stack
stack.Push(base) stack.Push(base)
case MUL: case MUL:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v * %v", y, x) self.Printf(" %v * %v", y, x)
@ -275,7 +291,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// Pop result back on the stack // Pop result back on the stack
stack.Push(base) stack.Push(base)
case DIV: case DIV:
require(2)
x, y := stack.Pop(), stack.Pop() x, y := stack.Pop(), stack.Pop()
self.Printf(" %v / %v", x, y) self.Printf(" %v / %v", x, y)
@ -289,7 +304,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// Pop result back on the stack // Pop result back on the stack
stack.Push(base) stack.Push(base)
case SDIV: case SDIV:
require(2)
x, y := S256(stack.Pop()), S256(stack.Pop()) x, y := S256(stack.Pop()), S256(stack.Pop())
self.Printf(" %v / %v", x, y) self.Printf(" %v / %v", x, y)
@ -312,7 +326,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" = %v", base) self.Printf(" = %v", base)
stack.Push(base) stack.Push(base)
case MOD: case MOD:
require(2)
x, y := stack.Pop(), stack.Pop() x, y := stack.Pop(), stack.Pop()
self.Printf(" %v %% %v", x, y) self.Printf(" %v %% %v", x, y)
@ -328,7 +341,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" = %v", base) self.Printf(" = %v", base)
stack.Push(base) stack.Push(base)
case SMOD: case SMOD:
require(2)
x, y := S256(stack.Pop()), S256(stack.Pop()) x, y := S256(stack.Pop()), S256(stack.Pop())
self.Printf(" %v %% %v", x, y) self.Printf(" %v %% %v", x, y)
@ -352,7 +364,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(base) stack.Push(base)
case EXP: case EXP:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v ** %v", y, x) self.Printf(" %v ** %v", y, x)
@ -365,14 +376,12 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(base) stack.Push(base)
case NEG: case NEG:
require(1)
base.Sub(Pow256, stack.Pop()) base.Sub(Pow256, stack.Pop())
base = U256(base) base = U256(base)
stack.Push(base) stack.Push(base)
case LT: case LT:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v < %v", y, x) self.Printf(" %v < %v", y, x)
// x < y // x < y
@ -382,7 +391,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
} }
case GT: case GT:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v > %v", y, x) self.Printf(" %v > %v", y, x)
@ -394,7 +402,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
} }
case SLT: case SLT:
require(2)
y, x := S256(stack.Pop()), S256(stack.Pop()) y, x := S256(stack.Pop()), S256(stack.Pop())
self.Printf(" %v < %v", y, x) self.Printf(" %v < %v", y, x)
// x < y // x < y
@ -404,7 +411,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
} }
case SGT: case SGT:
require(2)
y, x := S256(stack.Pop()), S256(stack.Pop()) y, x := S256(stack.Pop()), S256(stack.Pop())
self.Printf(" %v > %v", y, x) self.Printf(" %v > %v", y, x)
@ -416,7 +422,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
} }
case EQ: case EQ:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v == %v", y, x) self.Printf(" %v == %v", y, x)
@ -427,7 +432,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
} }
case NOT: case NOT:
require(1)
x := stack.Pop() x := stack.Pop()
if x.Cmp(ethutil.BigFalse) > 0 { if x.Cmp(ethutil.BigFalse) > 0 {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
@ -437,25 +441,21 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// 0x10 range // 0x10 range
case AND: case AND:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v & %v", y, x) self.Printf(" %v & %v", y, x)
stack.Push(base.And(y, x)) stack.Push(base.And(y, x))
case OR: case OR:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v | %v", y, x) self.Printf(" %v | %v", y, x)
stack.Push(base.Or(y, x)) stack.Push(base.Or(y, x))
case XOR: case XOR:
require(2)
x, y := stack.Popn() x, y := stack.Popn()
self.Printf(" %v ^ %v", y, x) self.Printf(" %v ^ %v", y, x)
stack.Push(base.Xor(y, x)) stack.Push(base.Xor(y, x))
case BYTE: case BYTE:
require(2)
val, th := stack.Popn() val, th := stack.Popn()
if th.Cmp(big.NewInt(32)) < 0 { if th.Cmp(big.NewInt(32)) < 0 {
@ -470,7 +470,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(base) stack.Push(base)
case ADDMOD: case ADDMOD:
require(3)
x := stack.Pop() x := stack.Pop()
y := stack.Pop() y := stack.Pop()
@ -485,7 +484,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(base) stack.Push(base)
case MULMOD: case MULMOD:
require(3)
x := stack.Pop() x := stack.Pop()
y := stack.Pop() y := stack.Pop()
@ -502,7 +500,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// 0x20 range // 0x20 range
case SHA3: case SHA3:
require(2)
size, offset := stack.Popn() size, offset := stack.Popn()
data := ethcrypto.Sha3(mem.Get(offset.Int64(), size.Int64())) data := ethcrypto.Sha3(mem.Get(offset.Int64(), size.Int64()))
@ -515,7 +512,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" => %x", closure.Address()) self.Printf(" => %x", closure.Address())
case BALANCE: case BALANCE:
require(1)
addr := stack.Pop().Bytes() addr := stack.Pop().Bytes()
balance := state.GetBalance(addr) balance := state.GetBalance(addr)
@ -541,7 +537,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" => %v", value) self.Printf(" => %v", value)
case CALLDATALOAD: case CALLDATALOAD:
require(1)
var ( var (
offset = stack.Pop() offset = stack.Pop()
data = make([]byte, 32) data = make([]byte, 32)
@ -675,7 +670,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" => 0x%x", data.Bytes()) self.Printf(" => 0x%x", data.Bytes())
case POP: case POP:
require(1)
stack.Pop() stack.Pop()
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: 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 + 1)
@ -692,21 +686,18 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" => [%d] %x [0] %x", n, x.Bytes(), y.Bytes()) self.Printf(" => [%d] %x [0] %x", n, x.Bytes(), y.Bytes())
case MLOAD: case MLOAD:
require(1)
offset := stack.Pop() offset := stack.Pop()
val := ethutil.BigD(mem.Get(offset.Int64(), 32)) val := ethutil.BigD(mem.Get(offset.Int64(), 32))
stack.Push(val) stack.Push(val)
self.Printf(" => 0x%x", val.Bytes()) self.Printf(" => 0x%x", val.Bytes())
case MSTORE: // Store the value at stack top-1 in to memory at location stack top case MSTORE: // Store the value at stack top-1 in to memory at location stack top
require(2)
// Pop value of the stack // Pop value of the stack
val, mStart := stack.Popn() val, mStart := stack.Popn()
mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(val, 256)) mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(val, 256))
self.Printf(" => 0x%x", val) self.Printf(" => 0x%x", val)
case MSTORE8: case MSTORE8:
require(2)
off := stack.Pop() off := stack.Pop()
val := stack.Pop() val := stack.Pop()
@ -714,14 +705,12 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" => [%v] 0x%x", off, val) self.Printf(" => [%v] 0x%x", off, val)
case SLOAD: case SLOAD:
require(1)
loc := stack.Pop() loc := stack.Pop()
val := ethutil.BigD(state.GetState(closure.Address(), loc.Bytes())) val := ethutil.BigD(state.GetState(closure.Address(), loc.Bytes()))
stack.Push(val) stack.Push(val)
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes()) self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
case SSTORE: case SSTORE:
require(2)
val, loc := stack.Popn() val, loc := stack.Popn()
state.SetState(closure.Address(), loc.Bytes(), val) state.SetState(closure.Address(), loc.Bytes(), val)
@ -732,13 +721,11 @@ 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)
jump(stack.Pop()) jump(stack.Pop())
continue continue
case JUMPI: case JUMPI:
require(2)
cond, pos := stack.Popn() cond, pos := stack.Popn()
if cond.Cmp(ethutil.BigTrue) >= 0 { if cond.Cmp(ethutil.BigTrue) >= 0 {
@ -756,7 +743,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
stack.Push(closure.Gas) stack.Push(closure.Gas)
// 0x60 range // 0x60 range
case CREATE: case CREATE:
require(3)
var ( var (
err error err error
@ -801,8 +787,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Dbg.SetCode(closure.Code) self.Dbg.SetCode(closure.Code)
} }
case CALL, CALLCODE: case CALL, CALLCODE:
require(7)
self.Endl() self.Endl()
gas := stack.Pop() gas := stack.Pop()
@ -842,7 +826,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
} }
case RETURN: case RETURN:
require(2)
size, offset := stack.Popn() size, offset := stack.Popn()
ret := mem.Get(offset.Int64(), size.Int64()) ret := mem.Get(offset.Int64(), size.Int64())
@ -850,7 +833,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
return closure.Return(ret), nil return closure.Return(ret), nil
case SUICIDE: case SUICIDE:
require(1)
receiver := state.GetOrNewStateObject(stack.Pop().Bytes()) receiver := state.GetOrNewStateObject(stack.Pop().Bytes())