aboutsummaryrefslogtreecommitdiffstats
path: root/vm/vm_debug.go
diff options
context:
space:
mode:
Diffstat (limited to 'vm/vm_debug.go')
-rw-r--r--vm/vm_debug.go160
1 files changed, 82 insertions, 78 deletions
diff --git a/vm/vm_debug.go b/vm/vm_debug.go
index 544e04a5f..0a541a769 100644
--- a/vm/vm_debug.go
+++ b/vm/vm_debug.go
@@ -38,8 +38,23 @@ func NewDebugVm(env Environment) *DebugVm {
return &DebugVm{env: env, logTy: lt, Recoverable: true}
}
-func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
- self.depth++
+func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
+ self.env.SetDepth(self.env.Depth() + 1)
+
+ msg := self.env.State().Manifest().AddMessage(&state.Message{
+ To: me.Address(), From: caller.Address(),
+ Input: callData,
+ Origin: self.env.Origin(),
+ Block: self.env.BlockHash(), Timestamp: self.env.Time(), Coinbase: self.env.Coinbase(), Number: self.env.BlockNumber(),
+ Value: value,
+ })
+ closure := NewClosure(msg, caller, me, code, gas, price)
+
+ if self.env.Depth() == MaxCallDepth {
+ closure.UseGas(gas)
+
+ return closure.Return(nil), DepthError{}
+ }
if self.Recoverable {
// Recover from any require exception
@@ -60,35 +75,35 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
var (
op OpCode
- destinations = analyseJumpDests(closure.Code)
- mem = NewMemory()
- stack = NewStack()
- pc = big.NewInt(0)
- step = 0
- prevStep = 0
- statedb = self.env.State()
- require = func(m int) {
+ destinations = analyseJumpDests(closure.Code)
+ mem = NewMemory()
+ stack = NewStack()
+ pc uint64 = 0
+ step = 0
+ prevStep = 0
+ statedb = self.env.State()
+ require = func(m int) {
if stack.Len() < m {
panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m))
}
}
- jump = func(from, to *big.Int) {
- p := int(to.Int64())
+ jump = func(from uint64, to *big.Int) {
+ p := to.Uint64()
self.Printf(" ~> %v", to)
// Return to start
if p == 0 {
- pc = big.NewInt(0)
+ pc = 0
} else {
nop := OpCode(closure.GetOp(p))
- if !(nop == JUMPDEST || destinations[from.Int64()] != nil) {
+ if !(nop == JUMPDEST || destinations[from] != nil) {
panic(fmt.Sprintf("JUMP missed JUMPDEST (%v) %v", nop, p))
} else if nop == JUMP || nop == JUMPI {
panic(fmt.Sprintf("not allowed to JUMP(I) in to JUMP"))
}
- pc = to
+ pc = to.Uint64()
}
@@ -96,17 +111,12 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
}
)
- // Debug hook
- if self.Dbg != nil {
- self.Dbg.SetCode(closure.Code)
- }
-
// Don't bother with the execution if there's no code.
- if len(closure.Code) == 0 {
+ if len(code) == 0 {
return closure.Return(nil), nil
}
- vmlogger.Debugf("(%d) %x gas: %v (d) %x\n", self.depth, closure.Address(), closure.Gas, closure.Args)
+ vmlogger.Debugf("(%d) %x gas: %v (d) %x\n", self.depth, closure.Address(), closure.Gas, callData)
for {
prevStep = step
@@ -115,26 +125,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
step++
// Get the memory location of pc
- op = closure.GetOp(int(pc.Uint64()))
-
- // 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:
- statedb.GetStateObject(closure.Address()).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 {
- b = []byte{0}
- }
-
- fmt.Printf("%x %x %x %x\n", closure.Address(), b, []byte{byte(op)}, closure.Gas.Bytes())
- }
+ op = closure.GetOp(pc)
gas := new(big.Int)
addStepGasUsage := func(amount *big.Int) {
@@ -151,7 +142,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// Stack checks only
case ISZERO, CALLDATALOAD, POP, JUMP, NOT: // 1
require(1)
- case ADD, SUB, DIV, SDIV, MOD, SMOD, EXP, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 2
+ case ADD, SUB, DIV, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 2
require(2)
case ADDMOD, MULMOD: // 3
require(3)
@@ -165,10 +156,23 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
n := int(op - LOG0)
require(n + 2)
- mSize, mStart := stack.Peekn()
gas.Set(GasLog)
addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog))
- addStepGasUsage(new(big.Int).Add(mSize, mStart))
+
+ mSize, mStart := stack.Peekn()
+ addStepGasUsage(mSize)
+
+ newMemSize = calcMemSize(mStart, mSize)
+ case EXP:
+ require(2)
+
+ exp := new(big.Int).Set(stack.data[stack.Len()-2])
+ nbytes := 0
+ for exp.Cmp(ethutil.Big0) > 0 {
+ nbytes += 1
+ exp.Rsh(exp, 8)
+ }
+ gas.Set(big.NewInt(int64(nbytes + 1)))
// Gas only
case STOP:
gas.Set(ethutil.Big0)
@@ -255,6 +259,12 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
newMemSize.Div(newMemSize, u256(32))
newMemSize.Mul(newMemSize, u256(32))
+ switch op {
+ // Additional gas usage on *CODPY
+ case CALLDATACOPY, CODECOPY, EXTCODECOPY:
+ addStepGasUsage(new(big.Int).Div(newMemSize, u256(32)))
+ }
+
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len())))
memGasUsage.Mul(GasMemory, memGasUsage)
@@ -262,7 +272,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
addStepGasUsage(memGasUsage)
- mem.Resize(newMemSize.Uint64())
}
}
@@ -280,6 +289,8 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
return closure.Return(nil), OOG(gas, tmp)
}
+ mem.Resize(newMemSize.Uint64())
+
switch op {
// 0x20 range
case ADD:
@@ -576,8 +587,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" => %x", caller)
case CALLVALUE:
- value := closure.exe.value
-
stack.Push(value)
self.Printf(" => %v", value)
@@ -585,27 +594,27 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
var (
offset = stack.Pop()
data = make([]byte, 32)
- lenData = big.NewInt(int64(len(closure.Args)))
+ lenData = big.NewInt(int64(len(callData)))
)
if lenData.Cmp(offset) >= 0 {
length := new(big.Int).Add(offset, ethutil.Big32)
length = ethutil.BigMin(length, lenData)
- copy(data, closure.Args[offset.Int64():length.Int64()])
+ copy(data, callData[offset.Int64():length.Int64()])
}
self.Printf(" => 0x%x", data)
stack.Push(ethutil.BigD(data))
case CALLDATASIZE:
- l := int64(len(closure.Args))
+ l := int64(len(callData))
stack.Push(big.NewInt(l))
self.Printf(" => %d", l)
case CALLDATACOPY:
var (
- size = int64(len(closure.Args))
+ size = int64(len(callData))
mOff = stack.Pop().Int64()
cOff = stack.Pop().Int64()
l = stack.Pop().Int64()
@@ -618,11 +627,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
l = 0
}
- code := closure.Args[cOff : cOff+l]
+ code := callData[cOff : cOff+l]
mem.Set(mOff, l, code)
- self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, code[cOff:cOff+l])
+ self.Printf(" => [%v, %v, %v] %x", mOff, cOff, l, callData[cOff:cOff+l])
case CODESIZE, EXTCODESIZE:
var code []byte
if op == EXTCODESIZE {
@@ -707,13 +716,15 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// 0x50 range
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
- a := big.NewInt(int64(op) - int64(PUSH1) + 1)
- pc.Add(pc, ethutil.Big1)
- data := closure.Gets(pc, a)
+ //a := big.NewInt(int64(op) - int64(PUSH1) + 1)
+ a := uint64(op - PUSH1 + 1)
+ //pc.Add(pc, ethutil.Big1)
+ data := closure.GetRangeValue(pc+1, a)
val := ethutil.BigD(data.Bytes())
// Push value to stack
stack.Push(val)
- pc.Add(pc, a.Sub(a, big.NewInt(1)))
+ pc += a
+ //pc.Add(pc, a.Sub(a, big.NewInt(1)))
step += int(op) - int(PUSH1) + 1
@@ -722,13 +733,9 @@ func (self *DebugVm) 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)
- v := stack.Dupn(n)
+ 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)
@@ -737,13 +744,13 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0)
topics := make([][]byte, n)
- mStart, mSize := stack.Pop().Int64(), stack.Pop().Int64()
+ mSize, mStart := stack.Pop().Int64(), stack.Pop().Int64()
data := mem.Geti(mStart, mSize)
for i := 0; i < n; i++ {
- topics[i] = stack.Pop().Bytes()
+ topics[i] = ethutil.LeftPadBytes(stack.Pop().Bytes(), 32)
}
- log := &state.Log{closure.Address(), topics, data}
+ log := &Log{closure.Address(), topics, data}
self.env.AddLog(log)
self.Printf(" => %v", log)
@@ -783,7 +790,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
case JUMP:
-
jump(pc, stack.Pop())
continue
@@ -798,13 +804,14 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
case JUMPDEST:
case PC:
- stack.Push(pc)
+ stack.Push(big.NewInt(int64(pc)))
case MSIZE:
stack.Push(big.NewInt(int64(mem.Len())))
case GAS:
stack.Push(closure.Gas)
// 0x60 range
case CREATE:
+
var (
err error
value = stack.Pop()
@@ -826,17 +833,14 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
closure.UseGas(closure.Gas)
- msg := NewExecution(self, addr, input, gas, closure.Price, value)
- ret, err := msg.Create(closure)
+ ret, err, ref := self.env.Create(closure, addr, input, gas, price, value)
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 {
- msg.object.Code = ret
+ ref.SetCode(ret)
+ msg.Output = ret
stack.Push(ethutil.BigD(addr))
}
@@ -868,14 +872,14 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
executeAddr = addr.Bytes()
}
- msg := NewExecution(self, executeAddr, args, gas, closure.Price, value)
- ret, err := msg.Exec(addr.Bytes(), closure)
+ ret, err := self.env.Call(closure, executeAddr, args, gas, price, value)
if err != nil {
stack.Push(ethutil.BigFalse)
vmlogger.Debugln(err)
} else {
stack.Push(ethutil.BigTrue)
+ msg.Output = ret
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
}
@@ -914,13 +918,13 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
return closure.Return(nil), fmt.Errorf("Invalid opcode %x", op)
}
- pc.Add(pc, ethutil.Big1)
+ pc++
self.Endl()
if self.Dbg != nil {
for _, instrNo := range self.Dbg.BreakPoints() {
- if pc.Cmp(big.NewInt(instrNo)) == 0 {
+ if pc == uint64(instrNo) {
self.Stepping = true
if !self.Dbg.BreakHook(prevStep, op, mem, stack, statedb.GetStateObject(closure.Address())) {