aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/mist/assets/backButtonDisabled.pngbin0 -> 634 bytes
-rw-r--r--cmd/mist/assets/backButtonDisabled@2x.pngbin0 -> 1458 bytes
-rw-r--r--cmd/mist/assets/backButtonHover.pngbin0 -> 657 bytes
-rw-r--r--cmd/mist/assets/backButtonHover@2x.pngbin0 -> 1517 bytes
-rw-r--r--cmd/mist/assets/browser.pngbin5329 -> 756 bytes
-rw-r--r--cmd/mist/assets/browser@2x.pngbin0 -> 1603 bytes
-rw-r--r--cmd/mist/assets/examples/coin.html5
-rw-r--r--cmd/mist/assets/examples/info.html4
-rw-r--r--cmd/mist/assets/ext/ethereum.js/dist/ethereum.js2
-rw-r--r--cmd/mist/assets/ext/mist.js35
-rw-r--r--cmd/mist/assets/miner.pngbin2100 -> 0 bytes
-rw-r--r--cmd/mist/assets/mining-icon.pngbin0 -> 1029 bytes
-rw-r--r--cmd/mist/assets/mining-icon@2x.pngbin0 -> 2312 bytes
-rw-r--r--cmd/mist/assets/qml/main.qml174
-rw-r--r--cmd/mist/assets/qml/views/browser.qml199
-rw-r--r--cmd/mist/assets/qml/views/catalog.qml35
-rw-r--r--cmd/mist/assets/qml/views/miner.qml2
-rw-r--r--cmd/mist/assets/qml/views/pending_tx.qml9
-rw-r--r--cmd/mist/assets/qml/views/wallet.qml1
-rw-r--r--cmd/mist/ext_app.go2
-rw-r--r--cmd/mist/gui.go41
-rw-r--r--cmd/mist/ui_lib.go14
-rw-r--r--core/chain_manager.go15
-rw-r--r--core/filter.go27
-rw-r--r--core/manager.go3
-rw-r--r--eth/backend.go82
-rw-r--r--event/filter/eth_filter.go7
-rw-r--r--logger/types.go6
-rw-r--r--miner/miner.go8
-rw-r--r--miner/worker.go7
-rw-r--r--p2p/discover/udp.go3
-rw-r--r--pow/ezp/pow.go2
-rw-r--r--rpc/args.go47
-rw-r--r--rpc/message.go28
-rw-r--r--rpc/packages.go93
-rw-r--r--state/state_object.go25
-rw-r--r--ui/filter.go6
-rw-r--r--ui/qt/filter.go2
-rw-r--r--xeth/xeth.go17
39 files changed, 534 insertions, 367 deletions
diff --git a/cmd/mist/assets/backButtonDisabled.png b/cmd/mist/assets/backButtonDisabled.png
new file mode 100644
index 000000000..428747870
--- /dev/null
+++ b/cmd/mist/assets/backButtonDisabled.png
Binary files differ
diff --git a/cmd/mist/assets/backButtonDisabled@2x.png b/cmd/mist/assets/backButtonDisabled@2x.png
new file mode 100644
index 000000000..0eaa6daa5
--- /dev/null
+++ b/cmd/mist/assets/backButtonDisabled@2x.png
Binary files differ
diff --git a/cmd/mist/assets/backButtonHover.png b/cmd/mist/assets/backButtonHover.png
new file mode 100644
index 000000000..8c5226f5a
--- /dev/null
+++ b/cmd/mist/assets/backButtonHover.png
Binary files differ
diff --git a/cmd/mist/assets/backButtonHover@2x.png b/cmd/mist/assets/backButtonHover@2x.png
new file mode 100644
index 000000000..406601ebc
--- /dev/null
+++ b/cmd/mist/assets/backButtonHover@2x.png
Binary files differ
diff --git a/cmd/mist/assets/browser.png b/cmd/mist/assets/browser.png
index 7b3b0870c..074c9ae3c 100644
--- a/cmd/mist/assets/browser.png
+++ b/cmd/mist/assets/browser.png
Binary files differ
diff --git a/cmd/mist/assets/browser@2x.png b/cmd/mist/assets/browser@2x.png
new file mode 100644
index 000000000..8ca417608
--- /dev/null
+++ b/cmd/mist/assets/browser@2x.png
Binary files differ
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
deleted file mode 100644
index 58e3f4dfe..000000000
--- a/cmd/mist/assets/miner.png
+++ /dev/null
Binary files differ
diff --git a/cmd/mist/assets/mining-icon.png b/cmd/mist/assets/mining-icon.png
new file mode 100644
index 000000000..db611e5c0
--- /dev/null
+++ b/cmd/mist/assets/mining-icon.png
Binary files differ
diff --git a/cmd/mist/assets/mining-icon@2x.png b/cmd/mist/assets/mining-icon@2x.png
new file mode 100644
index 000000000..16466d338
--- /dev/null
+++ b/cmd/mist/assets/mining-icon@2x.png
Binary files differ
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)