From d0b31e203053f3f176e61719d877dcaa04169bb3 Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Tue, 27 May 2014 13:09:47 +0200
Subject: [PATCH] New debugger

---
 ethereal/assets/debugger/debugger.qml | 310 +++++++++++++++++---------
 ethereal/ui/debugger.go               |  55 ++++-
 ethereal/ui/ui_lib.go                 |  38 ----
 3 files changed, 258 insertions(+), 145 deletions(-)

diff --git a/ethereal/assets/debugger/debugger.qml b/ethereal/assets/debugger/debugger.qml
index b7d954e73..07a78411b 100644
--- a/ethereal/assets/debugger/debugger.qml
+++ b/ethereal/assets/debugger/debugger.qml
@@ -7,108 +7,210 @@ import QtQuick.Controls.Styles 1.1
 import Ethereum 1.0
 
 ApplicationWindow {
-	id: debugWindow
-	visible: false
-	title: "Debugger"
-	minimumWidth: 600
-	minimumHeight: 600
-	width: 800
-	height: 600
-
-	SplitView {
-		anchors.fill: parent
-		property var asmModel: ListModel {
-			id: asmModel
-		}
-		TableView {
-			id: asmTableView
-			width: 200
-			TableViewColumn{ role: "value" ; title: "" ; width: 100 }
-			model: asmModel
-		}
-
-		Rectangle {
-			anchors.left: asmTableView.right
-			anchors.right: parent.right
-			SplitView {
-				orientation: Qt.Vertical
-				anchors.fill: parent
-
-				TableView {
-					property var memModel: ListModel {
-						id: memModel
-					}
-					height: parent.height/2
-					width: parent.width
-					TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50}
-					TableViewColumn{ role: "value" ; title: "Memory" ; width: 750}
-					model: memModel
-				}
-
-				SplitView {
-					orientation: Qt.Horizontal
-					TableView {
-						property var debuggerLog: ListModel {
-							id: debuggerLog
-						}
-						TableViewColumn{ role: "value"; title: "Debug messages" }
-						model: debuggerLog
-					}
-					TableView {
-						property var stackModel: ListModel {
-							id: stackModel
-						}
-						height: parent.height/2
-						width: parent.width
-						TableViewColumn{ role: "value" ; title: "Stack" ; width: 200 }
-						model: stackModel
-					}
-				}
-			}
-		}
-	}
-	statusBar: StatusBar {
-		RowLayout {
-			anchors.fill: parent
-			Button {
-				property var enabled: true
-				id: debugNextButton
-				onClicked: {
-					//db.next()
-				}
-				text: "Next"
-			}
-		}
-	}
-
-	function setAsm(asm) {
-		asmModel.append({asm: asm})
-	}
-
-	function setInstruction(num) {
-		asmTableView.selection.clear()
-		asmTableView.selection.select(num-1)
-	}
-
-	function clearAsm() {
-		asmModel.clear()
-	}
-
-	function setMem(mem) {
-		memModel.append({num: mem.num, value: mem.value})
-	}
-	function clearMem(){
-		memModel.clear()
-	}
-
-	function setStack(stack) {
-		stackModel.append({value: stack})
-	}
-	function addDebugMessage(message){
-		debuggerLog.append({value: message})
-	}
-
-	function clearStack() {
-		stackModel.clear()
-	}
+    visible: false
+    title: "Debugger"
+    minimumWidth: 1280
+    minimumHeight: 900
+    width: 1290
+    height: 900
+
+    SplitView {
+        anchors.fill: parent
+        property var asmModel: ListModel {
+            id: asmModel
+        }
+        TableView {
+            id: asmTableView
+            width: 200
+            TableViewColumn{ role: "value" ; title: "" ; width: 100 }
+            model: asmModel
+        }
+
+        Rectangle {
+            color: "#00000000"
+            anchors.left: asmTableView.right
+            anchors.right: parent.right
+            SplitView {
+                orientation: Qt.Vertical
+                anchors.fill: parent
+
+                Rectangle {
+                    color: "#00000000"
+                    height: 500
+                    anchors.left: parent.left
+                    anchors.right: parent.right
+
+                    TextArea {
+                        id: codeEditor
+                        anchors.top: parent.top
+                        anchors.bottom: parent.bottom
+                        anchors.left: parent.left
+                        anchors.right: settings.left
+                    }
+
+                    Column {
+                        id: settings
+                        spacing: 5
+                        width: 300
+                        height: parent.height
+                        anchors.right: parent.right
+                        anchors.top: parent.top
+                        anchors.bottom: parent.bottom
+
+                        Label {
+                            text: "Data"
+                        }
+                        TextArea {
+                            anchors.left: parent.left
+                            anchors.right: parent.right
+                            height: 150
+                        }
+
+                        Label {
+                            text: "Amount"
+                        }
+                        TextField {
+                            id: txValue
+                            width: 200
+                            placeholderText: "Amount"
+                            validator: RegExpValidator { regExp: /\d*/ }
+                        }
+                        Label {
+                            text: "Amount of gas"
+                        }
+                        TextField {
+                            id: txGas
+                            width: 200
+                            validator: RegExpValidator { regExp: /\d*/ }
+                            text: "10000"
+                            placeholderText: "Gas"
+                        }
+                        Label {
+                            text: "Gas price"
+                        }
+                        TextField {
+                            id: txGasPrice
+                            width: 200
+                            placeholderText: "Gas price"
+                            text: "1000000000000"
+                            validator: RegExpValidator { regExp: /\d*/ }
+                        }
+                    }
+                }
+
+                SplitView {
+                    orientation: Qt.Vertical
+                    id: inspectorPane
+                    height: 500
+
+                    SplitView {
+                        orientation: Qt.Horizontal
+                        height: 300
+
+                        TableView {
+                            id: stackTableView
+                            property var stackModel: ListModel {
+                                id: stackModel
+                            }
+                            height: parent.height
+                            width: 300
+                            TableViewColumn{ role: "value" ; title: "Stack" ; width: 200 }
+                            model: stackModel
+                        }
+
+                        TableView {
+                            id: memoryTableView
+                            property var memModel: ListModel {
+                                id: memModel
+                            }
+                            height: parent.height
+                            width: parent.width - stackTableView.width
+                            TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50}
+                            TableViewColumn{ role: "value" ; title: "Memory" ; width: 750}
+                            model: memModel
+                        }
+                    }
+
+                    SplitView {
+                        height: 300
+                        TableView {
+                            id: storageTableView
+                            property var memModel: ListModel {
+                                id: storageModel
+                            }
+                            height: parent.height
+                            width: parent.width - stackTableView.width
+                            TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2}
+                            TableViewColumn{ role: "value" ; title: "value" ; width:  storageTableView.width / 2}
+                            model: storageModel
+                        }
+                    }
+                }
+            }
+        }
+    }
+    statusBar: StatusBar {
+        RowLayout {
+            spacing: 5
+            anchors.fill: parent
+
+            Button {
+                property var enabled: true
+                id: debugStart
+                onClicked: {
+                    dbg.debug(txValue.text, txGas.text, txGasPrice.text, codeEditor.text)
+                }
+                text: "Debug"
+            }
+
+            Button {
+                property var enabled: true
+                id: debugNextButton
+                onClicked: {
+                    dbg.next()
+                }
+                text: "Next"
+            }
+        }
+    }
+
+    function setAsm(asm) {
+        console.log("set asm", asm)
+        asmModel.append({asm: asm})
+    }
+
+    function setInstruction(num) {
+        asmTableView.selection.clear()
+        asmTableView.selection.select(num-1)
+    }
+
+    function clearAsm() {
+        asmModel.clear()
+    }
+
+    function setMem(mem) {
+        memModel.append({num: mem.num, value: mem.value})
+    }
+    function clearMem(){
+        memModel.clear()
+    }
+
+    function setStack(stack) {
+        stackModel.append({value: stack})
+    }
+    function addDebugMessage(message){
+        debuggerLog.append({value: message})
+    }
+
+    function clearStack() {
+        stackModel.clear()
+    }
+
+    function clearStorage() {
+        storageModel.clear()
+    }
+
+    function setStorage(storage) {
+        storageModel.append({key: storage.key, value: storage.value})
+    }
 }
diff --git a/ethereal/ui/debugger.go b/ethereal/ui/debugger.go
index 4debc05b2..ce2d73b9a 100644
--- a/ethereal/ui/debugger.go
+++ b/ethereal/ui/debugger.go
@@ -30,13 +30,16 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
 }
 
 func (self *DebuggerWindow) Show() {
+	context := self.engine.Context()
+	context.SetVar("dbg", self)
+
 	go func() {
 		self.win.Show()
 		self.win.Wait()
 	}()
 }
 
-func (self *DebuggerWindow) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) {
+func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, data string) {
 	state := self.lib.eth.BlockChain().CurrentBlock.State()
 
 	script, err := ethutil.Compile(data)
@@ -50,14 +53,14 @@ func (self *DebuggerWindow) DebugTx(recipient, valueStr, gasStr, gasPriceStr, da
 	self.lib.win.Root().Call("clearAsm")
 
 	for _, str := range dis {
-		self.lib.win.Root().Call("setAsm", str)
+		self.win.Root().Call("setAsm", str)
 	}
 	// Contract addr as test address
 	keyPair := ethutil.GetKeyRing().Get(0)
 	callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), script)
 	callerTx.Sign(keyPair.PrivateKey)
 
-	account := self.lib.eth.StateManager().TransState().GetStateObject(keyPair.Address())
+	account := self.lib.eth.StateManager().TransState().GetAccount(keyPair.Address())
 	contract := ethchain.MakeContract(callerTx, state)
 	callerClosure := ethchain.NewClosure(account, contract, contract.Init(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr))
 
@@ -84,3 +87,49 @@ func (self *DebuggerWindow) DebugTx(recipient, valueStr, gasStr, gasPriceStr, da
 func (self *DebuggerWindow) Next() {
 	self.Db.Next()
 }
+
+type Debugger struct {
+	win  *qml.Window
+	N    chan bool
+	done bool
+}
+
+type storeVal struct {
+	Key, Value string
+}
+
+func (d *Debugger) halting(pc int, op ethchain.OpCode, mem *ethchain.Memory, stack *ethchain.Stack, stateObject *ethchain.StateObject) {
+	d.win.Root().Call("setInstruction", pc)
+	d.win.Root().Call("clearMem")
+	d.win.Root().Call("clearStack")
+	d.win.Root().Call("clearStorage")
+
+	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())
+	}
+
+	stateObject.State().EachStorage(func(key string, node *ethutil.Value) {
+		d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())})
+	})
+
+out:
+	for {
+		select {
+		case <-d.N:
+			break out
+		default:
+		}
+	}
+}
+
+func (d *Debugger) Next() {
+	if !d.done {
+		d.N <- true
+	}
+}
diff --git a/ethereal/ui/ui_lib.go b/ethereal/ui/ui_lib.go
index c3f9f52e6..998392525 100644
--- a/ethereal/ui/ui_lib.go
+++ b/ethereal/ui/ui_lib.go
@@ -2,7 +2,6 @@ package ethui
 
 import (
 	"bitbucket.org/kardianos/osext"
-	"fmt"
 	"github.com/ethereum/eth-go"
 	"github.com/ethereum/eth-go/ethchain"
 	"github.com/ethereum/eth-go/ethutil"
@@ -171,40 +170,3 @@ func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string)
 func (ui *UiLib) Next() {
 	ui.Db.Next()
 }
-
-type Debugger struct {
-	win  *qml.Window
-	N    chan bool
-	done 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() {
-	if !d.done {
-		d.N <- true
-	}
-}
-- 
GitLab