From a6f4eef1dadee9d8caa9b0ac20e2ce4a3034a100 Mon Sep 17 00:00:00 2001 From: Maran Date: Mon, 2 Jun 2014 15:16:37 +0200 Subject: [PATCH 01/10] Added Peer Window --- ethereal/assets/qml/wallet.qml | 50 +++++++++++++++++++++++++++++++++- ethereal/ui/gui.go | 12 +++++++- ethereum/repl.go | 4 +++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/ethereal/assets/qml/wallet.qml b/ethereal/assets/qml/wallet.qml index bbb147d89..8c04c6344 100644 --- a/ethereal/assets/qml/wallet.qml +++ b/ethereal/assets/qml/wallet.qml @@ -45,6 +45,13 @@ ApplicationWindow { addPeerWin.visible = true } } + MenuItem { + text: "Show Peers" + shortcut: "Ctrl+e" + onTriggered: { + peerWindow.visible = true + } + } } Menu { @@ -359,6 +366,10 @@ ApplicationWindow { id: peerImage anchors.right: parent.right width: 10; height: 10 + MouseArea { + onDoubleClicked: peerWindow.visible = true + anchors.fill: parent + } source: ui.assetPath("network.png") } } @@ -623,6 +634,20 @@ ApplicationWindow { function setPeers(text) { peerLabel.text = text } + + function addPeer(peer) { + // We could just append the whole peer object but it cries if you try to alter them + peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), version: peer.version}) + } + + function resetPeers(){ + peerModel.clear() + } + + function timeAgo(unixTs){ + var lapsed = (Date.now() - new Date(unixTs*1000)) / 1000 + return (lapsed + " seconds ago") + } function convertToPretty(unixTs){ var a = new Date(unixTs*1000); var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; @@ -635,6 +660,30 @@ ApplicationWindow { var time = date+' '+month+' '+year+' '+hour+':'+min+':'+sec ; return time; } + // ****************************************** + // Windows + // ****************************************** + Window { + id: peerWindow + height: 200 + width: 500 + Rectangle { + anchors.fill: parent + property var peerModel: ListModel { + id: peerModel + } + TableView { + anchors.fill: parent + id: peerTable + model: peerModel + TableViewColumn{width: 120; role: "ip" ; title: "IP" } + TableViewColumn{width: 60; role: "port" ; title: "Port" } + TableViewColumn{width: 120; role: "lastResponse"; title: "Last event" } + TableViewColumn{width: 180; role: "version" ; title: "Version" } + } + } + } + // ******************************************* // Components // ******************************************* @@ -810,7 +859,6 @@ ApplicationWindow { } } } - // New Transaction component Component { id: newTransaction diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index 44215efdb..db06add8e 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -12,6 +12,7 @@ import ( "github.com/go-qml/qml" "math/big" "strings" + "time" ) type Gui struct { @@ -91,7 +92,7 @@ func (gui *Gui) Start(assetPath string) { ethutil.Config.Log.AddLogSystem(gui) } if err != nil { - ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'") + ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'", err) panic(err) } @@ -235,6 +236,8 @@ func (gui *Gui) update() { reactor.Subscribe("object:"+string(namereg), objectChan) reactor.Subscribe("peerList", peerChan) + ticker := time.NewTicker(5 * time.Second) + state := gui.eth.StateManager().TransState() unconfirmedFunds := new(big.Int) @@ -284,12 +287,19 @@ func (gui *Gui) update() { gui.loadAddressBook() case <-peerChan: gui.setPeerInfo() + case <-ticker.C: + gui.setPeerInfo() } } } func (gui *Gui) setPeerInfo() { gui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", gui.eth.PeerCount(), gui.eth.MaxPeers)) + + gui.win.Root().Call("resetPeers") + for _, peer := range gui.pub.GetPeers() { + gui.win.Root().Call("addPeer", peer) + } } // Logging functions that log directly to the GUI interface diff --git a/ethereum/repl.go b/ethereum/repl.go index 10f51675e..e59814154 100644 --- a/ethereum/repl.go +++ b/ethereum/repl.go @@ -66,6 +66,10 @@ func (self *JSEthereum) GetBlock(hash string) otto.Value { return self.toVal(&JSBlock{self.PEthereum.GetBlock(hash), self}) } +func (self *JSEthereum) GetPeers() otto.Value { + return self.toVal(self.PEthereum.GetPeers()) +} + func (self *JSEthereum) GetKey() otto.Value { return self.toVal(self.PEthereum.GetKey()) } From 9e411d785bc4e104183dda537488f8aa2906ec13 Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 3 Jun 2014 10:42:36 +0200 Subject: [PATCH 02/10] Tweaks and latency added to peeroverview --- ethereal/assets/qml/wallet.qml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ethereal/assets/qml/wallet.qml b/ethereal/assets/qml/wallet.qml index 8c04c6344..b626bf044 100644 --- a/ethereal/assets/qml/wallet.qml +++ b/ethereal/assets/qml/wallet.qml @@ -637,7 +637,7 @@ ApplicationWindow { function addPeer(peer) { // We could just append the whole peer object but it cries if you try to alter them - peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), version: peer.version}) + peerModel.append({ip: peer.ip, port: peer.port, lastResponse:timeAgo(peer.lastSend), latency: peer.latency, version: peer.version}) } function resetPeers(){ @@ -666,7 +666,7 @@ ApplicationWindow { Window { id: peerWindow height: 200 - width: 500 + width: 700 Rectangle { anchors.fill: parent property var peerModel: ListModel { @@ -676,10 +676,11 @@ ApplicationWindow { anchors.fill: parent id: peerTable model: peerModel - TableViewColumn{width: 120; role: "ip" ; title: "IP" } + TableViewColumn{width: 100; role: "ip" ; title: "IP" } TableViewColumn{width: 60; role: "port" ; title: "Port" } - TableViewColumn{width: 120; role: "lastResponse"; title: "Last event" } - TableViewColumn{width: 180; role: "version" ; title: "Version" } + TableViewColumn{width: 140; role: "lastResponse"; title: "Last event" } + TableViewColumn{width: 100; role: "latency"; title: "Latency" } + TableViewColumn{width: 260; role: "version" ; title: "Version" } } } } From cc1d043423293eff97d01c8f4897b354112c8210 Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 3 Jun 2014 11:48:44 +0200 Subject: [PATCH 03/10] Implemented transaction catching up. Implements #73 --- ethereal/ui/gui.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index db06add8e..701bacf00 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -163,6 +163,17 @@ func (gui *Gui) setInitialBlockChain() { blk := gui.eth.BlockChain().GetBlock(sBlk) for ; blk != nil; blk = gui.eth.BlockChain().GetBlock(sBlk) { sBlk = blk.PrevHash + + // Loop through all transactions to see if we missed any while being offline + for _, tx := range blk.Transactions() { + if bytes.Compare(tx.Sender(), gui.addr) == 0 || bytes.Compare(tx.Recipient, gui.addr) == 0 { + if ok, _ := gui.txDb.Get(tx.Hash()); ok == nil { + gui.txDb.Put(tx.Hash(), tx.RlpEncode()) + } + + } + } + gui.processBlock(blk, true) } } From 3755616a2912f47a963d4ecc781bddd4229fe290 Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 3 Jun 2014 14:30:26 +0200 Subject: [PATCH 04/10] Added namereg register option to qml wallet --- ethereal/assets/qml/wallet.qml | 27 +++++++++++++++++++++++++-- ethereal/ui/gui.go | 5 +++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/ethereal/assets/qml/wallet.qml b/ethereal/assets/qml/wallet.qml index b626bf044..fece8e7d6 100644 --- a/ethereal/assets/qml/wallet.qml +++ b/ethereal/assets/qml/wallet.qml @@ -254,13 +254,12 @@ ApplicationWindow { } } - property var addressModel: ListModel { id: addressModel } TableView { id: addressView - width: parent.width + width: parent.width - 200 height: 200 anchors.bottom: logView.top TableViewColumn{ role: "name"; title: "name" } @@ -269,6 +268,30 @@ ApplicationWindow { model: addressModel } + Rectangle { + anchors.top: addressView.top + anchors.left: addressView.right + anchors.leftMargin: 20 + + TextField { + placeholderText: "Name to register" + id: nameToReg + width: 150 + } + + Button { + anchors.top: nameToReg.bottom + text: "Register" + MouseArea{ + anchors.fill: parent + onClicked: { + eth.registerName(nameToReg.text) + nameToReg.text = "" + } + } + } + } + property var logModel: ListModel { id: logModel diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index 701bacf00..9fc1abc28 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -329,6 +329,11 @@ func (gui *Gui) Printf(format string, v ...interface{}) { gui.win.Root().Call("addLog", line) } } +func (gui *Gui) RegisterName(name string) { + keyPair := ethutil.GetKeyRing().Get(0) + name = fmt.Sprintf("\"%s\"\n1", name) + gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), "namereg", "1000", "1000000", "150", name) +} func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) { keyPair := ethutil.GetKeyRing().Get(0) From 307fe4a3cd4ff2d3910ed992e6e98a7cd3ca6f87 Mon Sep 17 00:00:00 2001 From: Maran Date: Wed, 4 Jun 2014 12:19:50 +0200 Subject: [PATCH 05/10] Add loading of extra build in js files to JS-Repl. Implements #67 --- ethereum/javascript_runtime.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/ethereum/javascript_runtime.go b/ethereum/javascript_runtime.go index 93297f604..b05d39232 100644 --- a/ethereum/javascript_runtime.go +++ b/ethereum/javascript_runtime.go @@ -10,6 +10,7 @@ import ( "github.com/obscuren/otto" "io/ioutil" "os" + "path" "path/filepath" ) @@ -25,6 +26,20 @@ type JSRE struct { objectCb map[string][]otto.Value } +func (jsre *JSRE) LoadExtFile(path string) { + result, err := ioutil.ReadFile(path) + if err == nil { + jsre.vm.Run(result) + } else { + ethutil.Config.Log.Debugln("Could not load file:", path) + } +} + +func (jsre *JSRE) LoadIntFile(file string) { + assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "ethereal", "assets", "ext") + jsre.LoadExtFile(path.Join(assetPath, file)) +} + func NewJSRE(ethereum *eth.Ethereum) *JSRE { re := &JSRE{ ethereum, @@ -39,6 +54,10 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE { // Init the JS lib re.vm.Run(jsLib) + // Load extra javascript files + re.LoadIntFile("string.js") + re.LoadIntFile("big.js") + // We have to make sure that, whoever calls this, calls "Stop" go re.mainLoop() From 7843390ecd52df37a28282d76be198d5456ce385 Mon Sep 17 00:00:00 2001 From: Maran Date: Wed, 4 Jun 2014 15:54:33 +0200 Subject: [PATCH 06/10] Implement getStateKeyVal for JS bindings. Gives JS the option to 'loop' over contract key/val storage --- ethereal/assets/ext/ethereum.js | 4 ++++ ethereal/assets/qml/webapp.qml | 9 +++++++-- ethereal/ui/gui.go | 2 ++ ethereum/repl.go | 6 +++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ethereal/assets/ext/ethereum.js b/ethereal/assets/ext/ethereum.js index d4eaf97fd..c58fe24c2 100644 --- a/ethereal/assets/ext/ethereum.js +++ b/ethereal/assets/ext/ethereum.js @@ -32,6 +32,10 @@ window.eth = { postData({call: "getStorage", args: [address, storageAddress]}, cb); }, + getStateKeyVals: function(address, cb){ + postData({call: "getStateKeyVals", args: [address]}, cb); + }, + getKey: function(cb) { postData({call: "getKey"}, cb); }, diff --git a/ethereal/assets/qml/webapp.qml b/ethereal/assets/qml/webapp.qml index d3cffeeca..ec236a18c 100644 --- a/ethereal/assets/qml/webapp.qml +++ b/ethereal/assets/qml/webapp.qml @@ -34,7 +34,6 @@ ApplicationWindow { top: parent.top } */ - onTitleChanged: { window.title = title } experimental.preferences.javascriptEnabled: true experimental.preferences.navigatorQtObjectEnabled: true @@ -97,6 +96,12 @@ ApplicationWindow { var storage = stateObject.getStorage(data.args[1]) postData(data._seed, storage) + break + case "getStateKeyVals": + require(1); + var stateObject = eth.getStateObject(data.args[0]).stateKeyVal(true) + postData(data._seed,stateObject) + break case "getBalance": require(1); @@ -188,7 +193,7 @@ ApplicationWindow { WebView { id: inspector - visible: false + visible: true url: webview.experimental.remoteInspectorUrl anchors { left: root.left diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index 9fc1abc28..4dda5017f 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -65,6 +65,8 @@ func (gui *Gui) Start(assetPath string) { Init: func(p *ethpub.PBlock, obj qml.Object) { p.Number = 0; p.Hash = "" }, }, { Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, + }, { + Init: func(p *ethpub.KeyVal, obj qml.Object) { p.Key = ""; p.Value = "" }, }}) ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", version)) diff --git a/ethereum/repl.go b/ethereum/repl.go index e59814154..0208459ad 100644 --- a/ethereum/repl.go +++ b/ethereum/repl.go @@ -78,6 +78,10 @@ func (self *JSEthereum) GetStateObject(addr string) otto.Value { return self.toVal(self.PEthereum.GetStateObject(addr)) } +func (self *JSEthereum) GetStateKeyVals(addr string) otto.Value { + return self.toVal(self.PEthereum.GetStateObject(addr).StateKeyVal(false)) +} + func (self *JSEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value { r, err := self.PEthereum.Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr) if err != nil { @@ -105,7 +109,7 @@ func (self *JSEthereum) toVal(v interface{}) otto.Value { result, err := self.vm.ToValue(v) if err != nil { - fmt.Println(err) + fmt.Println("Value unknown:", err) return otto.UndefinedValue() } From 964587b14a52f5a64c166fe28cc5a51eb2bac1c7 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 5 Jun 2014 09:00:57 +0200 Subject: [PATCH 07/10] Added more debugger output --- ethereal/ui/debugger.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ethereal/ui/debugger.go b/ethereal/ui/debugger.go index a6b8e16d0..eb68b51dc 100644 --- a/ethereal/ui/debugger.go +++ b/ethereal/ui/debugger.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" "github.com/go-qml/qml" + "math/big" "strings" ) @@ -89,15 +90,17 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data self.win.Root().Call("setAsm", str) } + gas := ethutil.Big(gasStr) + gasPrice := ethutil.Big(gasPriceStr) // Contract addr as test address keyPair := ethutil.GetKeyRing().Get(0) - callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), ethutil.Big(gasStr), ethutil.Big(gasPriceStr), script) + callerTx := ethchain.NewContractCreationTx(ethutil.Big(valueStr), gas, gasPrice, script) callerTx.Sign(keyPair.PrivateKey) state := self.lib.eth.BlockChain().CurrentBlock.State() account := self.lib.eth.StateManager().TransState().GetAccount(keyPair.Address()) contract := ethchain.MakeContract(callerTx, state) - callerClosure := ethchain.NewClosure(account, contract, script, state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr)) + callerClosure := ethchain.NewClosure(account, contract, script, state, gas, gasPrice) block := self.lib.eth.BlockChain().CurrentBlock vm := ethchain.NewVm(state, self.lib.eth.StateManager(), ethchain.RuntimeVars{ @@ -111,12 +114,18 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data }) self.Db.done = false + self.Logf("callsize %d", len(script)) go func() { - ret, _, err := callerClosure.Call(vm, data, self.Db.halting) + ret, g, err := callerClosure.Call(vm, data, self.Db.halting) + self.Logln("gas usage", g, "total price =", new(big.Int).Mul(g, gasPrice)) if err != nil { self.Logln("exited with errors:", err) } else { - self.Logf("exited: %v", ret) + if len(ret) > 0 { + self.Logf("exited: % x", ret) + } else { + self.Logf("exited: nil") + } } state.Reset() From cc20b0e3a0754c77fe04a8b5c5668d0eda955bcf Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 6 Jun 2014 12:13:13 +0200 Subject: [PATCH 08/10] debugger output --- ethereal/ui/debugger.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ethereal/ui/debugger.go b/ethereal/ui/debugger.go index eb68b51dc..a4489cdf4 100644 --- a/ethereal/ui/debugger.go +++ b/ethereal/ui/debugger.go @@ -117,7 +117,8 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data self.Logf("callsize %d", len(script)) go func() { ret, g, err := callerClosure.Call(vm, data, self.Db.halting) - self.Logln("gas usage", g, "total price =", new(big.Int).Mul(g, gasPrice)) + tot := new(big.Int).Mul(g, gasPrice) + self.Logf("gas usage %v total price = %v (%v)", g, tot, ethutil.CurrencyToString(tot)) if err != nil { self.Logln("exited with errors:", err) } else { From ba3623d0cc0608f2d73e10e61a184238924fccdb Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 9 Jun 2014 22:04:16 +0200 Subject: [PATCH 09/10] Fixed debugger hang --- ethereal/assets/debugger/debugger.qml | 2 +- ethereal/ui/debugger.go | 38 ++++++++++++++++++++++----- ethereal/ui/gui.go | 2 +- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/ethereal/assets/debugger/debugger.qml b/ethereal/assets/debugger/debugger.qml index ca67e857d..bc34233fd 100644 --- a/ethereal/assets/debugger/debugger.qml +++ b/ethereal/assets/debugger/debugger.qml @@ -163,7 +163,7 @@ ApplicationWindow { height: parent.height width: parent.width TableViewColumn{ id: key ; role: "key" ; title: "#" ; width: storageTableView.width / 2} - TableViewColumn{ role: "value" ; title: "value" ; width: storageTableView.width / 2} + TableViewColumn{ role: "value" ; title: "Storage" ; width: storageTableView.width / 2} model: storageModel } } diff --git a/ethereal/ui/debugger.go b/ethereal/ui/debugger.go index a4489cdf4..919407b34 100644 --- a/ethereal/ui/debugger.go +++ b/ethereal/ui/debugger.go @@ -26,7 +26,7 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow { } win := component.CreateWindow(nil) - db := &Debugger{win, make(chan bool), make(chan bool), true} + db := &Debugger{win, make(chan bool), make(chan bool), true, false} return &DebuggerWindow{engine: engine, win: win, lib: lib, Db: db} } @@ -60,6 +60,12 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data self.Db.Q <- true } + defer func() { + if r := recover(); r != nil { + self.Logf("compile FAULT: %v", r) + } + }() + data := ethutil.StringToByteFunc(dataStr, func(s string) (ret []byte) { slice := strings.Split(dataStr, "\n") for _, dataItem := range slice { @@ -131,7 +137,11 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data state.Reset() - self.Db.done = true + if !self.Db.interrupt { + self.Db.done = true + } else { + self.Db.interrupt = false + } }() } @@ -149,10 +159,10 @@ func (self *DebuggerWindow) Next() { } type Debugger struct { - win *qml.Window - N chan bool - Q chan bool - done bool + win *qml.Window + N chan bool + Q chan bool + done, interrupt bool } type storeVal struct { @@ -185,7 +195,8 @@ out: case <-d.N: break out case <-d.Q: - d.done = true + d.interrupt = true + d.clearBuffers() return false } @@ -194,6 +205,19 @@ out: return true } +func (d *Debugger) clearBuffers() { +out: + // drain + for { + select { + case <-d.N: + case <-d.Q: + default: + break out + } + } +} + func (d *Debugger) Next() { if !d.done { d.N <- true diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index 4dda5017f..5954df70c 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -154,7 +154,7 @@ func (gui *Gui) createWindow(comp qml.Object) *qml.Window { gui.win = win gui.uiLib.win = win - db := &Debugger{gui.win, make(chan bool), make(chan bool), true} + db := &Debugger{gui.win, make(chan bool), make(chan bool), true, false} gui.lib.Db = db gui.uiLib.Db = db From d929c634749c3c2db9f3290e635a763eba211656 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 9 Jun 2014 22:23:33 +0200 Subject: [PATCH 10/10] bump --- README.md | 2 +- ethereal/ui/gui.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c32b51037..104e4725c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Ethereum Ethereum Go Client © 2014 Jeffrey Wilcke. -Current state: Proof of Concept 5.0 RC11. +Current state: Proof of Concept 5.0 RC12. For the development package please see the [eth-go package](https://github.com/ethereum/eth-go). diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index 5954df70c..2ba89ce22 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -56,7 +56,7 @@ func New(ethereum *eth.Ethereum) *Gui { } func (gui *Gui) Start(assetPath string) { - const version = "0.5.0 RC11" + const version = "0.5.0 RC12" defer gui.txDb.Close()