|
|
|
@ -16,6 +16,11 @@ import ( |
|
|
|
|
"strings" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type memAddr struct { |
|
|
|
|
Num string |
|
|
|
|
Value string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// UI Library that has some basic functionality exposed
|
|
|
|
|
type UiLib struct { |
|
|
|
|
engine *qml.Engine |
|
|
|
@ -24,6 +29,7 @@ type UiLib struct { |
|
|
|
|
assetPath string |
|
|
|
|
// The main application window
|
|
|
|
|
win *qml.Window |
|
|
|
|
Db *Debugger |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib { |
|
|
|
@ -89,48 +95,11 @@ func DefaultAssetPath() string { |
|
|
|
|
return base |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type memAddr struct { |
|
|
|
|
Num string |
|
|
|
|
Value string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type Debugger struct { |
|
|
|
|
ui *UiLib |
|
|
|
|
next chan bool |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (d *Debugger) halting(op ethchain.OpCode, mem *ethchain.Memory, stack *ethchain.Stack) { |
|
|
|
|
d.ui.win.Root().Call("clearMem") |
|
|
|
|
d.ui.win.Root().Call("clearStack") |
|
|
|
|
|
|
|
|
|
addr := 0 |
|
|
|
|
for i := 0; i+32 <= mem.Len(); i += 32 { |
|
|
|
|
d.ui.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("% x", mem.Data()[i:i+32])}) |
|
|
|
|
addr++ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, val := range stack.Data() { |
|
|
|
|
d.ui.win.Root().Call("setStack", val.String()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
out: |
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case <-d.next: |
|
|
|
|
break out |
|
|
|
|
default: |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (d *Debugger) Next() { |
|
|
|
|
d.next <- true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) { |
|
|
|
|
state := ui.eth.BlockChain().CurrentBlock.State() |
|
|
|
|
|
|
|
|
|
asm, err := mutan.Compile(strings.NewReader(data), false) |
|
|
|
|
mainInput, _ := ethutil.PreProcess(data) |
|
|
|
|
asm, err := mutan.Compile(strings.NewReader(mainInput), false) |
|
|
|
|
if err != nil { |
|
|
|
|
fmt.Println(err) |
|
|
|
|
} |
|
|
|
@ -160,11 +129,47 @@ func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) |
|
|
|
|
TxData: nil, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
db := &Debugger{ui, make(chan bool)} |
|
|
|
|
ui.engine.Context().SetVar("db", db) |
|
|
|
|
go func() { |
|
|
|
|
callerClosure.Call(vm, nil, db.halting) |
|
|
|
|
callerClosure.Call(vm, nil, ui.Db.halting) |
|
|
|
|
|
|
|
|
|
state.Reset() |
|
|
|
|
}() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (ui *UiLib) Next() { |
|
|
|
|
ui.Db.Next() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type Debugger struct { |
|
|
|
|
win *qml.Window |
|
|
|
|
N chan bool |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (d *Debugger) halting(pc int, op ethchain.OpCode, mem *ethchain.Memory, stack *ethchain.Stack) { |
|
|
|
|
d.win.Root().Call("setInstruction", pc) |
|
|
|
|
d.win.Root().Call("clearMem") |
|
|
|
|
d.win.Root().Call("clearStack") |
|
|
|
|
|
|
|
|
|
addr := 0 |
|
|
|
|
for i := 0; i+32 <= mem.Len(); i += 32 { |
|
|
|
|
d.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("% x", mem.Data()[i:i+32])}) |
|
|
|
|
addr++ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, val := range stack.Data() { |
|
|
|
|
d.win.Root().Call("setStack", val.String()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
out: |
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case <-d.N: |
|
|
|
|
break out |
|
|
|
|
default: |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (d *Debugger) Next() { |
|
|
|
|
d.N <- true |
|
|
|
|
} |
|
|
|
|