diff options
-rw-r--r-- | ethereal/assets/ext/big.js | 380 | ||||
-rw-r--r-- | ethereal/assets/ext/ethereum.js (renamed from ethereal/assets/ethereum.js) | 115 | ||||
-rw-r--r-- | ethereal/assets/ext/pre.js | 58 | ||||
-rw-r--r-- | ethereal/assets/ext/string.js | 58 | ||||
-rw-r--r-- | ethereal/assets/muted/index.html | 1 | ||||
-rw-r--r-- | ethereal/assets/qml/newTransaction/_new_contract.qml | 4 | ||||
-rw-r--r-- | ethereal/assets/qml/newTransaction/_simple_send.qml | 4 | ||||
-rw-r--r-- | ethereal/assets/qml/webapp.qml | 2 | ||||
-rw-r--r-- | ethereal/assets/samplecoin/samplecoin.html | 12 | ||||
-rw-r--r-- | ethereal/ethereum.go | 1 | ||||
-rw-r--r-- | ethereal/ui/gui.go | 148 | ||||
-rw-r--r-- | ethereal/ui/library.go | 85 | ||||
-rw-r--r-- | ethereal/ui/ui_lib.go | 16 | ||||
-rw-r--r-- | ethereum/ethereum.go | 4 |
14 files changed, 590 insertions, 298 deletions
diff --git a/ethereal/assets/ext/big.js b/ethereal/assets/ext/big.js new file mode 100644 index 000000000..db633fd2f --- /dev/null +++ b/ethereal/assets/ext/big.js @@ -0,0 +1,380 @@ +var bigInt = (function () { + var base = 10000000, logBase = 7; + var sign = { + positive: false, + negative: true + }; + + var normalize = function (first, second) { + var a = first.value, b = second.value; + var length = a.length > b.length ? a.length : b.length; + for (var i = 0; i < length; i++) { + a[i] = a[i] || 0; + b[i] = b[i] || 0; + } + for (var i = length - 1; i >= 0; i--) { + if (a[i] === 0 && b[i] === 0) { + a.pop(); + b.pop(); + } else break; + } + if (!a.length) a = [0], b = [0]; + first.value = a; + second.value = b; + }; + + var parse = function (text, first) { + if (typeof text === "object") return text; + text += ""; + var s = sign.positive, value = []; + if (text[0] === "-") { + s = sign.negative; + text = text.slice(1); + } + var base = 10; + if (text.slice(0, 2) == "0x") { + base = 16; + text = text.slice(2); + } + else { + var texts = text.split("e"); + if (texts.length > 2) throw new Error("Invalid integer"); + if (texts[1]) { + var exp = texts[1]; + if (exp[0] === "+") exp = exp.slice(1); + exp = parse(exp); + if (exp.lesser(0)) throw new Error("Cannot include negative exponent part for integers"); + while (exp.notEquals(0)) { + texts[0] += "0"; + exp = exp.prev(); + } + } + text = texts[0]; + } + if (text === "-0") text = "0"; + text = text.toUpperCase(); + var isValid = (base == 16 ? /^[0-9A-F]*$/ : /^[0-9]+$/).test(text); + if (!isValid) throw new Error("Invalid integer"); + if (base == 16) { + var val = bigInt(0); + while (text.length) { + v = text.charCodeAt(0) - 48; + if (v > 9) + v -= 7; + text = text.slice(1); + val = val.times(16).plus(v); + } + return val; + } + else { + while (text.length) { + var divider = text.length > logBase ? text.length - logBase : 0; + value.push(+text.slice(divider)); + text = text.slice(0, divider); + } + var val = bigInt(value, s); + if (first) normalize(first, val); + return val; + } + }; + + var goesInto = function (a, b) { + var a = bigInt(a, sign.positive), b = bigInt(b, sign.positive); + if (a.equals(0)) throw new Error("Cannot divide by 0"); + var n = 0; + do { + var inc = 1; + var c = bigInt(a.value, sign.positive), t = c.times(10); + while (t.lesser(b)) { + c = t; + inc *= 10; + t = t.times(10); + } + while (c.lesserOrEquals(b)) { + b = b.minus(c); + n += inc; + } + } while (a.lesserOrEquals(b)); + + return { + remainder: b.value, + result: n + }; + }; + + var bigInt = function (value, s) { + var self = { + value: value, + sign: s + }; + var o = { + value: value, + sign: s, + negate: function (m) { + var first = m || self; + return bigInt(first.value, !first.sign); + }, + abs: function (m) { + var first = m || self; + return bigInt(first.value, sign.positive); + }, + add: function (n, m) { + var s, first = self, second; + if (m) (first = parse(n)) && (second = parse(m)); + else second = parse(n, first); + s = first.sign; + if (first.sign !== second.sign) { + first = bigInt(first.value, sign.positive); + second = bigInt(second.value, sign.positive); + return s === sign.positive ? + o.subtract(first, second) : + o.subtract(second, first); + } + normalize(first, second); + var a = first.value, b = second.value; + var result = [], + carry = 0; + for (var i = 0; i < a.length || carry > 0; i++) { + var sum = (a[i] || 0) + (b[i] || 0) + carry; + carry = sum >= base ? 1 : 0; + sum -= carry * base; + result.push(sum); + } + return bigInt(result, s); + }, + plus: function (n, m) { + return o.add(n, m); + }, + subtract: function (n, m) { + var first = self, second; + if (m) (first = parse(n)) && (second = parse(m)); + else second = parse(n, first); + if (first.sign !== second.sign) return o.add(first, o.negate(second)); + if (first.sign === sign.negative) return o.subtract(o.negate(second), o.negate(first)); + if (o.compare(first, second) === -1) return o.negate(o.subtract(second, first)); + var a = first.value, b = second.value; + var result = [], + borrow = 0; + for (var i = 0; i < a.length; i++) { + var tmp = a[i] - borrow; + borrow = tmp < b[i] ? 1 : 0; + var minuend = (borrow * base) + tmp - b[i]; + result.push(minuend); + } + return bigInt(result, sign.positive); + }, + minus: function (n, m) { + return o.subtract(n, m); + }, + multiply: function (n, m) { + var s, first = self, second; + if (m) (first = parse(n)) && (second = parse(m)); + else second = parse(n, first); + s = first.sign !== second.sign; + var a = first.value, b = second.value; + var resultSum = []; + for (var i = 0; i < a.length; i++) { + resultSum[i] = []; + var j = i; + while (j--) { + resultSum[i].push(0); + } + } + var carry = 0; + for (var i = 0; i < a.length; i++) { + var x = a[i]; + for (var j = 0; j < b.length || carry > 0; j++) { + var y = b[j]; + var product = y ? (x * y) + carry : carry; + carry = product > base ? Math.floor(product / base) : 0; + product -= carry * base; + resultSum[i].push(product); + } + } + var max = -1; + for (var i = 0; i < resultSum.length; i++) { + var len = resultSum[i].length; + if (len > max) max = len; + } + var result = [], carry = 0; + for (var i = 0; i < max || carry > 0; i++) { + var sum = carry; + for (var j = 0; j < resultSum.length; j++) { + sum += resultSum[j][i] || 0; + } + carry = sum > base ? Math.floor(sum / base) : 0; + sum -= carry * base; + result.push(sum); + } + return bigInt(result, s); + }, + times: function (n, m) { + return o.multiply(n, m); + }, + divmod: function (n, m) { + var s, first = self, second; + if (m) (first = parse(n)) && (second = parse(m)); + else second = parse(n, first); + s = first.sign !== second.sign; + if (bigInt(first.value, first.sign).equals(0)) return { + quotient: bigInt([0], sign.positive), + remainder: bigInt([0], sign.positive) + }; + if (second.equals(0)) throw new Error("Cannot divide by zero"); + var a = first.value, b = second.value; + var result = [], remainder = []; + for (var i = a.length - 1; i >= 0; i--) { + var n = [a[i]].concat(remainder); + var quotient = goesInto(b, n); + result.push(quotient.result); + remainder = quotient.remainder; + } + result.reverse(); + return { + quotient: bigInt(result, s), + remainder: bigInt(remainder, first.sign) + }; + }, + divide: function (n, m) { + return o.divmod(n, m).quotient; + }, + over: function (n, m) { + return o.divide(n, m); + }, + mod: function (n, m) { + return o.divmod(n, m).remainder; + }, + pow: function (n, m) { + var first = self, second; + if (m) (first = parse(n)) && (second = parse(m)); + else second = parse(n, first); + var a = first, b = second; + if (b.lesser(0)) return ZERO; + if (b.equals(0)) return ONE; + var result = bigInt(a.value, a.sign); + + if (b.mod(2).equals(0)) { + var c = result.pow(b.over(2)); + return c.times(c); + } else { + return result.times(result.pow(b.minus(1))); + } + }, + next: function (m) { + var first = m || self; + return o.add(first, 1); + }, + prev: function (m) { + var first = m || self; + return o.subtract(first, 1); + }, + compare: function (n, m) { + var first = self, second; + if (m) (first = parse(n)) && (second = parse(m, first)); + else second = parse(n, first); + normalize(first, second); + if (first.value.length === 1 && second.value.length === 1 && first.value[0] === 0 && second.value[0] === 0) return 0; + if (second.sign !== first.sign) return first.sign === sign.positive ? 1 : -1; + var multiplier = first.sign === sign.positive ? 1 : -1; + var a = first.value, b = second.value; + for (var i = a.length - 1; i >= 0; i--) { + if (a[i] > b[i]) return 1 * multiplier; + if (b[i] > a[i]) return -1 * multiplier; + } + return 0; + }, + compareAbs: function (n, m) { + var first = self, second; + if (m) (first = parse(n)) && (second = parse(m, first)); + else second = parse(n, first); + first.sign = second.sign = sign.positive; + return o.compare(first, second); + }, + equals: function (n, m) { + return o.compare(n, m) === 0; + }, + notEquals: function (n, m) { + return !o.equals(n, m); + }, + lesser: function (n, m) { + return o.compare(n, m) < 0; + }, + greater: function (n, m) { + return o.compare(n, m) > 0; + }, + greaterOrEquals: function (n, m) { + return o.compare(n, m) >= 0; + }, + lesserOrEquals: function (n, m) { + return o.compare(n, m) <= 0; + }, + isPositive: function (m) { + var first = m || self; + return first.sign === sign.positive; + }, + isNegative: function (m) { + var first = m || self; + return first.sign === sign.negative; + }, + isEven: function (m) { + var first = m || self; + return first.value[0] % 2 === 0; + }, + isOdd: function (m) { + var first = m || self; + return first.value[0] % 2 === 1; + }, + toString: function (m) { + var first = m || self; + var str = "", len = first.value.length; + while (len--) { + if (first.value[len].toString().length === 8) str += first.value[len]; + else str += (base.toString() + first.value[len]).slice(-logBase); + } + while (str[0] === "0") { + str = str.slice(1); + } + if (!str.length) str = "0"; + var s = (first.sign === sign.positive || str == "0") ? "" : "-"; + return s + str; + }, + toHex: function (m) { + var first = m || self; + var str = ""; + var l = this.abs(); + while (l > 0) { + var qr = l.divmod(256); + var b = qr.remainder.toJSNumber(); + str = (b >> 4).toString(16) + (b & 15).toString(16) + str; + l = qr.quotient; + } + return (this.isNegative() ? "-" : "") + "0x" + str; + }, + toJSNumber: function (m) { + return +o.toString(m); + }, + valueOf: function (m) { + return o.toJSNumber(m); + } + }; + return o; + }; + + var ZERO = bigInt([0], sign.positive); + var ONE = bigInt([1], sign.positive); + var MINUS_ONE = bigInt([1], sign.negative); + + var fnReturn = function (a) { + if (typeof a === "undefined") return ZERO; + return parse(a); + }; + fnReturn.zero = ZERO; + fnReturn.one = ONE; + fnReturn.minusOne = MINUS_ONE; + return fnReturn; +})(); + +if (typeof module !== "undefined") { + module.exports = bigInt; +} + diff --git a/ethereal/assets/ethereum.js b/ethereal/assets/ext/ethereum.js index 8f1a60300..f565e58bd 100644 --- a/ethereal/assets/ethereum.js +++ b/ethereal/assets/ext/ethereum.js @@ -119,118 +119,3 @@ window.eth = { window.eth._callbacks = {} window.eth._onCallbacks = {} -function hello() { - debug("hello") - window.dataTest = true; -} - -function debug(/**/) { - var args = arguments; - var msg = "" - for(var i = 0; i < args.length; i++){ - if(typeof args[i] === "object") { - msg += " " + JSON.stringify(args[i]) - } else { - msg += args[i] - } - } - - postData({call:"debug", args:[msg]}) - document.getElementById("debug").innerHTML += "<br>" + msg -} - -// Helper function for generating pseudo callbacks and sending data to the QML part of the application -function postData(data, cb) { - data._seed = Math.floor(Math.random() * 1000000) - if(cb) { - eth._callbacks[data._seed] = cb; - } - - if(data.args === undefined) { - data.args = []; - } - - navigator.qt.postMessage(JSON.stringify(data)); -} - -navigator.qt.onmessage = function(ev) { - var data = JSON.parse(ev.data) - - if(data._event !== undefined) { - eth.trigger(data._event, data.data); - } else { - if(data._seed) { - var cb = eth._callbacks[data._seed]; - if(cb) { - // Figure out whether the returned data was an array - // array means multiple return arguments (multiple params) - if(data.data instanceof Array) { - cb.apply(this, data.data) - } else { - cb.call(this, data.data) - } - - // Remove the "trigger" callback - delete eth._callbacks[ev._seed]; - } - } - } -} - -window.eth._0 = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" -String.prototype.pad = function(len) { - var bin = this.bin(); - var l = bin.length; - if(l < 32) { - return eth._0.substr(0, 32 - bin.length) + bin; - } - - return bin; -} - -String.prototype.unpad = function() { - var i, l; - for(i = 0, l = this.length; i < l; i++) { - if(this[i] != "\0") { - return this.substr(i, this.length); - } - } - - return this.substr(i, this.length); -} - -String.prototype.bin = function() { - if(this.substr(0, 2) == "0x") { - return this.hex2bin(); - } else if(/^\d+$/.test(this)) { - return this.num2bin() - } - - // Otherwise we'll return the "String" object instead of an actual string - return this.substr(0, this.length) -} - -String.prototype.unbin = function() { - var i, l, o = ''; - for(i = 0, l = this.length; i < l; i++) { - var n = this.charCodeAt(i).toString(16); - o += n.length < 2 ? '0' + n : n; - } - - return "0x" + o; -} - -String.prototype.hex2bin = function() { - bytes = [] - - for(var i=2; i< this.length-1; i+=2) { - bytes.push(parseInt(this.substr(i, 2), 16)); - } - - return String.fromCharCode.apply(String, bytes); -} - -String.prototype.num2bin = function() { - return ("0x"+parseInt(this).toString(16)).bin() -} - diff --git a/ethereal/assets/ext/pre.js b/ethereal/assets/ext/pre.js new file mode 100644 index 000000000..ca520f152 --- /dev/null +++ b/ethereal/assets/ext/pre.js @@ -0,0 +1,58 @@ +function debug(/**/) { + var args = arguments; + var msg = "" + for(var i = 0; i < args.length; i++){ + if(typeof args[i] === "object") { + msg += " " + JSON.stringify(args[i]) + } else { + msg += " " + args[i] + } + } + + postData({call:"debug", args:[msg]}) + document.getElementById("debug").innerHTML += "<br>" + msg +} + +// Helper function for generating pseudo callbacks and sending data to the QML part of the application +function postData(data, cb) { + data._seed = Math.floor(Math.random() * 1000000) + if(cb) { + eth._callbacks[data._seed] = cb; + } + + if(data.args === undefined) { + data.args = []; + } + + navigator.qt.postMessage(JSON.stringify(data)); +} + +navigator.qt.onmessage = function(ev) { + var data = JSON.parse(ev.data) + + if(data._event !== undefined) { + eth.trigger(data._event, data.data); + } else { + if(data._seed) { + var cb = eth._callbacks[data._seed]; + if(cb) { + // Figure out whether the returned data was an array + // array means multiple return arguments (multiple params) + if(data.data instanceof Array) { + cb.apply(this, data.data) + } else { + cb.call(this, data.data) + } + + // Remove the "trigger" callback + delete eth._callbacks[ev._seed]; + } + } + } +} + +window.onerror = function(message, file, lineNumber, column, errorObj) { + debug(file, message, lineNumber+":"+column, errorObj); + + return false; +} diff --git a/ethereal/assets/ext/string.js b/ethereal/assets/ext/string.js new file mode 100644 index 000000000..2473b5c36 --- /dev/null +++ b/ethereal/assets/ext/string.js @@ -0,0 +1,58 @@ +String.prototype.pad = function(l, r) { + if (r === undefined) { + r = l + if (!(this.substr(0, 2) == "0x" || /^\d+$/.test(this))) + l = 0 + } + var ret = this.bin(); + while (ret.length < l) + ret = "\0" + ret + while (ret.length < r) + ret = ret + "\0" + return ret; +} + +String.prototype.unpad = function() { + var i = this.length; + while (i && this[i - 1] == "\0") + --i + return this.substr(0, i) +} + +String.prototype.bin = function() { + if (this.substr(0, 2) == "0x") { + bytes = [] + var i = 2; + + // Check if it's odd - pad with a zero if so. + if (this.length % 2) + bytes.push(parseInt(this.substr(i++, 1), 16)) + + for (; i < this.length - 1; i += 2) + bytes.push(parseInt(this.substr(i, 2), 16)); + + return String.fromCharCode.apply(String, bytes); + } else if (/^\d+$/.test(this)) + return bigInt(this.substr(0)).toHex().bin() + + // Otherwise we'll return the "String" object instead of an actual string + return this.substr(0, this.length) +} + +String.prototype.unbin = function() { + var i, l, o = ''; + for(i = 0, l = this.length; i < l; i++) { + var n = this.charCodeAt(i).toString(16); + o += n.length < 2 ? '0' + n : n; + } + + return "0x" + o; +} + +String.prototype.dec = function() { + return bigInt(this.substr(0)).toString() +} + +String.prototype.hex = function() { + return bigInt(this.substr(0)).toHex() +} diff --git a/ethereal/assets/muted/index.html b/ethereal/assets/muted/index.html index 14949b5ac..84584e373 100644 --- a/ethereal/assets/muted/index.html +++ b/ethereal/assets/muted/index.html @@ -46,7 +46,6 @@ .CodeMirror { height: 70%; - font-size: 14pt; } </style> </head> diff --git a/ethereal/assets/qml/newTransaction/_new_contract.qml b/ethereal/assets/qml/newTransaction/_new_contract.qml index 0794d3dcd..f8f3d53a0 100644 --- a/ethereal/assets/qml/newTransaction/_new_contract.qml +++ b/ethereal/assets/qml/newTransaction/_new_contract.qml @@ -150,7 +150,7 @@ Component { text: "Send" onClicked: { //this.enabled = false - var res = eth.createTx(txFuelRecipient.text, txValue.text, txGas.text, txGasPrice.text, codeView.text) + var res = eth.create(txFuelRecipient.text, txValue.text, txGas.text, txGasPrice.text, codeView.text) if(res[1]) { txResult.text = "Your contract <b>could not</b> be send over the network:\n<b>" txResult.text += res[1].error() @@ -158,7 +158,7 @@ Component { mainContractColumn.state = "ERROR" } else { txResult.text = "Your transaction has been submitted:\n" - txOutput.text = res[0] + txOutput.text = res[0].address mainContractColumn.state = "DONE" } } diff --git a/ethereal/assets/qml/newTransaction/_simple_send.qml b/ethereal/assets/qml/newTransaction/_simple_send.qml index d460797ea..12420c15a 100644 --- a/ethereal/assets/qml/newTransaction/_simple_send.qml +++ b/ethereal/assets/qml/newTransaction/_simple_send.qml @@ -77,12 +77,12 @@ Component { text: "Send" onClicked: { //this.enabled = false - var res = eth.createTx(txSimpleRecipient.text, txSimpleValue.text,"","","") + var res = eth.transact(txSimpleRecipient.text, txSimpleValue.text,"","","") if(res[1]) { txSimpleResult.text = "There has been an error broadcasting your transaction:" + res[1].error() } else { txSimpleResult.text = "Your transaction has been broadcasted over the network.\nYour transaction id is:" - txSimpleOutput.text = res[0] + txSimpleOutput.text = res[0].hash this.visible = false simpleSendColumn.state = "DONE" } diff --git a/ethereal/assets/qml/webapp.qml b/ethereal/assets/qml/webapp.qml index d02c9a82e..1f3c3874a 100644 --- a/ethereal/assets/qml/webapp.qml +++ b/ethereal/assets/qml/webapp.qml @@ -39,7 +39,7 @@ ApplicationWindow { experimental.preferences.javascriptEnabled: true experimental.preferences.navigatorQtObjectEnabled: true experimental.preferences.developerExtrasEnabled: true - experimental.userScripts: [ui.assetPath("ethereum.js")] + experimental.userScripts: [ui.assetPath("ext/pre.js"), ui.assetPath("ext/big.js"), ui.assetPath("ext/string.js"), ui.assetPath("ext/ethereum.js")] experimental.onMessageReceived: { console.log("[onMessageReceived]: ", message.data) // TODO move to messaging.js diff --git a/ethereal/assets/samplecoin/samplecoin.html b/ethereal/assets/samplecoin/samplecoin.html index c1ee941a2..384936780 100644 --- a/ethereal/assets/samplecoin/samplecoin.html +++ b/ethereal/assets/samplecoin/samplecoin.html @@ -5,19 +5,18 @@ <link rel="stylesheet" href="bootstrap.min.css"> <link rel="stylesheet" href="bootstrap-theme.min.css"> <link rel="stylesheet" href="samplecoin.css"> -<script src="promise.min.js"></script> <meta name="viewport" content="minimum-scale=1; maximum-scale=1; initial-scale=1;"> <script type="text/javascript"> -var jefcoinAddr = "3dff537f51350239abc95c76a5864aa605259e7d" +var jefcoinAddr = "b7cb72c47ec4f31751d0d628b5a33fd6671bbba0" var mAddr = "" function createTransaction() { - var addr = document.querySelector("#addr").value; - var amount = document.querySelector("#amount").value; + var addr = ("0x" + document.querySelector("#addr").value).pad(32); + var amount = document.querySelector("#amount").value.pad(32); - var data = (("0x"+addr).pad(32) + amount.pad(32)).unbin() + var data = (addr + amount).unbin(); eth.transact(mAddr, jefcoinAddr, 0, "10000000", "250", data, function(receipt) { debug("received tx hash:", reciept.address) }) @@ -27,9 +26,8 @@ function init() { eth.set({width: 500}); eth.getKey(function(sec) { + mAddr = sec; eth.getSecretToAddress(sec, function(addr) { - mAddr = addr; - eth.getStorageAt(jefcoinAddr, addr, function(storage) { document.querySelector("#current-amount").innerHTML = storage; }); diff --git a/ethereal/ethereum.go b/ethereal/ethereum.go index f3240adec..8b8889e37 100644 --- a/ethereal/ethereum.go +++ b/ethereal/ethereum.go @@ -42,7 +42,6 @@ func main() { ethchain.InitFees() ethutil.ReadConfig(DataDir) - ethutil.Config.Seed = UseSeed // Instantiated a eth stack ethereum, err := eth.New(eth.CapDefault, UseUPnP) diff --git a/ethereal/ui/gui.go b/ethereal/ui/gui.go index 522c081a3..92c6e9389 100644 --- a/ethereal/ui/gui.go +++ b/ethereal/ui/gui.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/eth-go/ethpub" "github.com/ethereum/eth-go/ethutil" "github.com/go-qml/qml" + "github.com/obscuren/mutan" "math/big" "strings" ) @@ -28,6 +29,8 @@ type Gui struct { txDb *ethdb.LDBDatabase addr []byte + + pub *ethpub.PEthereum } // Create GUI, but doesn't start it @@ -46,14 +49,16 @@ func New(ethereum *eth.Ethereum) *Gui { key := ethutil.Config.Db.GetKeys()[0] addr = key.Address() - ethereum.StateManager().WatchAddr(addr) + //ethereum.StateManager().WatchAddr(addr) } - return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr} + pub := ethpub.NewPEthereum(ethereum.StateManager(), ethereum.BlockChain(), ethereum.TxPool()) + + return &Gui{eth: ethereum, lib: lib, txDb: db, addr: addr, pub: pub} } -func (ui *Gui) Start(assetPath string) { - defer ui.txDb.Close() +func (gui *Gui) Start(assetPath string) { + defer gui.txDb.Close() // Register ethereum functions qml.RegisterTypes("Ethereum", 1, 0, []qml.TypeSpec{{ @@ -62,15 +67,15 @@ func (ui *Gui) Start(assetPath string) { Init: func(p *ethpub.PTx, obj qml.Object) { p.Value = ""; p.Hash = ""; p.Address = "" }, }}) - ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.2")) + ethutil.Config.SetClientString(fmt.Sprintf("/Ethereal v%s", "0.5.0 RC2")) ethutil.Config.Log.Infoln("[GUI] Starting GUI") // Create a new QML engine - ui.engine = qml.NewEngine() - context := ui.engine.Context() + gui.engine = qml.NewEngine() + context := gui.engine.Context() // Expose the eth library and the ui library to QML - context.SetVar("eth", ui.lib) - uiLib := NewUiLib(ui.engine, ui.eth, assetPath) + context.SetVar("eth", gui) + uiLib := NewUiLib(gui.engine, gui.eth, assetPath) context.SetVar("ui", uiLib) // Load the main QML interface @@ -80,9 +85,9 @@ func (ui *Gui) Start(assetPath string) { firstRun := len(data) == 0 if firstRun { - component, err = ui.engine.LoadFile(uiLib.AssetPath("qml/first_run.qml")) + component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/first_run.qml")) } else { - component, err = ui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml")) + component, err = gui.engine.LoadFile(uiLib.AssetPath("qml/wallet.qml")) } if err != nil { ethutil.Config.Log.Infoln("FATAL: asset not found: you can set an alternative asset path on on the command line using option 'asset_path'") @@ -90,65 +95,60 @@ func (ui *Gui) Start(assetPath string) { panic(err) } - ui.win = component.CreateWindow(nil) - uiLib.win = ui.win - db := &Debugger{ui.win, make(chan bool)} - ui.lib.Db = db + gui.win = component.CreateWindow(nil) + uiLib.win = gui.win + db := &Debugger{gui.win, make(chan bool)} + gui.lib.Db = db uiLib.Db = db - // Register the ui as a block processor - //ui.eth.BlockManager.SecondaryBlockProcessor = ui - //ui.eth.TxPool.SecondaryProcessor = ui - // Add the ui as a log system so we can log directly to the UGI - ethutil.Config.Log.AddLogSystem(ui) + ethutil.Config.Log.AddLogSystem(gui) // Loads previous blocks if firstRun == false { - go ui.setInitialBlockChain() - go ui.readPreviousTransactions() - go ui.update() + go gui.setInitialBlockChain() + go gui.readPreviousTransactions() + go gui.update() } - ui.win.Show() - ui.win.Wait() + gui.win.Show() + gui.win.Wait() - ui.eth.Stop() + gui.eth.Stop() } -func (ui *Gui) setInitialBlockChain() { +func (gui *Gui) setInitialBlockChain() { // Load previous 10 blocks - chain := ui.eth.BlockChain().GetChain(ui.eth.BlockChain().CurrentBlock.Hash(), 10) + chain := gui.eth.BlockChain().GetChain(gui.eth.BlockChain().CurrentBlock.Hash(), 10) for _, block := range chain { - ui.ProcessBlock(block) + gui.processBlock(block) } } -func (ui *Gui) readPreviousTransactions() { - it := ui.txDb.Db().NewIterator(nil, nil) +func (gui *Gui) readPreviousTransactions() { + it := gui.txDb.Db().NewIterator(nil, nil) for it.Next() { tx := ethchain.NewTransactionFromBytes(it.Value()) - ui.win.Root().Call("addTx", ethpub.NewPTx(tx)) + gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) } it.Release() } -func (ui *Gui) ProcessBlock(block *ethchain.Block) { - ui.win.Root().Call("addBlock", ethpub.NewPBlock(block)) +func (gui *Gui) processBlock(block *ethchain.Block) { + gui.win.Root().Call("addBlock", ethpub.NewPBlock(block)) } // Simple go routine function that updates the list of peers in the GUI -func (ui *Gui) update() { +func (gui *Gui) update() { txChan := make(chan ethchain.TxMsg, 1) - ui.eth.TxPool().Subscribe(txChan) + gui.eth.TxPool().Subscribe(txChan) - account := ui.eth.StateManager().GetAddrState(ui.addr).Object - unconfirmedFunds := new(big.Int) - ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(account.Amount))) + state := gui.eth.StateManager().TransState() - addrState := ui.eth.StateManager().GetAddrState(ui.addr) + unconfirmedFunds := new(big.Int) + gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(state.GetStateObject(gui.addr).Amount))) for { select { @@ -156,15 +156,19 @@ func (ui *Gui) update() { tx := txMsg.Tx if txMsg.Type == ethchain.TxPre { - if bytes.Compare(tx.Sender(), ui.addr) == 0 && addrState.Nonce <= tx.Nonce { - ui.win.Root().Call("addTx", ethpub.NewPTx(tx)) - ui.txDb.Put(tx.Hash(), tx.RlpEncode()) + object := state.GetStateObject(gui.addr) + + if bytes.Compare(tx.Sender(), gui.addr) == 0 && object.Nonce <= tx.Nonce { + gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) + gui.txDb.Put(tx.Hash(), tx.RlpEncode()) + + object.Nonce += 1 + state.SetStateObject(object) - addrState.Nonce += 1 unconfirmedFunds.Sub(unconfirmedFunds, tx.Value) - } else if bytes.Compare(tx.Recipient, ui.addr) == 0 { - ui.win.Root().Call("addTx", ethpub.NewPTx(tx)) - ui.txDb.Put(tx.Hash(), tx.RlpEncode()) + } else if bytes.Compare(tx.Recipient, gui.addr) == 0 { + gui.win.Root().Call("addTx", ethpub.NewPTx(tx)) + gui.txDb.Put(tx.Hash(), tx.RlpEncode()) unconfirmedFunds.Add(unconfirmedFunds, tx.Value) } @@ -174,46 +178,52 @@ func (ui *Gui) update() { pos = "-" } val := ethutil.CurrencyToString(new(big.Int).Abs(ethutil.BigCopy(unconfirmedFunds))) - str := fmt.Sprintf("%v (%s %v)", ethutil.CurrencyToString(account.Amount), pos, val) + str := fmt.Sprintf("%v (%s %v)", ethutil.CurrencyToString(object.Amount), pos, val) - ui.win.Root().Call("setWalletValue", str) + gui.win.Root().Call("setWalletValue", str) } else { - amount := account.Amount - if bytes.Compare(tx.Sender(), ui.addr) == 0 { - amount.Sub(account.Amount, tx.Value) - } else if bytes.Compare(tx.Recipient, ui.addr) == 0 { - amount.Add(account.Amount, tx.Value) + object := state.GetStateObject(gui.addr) + if bytes.Compare(tx.Sender(), gui.addr) == 0 { + object.SubAmount(tx.Value) + } else if bytes.Compare(tx.Recipient, gui.addr) == 0 { + object.AddAmount(tx.Value) } - ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(amount))) + gui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", ethutil.CurrencyToString(object.Amount))) + + state.SetStateObject(object) } } - - /* - accountAmount := ui.eth.BlockManager.GetAddrState(ui.addr).Account.Amount - ui.win.Root().Call("setWalletValue", fmt.Sprintf("%v", accountAmount)) - - ui.win.Root().Call("setPeers", fmt.Sprintf("%d / %d", ui.eth.Peers().Len(), ui.eth.MaxPeers)) - - time.Sleep(1 * time.Second) - */ - } } // Logging functions that log directly to the GUI interface -func (ui *Gui) Println(v ...interface{}) { +func (gui *Gui) Println(v ...interface{}) { str := strings.TrimRight(fmt.Sprintln(v...), "\n") lines := strings.Split(str, "\n") for _, line := range lines { - ui.win.Root().Call("addLog", line) + gui.win.Root().Call("addLog", line) } } -func (ui *Gui) Printf(format string, v ...interface{}) { +func (gui *Gui) Printf(format string, v ...interface{}) { str := strings.TrimRight(fmt.Sprintf(format, v...), "\n") lines := strings.Split(str, "\n") for _, line := range lines { - ui.win.Root().Call("addLog", line) + gui.win.Root().Call("addLog", line) } } + +func (gui *Gui) Transact(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) { + keyPair := ethutil.Config.Db.GetKeys()[0] + + return gui.pub.Transact(ethutil.Hex(keyPair.PrivateKey), recipient, value, gas, gasPrice, data) +} + +func (gui *Gui) Create(recipient, value, gas, gasPrice, data string) (*ethpub.PReceipt, error) { + keyPair := ethutil.Config.Db.GetKeys()[0] + + mainInput, initInput := mutan.PreProcess(data) + + return gui.pub.Create(ethutil.Hex(keyPair.PrivateKey), value, gas, gasPrice, initInput, mainInput) +} diff --git a/ethereal/ui/library.go b/ethereal/ui/library.go index 1328cd6b7..c889efb45 100644 --- a/ethereal/ui/library.go +++ b/ethereal/ui/library.go @@ -1,10 +1,8 @@ package ethui import ( - "encoding/hex" "fmt" "github.com/ethereum/eth-go/ethchain" - "github.com/ethereum/eth-go/ethpub" "github.com/ethereum/eth-go/ethutil" "github.com/ethereum/go-ethereum/utils" "github.com/obscuren/secp256k1-go" @@ -43,86 +41,3 @@ func (lib *EthLib) CreateAndSetPrivKey() (string, string, string, string) { mnemonicString := strings.Join(mne, " ") return mnemonicString, fmt.Sprintf("%x", pair.Address()), fmt.Sprintf("%x", prv), fmt.Sprintf("%x", pub) } - -func (lib *EthLib) GetKey() string { - return ethutil.Hex(ethutil.Config.Db.GetKeys()[0].Address()) -} - -func (lib *EthLib) GetStateObject(address string) *ethpub.PStateObject { - stateObject := lib.stateManager.ProcState().GetContract(ethutil.FromHex(address)) - if stateObject != nil { - return ethpub.NewPStateObject(stateObject) - } - - // See GetStorage for explanation on "nil" - return ethpub.NewPStateObject(nil) -} - -func (lib *EthLib) Watch(addr, storageAddr string) { - // lib.stateManager.Watch(ethutil.FromHex(addr), ethutil.FromHex(storageAddr)) -} - -func (lib *EthLib) CreateTx(recipient, valueStr, gasStr, gasPriceStr, dataStr string) (string, error) { - return lib.Transact(recipient, valueStr, gasStr, gasPriceStr, dataStr) -} - -func (lib *EthLib) Transact(recipient, valueStr, gasStr, gasPriceStr, dataStr string) (string, error) { - var hash []byte - var contractCreation bool - if len(recipient) == 0 { - contractCreation = true - } else { - var err error - hash, err = hex.DecodeString(recipient) - if err != nil { - return "", err - } - } - - keyPair := ethutil.Config.Db.GetKeys()[0] - value := ethutil.Big(valueStr) - gas := ethutil.Big(gasStr) - gasPrice := ethutil.Big(gasPriceStr) - var tx *ethchain.Transaction - // Compile and assemble the given data - if contractCreation { - // Compile script - mainScript, initScript, err := utils.CompileScript(dataStr) - if err != nil { - return "", err - } - - tx = ethchain.NewContractCreationTx(value, gas, gasPrice, mainScript, initScript) - } else { - lines := strings.Split(dataStr, "\n") - var data []byte - for _, line := range lines { - data = append(data, ethutil.BigToBytes(ethutil.Big(line), 256)...) - } - - tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, data) - } - acc := lib.stateManager.GetAddrState(keyPair.Address()) - tx.Nonce = acc.Nonce - tx.Sign(keyPair.PrivateKey) - lib.txPool.QueueTransaction(tx) - - if contractCreation { - ethutil.Config.Log.Infof("Contract addr %x", tx.Hash()[12:]) - } else { - ethutil.Config.Log.Infof("Tx hash %x", tx.Hash()) - } - - return ethutil.Hex(tx.Hash()), nil -} - -func (lib *EthLib) GetBlock(hexHash string) *ethpub.PBlock { - hash, err := hex.DecodeString(hexHash) - if err != nil { - return nil - } - - block := lib.blockChain.GetBlock(hash) - - return ðpub.PBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Hex(block.Hash())} -} diff --git a/ethereal/ui/ui_lib.go b/ethereal/ui/ui_lib.go index 0feb522bc..35ceb7d79 100644 --- a/ethereal/ui/ui_lib.go +++ b/ethereal/ui/ui_lib.go @@ -59,14 +59,6 @@ func (ui *UiLib) OpenHtml(path string) { go app.run() } -func (ui *UiLib) Watch(addr, storageAddr string) { - if len(storageAddr) == 0 { - ui.eth.Reactor().Subscribe("storage:"+string(ethutil.FromHex(addr))+":"+string(ethutil.FromHex(storageAddr)), nil) - } else { - ui.eth.Reactor().Subscribe("object:"+string(ethutil.FromHex(addr)), nil) - } -} - func (ui *UiLib) Muted(content string) { component, err := ui.engine.LoadFile(ui.AssetPath("qml/muted.qml")) if err != nil { @@ -78,8 +70,6 @@ func (ui *UiLib) Muted(content string) { go func() { path := "file://" + ui.AssetPath("muted/index.html") win.Set("url", path) - //debuggerPath := "file://" + ui.AssetPath("muted/debugger.html") - //win.Set("debugUrl", debuggerPath) win.Show() win.Wait() @@ -88,7 +78,7 @@ func (ui *UiLib) Muted(content string) { func (ui *UiLib) Connect(button qml.Object) { if !ui.connected { - ui.eth.Start() + ui.eth.Start(true) ui.connected = true button.Set("enabled", false) } @@ -149,9 +139,9 @@ func (ui *UiLib) DebugTx(recipient, valueStr, gasStr, gasPriceStr, data string) // Contract addr as test address keyPair := ethutil.Config.Db.GetKeys()[0] - account := ui.eth.StateManager().GetAddrState(keyPair.Address()).Object + account := ui.eth.StateManager().TransState().GetStateObject(keyPair.Address()) c := ethchain.MakeContract(callerTx, state) - callerClosure := ethchain.NewClosure(account, c, c.Script(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr), ethutil.Big(valueStr)) + callerClosure := ethchain.NewClosure(account, c, c.Script(), state, ethutil.Big(gasStr), ethutil.Big(gasPriceStr)) block := ui.eth.BlockChain().CurrentBlock vm := ethchain.NewVm(state, ui.eth.StateManager(), ethchain.RuntimeVars{ diff --git a/ethereum/ethereum.go b/ethereum/ethereum.go index 8719f3e87..2f05bf2a1 100644 --- a/ethereum/ethereum.go +++ b/ethereum/ethereum.go @@ -73,7 +73,6 @@ func main() { }*/ ethchain.InitFees() - ethutil.Config.Seed = UseSeed // Instantiated a eth stack ethereum, err := eth.New(eth.CapDefault, UseUPnP) @@ -139,7 +138,8 @@ func main() { } RegisterInterrupts(ethereum) - ethereum.Start() + + ethereum.Start(UseSeed) if StartMining { logger.Infoln("Miner started") |