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/ext/ethereum.js b/ethereal/assets/ext/ethereum.js new file mode 100644 index 000000000..f565e58bd --- /dev/null +++ b/ethereal/assets/ext/ethereum.js @@ -0,0 +1,121 @@ +// Main Ethereum library +window.eth = { + prototype: Object(), + + // Retrieve block + // + // Either supply a number or a string. Type is determent for the lookup method + // string - Retrieves the block by looking up the hash + // number - Retrieves the block by looking up the block number + getBlock: function(numberOrHash, cb) { + var func; + if(typeof numberOrHash == "string") { + func = "getBlockByHash"; + } else { + func = "getBlockByNumber"; + } + postData({call: func, args: [numberOrHash]}, cb); + }, + + // Create transaction + // + // Transact between two state objects + transact: function(sec, recipient, value, gas, gasPrice, data, cb) { + postData({call: "transact", args: [sec, recipient, value, gas, gasPrice, data]}, cb); + }, + + create: function(sec, value, gas, gasPrice, init, body, cb) { + postData({call: "create", args: [sec, value, gas, gasPrice, init, body]}, cb); + }, + + getStorageAt: function(address, storageAddress, cb) { + postData({call: "getStorage", args: [address, storageAddress]}, cb); + }, + + getKey: function(cb) { + postData({call: "getKey"}, cb); + }, + + getBalanceAt: function(address, cb) { + postData({call: "getBalance", args: [address]}, cb); + }, + + getSecretToAddress: function(sec, cb) { + postData({call: "getSecretToAddress", args: [sec]}, cb); + }, + + watch: function(address, storageAddrOrCb, cb) { + var ev; + if(cb === undefined) { + cb = storageAddrOrCb; + storageAddrOrCb = ""; + ev = "object:"+address; + } else { + ev = "storage:"+address+":"+storageAddrOrCb; + } + + eth.on(ev, cb) + + postData({call: "watch", args: [address, storageAddrOrCb]}); + }, + + disconnect: function(address, storageAddrOrCb, cb) { + var ev; + if(cb === undefined) { + cb = storageAddrOrCb; + storageAddrOrCb = ""; + ev = "object:"+address; + } else { + ev = "storage:"+address+":"+storageAddrOrCb; + } + + eth.off(ev, cb) + + postData({call: "disconnect", args: [address, storageAddrOrCb]}); + }, + + set: function(props) { + postData({call: "set", args: props}); + }, + + on: function(event, cb) { + if(eth._onCallbacks[event] === undefined) { + eth._onCallbacks[event] = []; + } + + eth._onCallbacks[event].push(cb); + + return this + }, + + off: function(event, cb) { + if(eth._onCallbacks[event] !== undefined) { + var callbacks = eth._onCallbacks[event]; + for(var i = 0; i < callbacks.length; i++) { + if(callbacks[i] === cb) { + delete callbacks[i]; + } + } + } + + return this + }, + + trigger: function(event, data) { + var callbacks = eth._onCallbacks[event]; + if(callbacks !== undefined) { + for(var i = 0; i < callbacks.length; i++) { + // Figure out whether the returned data was an array + // array means multiple return arguments (multiple params) + if(data instanceof Array) { + callbacks[i].apply(this, data); + } else { + callbacks[i].call(this, data); + } + } + } + }, +} +window.eth._callbacks = {} +window.eth._onCallbacks = {} + 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 += "
" + 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/samplecoin/samplecoin.html b/ethereal/assets/samplecoin/samplecoin.html index 6330b9ea2..384936780 100644 --- a/ethereal/assets/samplecoin/samplecoin.html +++ b/ethereal/assets/samplecoin/samplecoin.html @@ -13,11 +13,9 @@ 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); - addr = ("0x"+addr).pad(32) - amount = amount.pad(32) var data = (addr + amount).unbin(); eth.transact(mAddr, jefcoinAddr, 0, "10000000", "250", data, function(receipt) { debug("received tx hash:", reciept.address)