diff options
39 files changed, 534 insertions, 367 deletions
diff --git a/cmd/mist/assets/backButtonDisabled.png b/cmd/mist/assets/backButtonDisabled.png Binary files differnew file mode 100644 index 000000000..428747870 --- /dev/null +++ b/cmd/mist/assets/backButtonDisabled.png diff --git a/cmd/mist/assets/backButtonDisabled@2x.png b/cmd/mist/assets/backButtonDisabled@2x.png Binary files differnew file mode 100644 index 000000000..0eaa6daa5 --- /dev/null +++ b/cmd/mist/assets/backButtonDisabled@2x.png diff --git a/cmd/mist/assets/backButtonHover.png b/cmd/mist/assets/backButtonHover.png Binary files differnew file mode 100644 index 000000000..8c5226f5a --- /dev/null +++ b/cmd/mist/assets/backButtonHover.png diff --git a/cmd/mist/assets/backButtonHover@2x.png b/cmd/mist/assets/backButtonHover@2x.png Binary files differnew file mode 100644 index 000000000..406601ebc --- /dev/null +++ b/cmd/mist/assets/backButtonHover@2x.png diff --git a/cmd/mist/assets/browser.png b/cmd/mist/assets/browser.png Binary files differindex 7b3b0870c..074c9ae3c 100644 --- a/cmd/mist/assets/browser.png +++ b/cmd/mist/assets/browser.png diff --git a/cmd/mist/assets/browser@2x.png b/cmd/mist/assets/browser@2x.png Binary files differnew file mode 100644 index 000000000..8ca417608 --- /dev/null +++ b/cmd/mist/assets/browser@2x.png diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html index ca7a9c0dd..cb9d471de 100644 --- a/cmd/mist/assets/examples/coin.html +++ b/cmd/mist/assets/examples/coin.html @@ -80,11 +80,6 @@ refresh(); }); - var ev = contract.SingleTransact({}) - ev.watch(function(log) { - someElement.innerHTML += "tnaheousnthaoeu"; - }); - eth.watch('chain').changed(function() { refresh(); }); diff --git a/cmd/mist/assets/examples/info.html b/cmd/mist/assets/examples/info.html index d8816b19f..2a405c280 100644 --- a/cmd/mist/assets/examples/info.html +++ b/cmd/mist/assets/examples/info.html @@ -71,6 +71,10 @@ document.querySelector("#gas_price").innerHTML = eth.gasPrice; document.querySelector("#mining").innerHTML = eth.mining; document.querySelector("#listening").innerHTML = eth.listening; + eth.watch('chain').changed(function() { + document.querySelector("#number").innerHTML = eth.number; + }); + </script> </html> diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js index d0e9d3cb7..83b598b3f 100644 --- a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js +++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js @@ -1417,6 +1417,8 @@ var ethMethods = function () { var methods = [ { name: 'balanceAt', call: 'eth_balanceAt' }, + { name: 'register', call: 'eth_register' }, + { name: 'unregister', call: 'eth_unregister' }, { name: 'stateAt', call: 'eth_stateAt' }, { name: 'storageAt', call: 'eth_storageAt' }, { name: 'countAt', call: 'eth_countAt'}, diff --git a/cmd/mist/assets/ext/mist.js b/cmd/mist/assets/ext/mist.js new file mode 100644 index 000000000..8734f8dc7 --- /dev/null +++ b/cmd/mist/assets/ext/mist.js @@ -0,0 +1,35 @@ +// Copyright (c) 2015, ETHDEV. All rights reserved. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301 USA + +// this function is included locally, but you can also include separately via a header definition + +console.log("loaded?"); + +document.onkeydown = function(evt) { + evt = evt || window.event; + if (evt.ctrlKey && evt.keyCode == 67) { + window.document.execCommand("copy"); + console.log("Ctrl-C"); + } else if (evt.ctrlKey && evt.keyCode == 88) { + window.document.execCommand("cut"); + console.log("Ctrl-X"); + } if (evt.ctrlKey && evt.keyCode == 86) { + console.log("Ctrl-V"); + } if (evt.ctrlKey && evt.keyCode == 90) { + console.log("Ctrl-Z"); + } +};
\ No newline at end of file diff --git a/cmd/mist/assets/miner.png b/cmd/mist/assets/miner.png Binary files differdeleted file mode 100644 index 58e3f4dfe..000000000 --- a/cmd/mist/assets/miner.png +++ /dev/null diff --git a/cmd/mist/assets/mining-icon.png b/cmd/mist/assets/mining-icon.png Binary files differnew file mode 100644 index 000000000..db611e5c0 --- /dev/null +++ b/cmd/mist/assets/mining-icon.png diff --git a/cmd/mist/assets/mining-icon@2x.png b/cmd/mist/assets/mining-icon@2x.png Binary files differnew file mode 100644 index 000000000..16466d338 --- /dev/null +++ b/cmd/mist/assets/mining-icon@2x.png diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml index e1e6a028f..3089fc46f 100644 --- a/cmd/mist/assets/qml/main.qml +++ b/cmd/mist/assets/qml/main.qml @@ -40,10 +40,14 @@ ApplicationWindow { // Takes care of loading all default plugins Component.onCompleted: { - catalog = addPlugin("./views/catalog.qml", {noAdd: true, close: false, section: "begin"}); - var wallet = addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "ethereum", active: true}); + catalog = addPlugin("./views/catalog.qml", {noAdd: true, close: false, section: "begin", active: true}); - addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: true}); + var walletWeb = addPlugin("./views/browser.qml", {noAdd: true, close: false, section: "ethereum", active: false}); + walletWeb.view.url = "http://ethereum-dapp-wallet.meteor.com/"; + walletWeb.menuItem.title = "Wallet"; + + addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "legacy"}); + addPlugin("./views/miner.qml", {noAdd: true, close: false, section: "ethereum", active: false}); addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"}); addPlugin("./views/whisper.qml", {noAdd: true, close: false, section: "legacy"}); addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"}); @@ -60,13 +64,14 @@ ApplicationWindow { function activeView(view, menuItem) { mainSplit.setView(view, menuItem) - if (view.hideUrl) { - //urlPane.visible = false; - //mainView.anchors.top = rootView.top + /*if (view.hideUrl) { + urlPane.visible = false; + mainView.anchors.top = rootView.top } else { - //urlPane.visible = true; - //mainView.anchors.top = divider.bottom - } + urlPane.visible = true; + mainView.anchors.top = divider.bottom + }*/ + } function addViews(view, path, options) { @@ -121,13 +126,10 @@ ApplicationWindow { var domainAlreadyOpen = false; - console.log("requested: " + requestedDomain ) - for(var i = 0; i < mainSplit.views.length; i++) { if (mainSplit.views[i].view.url) { var matches = mainSplit.views[i].view.url.toString().match(/^[a-z]*\:\/\/(?:www\.)?([^\/?#]+)(?:[\/?#]|$)/i); var existingDomain = matches && matches[1]; - console.log("exists: " + existingDomain); if (requestedDomain == existingDomain) { domainAlreadyOpen = true; mainSplit.views[i].view.url = url; @@ -247,79 +249,6 @@ ApplicationWindow { } } - statusBar: StatusBar { - //height: 32 - visible: false - - id: statusBar - Label { - //y: 6 - id: walletValueLabel - - font.pixelSize: 10 - styleColor: "#797979" - } - - /* - Label { - //y: 6 - objectName: "miningLabel" - visible: true - font.pixelSize: 10 - anchors.right: lastBlockLabel.left - anchors.rightMargin: 5 - } - - Label { - id: lastBlockLabel - objectName: "lastBlockLabel" - visible: true - text: "---" - font.pixelSize: 10 - anchors.right: peerGroup.left - anchors.rightMargin: 5 - } - */ - - ProgressBar { - visible: false - id: downloadIndicator - value: 0 - objectName: "downloadIndicator" - y: -4 - x: statusBar.width / 2 - this.width / 2 - width: 160 - } - - Label { - visible: false - objectName: "downloadLabel" - //y: 7 - anchors.left: downloadIndicator.right - anchors.leftMargin: 5 - font.pixelSize: 10 - text: "0 / 0" - } - - - RowLayout { - id: peerGroup - //y: 7 - anchors.right: parent.right - MouseArea { - onDoubleClicked: peerWindow.visible = true - anchors.fill: parent - } - - Label { - id: peerCounterLabel - font.pixelSize: 10 - text: "0 / 0" - } - } - } - - property var blockModel: ListModel { id: blockModel } @@ -445,10 +374,14 @@ ApplicationWindow { property var view; property var path; property var closable; + property var badgeContent; property alias title: label.text property alias icon: icon.source property alias secondaryTitle: secondary.text + property alias badgeNumber: badgeNumberLabel.text + property alias badgeIcon: badgeIconLabel.text + function setSelection(on) { sel.visible = on @@ -462,7 +395,7 @@ ApplicationWindow { label.visible = !on buttonLabel.visible = on } - + width: 192 height: 55 color: "#00000000" @@ -541,7 +474,6 @@ ApplicationWindow { if (parent.closable == true) { closeIcon.visible = sel.visible } - } onExited: { closeIcon.visible = false @@ -550,8 +482,8 @@ ApplicationWindow { Image { id: icon - height: 24 - width: 24 + height: 28 + width: 28 anchors { left: parent.left verticalCenter: parent.verticalCenter @@ -574,18 +506,24 @@ ApplicationWindow { id: label font.family: sourceSansPro.name font.weight: Font.DemiBold + elide: Text.ElideRight + x:250 + color: "#665F5F" + font.pixelSize: 14 anchors { left: icon.right + right: parent.right verticalCenter: parent.verticalCenter leftMargin: 6 - // verticalCenterOffset: -10 + rightMargin: 8 + verticalCenterOffset: (secondaryTitle == "") ? 0 : -10; } - x:250 - color: "#665F5F" - font.pixelSize: 14 - } + + + } + Text { id: secondary font.family: sourceSansPro.name @@ -604,7 +542,7 @@ ApplicationWindow { visible: false width: 10 height: 10 - color: "#FFFFFF" + color: "#FAFAFA" anchors { fill: icon } @@ -623,9 +561,49 @@ ApplicationWindow { centerIn: parent } color: "#665F5F" - font.pixelSize: 18 + font.pixelSize: 20 text: "\ue082" } + } + + Rectangle { + id: badge + visible: (badgeContent == "icon" || badgeContent == "number" )? true : false + width: 32 + color: "#05000000" + anchors { + right: parent.right; + top: parent.top; + bottom: parent.bottom; + rightMargin: 4; + } + + Text { + id: badgeIconLabel + visible: (badgeContent == "icon") ? true : false; + font.family: simpleLineIcons.name + anchors { + centerIn: parent + } + horizontalAlignment: Text.AlignCenter + color: "#AAA0A0" + font.pixelSize: 20 + text: badgeIcon + } + + Text { + id: badgeNumberLabel + visible: (badgeContent == "number") ? true : false; + anchors { + centerIn: parent + } + horizontalAlignment: Text.AlignCenter + font.family: sourceSansPro.name + font.weight: Font.Light + color: "#AAA0A0" + font.pixelSize: 18 + text: badgeNumber + } } @@ -898,7 +876,7 @@ ApplicationWindow { } function setWalletValue(value) { - walletValueLabel.text = value + //walletValueLabel.text = value } function loadPlugin(name) { @@ -910,7 +888,7 @@ ApplicationWindow { function addPeer(peer) { peerModel.append(peer) } function setPeerCounters(text) { - peerCounterLabel.text = text + //peerCounterLabel.text = text } function timeAgo(unixTs){ diff --git a/cmd/mist/assets/qml/views/browser.qml b/cmd/mist/assets/qml/views/browser.qml index 631ef5a16..54f5d755e 100644 --- a/cmd/mist/assets/qml/views/browser.qml +++ b/cmd/mist/assets/qml/views/browser.qml @@ -3,7 +3,7 @@ import QtQuick.Controls 1.0; import QtQuick.Controls.Styles 1.0 import QtQuick.Layouts 1.0; import QtWebEngine 1.0 -import QtWebEngine.experimental 1.0 +//import QtWebEngine.experimental 1.0 import QtQuick.Window 2.0; Rectangle { @@ -64,23 +64,15 @@ Rectangle { } function showFullUrlBar(on){ - if (on) { - //appTitle.visible = false - //appDomain.visible = false - - //uriNav.visible = true - clickAnywhereOnApp.visible = true - - navBar.state = "fullUrlVisible" - } else { - //appTitle.visible = true - //appDomain.visible = true - //uriNav.visible = false - clickAnywhereOnApp.visible = false - - navBar.state = "titleVisible" - - } + if (uriNav.focus == false ) { + if (on == false) { + clickAnywhereOnApp.visible = false + navBar.state = "titleVisible" + } else { + clickAnywhereOnApp.visible = true + navBar.state = "fullUrlVisible" + } + } } @@ -90,24 +82,40 @@ Rectangle { Item { objectName: "root" id: root - anchors.fill: parent + anchors { + fill: parent + } + state: "inspectorShown" MouseArea { id: clickAnywhereOnApp z:15 - //hoverEnabled: true - anchors.fill: parent - /*hoverEnabled: true*/ + // Using a secondary screen to catch on mouse exits for the area, because + // there are many hover actions conflicting + + anchors { + top: parent.top + topMargin: 50 + right: parent.right + bottom: parent.bottom + left: parent.left + } + hoverEnabled: true - onClicked: { + onEntered: { showFullUrlBar(false); } - /*Rectangle { - anchors.fill: parent - color: "#88888888" - }*/ + onClicked: { + uriNav.focus = false + showFullUrlBar(false); + } + + // Rectangle { + // anchors.fill: parent + // color: "#88888888" + // } } RowLayout { @@ -121,40 +129,44 @@ Rectangle { Button { id: back - - onClicked: { - webview.goBack() + z: 30 + onClicked: { + webview.goBack() } - anchors{ + anchors { left: parent.left leftMargin: 6 } style: ButtonStyle { - background: Image { - source: "../../backButton.png" - width: 20 - height: 30 - } + background: Image { + source: (webview.canGoBack) ? + (control.hovered ? "../../backButtonHover.png" : "../../backButton.png") : + "../../backButtonDisabled.png" + width: 20 + height: 30 + } } } Rectangle { - id: appInfoPane - height: 28 - color: "#FFFFFF" - radius: 6 - - - MouseArea { + id: appInfoPane + height: 28 + color: "#FFFFFF" + radius: 6 + z:2 + MouseArea { anchors.fill: parent z: 10 hoverEnabled: true onEntered: { - showFullUrlBar(true); - } + showFullUrlBar(true); + } + /*onExited: { + showFullUrlBar(false); + }*/ } @@ -171,14 +183,15 @@ Rectangle { font.bold: true font.capitalization: Font.AllUppercase horizontalAlignment: Text.AlignRight - verticalAlignment: Text.AlignVCenter - + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + anchors { left: parent.left right: parent.horizontalCenter top: parent.top bottom: parent.bottom - rightMargin: 10 + leftMargin: 32 } color: "#928484" } @@ -189,13 +202,15 @@ Rectangle { font.bold: false horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter + elide: Text.ElideLeft anchors { left: parent.horizontalCenter right: parent.right top: parent.top bottom: parent.bottom - leftMargin: 10 + leftMargin: 32 + } color: "#C0AFAF" } @@ -212,7 +227,7 @@ Rectangle { } horizontalAlignment: Text.AlignHCenter - + style: TextFieldStyle { textColor: "#928484" background: Rectangle { @@ -225,16 +240,16 @@ Rectangle { z: 20 activeFocusOnPress: true Keys.onReturnPressed: { - webview.url = this.text; + // if there's no http, add it. + var url = this.text, + matches = url.match(/^([a-z]*\:\/\/)?([^\/.]+)(:?\/)(.*|$)/i), + requestedProtocol = (matches && matches[1] != "undefined")? "" : "http://"; + + webview.url = requestedProtocol + url; } - /* onFocusedChanged: { - if (focused) { - //uriNav.selectAll(); - } - }*/ } - z:2 + } Rectangle { @@ -243,6 +258,7 @@ Rectangle { height: 30 color: "#BDB6B6" radius: 6 + z:1 anchors { left: back.right @@ -251,19 +267,17 @@ Rectangle { rightMargin:10 top: parent.top topMargin: 23 - } - - z:1 + } } Rectangle { id: navBarBackground anchors.fill: parent + z:-1 gradient: Gradient { GradientStop { position: 0.0; color: "#F6F1F2" } GradientStop { position: 1.0; color: "#DED5D5" } } - z:-1 } states: [ @@ -326,8 +340,8 @@ Rectangle { WebEngineView { objectName: "webView" id: webview - experimental.settings.javascriptCanAccessClipboard: true - experimental.settings.localContentCanAccessRemoteUrls: true + //experimental.settings.javascriptCanAccessClipboard: true + //experimental.settings.localContentCanAccessRemoteUrls: true anchors { left: parent.left right: parent.right @@ -337,13 +351,49 @@ Rectangle { z: 10 Timer { - interval: 500; running: true; repeat: true + interval: 2000; running: true; repeat: true onTriggered: { - webview.runJavaScript("try{document.querySelector('meta[name=badge]').getAttribute('content')}catch(e){}", function(badge) { - if (badge) { - menuItem.secondaryTitle = badge; - } - }); + webview.runJavaScript("try{document.querySelector('meta[name=ethereum-dapp-info]').getAttribute('content')}catch(e){}", function(extraInfo) { + if (extraInfo) { + menuItem.secondaryTitle = extraInfo; + } + }); + webview.runJavaScript("try{document.querySelector('meta[name=ethereum-dapp-badge]').getAttribute('content')}catch(e){}", function(badge) { + if (badge) { + if (Number(badge)>0 && Number(badge)<999) { + menuItem.badgeNumber = Number(badge); + menuItem.badgeContent = "number" + } else if (badge == "warning") { + menuItem.badgeIcon = "\ue00e" + menuItem.badgeContent = "icon" + + } else if (badge == "ghost") { + menuItem.badgeIcon = "\ue01a" + menuItem.badgeContent = "icon" + + } else if (badge == "question") { + menuItem.badgeIcon = "\ue05d" + menuItem.badgeContent = "icon" + + } else if (badge == "info") { + menuItem.badgeIcon = "\ue08b" + menuItem.badgeContent = "icon" + + } else if (badge == "check") { + menuItem.badgeIcon = "\ue080" + menuItem.badgeContent = "icon" + + } else if (badge == "gear") { + menuItem.badgeIcon = "\ue09a" + menuItem.badgeContent = "icon" + + } else { + menuItem.badgeContent = "" + } + } else { + menuItem.badgeContent = "" + } + }); } } @@ -353,6 +403,12 @@ Rectangle { menuItem.title = pageTitle; }); + webView.runJavaScript("try{document.querySelector(\"link[rel='icon']\").getAttribute(\"href\")}catch(e){}", function(sideIcon){ + if(sideIcon){ + menuItem.icon = webview.url + sideIcon; + }; + }); + webView.runJavaScript("try{document.querySelector(\"meta[name='ethereum-dapp-url-bar-style']\").getAttribute(\"content\")}catch(e){}", function(topBarStyle){ if (!topBarStyle) { showFullUrlBar(true); @@ -382,10 +438,15 @@ Rectangle { }; }); + + webview.runJavaScript(eth.readFile("bignumber.min.js")); + webview.runJavaScript(eth.readFile("ethereum.js/dist/ethereum.js")); + var cleanTitle = webview.url.toString() var matches = cleanTitle.match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i); var domain = matches && matches[1]; + if (domain) appDomain.text = domain //webview.url.replace("a", "z") if (webview.title) diff --git a/cmd/mist/assets/qml/views/catalog.qml b/cmd/mist/assets/qml/views/catalog.qml index 884493eef..497d69ed1 100644 --- a/cmd/mist/assets/qml/views/catalog.qml +++ b/cmd/mist/assets/qml/views/catalog.qml @@ -85,35 +85,21 @@ Rectangle { property var domain: "ethereum-dapp-catalog.meteor.com" url: protocol + domain - //navigationRequest: WebEngineView.IgnoreRequest - // onLoadingChanged: { - // if (loadRequest.status == WebEngineView.LoadSucceededStatus) { - // webview.runJavaScript(eth.readFile("bignumber.min.js")); - // webview.runJavaScript(eth.readFile("ethereum.js/dist/ethereum.js")); - // } - // } - - //onNavigationRequested: { - // detect URL scheme prefix, most likely an external link - //var schemaRE = /^\w+:/; - //if (schemaRE.test(request.url)) { - // request.action = WebView.AcceptRequest; - //} else { - //request.action = WebView.IgnoreRequest; - // delegate request.url here - //} - //} + //experimental.settings.javascriptCanAccessClipboard: true + onJavaScriptConsoleMessage: { console.log(sourceID + ":" + lineNumber + ":" + JSON.stringify(message)); } - onNavigationRequested: { + onNavigationRequested: { + // this checks if the domain of the requested link is the same as the catalog's + // If it is, it opens on the same window, if it's not it opens a new tab + var cleanTitle = request.url.toString() var matches = cleanTitle.match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i); var requestedDomain = matches && matches[1]; - console.debug ("NavigationRequested: " + request.url + " navigationType=" + request.navigationType) if(request.navigationType==0){ @@ -126,10 +112,18 @@ Rectangle { } } + // onLoadingChanged: { + // if (loadRequest.status == WebEngineView.LoadSucceededStatus) { + // webview.runJavaScript(eth.readFile("mist.js")); + // } + // } } + + + WebEngineView { id: inspector visible: false @@ -137,6 +131,7 @@ Rectangle { anchors { left: root.left right: root.right + top: root.top bottom: root.bottom } diff --git a/cmd/mist/assets/qml/views/miner.qml b/cmd/mist/assets/qml/views/miner.qml index 6a199a925..e239c7d7b 100644 --- a/cmd/mist/assets/qml/views/miner.qml +++ b/cmd/mist/assets/qml/views/miner.qml @@ -9,7 +9,7 @@ import Ethereum 1.0 Rectangle { id: root property var title: "Miner" - property var iconSource: "../miner.png" + property var iconSource: "../mining-icon.png" property var menuItem color: "#00000000" diff --git a/cmd/mist/assets/qml/views/pending_tx.qml b/cmd/mist/assets/qml/views/pending_tx.qml index 4442a69db..3dcedeff2 100644 --- a/cmd/mist/assets/qml/views/pending_tx.qml +++ b/cmd/mist/assets/qml/views/pending_tx.qml @@ -41,4 +41,13 @@ Rectangle { pendingTxModel.insert(0, {hash: tx.hash, to: tx.address, from: tx.sender, value: tx.value, contract: isContract}) } + + function removeTx(tx) { + for (var i = 0; i < pendingTxModel.count; i++) { + if (tx.hash === pendingTxModel.get(i).hash) { + pendingTxModel.remove(i); + break; + } + } + } } diff --git a/cmd/mist/assets/qml/views/wallet.qml b/cmd/mist/assets/qml/views/wallet.qml index 59dbae848..2369390c3 100644 --- a/cmd/mist/assets/qml/views/wallet.qml +++ b/cmd/mist/assets/qml/views/wallet.qml @@ -9,7 +9,6 @@ import Ethereum 1.0 Rectangle { id: root property var title: "Wallet" - property var iconSource: "../facet.png" property var menuItem objectName: "walletView" diff --git a/cmd/mist/ext_app.go b/cmd/mist/ext_app.go index 4831884e5..7ac51db0b 100644 --- a/cmd/mist/ext_app.go +++ b/cmd/mist/ext_app.go @@ -43,7 +43,7 @@ type AppContainer interface { type ExtApplication struct { *xeth.XEth - eth core.EthManager + eth core.Backend events event.Subscription watcherQuitChan chan bool diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go index 208b553d2..c9419473c 100644 --- a/cmd/mist/gui.go +++ b/cmd/mist/gui.go @@ -41,7 +41,6 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/ui/qt/qwhisper" "github.com/ethereum/go-ethereum/xeth" "github.com/obscuren/qml" @@ -81,8 +80,6 @@ type Gui struct { config *ethutil.ConfigManager plugins map[string]plugin - - miner *miner.Miner } // Create GUI, but doesn't start it @@ -397,8 +394,6 @@ func (gui *Gui) update() { miningLabel := gui.getObjectByName("miningLabel") events := gui.eth.EventMux().Subscribe( - //eth.PeerListEvent{}, - core.NewBlockEvent{}, core.TxPreEvent{}, core.TxPostEvent{}, ) @@ -411,41 +406,11 @@ func (gui *Gui) update() { return } switch ev := ev.(type) { - case core.NewBlockEvent: - gui.processBlock(ev.Block, false) - //gui.setWalletValue(gui.eth.ChainManager().State().GetBalance(gui.address()), nil) - balance := ethutil.CurrencyToString(gui.eth.ChainManager().State().GetBalance(gui.address())) - gui.getObjectByName("balanceLabel").Set("text", fmt.Sprintf("%v", balance)) - case core.TxPreEvent: - tx := ev.Tx - - tstate := gui.eth.ChainManager().TransState() - cstate := gui.eth.ChainManager().State() - - taccount := tstate.GetAccount(gui.address()) - caccount := cstate.GetAccount(gui.address()) - unconfirmedFunds := new(big.Int).Sub(taccount.Balance(), caccount.Balance()) - - gui.setWalletValue(taccount.Balance(), unconfirmedFunds) - gui.insertTransaction("pre", tx) + gui.insertTransaction("pre", ev.Tx) case core.TxPostEvent: - tx := ev.Tx - object := state.GetAccount(gui.address()) - - if bytes.Compare(tx.From(), gui.address()) == 0 { - object.SubAmount(tx.Value()) - - gui.txDb.Put(tx.Hash(), tx.RlpEncode()) - } else if bytes.Compare(tx.To(), gui.address()) == 0 { - object.AddAmount(tx.Value()) - - gui.txDb.Put(tx.Hash(), tx.RlpEncode()) - } - - gui.setWalletValue(object.Balance(), nil) - state.UpdateStateObject(object) + gui.getObjectByName("pendingTxView").Call("removeTx", xeth.NewTx(ev.Tx)) } case <-peerUpdateTicker.C: @@ -454,7 +419,7 @@ func (gui *Gui) update() { case <-generalUpdateTicker.C: statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number().String() lastBlockLabel.Set("text", statusText) - miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.HashRate(), 10)+"/Khash") + miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.Miner().HashRate(), 10)+"/Khash") /* blockLength := gui.eth.BlockPool().BlocksProcessed diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go index 368fb002b..1a4d21012 100644 --- a/cmd/mist/ui_lib.go +++ b/cmd/mist/ui_lib.go @@ -30,7 +30,6 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event/filter" "github.com/ethereum/go-ethereum/javascript" - "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/xeth" "github.com/obscuren/qml" ) @@ -56,13 +55,10 @@ type UiLib struct { filterCallbacks map[int][]int filterManager *filter.FilterManager - - miner *miner.Miner } func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib { lib := &UiLib{XEth: xeth.New(eth), engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(eth), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*xeth.JSFilter)} - lib.miner = miner.New(eth.KeyManager().Address(), eth) lib.filterManager = filter.NewFilterManager(eth.EventMux()) go lib.filterManager.Start() @@ -221,20 +217,20 @@ func (self *UiLib) RemoveLocalTransaction(id int) { } func (self *UiLib) SetGasPrice(price string) { - self.miner.MinAcceptedGasPrice = ethutil.Big(price) + self.Miner().MinAcceptedGasPrice = ethutil.Big(price) } func (self *UiLib) SetExtra(extra string) { - self.miner.Extra = extra + self.Miner().Extra = extra } func (self *UiLib) ToggleMining() bool { - if !self.miner.Mining() { - self.miner.Start() + if !self.Miner().Mining() { + self.Miner().Start() return true } else { - self.miner.Stop() + self.Miner().Stop() return false } diff --git a/core/chain_manager.go b/core/chain_manager.go index c28e901c6..22d54be03 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -79,6 +79,7 @@ type ChainManager struct { genesisBlock *types.Block // Last known total difficulty mu sync.RWMutex + tsmu sync.RWMutex td *big.Int currentBlock *types.Block lastBlockHash []byte @@ -131,9 +132,19 @@ func (self *ChainManager) State() *state.StateDB { } func (self *ChainManager) TransState() *state.StateDB { + self.tsmu.RLock() + defer self.tsmu.RUnlock() + //tmp := self.transState + return self.transState } +func (self *ChainManager) setTransState(statedb *state.StateDB) { + self.tsmu.Lock() + defer self.tsmu.Unlock() + self.transState = statedb +} + func (bc *ChainManager) setLastBlock() { data, _ := bc.db.Get([]byte("LastBlock")) if len(data) != 0 { @@ -376,14 +387,12 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { self.setTotalDifficulty(td) self.insert(block) - self.transState = state.New(cblock.Root(), self.db) + self.setTransState(state.New(cblock.Root(), self.db)) self.eventMux.Post(ChainEvent{block, td}) } } self.mu.Unlock() - - self.eventMux.Post(NewBlockEvent{block}) } return nil diff --git a/core/filter.go b/core/filter.go index b93fcc8a5..88f12a67c 100644 --- a/core/filter.go +++ b/core/filter.go @@ -16,7 +16,7 @@ type FilterOptions struct { Earliest int64 Latest int64 - Address []byte + Address [][]byte Topics [][]byte Skip int @@ -25,11 +25,11 @@ type FilterOptions struct { // Filtering interface type Filter struct { - eth EthManager + eth Backend earliest int64 latest int64 skip int - address []byte + address [][]byte max int topics [][]byte @@ -40,7 +40,7 @@ type Filter struct { // Create a new filter which uses a bloom filter on blocks to figure out whether a particular block // is interesting or not. -func NewFilter(eth EthManager) *Filter { +func NewFilter(eth Backend) *Filter { return &Filter{eth: eth} } @@ -65,7 +65,7 @@ func (self *Filter) SetLatestBlock(latest int64) { self.latest = latest } -func (self *Filter) SetAddress(addr []byte) { +func (self *Filter) SetAddress(addr [][]byte) { self.address = addr } @@ -145,7 +145,8 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs { // Filter the logs for interesting stuff Logs: for _, log := range logs { - if !bytes.Equal(self.address, log.Address()) { + if !includes(self.address, log.Address()) { + //if !bytes.Equal(self.address, log.Address()) { continue } @@ -163,8 +164,18 @@ Logs: } func (self *Filter) bloomFilter(block *types.Block) bool { - if len(self.address) > 0 && !types.BloomLookup(block.Bloom(), self.address) { - return false + if len(self.address) > 0 { + var included bool + for _, addr := range self.address { + if types.BloomLookup(block.Bloom(), addr) { + included = true + break + } + } + + if !included { + return false + } } for _, topic := range self.topics { diff --git a/core/manager.go b/core/manager.go index f960fc5f0..bb039d063 100644 --- a/core/manager.go +++ b/core/manager.go @@ -7,12 +7,11 @@ import ( "github.com/ethereum/go-ethereum/p2p" ) -type EthManager interface { +type Backend interface { BlockProcessor() *BlockProcessor ChainManager() *ChainManager TxPool() *TxPool PeerCount() int - IsMining() bool IsListening() bool Peers() []*p2p.Peer KeyManager() *crypto.KeyManager diff --git a/eth/backend.go b/eth/backend.go index 8c2073574..690c7136d 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" ethlogger "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/nat" @@ -95,6 +96,7 @@ type Ethereum struct { eventMux *event.TypeMux txSub event.Subscription blockSub event.Subscription + miner *miner.Miner RpcServer rpc.RpcServer WsServer rpc.RpcServer @@ -151,6 +153,7 @@ func New(config *Config) (*Ethereum, error) { eth.blockProcessor = core.NewBlockProcessor(db, eth.txPool, eth.chainManager, eth.EventMux()) eth.chainManager.SetProcessor(eth.blockProcessor) eth.whisper = whisper.New() + eth.miner = miner.New(keyManager.Address(), eth) hasBlock := eth.chainManager.HasBlock insertChain := eth.chainManager.InsertChain @@ -181,69 +184,22 @@ func New(config *Config) (*Ethereum, error) { return eth, nil } -func (s *Ethereum) KeyManager() *crypto.KeyManager { - return s.keyManager -} - -func (s *Ethereum) Logger() ethlogger.LogSystem { - return s.logger -} - -func (s *Ethereum) Name() string { - return s.net.Name -} - -func (s *Ethereum) ChainManager() *core.ChainManager { - return s.chainManager -} - -func (s *Ethereum) BlockProcessor() *core.BlockProcessor { - return s.blockProcessor -} - -func (s *Ethereum) TxPool() *core.TxPool { - return s.txPool -} - -func (s *Ethereum) BlockPool() *BlockPool { - return s.blockPool -} - -func (s *Ethereum) Whisper() *whisper.Whisper { - return s.whisper -} - -func (s *Ethereum) EventMux() *event.TypeMux { - return s.eventMux -} -func (self *Ethereum) Db() ethutil.Database { - return self.db -} - -func (s *Ethereum) IsMining() bool { - return s.Mining -} - -func (s *Ethereum) IsListening() bool { - // XXX TODO - return false -} - -func (s *Ethereum) PeerCount() int { - return s.net.PeerCount() -} - -func (s *Ethereum) Peers() []*p2p.Peer { - return s.net.Peers() -} - -func (s *Ethereum) MaxPeers() int { - return s.net.MaxPeers -} - -func (s *Ethereum) Coinbase() []byte { - return nil // TODO -} +func (s *Ethereum) KeyManager() *crypto.KeyManager { return s.keyManager } +func (s *Ethereum) Logger() ethlogger.LogSystem { return s.logger } +func (s *Ethereum) Name() string { return s.net.Name } +func (s *Ethereum) ChainManager() *core.ChainManager { return s.chainManager } +func (s *Ethereum) BlockProcessor() *core.BlockProcessor { return s.blockProcessor } +func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } +func (s *Ethereum) BlockPool() *BlockPool { return s.blockPool } +func (s *Ethereum) Whisper() *whisper.Whisper { return s.whisper } +func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } +func (s *Ethereum) Db() ethutil.Database { return s.db } +func (s *Ethereum) Miner() *miner.Miner { return s.miner } +func (s *Ethereum) IsListening() bool { return true } // Always listening +func (s *Ethereum) PeerCount() int { return s.net.PeerCount() } +func (s *Ethereum) Peers() []*p2p.Peer { return s.net.Peers() } +func (s *Ethereum) MaxPeers() int { return s.net.MaxPeers } +func (s *Ethereum) Coinbase() []byte { return nil } // TODO // Start the ethereum func (s *Ethereum) Start() error { diff --git a/event/filter/eth_filter.go b/event/filter/eth_filter.go index 295fcfbbf..d298d914d 100644 --- a/event/filter/eth_filter.go +++ b/event/filter/eth_filter.go @@ -60,7 +60,10 @@ func (self *FilterManager) GetFilter(id int) *core.Filter { func (self *FilterManager) filterLoop() { // Subscribe to events - events := self.eventMux.Subscribe(core.PendingBlockEvent{}, core.NewBlockEvent{}, state.Logs(nil)) + events := self.eventMux.Subscribe( + core.PendingBlockEvent{}, + core.ChainEvent{}, + state.Logs(nil)) out: for { @@ -69,7 +72,7 @@ out: break out case event := <-events.Chan(): switch event := event.(type) { - case core.NewBlockEvent: + case core.ChainEvent: self.filterMu.RLock() for _, filter := range self.filters { if filter.BlockCallback != nil { diff --git a/logger/types.go b/logger/types.go index f8dcb4e78..419382231 100644 --- a/logger/types.go +++ b/logger/types.go @@ -44,8 +44,10 @@ func (l *P2PConnecting) EventName() string { } type P2PConnected struct { - NumConnections int `json:"num_connections"` - RemoteId string `json:"remote_id"` + RemoteId string `json:"remote_id"` + RemoteAddress string `json:"remote_addr"` + RemoteVersionString string `json:"remote_version_string"` + NumConnections int `json:"num_connections"` LogEvent } diff --git a/miner/miner.go b/miner/miner.go index e3e7bead2..27afcf684 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -3,7 +3,7 @@ package miner import ( "math/big" - "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/pow/ezp" ) @@ -16,13 +16,13 @@ type Miner struct { MinAcceptedGasPrice *big.Int Extra string - coinbase []byte + Coinbase []byte mining bool } -func New(coinbase []byte, eth *eth.Ethereum) *Miner { +func New(coinbase []byte, eth core.Backend) *Miner { miner := &Miner{ - coinbase: coinbase, + Coinbase: coinbase, worker: newWorker(coinbase, eth), } diff --git a/miner/worker.go b/miner/worker.go index 2b64f3210..47b462e53 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/pow" @@ -25,7 +24,7 @@ type environment struct { uncles *set.Set } -func env(block *types.Block, eth *eth.Ethereum) *environment { +func env(block *types.Block, eth core.Backend) *environment { state := state.New(block.Root(), eth.Db()) env := &environment{ totalUsedGas: new(big.Int), @@ -63,7 +62,7 @@ type worker struct { quit chan struct{} pow pow.PoW - eth *eth.Ethereum + eth core.Backend chain *core.ChainManager proc *core.BlockProcessor coinbase []byte @@ -73,7 +72,7 @@ type worker struct { mining bool } -func newWorker(coinbase []byte, eth *eth.Ethereum) *worker { +func newWorker(coinbase []byte, eth core.Backend) *worker { return &worker{ eth: eth, mux: eth.EventMux(), diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go index b2a895442..69e9f3c2e 100644 --- a/p2p/discover/udp.go +++ b/p2p/discover/udp.go @@ -253,7 +253,8 @@ func (t *udp) loop() { case reply := <-t.replies: // run matching callbacks, remove if they return false. - for i, p := range pending { + for i := 0; i < len(pending); i++ { + p := pending[i] if reply.from == p.from && reply.ptype == p.ptype && p.callback(reply.data) { p.errc <- nil copy(pending[i:], pending[i+1:]) diff --git a/pow/ezp/pow.go b/pow/ezp/pow.go index 540381243..f4a8b80e5 100644 --- a/pow/ezp/pow.go +++ b/pow/ezp/pow.go @@ -21,7 +21,7 @@ type EasyPow struct { } func New() *EasyPow { - return &EasyPow{turbo: false} + return &EasyPow{turbo: true} } func (pow *EasyPow) GetHashrate() int64 { diff --git a/rpc/args.go b/rpc/args.go index 12e3103bc..429b385d5 100644 --- a/rpc/args.go +++ b/rpc/args.go @@ -1,6 +1,7 @@ package rpc import "encoding/json" + import "github.com/ethereum/go-ethereum/core" type GetBlockArgs struct { @@ -37,6 +38,35 @@ type NewTxArgs struct { Data string `json:"data"` } +func (obj *NewTxArgs) UnmarshalJSON(b []byte) (err error) { + // Data can be either specified as "data" or "code" :-/ + var ext struct { + From string + To string + Value string + Gas string + GasPrice string + Data string + Code string + } + + if err = json.Unmarshal(b, &ext); err == nil { + if len(ext.Data) == 0 { + ext.Data = ext.Code + } + obj.From = ext.From + obj.To = ext.To + obj.Value = ext.Value + obj.Gas = ext.Gas + obj.GasPrice = ext.GasPrice + obj.Data = ext.Data + + return + } + + return NewErrorResponse(ErrorDecodeArgs) +} + type PushTxArgs struct { Tx string `json:"tx"` } @@ -203,7 +233,7 @@ func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) { type FilterOptions struct { Earliest int64 Latest int64 - Address string + Address interface{} Topic []string Skip int Max int @@ -211,9 +241,22 @@ type FilterOptions struct { func toFilterOptions(options *FilterOptions) core.FilterOptions { var opts core.FilterOptions + + // Convert optional address slice/string to byte slice + if str, ok := options.Address.(string); ok { + opts.Address = [][]byte{fromHex(str)} + } else if slice, ok := options.Address.([]interface{}); ok { + bslice := make([][]byte, len(slice)) + for i, addr := range slice { + if saddr, ok := addr.(string); ok { + bslice[i] = fromHex(saddr) + } + } + opts.Address = bslice + } + opts.Earliest = options.Earliest opts.Latest = options.Latest - opts.Address = fromHex(options.Address) opts.Topics = make([][]byte, len(options.Topic)) for i, topic := range options.Topic { opts.Topics[i] = fromHex(topic) diff --git a/rpc/message.go b/rpc/message.go index 7983e003d..b5b852f54 100644 --- a/rpc/message.go +++ b/rpc/message.go @@ -342,3 +342,31 @@ func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) { rpclogger.DebugDetailf("%T %v", args, args) return args, nil } + +func (req *RpcRequest) ToRegisterArgs() (string, error) { + if len(req.Params) < 1 { + return "", NewErrorResponse(ErrorArguments) + } + + var args string + err := json.Unmarshal(req.Params[0], &args) + if err != nil { + return "", err + } + rpclogger.DebugDetailf("%T %v", args, args) + return args, nil +} + +func (req *RpcRequest) ToWatchTxArgs() (string, error) { + if len(req.Params) < 1 { + return "", NewErrorResponse(ErrorArguments) + } + + var args string + err := json.Unmarshal(req.Params[0], &args) + if err != nil { + return "", err + } + rpclogger.DebugDetailf("%T %v", args, args) + return args, nil +} diff --git a/rpc/packages.go b/rpc/packages.go index ef31ff1e1..8aa604aa5 100644 --- a/rpc/packages.go +++ b/rpc/packages.go @@ -1,21 +1,4 @@ /* - This file is part of go-ethereum - - go-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - go-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. -*/ -/* - For each request type, define the following: 1. RpcRequest "To" method [message.go], which does basic validation and conversion to "Args" type via json.Decoder() @@ -55,6 +38,9 @@ type EthereumApi struct { messagesMut sync.RWMutex messages map[int][]xeth.WhisperMessage + // Register keeps a list of accounts and transaction data + regmut sync.Mutex + register map[string][]*NewTxArgs db ethutil.Database } @@ -73,6 +59,36 @@ func NewEthereumApi(eth *xeth.XEth) *EthereumApi { return api } +func (self *EthereumApi) Register(args string, reply *interface{}) error { + self.regmut.Lock() + defer self.regmut.Unlock() + + if _, ok := self.register[args]; ok { + self.register[args] = nil // register with empty + } + return nil +} + +func (self *EthereumApi) Unregister(args string, reply *interface{}) error { + self.regmut.Lock() + defer self.regmut.Unlock() + + delete(self.register, args) + + return nil +} + +func (self *EthereumApi) WatchTx(args string, reply *interface{}) error { + self.regmut.Lock() + defer self.regmut.Unlock() + + txs := self.register[args] + self.register[args] = nil + + *reply = txs + return nil +} + func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error { var id int filter := core.NewFilter(self.xeth.Backend()) @@ -94,6 +110,9 @@ func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error filter := core.NewFilter(self.xeth.Backend()) callback := func(block *types.Block) { + self.logMut.Lock() + defer self.logMut.Unlock() + self.logs[id] = append(self.logs[id], &state.StateLog{}) } if args == "pending" { @@ -120,8 +139,13 @@ func (self *EthereumApi) FilterChanged(id int, reply *interface{}) error { } func (self *EthereumApi) Logs(id int, reply *interface{}) error { + self.logMut.Lock() + defer self.logMut.Unlock() + filter := self.filterManager.GetFilter(id) - *reply = toLogs(filter.Find()) + if filter != nil { + *reply = toLogs(filter.Find()) + } return nil } @@ -149,8 +173,13 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error { args.GasPrice = defaultGasPrice } - result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data) - *reply = result + // TODO if no_private_key then + if _, exists := p.register[args.From]; exists { + p.register[args.From] = append(p.register[args.From], args) + } else { + result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data) + *reply = result + } return nil } @@ -421,9 +450,33 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error return err } return p.FilterChanged(args, reply) + case "eth_filterLogs": + args, err := req.ToFilterChangedArgs() + if err != nil { + return err + } + return p.Logs(args, reply) case "eth_gasPrice": *reply = defaultGasPrice return nil + case "eth_register": + args, err := req.ToRegisterArgs() + if err != nil { + return err + } + return p.Register(args, reply) + case "eth_unregister": + args, err := req.ToRegisterArgs() + if err != nil { + return err + } + return p.Unregister(args, reply) + case "eth_watchTx": + args, err := req.ToWatchTxArgs() + if err != nil { + return err + } + return p.WatchTx(args, reply) case "web3_sha3": args, err := req.ToSha3Args() if err != nil { diff --git a/state/state_object.go b/state/state_object.go index 340939a5d..0c157403c 100644 --- a/state/state_object.go +++ b/state/state_object.go @@ -1,11 +1,13 @@ package state import ( + "bytes" "fmt" "math/big" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" ) @@ -71,8 +73,28 @@ func NewStateObject(addr []byte, db ethutil.Database) *StateObject { } func NewStateObjectFromBytes(address, data []byte, db ethutil.Database) *StateObject { + // TODO clean me up + var extobject struct { + Nonce uint64 + Balance *big.Int + Root []byte + CodeHash []byte + } + err := rlp.Decode(bytes.NewReader(data), &extobject) + if err != nil { + fmt.Println(err) + return nil + } + object := &StateObject{address: address, db: db} - object.RlpDecode(data) + //object.RlpDecode(data) + object.Nonce = extobject.Nonce + object.balance = extobject.Balance + object.codeHash = extobject.CodeHash + object.State = New(extobject.Root, db) + object.storage = make(map[string]*ethutil.Value) + object.gasPool = new(big.Int) + object.Code, _ = db.Get(extobject.CodeHash) return object } @@ -271,7 +293,6 @@ func (c *StateObject) CodeHash() ethutil.Bytes { func (c *StateObject) RlpDecode(data []byte) { decoder := ethutil.NewValueFromBytes(data) - c.Nonce = decoder.Get(0).Uint() c.balance = decoder.Get(1).BigInt() c.State = New(decoder.Get(2).Bytes(), c.db) //New(trie.New(ethutil.Config.Db, decoder.Get(2).Interface())) diff --git a/ui/filter.go b/ui/filter.go index 8f298a40c..0d1746915 100644 --- a/ui/filter.go +++ b/ui/filter.go @@ -15,7 +15,7 @@ func fromHex(s string) []byte { return nil } -func NewFilterFromMap(object map[string]interface{}, eth core.EthManager) *core.Filter { +func NewFilterFromMap(object map[string]interface{}, eth core.Backend) *core.Filter { filter := core.NewFilter(eth) if object["earliest"] != nil { @@ -29,8 +29,8 @@ func NewFilterFromMap(object map[string]interface{}, eth core.EthManager) *core. } if object["address"] != nil { - val := ethutil.NewValue(object["address"]) - filter.SetAddress(fromHex(val.Str())) + //val := ethutil.NewValue(object["address"]) + //filter.SetAddress(fromHex(val.Str())) } if object["max"] != nil { diff --git a/ui/qt/filter.go b/ui/qt/filter.go index bd3ad0303..48e8a7fae 100644 --- a/ui/qt/filter.go +++ b/ui/qt/filter.go @@ -6,7 +6,7 @@ import ( "github.com/obscuren/qml" ) -func NewFilterFromMap(object map[string]interface{}, eth core.EthManager) *core.Filter { +func NewFilterFromMap(object map[string]interface{}, eth core.Backend) *core.Filter { filter := ui.NewFilterFromMap(object, eth) if object["topics"] != nil { diff --git a/xeth/xeth.go b/xeth/xeth.go index 75d83f80b..f005105bb 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -14,8 +14,8 @@ import ( "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/whisper" ) @@ -27,13 +27,13 @@ type Backend interface { ChainManager() *core.ChainManager TxPool() *core.TxPool PeerCount() int - IsMining() bool IsListening() bool Peers() []*p2p.Peer KeyManager() *crypto.KeyManager Db() ethutil.Database EventMux() *event.TypeMux Whisper() *whisper.Whisper + Miner() *miner.Miner } type XEth struct { @@ -42,6 +42,7 @@ type XEth struct { chainManager *core.ChainManager state *State whisper *Whisper + miner *miner.Miner } func New(eth Backend) *XEth { @@ -50,15 +51,17 @@ func New(eth Backend) *XEth { blockProcessor: eth.BlockProcessor(), chainManager: eth.ChainManager(), whisper: NewWhisper(eth.Whisper()), + miner: eth.Miner(), } xeth.state = NewState(xeth) return xeth } -func (self *XEth) Backend() Backend { return self.eth } -func (self *XEth) State() *State { return self.state } -func (self *XEth) Whisper() *Whisper { return self.whisper } +func (self *XEth) Backend() Backend { return self.eth } +func (self *XEth) State() *State { return self.state } +func (self *XEth) Whisper() *Whisper { return self.whisper } +func (self *XEth) Miner() *miner.Miner { return self.miner } func (self *XEth) BlockByHash(strHash string) *Block { hash := fromHex(strHash) @@ -96,7 +99,7 @@ func (self *XEth) PeerCount() int { } func (self *XEth) IsMining() bool { - return self.eth.IsMining() + return self.miner.Mining() } func (self *XEth) IsListening() bool { @@ -216,7 +219,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st var ( statedb = self.chainManager.TransState() key = self.eth.KeyManager().KeyPair() - from = state.NewStateObject(key.Address(), self.eth.Db()) + from = statedb.GetOrNewStateObject(key.Address()) block = self.chainManager.CurrentBlock() to = statedb.GetOrNewStateObject(fromHex(toStr)) data = fromHex(dataStr) |