New debugger
This commit is contained in:
		
							parent
							
								
									4fd267a778
								
							
						
					
					
						commit
						d0b31e2030
					
				| @ -7,108 +7,210 @@ import QtQuick.Controls.Styles 1.1 | |||||||
| import Ethereum 1.0 | import Ethereum 1.0 | ||||||
| 
 | 
 | ||||||
| ApplicationWindow { | ApplicationWindow { | ||||||
| 	id: debugWindow |     visible: false | ||||||
| 	visible: false |     title: "Debugger" | ||||||
| 	title: "Debugger" |     minimumWidth: 1280 | ||||||
| 	minimumWidth: 600 |     minimumHeight: 900 | ||||||
| 	minimumHeight: 600 |     width: 1290 | ||||||
| 	width: 800 |     height: 900 | ||||||
| 	height: 600 |  | ||||||
| 
 | 
 | ||||||
| 	SplitView { |     SplitView { | ||||||
| 		anchors.fill: parent |         anchors.fill: parent | ||||||
| 		property var asmModel: ListModel { |         property var asmModel: ListModel { | ||||||
| 			id: asmModel |             id: asmModel | ||||||
| 		} |         } | ||||||
| 		TableView { |         TableView { | ||||||
| 			id: asmTableView |             id: asmTableView | ||||||
| 			width: 200 |             width: 200 | ||||||
| 			TableViewColumn{ role: "value" ; title: "" ; width: 100 } |             TableViewColumn{ role: "value" ; title: "" ; width: 100 } | ||||||
| 			model: asmModel |             model: asmModel | ||||||
| 		} |         } | ||||||
| 
 | 
 | ||||||
| 		Rectangle { |         Rectangle { | ||||||
| 			anchors.left: asmTableView.right |             color: "#00000000" | ||||||
| 			anchors.right: parent.right |             anchors.left: asmTableView.right | ||||||
| 			SplitView { |             anchors.right: parent.right | ||||||
| 				orientation: Qt.Vertical |             SplitView { | ||||||
| 				anchors.fill: parent |                 orientation: Qt.Vertical | ||||||
|  |                 anchors.fill: parent | ||||||
| 
 | 
 | ||||||
| 				TableView { |                 Rectangle { | ||||||
| 					property var memModel: ListModel { |                     color: "#00000000" | ||||||
| 						id: memModel |                     height: 500 | ||||||
| 					} |                     anchors.left: parent.left | ||||||
| 					height: parent.height/2 |                     anchors.right: parent.right | ||||||
| 					width: parent.width |  | ||||||
| 					TableViewColumn{ id:mnumColmn ; role: "num" ; title: "#" ; width: 50} |  | ||||||
| 					TableViewColumn{ role: "value" ; title: "Memory" ; width: 750} |  | ||||||
| 					model: memModel |  | ||||||
| 				} |  | ||||||
| 
 | 
 | ||||||
| 				SplitView { |                     TextArea { | ||||||
| 					orientation: Qt.Horizontal |                         id: codeEditor | ||||||
| 					TableView { |                         anchors.top: parent.top | ||||||
| 						property var debuggerLog: ListModel { |                         anchors.bottom: parent.bottom | ||||||
| 							id: debuggerLog |                         anchors.left: parent.left | ||||||
| 						} |                         anchors.right: settings.left | ||||||
| 						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) { |                     Column { | ||||||
| 		asmModel.append({asm: asm}) |                         id: settings | ||||||
| 	} |                         spacing: 5 | ||||||
|  |                         width: 300 | ||||||
|  |                         height: parent.height | ||||||
|  |                         anchors.right: parent.right | ||||||
|  |                         anchors.top: parent.top | ||||||
|  |                         anchors.bottom: parent.bottom | ||||||
| 
 | 
 | ||||||
| 	function setInstruction(num) { |                         Label { | ||||||
| 		asmTableView.selection.clear() |                             text: "Data" | ||||||
| 		asmTableView.selection.select(num-1) |                         } | ||||||
| 	} |                         TextArea { | ||||||
|  |                             anchors.left: parent.left | ||||||
|  |                             anchors.right: parent.right | ||||||
|  |                             height: 150 | ||||||
|  |                         } | ||||||
| 
 | 
 | ||||||
| 	function clearAsm() { |                         Label { | ||||||
| 		asmModel.clear() |                             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*/ } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
| 	function setMem(mem) { |                 SplitView { | ||||||
| 		memModel.append({num: mem.num, value: mem.value}) |                     orientation: Qt.Vertical | ||||||
| 	} |                     id: inspectorPane | ||||||
| 	function clearMem(){ |                     height: 500 | ||||||
| 		memModel.clear() |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	function setStack(stack) { |                     SplitView { | ||||||
| 		stackModel.append({value: stack}) |                         orientation: Qt.Horizontal | ||||||
| 	} |                         height: 300 | ||||||
| 	function addDebugMessage(message){ |  | ||||||
| 		debuggerLog.append({value: message}) |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	function clearStack() { |                         TableView { | ||||||
| 		stackModel.clear() |                             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}) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -30,13 +30,16 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (self *DebuggerWindow) Show() { | func (self *DebuggerWindow) Show() { | ||||||
|  | 	context := self.engine.Context() | ||||||
|  | 	context.SetVar("dbg", self) | ||||||
|  | 
 | ||||||
| 	go func() { | 	go func() { | ||||||
| 		self.win.Show() | 		self.win.Show() | ||||||
| 		self.win.Wait() | 		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() | 	state := self.lib.eth.BlockChain().CurrentBlock.State() | ||||||
| 
 | 
 | ||||||
| 	script, err := ethutil.Compile(data) | 	script, err := ethutil.Compile(data) | ||||||
| @ -50,14 +53,14 @@ func (self *DebuggerWindow) DebugTx(recipient, valueStr, gasStr, gasPriceStr, da | |||||||
| 	self.lib.win.Root().Call("clearAsm") | 	self.lib.win.Root().Call("clearAsm") | ||||||
| 
 | 
 | ||||||
| 	for _, str := range dis { | 	for _, str := range dis { | ||||||
| 		self.lib.win.Root().Call("setAsm", str) | 		self.win.Root().Call("setAsm", str) | ||||||
| 	} | 	} | ||||||
| 	// Contract addr as test address
 | 	// Contract addr as test address
 | ||||||
| 	keyPair := ethutil.GetKeyRing().Get(0) | 	keyPair := ethutil.GetKeyRing().Get(0) | ||||||
| 	callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), script) | 	callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), script) | ||||||
| 	callerTx.Sign(keyPair.PrivateKey) | 	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) | 	contract := ethchain.MakeContract(callerTx, state) | ||||||
| 	callerClosure := ethchain.NewClosure(account, contract, contract.Init(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr)) | 	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() { | func (self *DebuggerWindow) Next() { | ||||||
| 	self.Db.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 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
| @ -2,7 +2,6 @@ package ethui | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bitbucket.org/kardianos/osext" | 	"bitbucket.org/kardianos/osext" | ||||||
| 	"fmt" |  | ||||||
| 	"github.com/ethereum/eth-go" | 	"github.com/ethereum/eth-go" | ||||||
| 	"github.com/ethereum/eth-go/ethchain" | 	"github.com/ethereum/eth-go/ethchain" | ||||||
| 	"github.com/ethereum/eth-go/ethutil" | 	"github.com/ethereum/eth-go/ethutil" | ||||||
| @ -171,40 +170,3 @@ func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) | |||||||
| func (ui *UiLib) Next() { | func (ui *UiLib) Next() { | ||||||
| 	ui.Db.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 |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user