Christoph Jentzsch
10 years ago
76 changed files with 5491 additions and 2552 deletions
@ -1,379 +0,0 @@ |
|||||
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; |
|
||||
} |
|
@ -1,217 +0,0 @@ |
|||||
/*
|
|
||||
This file is part of cpp-ethereum. |
|
||||
|
|
||||
cpp-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. |
|
||||
|
|
||||
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file EthStubServer.cpp
|
|
||||
* @authors: |
|
||||
* Gav Wood <i@gavwood.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
#if ETH_JSONRPC |
|
||||
#include "EthStubServer.h" |
|
||||
#include <libevmface/Instruction.h> |
|
||||
#include <liblll/Compiler.h> |
|
||||
#include <libethereum/Client.h> |
|
||||
#include <libwebthree/WebThree.h> |
|
||||
#include "CommonJS.h" |
|
||||
using namespace std; |
|
||||
using namespace dev; |
|
||||
using namespace dev::eth; |
|
||||
|
|
||||
EthStubServer::EthStubServer(jsonrpc::AbstractServerConnector* _conn, WebThreeDirect& _web3): |
|
||||
AbstractEthStubServer(_conn), |
|
||||
m_web3(_web3) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
//only works with a json spec that doesn't have notifications for now
|
|
||||
Json::Value EthStubServer::procedures() |
|
||||
{ |
|
||||
Json::Value ret; |
|
||||
|
|
||||
for (auto proc: this->GetProtocolHanlder()->GetProcedures()) |
|
||||
{ |
|
||||
Json::Value proc_j; |
|
||||
|
|
||||
proc_j[proc.second->GetProcedureType() == 0 ? "method" : "notification"] = proc.first; |
|
||||
|
|
||||
Json::Value params_j; |
|
||||
for (auto params: proc.second->GetParameters()) |
|
||||
params_j[params.first] = jsontypeToValue(params.second); |
|
||||
proc_j["params"] = params_j; |
|
||||
|
|
||||
proc_j["returns"] = jsontypeToValue(proc.second->GetReturnType()); |
|
||||
|
|
||||
ret.append(proc_j); |
|
||||
} |
|
||||
return ret; |
|
||||
} |
|
||||
|
|
||||
dev::eth::Client& EthStubServer::ethereum() const |
|
||||
{ |
|
||||
return *m_web3.ethereum(); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::coinbase() |
|
||||
{ |
|
||||
return toJS(ethereum().address()); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::balanceAt(std::string const& _a) |
|
||||
{ |
|
||||
return toJS(ethereum().balanceAt(jsToAddress(_a), 0)); |
|
||||
} |
|
||||
|
|
||||
Json::Value EthStubServer::check(Json::Value const& _as) |
|
||||
{ |
|
||||
// TODO
|
|
||||
// if (ethereum().changed())
|
|
||||
return _as; |
|
||||
/* else
|
|
||||
{ |
|
||||
Json::Value ret; |
|
||||
ret.resize(0); |
|
||||
return ret; |
|
||||
}*/ |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::create(const std::string& _bCode, const std::string& _sec, const std::string& _xEndowment, const std::string& _xGas, const std::string& _xGasPrice) |
|
||||
{ |
|
||||
Address ret = ethereum().transact(jsToSecret(_sec), jsToU256(_xEndowment), jsToBytes(_bCode), jsToU256(_xGas), jsToU256(_xGasPrice)); |
|
||||
return toJS(ret); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::lll(const std::string& _s) |
|
||||
{ |
|
||||
return "0x" + toHex(dev::eth::compileLLL(_s)); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::gasPrice() |
|
||||
{ |
|
||||
return "100000000000000"; |
|
||||
} |
|
||||
|
|
||||
bool EthStubServer::isContractAt(const std::string& _a) |
|
||||
{ |
|
||||
return ethereum().codeAt(jsToAddress(_a), 0).size(); |
|
||||
} |
|
||||
|
|
||||
bool EthStubServer::isListening() |
|
||||
{ |
|
||||
return m_web3.haveNetwork(); |
|
||||
} |
|
||||
|
|
||||
bool EthStubServer::isMining() |
|
||||
{ |
|
||||
return ethereum().isMining(); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::key() |
|
||||
{ |
|
||||
if (!m_keys.size()) |
|
||||
return std::string(); |
|
||||
return toJS(m_keys[0].sec()); |
|
||||
} |
|
||||
|
|
||||
Json::Value EthStubServer::keys() |
|
||||
{ |
|
||||
Json::Value ret; |
|
||||
for (auto i: m_keys) |
|
||||
ret.append(toJS(i.secret())); |
|
||||
return ret; |
|
||||
} |
|
||||
|
|
||||
int EthStubServer::peerCount() |
|
||||
{ |
|
||||
return m_web3.peerCount(); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::storageAt(const std::string& _a, const std::string& x) |
|
||||
{ |
|
||||
return toJS(ethereum().stateAt(jsToAddress(_a), jsToU256(x), 0)); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::stateAt(const std::string& _a, const std::string& x, const std::string& s) |
|
||||
{ |
|
||||
return toJS(ethereum().stateAt(jsToAddress(_a), jsToU256(x), std::atol(s.c_str()))); |
|
||||
} |
|
||||
|
|
||||
Json::Value EthStubServer::transact(const std::string& _aDest, const std::string& _bData, const std::string& _sec, const std::string& _xGas, const std::string& _xGasPrice, const std::string& _xValue) |
|
||||
{ |
|
||||
ethereum().transact(jsToSecret(_sec), jsToU256(_xValue), jsToAddress(_aDest), jsToBytes(_bData), jsToU256(_xGas), jsToU256(_xGasPrice)); |
|
||||
return Json::Value(); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::txCountAt(const std::string& _a) |
|
||||
{ |
|
||||
return toJS(ethereum().countAt(jsToAddress(_a), 0)); |
|
||||
} |
|
||||
|
|
||||
std::string EthStubServer::secretToAddress(const std::string& _a) |
|
||||
{ |
|
||||
return toJS(KeyPair(jsToSecret(_a)).address()); |
|
||||
} |
|
||||
|
|
||||
Json::Value EthStubServer::lastBlock() |
|
||||
{ |
|
||||
return blockJson(""); |
|
||||
} |
|
||||
|
|
||||
Json::Value EthStubServer::block(const std::string& _hash) |
|
||||
{ |
|
||||
return blockJson(_hash); |
|
||||
} |
|
||||
|
|
||||
Json::Value EthStubServer::blockJson(const std::string& _hash) |
|
||||
{ |
|
||||
Json::Value res; |
|
||||
auto const& bc = ethereum().blockChain(); |
|
||||
|
|
||||
auto b = _hash.length() ? bc.block(h256(_hash)) : bc.block(); |
|
||||
|
|
||||
auto bi = BlockInfo(b); |
|
||||
res["number"] = boost::lexical_cast<string>(bi.number); |
|
||||
res["hash"] = boost::lexical_cast<string>(bi.hash); |
|
||||
res["parentHash"] = boost::lexical_cast<string>(bi.parentHash); |
|
||||
res["sha3Uncles"] = boost::lexical_cast<string>(bi.sha3Uncles); |
|
||||
res["coinbaseAddress"] = boost::lexical_cast<string>(bi.coinbaseAddress); |
|
||||
res["stateRoot"] = boost::lexical_cast<string>(bi.stateRoot); |
|
||||
res["transactionsRoot"] = boost::lexical_cast<string>(bi.transactionsRoot); |
|
||||
res["minGasPrice"] = boost::lexical_cast<string>(bi.minGasPrice); |
|
||||
res["gasLimit"] = boost::lexical_cast<string>(bi.gasLimit); |
|
||||
res["gasUsed"] = boost::lexical_cast<string>(bi.gasUsed); |
|
||||
res["difficulty"] = boost::lexical_cast<string>(bi.difficulty); |
|
||||
res["timestamp"] = boost::lexical_cast<string>(bi.timestamp); |
|
||||
res["nonce"] = boost::lexical_cast<string>(bi.nonce); |
|
||||
|
|
||||
return res; |
|
||||
} |
|
||||
|
|
||||
Json::Value EthStubServer::jsontypeToValue(int _jsontype) |
|
||||
{ |
|
||||
switch (_jsontype) |
|
||||
{ |
|
||||
case jsonrpc::JSON_STRING: return ""; //Json::stringValue segfault, fuck knows why
|
|
||||
case jsonrpc::JSON_BOOLEAN: return Json::booleanValue; |
|
||||
case jsonrpc::JSON_INTEGER: return Json::intValue; |
|
||||
case jsonrpc::JSON_REAL: return Json::realValue; |
|
||||
case jsonrpc::JSON_OBJECT: return Json::objectValue; |
|
||||
case jsonrpc::JSON_ARRAY: return Json::arrayValue; |
|
||||
default: return Json::nullValue; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
#endif |
|
@ -1,66 +0,0 @@ |
|||||
/*
|
|
||||
This file is part of cpp-ethereum. |
|
||||
|
|
||||
cpp-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. |
|
||||
|
|
||||
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||
*/ |
|
||||
/** @file EthStubServer.h
|
|
||||
* @author Gav Wood <i@gavwood.com> |
|
||||
* @date 2014 |
|
||||
*/ |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <iostream> |
|
||||
#include <jsonrpc/rpc.h> |
|
||||
#include <libdevcrypto/Common.h> |
|
||||
#pragma GCC diagnostic push |
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter" |
|
||||
#include "abstractethstubserver.h" |
|
||||
#pragma GCC diagnostic pop |
|
||||
|
|
||||
namespace dev { class WebThreeDirect; namespace eth { class Client; } class KeyPair; } |
|
||||
|
|
||||
class EthStubServer: public AbstractEthStubServer |
|
||||
{ |
|
||||
public: |
|
||||
EthStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3); |
|
||||
|
|
||||
virtual Json::Value procedures(); |
|
||||
virtual std::string balanceAt(std::string const& _a); |
|
||||
virtual Json::Value check(Json::Value const& _as); |
|
||||
virtual std::string coinbase(); |
|
||||
virtual std::string create(const std::string& bCode, const std::string& sec, const std::string& xEndowment, const std::string& xGas, const std::string& xGasPrice); |
|
||||
virtual std::string gasPrice(); |
|
||||
virtual bool isContractAt(const std::string& a); |
|
||||
virtual bool isListening(); |
|
||||
virtual bool isMining(); |
|
||||
virtual std::string key(); |
|
||||
virtual Json::Value keys(); |
|
||||
virtual int peerCount(); |
|
||||
virtual std::string storageAt(const std::string& a, const std::string& x); |
|
||||
virtual std::string stateAt(const std::string& a, const std::string& x, const std::string& s); |
|
||||
virtual Json::Value transact(const std::string& aDest, const std::string& bData, const std::string& sec, const std::string& xGas, const std::string& xGasPrice, const std::string& xValue); |
|
||||
virtual std::string txCountAt(const std::string& a); |
|
||||
virtual std::string secretToAddress(const std::string& a); |
|
||||
virtual Json::Value lastBlock(); |
|
||||
virtual std::string lll(const std::string& s); |
|
||||
virtual Json::Value block(const std::string&); |
|
||||
void setKeys(std::vector<dev::KeyPair> _keys) { m_keys = _keys; } |
|
||||
private: |
|
||||
dev::eth::Client& ethereum() const; |
|
||||
dev::WebThreeDirect& m_web3; |
|
||||
std::vector<dev::KeyPair> m_keys; |
|
||||
Json::Value jsontypeToValue(int); |
|
||||
Json::Value blockJson(const std::string&); |
|
||||
}; |
|
@ -1,162 +0,0 @@ |
|||||
/**
|
|
||||
* THIS FILE IS GENERATED BY jsonrpcstub, DO NOT CHANGE IT!!!!! |
|
||||
*/ |
|
||||
|
|
||||
#ifndef _ABSTRACTETHSTUBSERVER_H_ |
|
||||
#define _ABSTRACTETHSTUBSERVER_H_ |
|
||||
|
|
||||
#include <jsonrpc/rpc.h> |
|
||||
|
|
||||
class AbstractEthStubServer : public jsonrpc::AbstractServer<AbstractEthStubServer> |
|
||||
{ |
|
||||
public: |
|
||||
AbstractEthStubServer(jsonrpc::AbstractServerConnector* conn) : |
|
||||
jsonrpc::AbstractServer<AbstractEthStubServer>(conn) |
|
||||
{ |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("balanceAt", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::balanceAtI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("block", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "a",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::blockI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("check", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_ARRAY, "a",jsonrpc::JSON_ARRAY, NULL), &AbstractEthStubServer::checkI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("coinbase", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::coinbaseI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("create", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "bCode",jsonrpc::JSON_STRING,"sec",jsonrpc::JSON_STRING,"xEndowment",jsonrpc::JSON_STRING,"xGas",jsonrpc::JSON_STRING,"xGasPrice",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::createI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("gasPrice", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::gasPriceI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("isContractAt", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_BOOLEAN, "a",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::isContractAtI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("isListening", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_BOOLEAN, NULL), &AbstractEthStubServer::isListeningI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("isMining", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_BOOLEAN, NULL), &AbstractEthStubServer::isMiningI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("key", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::keyI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("keys", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_ARRAY, NULL), &AbstractEthStubServer::keysI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("lastBlock", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, NULL), &AbstractEthStubServer::lastBlockI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("lll", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "s",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::lllI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("peerCount", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_INTEGER, NULL), &AbstractEthStubServer::peerCountI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("procedures", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_ARRAY, NULL), &AbstractEthStubServer::proceduresI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("secretToAddress", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::secretToAddressI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("storageAt", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING,"x",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::storageAtI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("stateAt", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING,"x",jsonrpc::JSON_STRING,"s",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::stateAtI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("transact", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "aDest",jsonrpc::JSON_STRING,"bData",jsonrpc::JSON_STRING,"sec",jsonrpc::JSON_STRING,"xGas",jsonrpc::JSON_STRING,"xGasPrice",jsonrpc::JSON_STRING,"xValue",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::transactI); |
|
||||
this->bindAndAddMethod(new jsonrpc::Procedure("txCountAt", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::txCountAtI); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
inline virtual void balanceAtI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->balanceAt(request["a"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void blockI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->block(request["a"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void checkI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->check(request["a"]); |
|
||||
} |
|
||||
|
|
||||
inline virtual void coinbaseI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->coinbase(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void createI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->create(request["bCode"].asString(), request["sec"].asString(), request["xEndowment"].asString(), request["xGas"].asString(), request["xGasPrice"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void gasPriceI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->gasPrice(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void isContractAtI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->isContractAt(request["a"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void isListeningI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->isListening(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void isMiningI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->isMining(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void keyI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->key(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void keysI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->keys(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void lastBlockI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->lastBlock(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void lllI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->lll(request["s"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void peerCountI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->peerCount(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void proceduresI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->procedures(); |
|
||||
} |
|
||||
|
|
||||
inline virtual void secretToAddressI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->secretToAddress(request["a"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void storageAtI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->storageAt(request["a"].asString(), request["x"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void stateAtI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->stateAt(request["a"].asString(), request["x"].asString(), request["s"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void transactI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->transact(request["aDest"].asString(), request["bData"].asString(), request["sec"].asString(), request["xGas"].asString(), request["xGasPrice"].asString(), request["xValue"].asString()); |
|
||||
} |
|
||||
|
|
||||
inline virtual void txCountAtI(const Json::Value& request, Json::Value& response) |
|
||||
{ |
|
||||
response = this->txCountAt(request["a"].asString()); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
virtual std::string balanceAt(const std::string& a) = 0; |
|
||||
virtual Json::Value block(const std::string& a) = 0; |
|
||||
virtual Json::Value check(const Json::Value& a) = 0; |
|
||||
virtual std::string coinbase() = 0; |
|
||||
virtual std::string create(const std::string& bCode, const std::string& sec, const std::string& xEndowment, const std::string& xGas, const std::string& xGasPrice) = 0; |
|
||||
virtual std::string gasPrice() = 0; |
|
||||
virtual bool isContractAt(const std::string& a) = 0; |
|
||||
virtual bool isListening() = 0; |
|
||||
virtual bool isMining() = 0; |
|
||||
virtual std::string key() = 0; |
|
||||
virtual Json::Value keys() = 0; |
|
||||
virtual Json::Value lastBlock() = 0; |
|
||||
virtual std::string lll(const std::string& s) = 0; |
|
||||
virtual int peerCount() = 0; |
|
||||
virtual Json::Value procedures() = 0; |
|
||||
virtual std::string secretToAddress(const std::string& a) = 0; |
|
||||
virtual std::string storageAt(const std::string& a, const std::string& x) = 0; |
|
||||
virtual std::string stateAt(const std::string& a, const std::string& x, const std::string& b) = 0; |
|
||||
virtual Json::Value transact(const std::string& aDest, const std::string& bData, const std::string& sec, const std::string& xGas, const std::string& xGasPrice, const std::string& xValue) = 0; |
|
||||
virtual std::string txCountAt(const std::string& a) = 0; |
|
||||
|
|
||||
}; |
|
||||
#endif //_ABSTRACTETHSTUBSERVER_H_
|
|
@ -1,137 +0,0 @@ |
|||||
if (typeof(window.eth) === "undefined") |
|
||||
{ |
|
||||
if (typeof(require) !== "undefined") |
|
||||
require( ['ethString'], function() {} ) |
|
||||
else if (typeof(String.prototype.pad) === "undefined") |
|
||||
{ |
|
||||
var scriptTag = document.getElementsByTagName('script'); |
|
||||
scriptTag = scriptTag[scriptTag.length - 1]; |
|
||||
var scriptPath = scriptTag.src; |
|
||||
var path = scriptPath.substr(0, scriptPath.lastIndexOf( '/' )); |
|
||||
var start = '<script src="' + path + '/'; |
|
||||
var slash = '"><'+'/script>'; |
|
||||
document.write(start + 'BigInteger.js' + slash); |
|
||||
document.write(start + 'ethString.js' + slash); |
|
||||
} |
|
||||
|
|
||||
var spec = [ |
|
||||
{ "method": "procedures", "params": null, "order": [], "returns": [] }, |
|
||||
{ "method": "coinbase", "params": null, "order": [], "returns" : "" }, |
|
||||
{ "method": "isListening", "params": null, "order": [], "returns" : false }, |
|
||||
{ "method": "isMining", "params": null, "order": [], "returns" : false }, |
|
||||
{ "method": "gasPrice", "params": null, "order": [], "returns" : "" }, |
|
||||
{ "method": "key", "params": null, "order": [], "returns" : "" }, |
|
||||
{ "method": "keys", "params": null, "order": [], "returns" : [] }, |
|
||||
{ "method": "peerCount", "params": null, "order": [], "returns" : 0 }, |
|
||||
{ "method": "balanceAt", "params": { "a": "" }, "order": ["a"], "returns" : "" }, |
|
||||
{ "method": "storageAt", "params": { "a": "", "x": "" }, "order": ["a", "x"], "returns" : "" }, |
|
||||
{ "method": "stateAt", "params": { "a": "", "x": "", "s": "" }, "order": ["a", "x", "s"], "returns" : "" }, |
|
||||
{ "method": "txCountAt", "params": { "a": "" },"order": ["a"], "returns" : "" }, |
|
||||
{ "method": "isContractAt", "params": { "a": "" }, "order": ["a"], "returns" : false }, |
|
||||
{ "method": "create", "params": { "sec": "", "xEndowment": "", "bCode": "", "xGas": "", "xGasPrice": "" }, "order": ["sec", "xEndowment", "bCode", "xGas", "xGasPrice"] , "returns": "" }, |
|
||||
{ "method": "transact", "params": { "sec": "", "xValue": "", "aDest": "", "bData": "", "xGas": "", "xGasPrice": "" }, "order": ["sec", "xValue", "aDest", "bData", "xGas", "xGasPrice"], "returns": {} }, |
|
||||
{ "method": "secretToAddress", "params": { "a": "" }, "order": ["a"], "returns" : "" }, |
|
||||
{ "method": "lll", "params": { "s": "" }, "order": ["s"], "returns" : "" } |
|
||||
]; |
|
||||
|
|
||||
window.eth = (function ethScope() { |
|
||||
var m_reqId = 0 |
|
||||
var ret = {} |
|
||||
function reformat(m, d) { return m == "lll" ? d.bin() : d; } |
|
||||
function reqSync(m, p) { |
|
||||
var req = { "jsonrpc": "2.0", "method": m, "params": p, "id": m_reqId } |
|
||||
m_reqId++ |
|
||||
var request = new XMLHttpRequest(); |
|
||||
request.open("POST", "http://localhost:8080", false) |
|
||||
// console.log("Sending " + JSON.stringify(req))
|
|
||||
request.send(JSON.stringify(req)) |
|
||||
return reformat(m, JSON.parse(request.responseText).result) |
|
||||
} |
|
||||
function reqAsync(m, p, f) { |
|
||||
var req = { "jsonrpc": "2.0", "method": m, "params": p, "id": m_reqId } |
|
||||
m_reqId++ |
|
||||
var request = new XMLHttpRequest(); |
|
||||
request.open("POST", "http://localhost:8080", true) |
|
||||
request.send(JSON.stringify(req)) |
|
||||
request.onreadystatechange = function() { |
|
||||
if (request.readyState === 4) |
|
||||
f(reformat(m, JSON.parse(request.responseText).result)) |
|
||||
}; |
|
||||
} |
|
||||
function isEmpty(obj) { |
|
||||
for (var prop in obj) |
|
||||
if (obj.hasOwnProperty(prop)) |
|
||||
return false |
|
||||
return true |
|
||||
} |
|
||||
|
|
||||
var m_watching = {}; |
|
||||
|
|
||||
for (si in spec) (function(s) { |
|
||||
var m = s.method; |
|
||||
var am = "get" + m.slice(0, 1).toUpperCase() + m.slice(1); |
|
||||
var getParams = function(a) { |
|
||||
var p = s.params ? {} : null; |
|
||||
if (m == "stateAt") |
|
||||
if (a.length == 2) |
|
||||
a[2] = "0"; |
|
||||
else |
|
||||
a[2] = String(a[2]); |
|
||||
for (j in s.order) |
|
||||
p[s.order[j]] = (s.order[j][0] === "b") ? a[j].unbin() : a[j]; |
|
||||
return p |
|
||||
}; |
|
||||
if (m == "create" || m == "transact") |
|
||||
ret[m] = function() { return reqAsync(m, getParams(arguments), arguments[s.order.length]) } |
|
||||
else |
|
||||
{ |
|
||||
ret[am] = function() { return reqAsync(m, getParams(arguments), arguments[s.order.length]) } |
|
||||
if (s.params) |
|
||||
ret[m] = function() { return reqSync(m, getParams(arguments)) } |
|
||||
else |
|
||||
Object.defineProperty(ret, m, { |
|
||||
get: function() { return reqSync(m, {}); }, |
|
||||
set: function(v) {} |
|
||||
}) |
|
||||
} |
|
||||
})(spec[si]); |
|
||||
|
|
||||
ret.check = function(force) { |
|
||||
if (!force && isEmpty(m_watching)) |
|
||||
return |
|
||||
var watching = []; |
|
||||
for (var w in m_watching) |
|
||||
watching.push(w) |
|
||||
var changed = reqSync("check", { "a": watching } ); |
|
||||
// console.log("Got " + JSON.stringify(changed));
|
|
||||
for (var c in changed) |
|
||||
m_watching[changed[c]]() |
|
||||
var that = this; |
|
||||
setTimeout(function() { that.check() }, 12000) |
|
||||
} |
|
||||
|
|
||||
ret.watch = function(a, fx, f) { |
|
||||
var old = isEmpty(m_watching) |
|
||||
if (f) |
|
||||
m_watching[a + fx] = f |
|
||||
else |
|
||||
m_watching[a] = fx |
|
||||
(f ? f : fx)() |
|
||||
if (isEmpty(m_watching) != old) |
|
||||
this.check() |
|
||||
} |
|
||||
ret.unwatch = function(f, fx) { |
|
||||
delete m_watching[fx ? f + fx : f]; |
|
||||
} |
|
||||
ret.newBlock = function(f) { |
|
||||
var old = isEmpty(m_watching) |
|
||||
m_watching[""] = f |
|
||||
f() |
|
||||
if (isEmpty(m_watching) != old) |
|
||||
this.check() |
|
||||
} |
|
||||
return ret; |
|
||||
}()); |
|
||||
|
|
||||
} |
|
||||
|
|
@ -1,62 +0,0 @@ |
|||||
if (typeof(require) !== "undefined") |
|
||||
require( ['BigInteger'], function() {} ) |
|
||||
else if (typeof(bigInt) === "undefined") |
|
||||
alert("You need to have included BigInteger.js for eth to work.") |
|
||||
|
|
||||
String.prototype.pad = function(l, r) { |
|
||||
if (r === null) { |
|
||||
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() |
|
||||
} |
|
||||
|
|
||||
|
|
@ -1,24 +0,0 @@ |
|||||
[ |
|
||||
{ "method": "procedures", "params": null, "order": [], "returns": [] }, |
|
||||
{ "method": "coinbase", "params": null, "order": [], "returns" : "" }, |
|
||||
{ "method": "isListening", "params": null, "order": [], "returns" : false }, |
|
||||
{ "method": "isMining", "params": null, "order": [], "returns" : false }, |
|
||||
{ "method": "gasPrice", "params": null, "order": [], "returns" : "" }, |
|
||||
{ "method": "key", "params": null, "order": [], "returns" : "" }, |
|
||||
{ "method": "keys", "params": null, "order": [], "returns" : [] }, |
|
||||
{ "method": "peerCount", "params": null, "order": [], "returns" : 0 }, |
|
||||
{ "method": "balanceAt", "params": { "a": "" }, "order": ["a"], "returns" : "" }, |
|
||||
{ "method": "storageAt", "params": { "a": "", "x": "" }, "order": ["a", "x"], "returns" : "" }, |
|
||||
{ "method": "txCountAt", "params": { "a": "" },"order": ["a"], "returns" : "" }, |
|
||||
{ "method": "isContractAt", "params": { "a": "" }, "order": ["a"], "returns" : false }, |
|
||||
{ "method": "create", "params": { "sec": "", "xEndowment": "", "bCode": "", "xGas": "", "xGasPrice": "" }, "order": ["sec", "xEndowment", "bCode", "xGas", "xGasPrice"] , "returns": "" }, |
|
||||
{ "method": "transact", "params": { "sec": "", "xValue": "", "aDest": "", "bData": "", "xGas": "", "xGasPrice": "" }, "order": ["sec", "xValue", "aDest", "bData", "xGas", "xGasPrice"], "returns": {} }, |
|
||||
{ "method": "secretToAddress", "params": { "a": "" }, "order": ["a"], "returns" : "" }, |
|
||||
{ "method": "lll", "params": { "s": "" }, "order": ["s"], "returns" : "" } |
|
||||
, |
|
||||
{ "method": "check", "params": { "a": [] }, "order": ["a"], "returns" : [] }, |
|
||||
{ "method": "lastBlock", "params": null, "order": [], "returns": {}}, |
|
||||
{ "method": "block", "params": {"a":""}, "order": ["a"], "returns": {}} |
|
||||
] |
|
||||
|
|
||||
|
|
@ -0,0 +1,24 @@ |
|||||
|
cmake_policy(SET CMP0015 NEW) |
||||
|
|
||||
|
# Find Qt5 for Apple and update src_list for windows |
||||
|
if (APPLE) |
||||
|
# homebrew defaults to qt4 and installs qt5 as 'keg-only' |
||||
|
# which places it into /usr/local/opt insteadof /usr/local. |
||||
|
|
||||
|
set(CMAKE_PREFIX_PATH /usr/local/opt/qt5) |
||||
|
include_directories(/usr/local/opt/qt5/include /usr/local/include) |
||||
|
elseif ("${TARGET_PLATFORM}" STREQUAL "w64") |
||||
|
set(SRC_LIST ${SRC_LIST} ../windows/qt_plugin_import.cpp) |
||||
|
elseif (UNIX) |
||||
|
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ";$ENV{QTDIR}/lib/cmake") |
||||
|
endif () |
||||
|
|
||||
|
find_package(Qt5Core) |
||||
|
|
||||
|
set(CMAKE_AUTOMOC OFF) |
||||
|
|
||||
|
qt5_add_resources(JSQRC js.qrc) |
||||
|
add_library(jsqrc STATIC ${JSQRC}) |
||||
|
qt5_use_modules(jsqrc Core) |
||||
|
|
||||
|
install( TARGETS jsqrc ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) |
@ -0,0 +1,966 @@ |
|||||
|
/*! |
||||
|
* @overview es6-promise - a tiny implementation of Promises/A+. |
||||
|
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) |
||||
|
* @license Licensed under MIT license |
||||
|
* See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
|
||||
|
* @version 2.0.0 |
||||
|
*/ |
||||
|
|
||||
|
(function() { |
||||
|
"use strict"; |
||||
|
|
||||
|
function $$utils$$objectOrFunction(x) { |
||||
|
return typeof x === 'function' || (typeof x === 'object' && x !== null); |
||||
|
} |
||||
|
|
||||
|
function $$utils$$isFunction(x) { |
||||
|
return typeof x === 'function'; |
||||
|
} |
||||
|
|
||||
|
function $$utils$$isMaybeThenable(x) { |
||||
|
return typeof x === 'object' && x !== null; |
||||
|
} |
||||
|
|
||||
|
var $$utils$$_isArray; |
||||
|
|
||||
|
if (!Array.isArray) { |
||||
|
$$utils$$_isArray = function (x) { |
||||
|
return Object.prototype.toString.call(x) === '[object Array]'; |
||||
|
}; |
||||
|
} else { |
||||
|
$$utils$$_isArray = Array.isArray; |
||||
|
} |
||||
|
|
||||
|
var $$utils$$isArray = $$utils$$_isArray; |
||||
|
var $$utils$$now = Date.now || function() { return new Date().getTime(); }; |
||||
|
function $$utils$$F() { } |
||||
|
|
||||
|
var $$utils$$o_create = (Object.create || function (o) { |
||||
|
if (arguments.length > 1) { |
||||
|
throw new Error('Second argument not supported'); |
||||
|
} |
||||
|
if (typeof o !== 'object') { |
||||
|
throw new TypeError('Argument must be an object'); |
||||
|
} |
||||
|
$$utils$$F.prototype = o; |
||||
|
return new $$utils$$F(); |
||||
|
}); |
||||
|
|
||||
|
var $$asap$$len = 0; |
||||
|
|
||||
|
var $$asap$$default = function asap(callback, arg) { |
||||
|
$$asap$$queue[$$asap$$len] = callback; |
||||
|
$$asap$$queue[$$asap$$len + 1] = arg; |
||||
|
$$asap$$len += 2; |
||||
|
if ($$asap$$len === 2) { |
||||
|
// If len is 1, that means that we need to schedule an async flush.
|
||||
|
// If additional callbacks are queued before the queue is flushed, they
|
||||
|
// will be processed by this flush that we are scheduling.
|
||||
|
$$asap$$scheduleFlush(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
var $$asap$$browserGlobal = (typeof window !== 'undefined') ? window : {}; |
||||
|
var $$asap$$BrowserMutationObserver = $$asap$$browserGlobal.MutationObserver || $$asap$$browserGlobal.WebKitMutationObserver; |
||||
|
|
||||
|
// test for web worker but not in IE10
|
||||
|
var $$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' && |
||||
|
typeof importScripts !== 'undefined' && |
||||
|
typeof MessageChannel !== 'undefined'; |
||||
|
|
||||
|
// node
|
||||
|
function $$asap$$useNextTick() { |
||||
|
return function() { |
||||
|
process.nextTick($$asap$$flush); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
function $$asap$$useMutationObserver() { |
||||
|
var iterations = 0; |
||||
|
var observer = new $$asap$$BrowserMutationObserver($$asap$$flush); |
||||
|
var node = document.createTextNode(''); |
||||
|
observer.observe(node, { characterData: true }); |
||||
|
|
||||
|
return function() { |
||||
|
node.data = (iterations = ++iterations % 2); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
// web worker
|
||||
|
function $$asap$$useMessageChannel() { |
||||
|
var channel = new MessageChannel(); |
||||
|
channel.port1.onmessage = $$asap$$flush; |
||||
|
return function () { |
||||
|
channel.port2.postMessage(0); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
function $$asap$$useSetTimeout() { |
||||
|
return function() { |
||||
|
setTimeout($$asap$$flush, 1); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
var $$asap$$queue = new Array(1000); |
||||
|
|
||||
|
function $$asap$$flush() { |
||||
|
for (var i = 0; i < $$asap$$len; i+=2) { |
||||
|
var callback = $$asap$$queue[i]; |
||||
|
var arg = $$asap$$queue[i+1]; |
||||
|
|
||||
|
callback(arg); |
||||
|
|
||||
|
$$asap$$queue[i] = undefined; |
||||
|
$$asap$$queue[i+1] = undefined; |
||||
|
} |
||||
|
|
||||
|
$$asap$$len = 0; |
||||
|
} |
||||
|
|
||||
|
var $$asap$$scheduleFlush; |
||||
|
|
||||
|
// Decide what async method to use to triggering processing of queued callbacks:
|
||||
|
if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { |
||||
|
$$asap$$scheduleFlush = $$asap$$useNextTick(); |
||||
|
} else if ($$asap$$BrowserMutationObserver) { |
||||
|
$$asap$$scheduleFlush = $$asap$$useMutationObserver(); |
||||
|
} else if ($$asap$$isWorker) { |
||||
|
$$asap$$scheduleFlush = $$asap$$useMessageChannel(); |
||||
|
} else { |
||||
|
$$asap$$scheduleFlush = $$asap$$useSetTimeout(); |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$noop() {} |
||||
|
var $$$internal$$PENDING = void 0; |
||||
|
var $$$internal$$FULFILLED = 1; |
||||
|
var $$$internal$$REJECTED = 2; |
||||
|
var $$$internal$$GET_THEN_ERROR = new $$$internal$$ErrorObject(); |
||||
|
|
||||
|
function $$$internal$$selfFullfillment() { |
||||
|
return new TypeError("You cannot resolve a promise with itself"); |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$cannotReturnOwn() { |
||||
|
return new TypeError('A promises callback cannot return that same promise.') |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$getThen(promise) { |
||||
|
try { |
||||
|
return promise.then; |
||||
|
} catch(error) { |
||||
|
$$$internal$$GET_THEN_ERROR.error = error; |
||||
|
return $$$internal$$GET_THEN_ERROR; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) { |
||||
|
try { |
||||
|
then.call(value, fulfillmentHandler, rejectionHandler); |
||||
|
} catch(e) { |
||||
|
return e; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$handleForeignThenable(promise, thenable, then) { |
||||
|
$$asap$$default(function(promise) { |
||||
|
var sealed = false; |
||||
|
var error = $$$internal$$tryThen(then, thenable, function(value) { |
||||
|
if (sealed) { return; } |
||||
|
sealed = true; |
||||
|
if (thenable !== value) { |
||||
|
$$$internal$$resolve(promise, value); |
||||
|
} else { |
||||
|
$$$internal$$fulfill(promise, value); |
||||
|
} |
||||
|
}, function(reason) { |
||||
|
if (sealed) { return; } |
||||
|
sealed = true; |
||||
|
|
||||
|
$$$internal$$reject(promise, reason); |
||||
|
}, 'Settle: ' + (promise._label || ' unknown promise')); |
||||
|
|
||||
|
if (!sealed && error) { |
||||
|
sealed = true; |
||||
|
$$$internal$$reject(promise, error); |
||||
|
} |
||||
|
}, promise); |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$handleOwnThenable(promise, thenable) { |
||||
|
if (thenable._state === $$$internal$$FULFILLED) { |
||||
|
$$$internal$$fulfill(promise, thenable._result); |
||||
|
} else if (promise._state === $$$internal$$REJECTED) { |
||||
|
$$$internal$$reject(promise, thenable._result); |
||||
|
} else { |
||||
|
$$$internal$$subscribe(thenable, undefined, function(value) { |
||||
|
$$$internal$$resolve(promise, value); |
||||
|
}, function(reason) { |
||||
|
$$$internal$$reject(promise, reason); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$handleMaybeThenable(promise, maybeThenable) { |
||||
|
if (maybeThenable.constructor === promise.constructor) { |
||||
|
$$$internal$$handleOwnThenable(promise, maybeThenable); |
||||
|
} else { |
||||
|
var then = $$$internal$$getThen(maybeThenable); |
||||
|
|
||||
|
if (then === $$$internal$$GET_THEN_ERROR) { |
||||
|
$$$internal$$reject(promise, $$$internal$$GET_THEN_ERROR.error); |
||||
|
} else if (then === undefined) { |
||||
|
$$$internal$$fulfill(promise, maybeThenable); |
||||
|
} else if ($$utils$$isFunction(then)) { |
||||
|
$$$internal$$handleForeignThenable(promise, maybeThenable, then); |
||||
|
} else { |
||||
|
$$$internal$$fulfill(promise, maybeThenable); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$resolve(promise, value) { |
||||
|
if (promise === value) { |
||||
|
$$$internal$$reject(promise, $$$internal$$selfFullfillment()); |
||||
|
} else if ($$utils$$objectOrFunction(value)) { |
||||
|
$$$internal$$handleMaybeThenable(promise, value); |
||||
|
} else { |
||||
|
$$$internal$$fulfill(promise, value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$publishRejection(promise) { |
||||
|
if (promise._onerror) { |
||||
|
promise._onerror(promise._result); |
||||
|
} |
||||
|
|
||||
|
$$$internal$$publish(promise); |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$fulfill(promise, value) { |
||||
|
if (promise._state !== $$$internal$$PENDING) { return; } |
||||
|
|
||||
|
promise._result = value; |
||||
|
promise._state = $$$internal$$FULFILLED; |
||||
|
|
||||
|
if (promise._subscribers.length === 0) { |
||||
|
} else { |
||||
|
$$asap$$default($$$internal$$publish, promise); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$reject(promise, reason) { |
||||
|
if (promise._state !== $$$internal$$PENDING) { return; } |
||||
|
promise._state = $$$internal$$REJECTED; |
||||
|
promise._result = reason; |
||||
|
|
||||
|
$$asap$$default($$$internal$$publishRejection, promise); |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$subscribe(parent, child, onFulfillment, onRejection) { |
||||
|
var subscribers = parent._subscribers; |
||||
|
var length = subscribers.length; |
||||
|
|
||||
|
parent._onerror = null; |
||||
|
|
||||
|
subscribers[length] = child; |
||||
|
subscribers[length + $$$internal$$FULFILLED] = onFulfillment; |
||||
|
subscribers[length + $$$internal$$REJECTED] = onRejection; |
||||
|
|
||||
|
if (length === 0 && parent._state) { |
||||
|
$$asap$$default($$$internal$$publish, parent); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$publish(promise) { |
||||
|
var subscribers = promise._subscribers; |
||||
|
var settled = promise._state; |
||||
|
|
||||
|
if (subscribers.length === 0) { return; } |
||||
|
|
||||
|
var child, callback, detail = promise._result; |
||||
|
|
||||
|
for (var i = 0; i < subscribers.length; i += 3) { |
||||
|
child = subscribers[i]; |
||||
|
callback = subscribers[i + settled]; |
||||
|
|
||||
|
if (child) { |
||||
|
$$$internal$$invokeCallback(settled, child, callback, detail); |
||||
|
} else { |
||||
|
callback(detail); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
promise._subscribers.length = 0; |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$ErrorObject() { |
||||
|
this.error = null; |
||||
|
} |
||||
|
|
||||
|
var $$$internal$$TRY_CATCH_ERROR = new $$$internal$$ErrorObject(); |
||||
|
|
||||
|
function $$$internal$$tryCatch(callback, detail) { |
||||
|
try { |
||||
|
return callback(detail); |
||||
|
} catch(e) { |
||||
|
$$$internal$$TRY_CATCH_ERROR.error = e; |
||||
|
return $$$internal$$TRY_CATCH_ERROR; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$invokeCallback(settled, promise, callback, detail) { |
||||
|
var hasCallback = $$utils$$isFunction(callback), |
||||
|
value, error, succeeded, failed; |
||||
|
|
||||
|
if (hasCallback) { |
||||
|
value = $$$internal$$tryCatch(callback, detail); |
||||
|
|
||||
|
if (value === $$$internal$$TRY_CATCH_ERROR) { |
||||
|
failed = true; |
||||
|
error = value.error; |
||||
|
value = null; |
||||
|
} else { |
||||
|
succeeded = true; |
||||
|
} |
||||
|
|
||||
|
if (promise === value) { |
||||
|
$$$internal$$reject(promise, $$$internal$$cannotReturnOwn()); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
} else { |
||||
|
value = detail; |
||||
|
succeeded = true; |
||||
|
} |
||||
|
|
||||
|
if (promise._state !== $$$internal$$PENDING) { |
||||
|
// noop
|
||||
|
} else if (hasCallback && succeeded) { |
||||
|
$$$internal$$resolve(promise, value); |
||||
|
} else if (failed) { |
||||
|
$$$internal$$reject(promise, error); |
||||
|
} else if (settled === $$$internal$$FULFILLED) { |
||||
|
$$$internal$$fulfill(promise, value); |
||||
|
} else if (settled === $$$internal$$REJECTED) { |
||||
|
$$$internal$$reject(promise, value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$internal$$initializePromise(promise, resolver) { |
||||
|
try { |
||||
|
resolver(function resolvePromise(value){ |
||||
|
$$$internal$$resolve(promise, value); |
||||
|
}, function rejectPromise(reason) { |
||||
|
$$$internal$$reject(promise, reason); |
||||
|
}); |
||||
|
} catch(e) { |
||||
|
$$$internal$$reject(promise, e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$enumerator$$makeSettledResult(state, position, value) { |
||||
|
if (state === $$$internal$$FULFILLED) { |
||||
|
return { |
||||
|
state: 'fulfilled', |
||||
|
value: value |
||||
|
}; |
||||
|
} else { |
||||
|
return { |
||||
|
state: 'rejected', |
||||
|
reason: value |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function $$$enumerator$$Enumerator(Constructor, input, abortOnReject, label) { |
||||
|
this._instanceConstructor = Constructor; |
||||
|
this.promise = new Constructor($$$internal$$noop, label); |
||||
|
this._abortOnReject = abortOnReject; |
||||
|
|
||||
|
if (this._validateInput(input)) { |
||||
|
this._input = input; |
||||
|
this.length = input.length; |
||||
|
this._remaining = input.length; |
||||
|
|
||||
|
this._init(); |
||||
|
|
||||
|
if (this.length === 0) { |
||||
|
$$$internal$$fulfill(this.promise, this._result); |
||||
|
} else { |
||||
|
this.length = this.length || 0; |
||||
|
this._enumerate(); |
||||
|
if (this._remaining === 0) { |
||||
|
$$$internal$$fulfill(this.promise, this._result); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
$$$internal$$reject(this.promise, this._validationError()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$$$enumerator$$Enumerator.prototype._validateInput = function(input) { |
||||
|
return $$utils$$isArray(input); |
||||
|
}; |
||||
|
|
||||
|
$$$enumerator$$Enumerator.prototype._validationError = function() { |
||||
|
return new Error('Array Methods must be provided an Array'); |
||||
|
}; |
||||
|
|
||||
|
$$$enumerator$$Enumerator.prototype._init = function() { |
||||
|
this._result = new Array(this.length); |
||||
|
}; |
||||
|
|
||||
|
var $$$enumerator$$default = $$$enumerator$$Enumerator; |
||||
|
|
||||
|
$$$enumerator$$Enumerator.prototype._enumerate = function() { |
||||
|
var length = this.length; |
||||
|
var promise = this.promise; |
||||
|
var input = this._input; |
||||
|
|
||||
|
for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { |
||||
|
this._eachEntry(input[i], i); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
$$$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) { |
||||
|
var c = this._instanceConstructor; |
||||
|
if ($$utils$$isMaybeThenable(entry)) { |
||||
|
if (entry.constructor === c && entry._state !== $$$internal$$PENDING) { |
||||
|
entry._onerror = null; |
||||
|
this._settledAt(entry._state, i, entry._result); |
||||
|
} else { |
||||
|
this._willSettleAt(c.resolve(entry), i); |
||||
|
} |
||||
|
} else { |
||||
|
this._remaining--; |
||||
|
this._result[i] = this._makeResult($$$internal$$FULFILLED, i, entry); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
$$$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) { |
||||
|
var promise = this.promise; |
||||
|
|
||||
|
if (promise._state === $$$internal$$PENDING) { |
||||
|
this._remaining--; |
||||
|
|
||||
|
if (this._abortOnReject && state === $$$internal$$REJECTED) { |
||||
|
$$$internal$$reject(promise, value); |
||||
|
} else { |
||||
|
this._result[i] = this._makeResult(state, i, value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (this._remaining === 0) { |
||||
|
$$$internal$$fulfill(promise, this._result); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
$$$enumerator$$Enumerator.prototype._makeResult = function(state, i, value) { |
||||
|
return value; |
||||
|
}; |
||||
|
|
||||
|
$$$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) { |
||||
|
var enumerator = this; |
||||
|
|
||||
|
$$$internal$$subscribe(promise, undefined, function(value) { |
||||
|
enumerator._settledAt($$$internal$$FULFILLED, i, value); |
||||
|
}, function(reason) { |
||||
|
enumerator._settledAt($$$internal$$REJECTED, i, reason); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
var $$promise$all$$default = function all(entries, label) { |
||||
|
return new $$$enumerator$$default(this, entries, true /* abort on reject */, label).promise; |
||||
|
}; |
||||
|
|
||||
|
var $$promise$race$$default = function race(entries, label) { |
||||
|
/*jshint validthis:true */ |
||||
|
var Constructor = this; |
||||
|
|
||||
|
var promise = new Constructor($$$internal$$noop, label); |
||||
|
|
||||
|
if (!$$utils$$isArray(entries)) { |
||||
|
$$$internal$$reject(promise, new TypeError('You must pass an array to race.')); |
||||
|
return promise; |
||||
|
} |
||||
|
|
||||
|
var length = entries.length; |
||||
|
|
||||
|
function onFulfillment(value) { |
||||
|
$$$internal$$resolve(promise, value); |
||||
|
} |
||||
|
|
||||
|
function onRejection(reason) { |
||||
|
$$$internal$$reject(promise, reason); |
||||
|
} |
||||
|
|
||||
|
for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { |
||||
|
$$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); |
||||
|
} |
||||
|
|
||||
|
return promise; |
||||
|
}; |
||||
|
|
||||
|
var $$promise$resolve$$default = function resolve(object, label) { |
||||
|
/*jshint validthis:true */ |
||||
|
var Constructor = this; |
||||
|
|
||||
|
if (object && typeof object === 'object' && object.constructor === Constructor) { |
||||
|
return object; |
||||
|
} |
||||
|
|
||||
|
var promise = new Constructor($$$internal$$noop, label); |
||||
|
$$$internal$$resolve(promise, object); |
||||
|
return promise; |
||||
|
}; |
||||
|
|
||||
|
var $$promise$reject$$default = function reject(reason, label) { |
||||
|
/*jshint validthis:true */ |
||||
|
var Constructor = this; |
||||
|
var promise = new Constructor($$$internal$$noop, label); |
||||
|
$$$internal$$reject(promise, reason); |
||||
|
return promise; |
||||
|
}; |
||||
|
|
||||
|
var $$es6$promise$promise$$counter = 0; |
||||
|
|
||||
|
function $$es6$promise$promise$$needsResolver() { |
||||
|
throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); |
||||
|
} |
||||
|
|
||||
|
function $$es6$promise$promise$$needsNew() { |
||||
|
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); |
||||
|
} |
||||
|
|
||||
|
var $$es6$promise$promise$$default = $$es6$promise$promise$$Promise; |
||||
|
|
||||
|
/** |
||||
|
Promise objects represent the eventual result of an asynchronous operation. The |
||||
|
primary way of interacting with a promise is through its `then` method, which |
||||
|
registers callbacks to receive either a promise’s eventual value or the reason |
||||
|
why the promise cannot be fulfilled. |
||||
|
|
||||
|
Terminology |
||||
|
----------- |
||||
|
|
||||
|
- `promise` is an object or function with a `then` method whose behavior conforms to this specification. |
||||
|
- `thenable` is an object or function that defines a `then` method. |
||||
|
- `value` is any legal JavaScript value (including undefined, a thenable, or a promise). |
||||
|
- `exception` is a value that is thrown using the throw statement. |
||||
|
- `reason` is a value that indicates why a promise was rejected. |
||||
|
- `settled` the final resting state of a promise, fulfilled or rejected. |
||||
|
|
||||
|
A promise can be in one of three states: pending, fulfilled, or rejected. |
||||
|
|
||||
|
Promises that are fulfilled have a fulfillment value and are in the fulfilled |
||||
|
state. Promises that are rejected have a rejection reason and are in the |
||||
|
rejected state. A fulfillment value is never a thenable. |
||||
|
|
||||
|
Promises can also be said to *resolve* a value. If this value is also a |
||||
|
promise, then the original promise's settled state will match the value's |
||||
|
settled state. So a promise that *resolves* a promise that rejects will |
||||
|
itself reject, and a promise that *resolves* a promise that fulfills will |
||||
|
itself fulfill. |
||||
|
|
||||
|
|
||||
|
Basic Usage: |
||||
|
------------ |
||||
|
|
||||
|
```js
|
||||
|
var promise = new Promise(function(resolve, reject) { |
||||
|
// on success
|
||||
|
resolve(value); |
||||
|
|
||||
|
// on failure
|
||||
|
reject(reason); |
||||
|
}); |
||||
|
|
||||
|
promise.then(function(value) { |
||||
|
// on fulfillment
|
||||
|
}, function(reason) { |
||||
|
// on rejection
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Advanced Usage: |
||||
|
--------------- |
||||
|
|
||||
|
Promises shine when abstracting away asynchronous interactions such as |
||||
|
`XMLHttpRequest`s. |
||||
|
|
||||
|
```js
|
||||
|
function getJSON(url) { |
||||
|
return new Promise(function(resolve, reject){ |
||||
|
var xhr = new XMLHttpRequest(); |
||||
|
|
||||
|
xhr.open('GET', url); |
||||
|
xhr.onreadystatechange = handler; |
||||
|
xhr.responseType = 'json'; |
||||
|
xhr.setRequestHeader('Accept', 'application/json'); |
||||
|
xhr.send(); |
||||
|
|
||||
|
function handler() { |
||||
|
if (this.readyState === this.DONE) { |
||||
|
if (this.status === 200) { |
||||
|
resolve(this.response); |
||||
|
} else { |
||||
|
reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
getJSON('/posts.json').then(function(json) { |
||||
|
// on fulfillment
|
||||
|
}, function(reason) { |
||||
|
// on rejection
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Unlike callbacks, promises are great composable primitives. |
||||
|
|
||||
|
```js
|
||||
|
Promise.all([ |
||||
|
getJSON('/posts'), |
||||
|
getJSON('/comments') |
||||
|
]).then(function(values){ |
||||
|
values[0] // => postsJSON
|
||||
|
values[1] // => commentsJSON
|
||||
|
|
||||
|
return values; |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
@class Promise |
||||
|
@param {function} resolver |
||||
|
@param {String} label optional string for labeling the promise. |
||||
|
Useful for tooling. |
||||
|
@constructor |
||||
|
*/ |
||||
|
function $$es6$promise$promise$$Promise(resolver, label) { |
||||
|
this._id = $$es6$promise$promise$$counter++; |
||||
|
this._label = label; |
||||
|
this._state = undefined; |
||||
|
this._result = undefined; |
||||
|
this._subscribers = []; |
||||
|
|
||||
|
if ($$$internal$$noop !== resolver) { |
||||
|
if (!$$utils$$isFunction(resolver)) { |
||||
|
$$es6$promise$promise$$needsResolver(); |
||||
|
} |
||||
|
|
||||
|
if (!(this instanceof $$es6$promise$promise$$Promise)) { |
||||
|
$$es6$promise$promise$$needsNew(); |
||||
|
} |
||||
|
|
||||
|
$$$internal$$initializePromise(this, resolver); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$$es6$promise$promise$$Promise.all = $$promise$all$$default; |
||||
|
$$es6$promise$promise$$Promise.race = $$promise$race$$default; |
||||
|
$$es6$promise$promise$$Promise.resolve = $$promise$resolve$$default; |
||||
|
$$es6$promise$promise$$Promise.reject = $$promise$reject$$default; |
||||
|
|
||||
|
$$es6$promise$promise$$Promise.prototype = { |
||||
|
constructor: $$es6$promise$promise$$Promise, |
||||
|
|
||||
|
/** |
||||
|
The primary way of interacting with a promise is through its `then` method, |
||||
|
which registers callbacks to receive either a promise's eventual value or the |
||||
|
reason why the promise cannot be fulfilled. |
||||
|
|
||||
|
```js
|
||||
|
findUser().then(function(user){ |
||||
|
// user is available
|
||||
|
}, function(reason){ |
||||
|
// user is unavailable, and you are given the reason why
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Chaining |
||||
|
-------- |
||||
|
|
||||
|
The return value of `then` is itself a promise. This second, 'downstream' |
||||
|
promise is resolved with the return value of the first promise's fulfillment |
||||
|
or rejection handler, or rejected if the handler throws an exception. |
||||
|
|
||||
|
```js
|
||||
|
findUser().then(function (user) { |
||||
|
return user.name; |
||||
|
}, function (reason) { |
||||
|
return 'default name'; |
||||
|
}).then(function (userName) { |
||||
|
// If `findUser` fulfilled, `userName` will be the user's name, otherwise it
|
||||
|
// will be `'default name'`
|
||||
|
}); |
||||
|
|
||||
|
findUser().then(function (user) { |
||||
|
throw new Error('Found user, but still unhappy'); |
||||
|
}, function (reason) { |
||||
|
throw new Error('`findUser` rejected and we're unhappy'); |
||||
|
}).then(function (value) { |
||||
|
// never reached
|
||||
|
}, function (reason) { |
||||
|
// if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
|
||||
|
// If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
|
||||
|
}); |
||||
|
``` |
||||
|
If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. |
||||
|
|
||||
|
```js
|
||||
|
findUser().then(function (user) { |
||||
|
throw new PedagogicalException('Upstream error'); |
||||
|
}).then(function (value) { |
||||
|
// never reached
|
||||
|
}).then(function (value) { |
||||
|
// never reached
|
||||
|
}, function (reason) { |
||||
|
// The `PedgagocialException` is propagated all the way down to here
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Assimilation |
||||
|
------------ |
||||
|
|
||||
|
Sometimes the value you want to propagate to a downstream promise can only be |
||||
|
retrieved asynchronously. This can be achieved by returning a promise in the |
||||
|
fulfillment or rejection handler. The downstream promise will then be pending |
||||
|
until the returned promise is settled. This is called *assimilation*. |
||||
|
|
||||
|
```js
|
||||
|
findUser().then(function (user) { |
||||
|
return findCommentsByAuthor(user); |
||||
|
}).then(function (comments) { |
||||
|
// The user's comments are now available
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
If the assimliated promise rejects, then the downstream promise will also reject. |
||||
|
|
||||
|
```js
|
||||
|
findUser().then(function (user) { |
||||
|
return findCommentsByAuthor(user); |
||||
|
}).then(function (comments) { |
||||
|
// If `findCommentsByAuthor` fulfills, we'll have the value here
|
||||
|
}, function (reason) { |
||||
|
// If `findCommentsByAuthor` rejects, we'll have the reason here
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Simple Example |
||||
|
-------------- |
||||
|
|
||||
|
Synchronous Example |
||||
|
|
||||
|
```javascript
|
||||
|
var result; |
||||
|
|
||||
|
try { |
||||
|
result = findResult(); |
||||
|
// success
|
||||
|
} catch(reason) { |
||||
|
// failure
|
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
Errback Example |
||||
|
|
||||
|
```js
|
||||
|
findResult(function(result, err){ |
||||
|
if (err) { |
||||
|
// failure
|
||||
|
} else { |
||||
|
// success
|
||||
|
} |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Promise Example; |
||||
|
|
||||
|
```javascript
|
||||
|
findResult().then(function(result){ |
||||
|
// success
|
||||
|
}, function(reason){ |
||||
|
// failure
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Advanced Example |
||||
|
-------------- |
||||
|
|
||||
|
Synchronous Example |
||||
|
|
||||
|
```javascript
|
||||
|
var author, books; |
||||
|
|
||||
|
try { |
||||
|
author = findAuthor(); |
||||
|
books = findBooksByAuthor(author); |
||||
|
// success
|
||||
|
} catch(reason) { |
||||
|
// failure
|
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
Errback Example |
||||
|
|
||||
|
```js
|
||||
|
|
||||
|
function foundBooks(books) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
function failure(reason) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
findAuthor(function(author, err){ |
||||
|
if (err) { |
||||
|
failure(err); |
||||
|
// failure
|
||||
|
} else { |
||||
|
try { |
||||
|
findBoooksByAuthor(author, function(books, err) { |
||||
|
if (err) { |
||||
|
failure(err); |
||||
|
} else { |
||||
|
try { |
||||
|
foundBooks(books); |
||||
|
} catch(reason) { |
||||
|
failure(reason); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} catch(error) { |
||||
|
failure(err); |
||||
|
} |
||||
|
// success
|
||||
|
} |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Promise Example; |
||||
|
|
||||
|
```javascript
|
||||
|
findAuthor(). |
||||
|
then(findBooksByAuthor). |
||||
|
then(function(books){ |
||||
|
// found books
|
||||
|
}).catch(function(reason){ |
||||
|
// something went wrong
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
@method then |
||||
|
@param {Function} onFulfilled |
||||
|
@param {Function} onRejected |
||||
|
@param {String} label optional string for labeling the promise. |
||||
|
Useful for tooling. |
||||
|
@return {Promise} |
||||
|
*/ |
||||
|
then: function(onFulfillment, onRejection, label) { |
||||
|
var parent = this; |
||||
|
var state = parent._state; |
||||
|
|
||||
|
if (state === $$$internal$$FULFILLED && !onFulfillment || state === $$$internal$$REJECTED && !onRejection) { |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
parent._onerror = null; |
||||
|
|
||||
|
var child = new this.constructor($$$internal$$noop, label); |
||||
|
var result = parent._result; |
||||
|
|
||||
|
if (state) { |
||||
|
var callback = arguments[state - 1]; |
||||
|
$$asap$$default(function(){ |
||||
|
$$$internal$$invokeCallback(state, child, callback, result); |
||||
|
}); |
||||
|
} else { |
||||
|
$$$internal$$subscribe(parent, child, onFulfillment, onRejection); |
||||
|
} |
||||
|
|
||||
|
return child; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
`catch` is simply sugar for `then(undefined, onRejection)` which makes it the same |
||||
|
as the catch block of a try/catch statement. |
||||
|
|
||||
|
```js
|
||||
|
function findAuthor(){ |
||||
|
throw new Error('couldn't find that author'); |
||||
|
} |
||||
|
|
||||
|
// synchronous
|
||||
|
try { |
||||
|
findAuthor(); |
||||
|
} catch(reason) { |
||||
|
// something went wrong
|
||||
|
} |
||||
|
|
||||
|
// async with promises
|
||||
|
findAuthor().catch(function(reason){ |
||||
|
// something went wrong
|
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
@method catch |
||||
|
@param {Function} onRejection |
||||
|
@param {String} label optional string for labeling the promise. |
||||
|
Useful for tooling. |
||||
|
@return {Promise} |
||||
|
*/ |
||||
|
'catch': function(onRejection, label) { |
||||
|
return this.then(null, onRejection, label); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
var $$es6$promise$polyfill$$default = function polyfill() { |
||||
|
var local; |
||||
|
|
||||
|
if (typeof global !== 'undefined') { |
||||
|
local = global; |
||||
|
} else if (typeof window !== 'undefined' && window.document) { |
||||
|
local = window; |
||||
|
} else { |
||||
|
local = self; |
||||
|
} |
||||
|
|
||||
|
var es6PromiseSupport = |
||||
|
"Promise" in local && |
||||
|
// Some of these methods are missing from
|
||||
|
// Firefox/Chrome experimental implementations
|
||||
|
"resolve" in local.Promise && |
||||
|
"reject" in local.Promise && |
||||
|
"all" in local.Promise && |
||||
|
"race" in local.Promise && |
||||
|
// Older version of the spec had a resolver object
|
||||
|
// as the arg rather than a function
|
||||
|
(function() { |
||||
|
var resolve; |
||||
|
new local.Promise(function(r) { resolve = r; }); |
||||
|
return $$utils$$isFunction(resolve); |
||||
|
}()); |
||||
|
|
||||
|
if (!es6PromiseSupport) { |
||||
|
local.Promise = $$es6$promise$promise$$default; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
var es6$promise$umd$$ES6Promise = { |
||||
|
Promise: $$es6$promise$promise$$default, |
||||
|
polyfill: $$es6$promise$polyfill$$default |
||||
|
}; |
||||
|
|
||||
|
/* global define:true module:true window: true */ |
||||
|
if (typeof define === 'function' && define['amd']) { |
||||
|
define(function() { return es6$promise$umd$$ES6Promise; }); |
||||
|
} else if (typeof module !== 'undefined' && module['exports']) { |
||||
|
module['exports'] = es6$promise$umd$$ES6Promise; |
||||
|
} else if (typeof this !== 'undefined') { |
||||
|
this['ES6Promise'] = es6$promise$umd$$ES6Promise; |
||||
|
} |
||||
|
}).call(this); |
@ -0,0 +1,8 @@ |
|||||
|
<RCC version="1.0"> |
||||
|
<qresource prefix="/js"> |
||||
|
<file>es6-promise-2.0.0.js</file> |
||||
|
<file>setup.js</file> |
||||
|
<file>main.js</file> |
||||
|
<file>qt.js</file> |
||||
|
</qresource> |
||||
|
</RCC> |
@ -0,0 +1,458 @@ |
|||||
|
/* |
||||
|
This file is part of ethereum.js. |
||||
|
|
||||
|
ethereum.js 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. |
||||
|
|
||||
|
ethereum.js 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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file ethereum.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
(function(window) { |
||||
|
function isPromise(o) { |
||||
|
return o instanceof Promise |
||||
|
} |
||||
|
|
||||
|
function flattenPromise (obj) { |
||||
|
if (obj instanceof Promise) { |
||||
|
return Promise.resolve(obj); |
||||
|
} |
||||
|
|
||||
|
if (obj instanceof Array) { |
||||
|
return new Promise(function (resolve) { |
||||
|
var promises = obj.map(function (o) { |
||||
|
return flattenPromise(o); |
||||
|
}); |
||||
|
|
||||
|
return Promise.all(promises).then(function (res) { |
||||
|
for (var i = 0; i < obj.length; i++) { |
||||
|
obj[i] = res[i]; |
||||
|
} |
||||
|
resolve(obj); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
if (obj instanceof Object) { |
||||
|
return new Promise(function (resolve) { |
||||
|
var keys = Object.keys(obj); |
||||
|
var promises = keys.map(function (key) { |
||||
|
return flattenPromise(obj[key]); |
||||
|
}); |
||||
|
|
||||
|
return Promise.all(promises).then(function (res) { |
||||
|
for (var i = 0; i < keys.length; i++) { |
||||
|
obj[keys[i]] = res[i]; |
||||
|
} |
||||
|
resolve(obj); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return Promise.resolve(obj); |
||||
|
}; |
||||
|
|
||||
|
var ethMethods = function () { |
||||
|
var blockCall = function (args) { |
||||
|
return typeof args[0] === "string" ? "blockByHash" : "blockByNumber"; |
||||
|
}; |
||||
|
|
||||
|
var transactionCall = function (args) { |
||||
|
return typeof args[0] === "string" ? 'transactionByHash' : 'transactionByNumber'; |
||||
|
}; |
||||
|
|
||||
|
var uncleCall = function (args) { |
||||
|
return typeof args[0] === "string" ? 'uncleByHash' : 'uncleByNumber'; |
||||
|
}; |
||||
|
|
||||
|
var methods = [ |
||||
|
{ name: 'balanceAt', call: 'balanceAt' }, |
||||
|
{ name: 'stateAt', call: 'stateAt' }, |
||||
|
{ name: 'countAt', call: 'countAt'}, |
||||
|
{ name: 'codeAt', call: 'codeAt' }, |
||||
|
{ name: 'transact', call: 'transact' }, |
||||
|
{ name: 'call', call: 'call' }, |
||||
|
{ name: 'block', call: blockCall }, |
||||
|
{ name: 'transaction', call: transactionCall }, |
||||
|
{ name: 'uncle', call: uncleCall }, |
||||
|
{ name: 'compile', call: 'compile' } |
||||
|
]; |
||||
|
return methods; |
||||
|
}; |
||||
|
|
||||
|
var ethProperties = function () { |
||||
|
return [ |
||||
|
{ name: 'coinbase', getter: 'coinbase', setter: 'setCoinbase' }, |
||||
|
{ name: 'listening', getter: 'listening', setter: 'setListening' }, |
||||
|
{ name: 'mining', getter: 'mining', setter: 'setMining' }, |
||||
|
{ name: 'gasPrice', getter: 'gasPrice' }, |
||||
|
{ name: 'account', getter: 'account' }, |
||||
|
{ name: 'accounts', getter: 'accounts' }, |
||||
|
{ name: 'peerCount', getter: 'peerCount' }, |
||||
|
{ name: 'defaultBlock', getter: 'defaultBlock', setter: 'setDefaultBlock' }, |
||||
|
{ name: 'number', getter: 'number'} |
||||
|
]; |
||||
|
}; |
||||
|
|
||||
|
var dbMethods = function () { |
||||
|
return [ |
||||
|
{ name: 'put', call: 'put' }, |
||||
|
{ name: 'get', call: 'get' }, |
||||
|
{ name: 'putString', call: 'putString' }, |
||||
|
{ name: 'getString', call: 'getString' } |
||||
|
]; |
||||
|
}; |
||||
|
|
||||
|
var shhMethods = function () { |
||||
|
return [ |
||||
|
{ name: 'post', call: 'post' }, |
||||
|
{ name: 'newIdentity', call: 'newIdentity' }, |
||||
|
{ name: 'haveIdentity', call: 'haveIdentity' }, |
||||
|
{ name: 'newGroup', call: 'newGroup' }, |
||||
|
{ name: 'addToGroup', call: 'addToGroup' } |
||||
|
]; |
||||
|
}; |
||||
|
|
||||
|
var ethWatchMethods = function () { |
||||
|
var newFilter = function (args) { |
||||
|
return typeof args[0] === 'string' ? 'newFilterString' : 'newFilter'; |
||||
|
}; |
||||
|
|
||||
|
return [ |
||||
|
{ name: 'newFilter', call: newFilter }, |
||||
|
{ name: 'uninstallFilter', call: 'uninstallFilter' }, |
||||
|
{ name: 'getMessages', call: 'getMessages' } |
||||
|
]; |
||||
|
}; |
||||
|
|
||||
|
var shhWatchMethods = function () { |
||||
|
return [ |
||||
|
{ name: 'newFilter', call: 'shhNewFilter' }, |
||||
|
{ name: 'uninstallFilter', call: 'shhUninstallFilter' }, |
||||
|
{ name: 'getMessage', call: 'shhGetMessages' } |
||||
|
]; |
||||
|
}; |
||||
|
|
||||
|
var setupMethods = function (obj, methods) { |
||||
|
methods.forEach(function (method) { |
||||
|
obj[method.name] = function () { |
||||
|
return flattenPromise(Array.prototype.slice.call(arguments)).then(function (args) { |
||||
|
var call = typeof method.call === "function" ? method.call(args) : method.call; |
||||
|
return {call: call, args: args}; |
||||
|
}).then(function (request) { |
||||
|
return new Promise(function (resolve, reject) { |
||||
|
web3.provider.send(request, function (result) { |
||||
|
if (result || typeof result === "boolean") { |
||||
|
resolve(result); |
||||
|
return; |
||||
|
} |
||||
|
reject(result); |
||||
|
}); |
||||
|
}); |
||||
|
}).catch(function( err) { |
||||
|
console.error(err); |
||||
|
}); |
||||
|
}; |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
var setupProperties = function (obj, properties) { |
||||
|
properties.forEach(function (property) { |
||||
|
var proto = {}; |
||||
|
proto.get = function () { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
web3.provider.send({call: property.getter}, function(result) { |
||||
|
resolve(result); |
||||
|
}); |
||||
|
}); |
||||
|
}; |
||||
|
if (property.setter) { |
||||
|
proto.set = function (val) { |
||||
|
return flattenPromise([val]).then(function (args) { |
||||
|
return new Promise(function (resolve) { |
||||
|
web3.provider.send({call: property.setter, args: args}, function (result) { |
||||
|
if (result) { |
||||
|
resolve(result); |
||||
|
} else { |
||||
|
reject(result); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}).catch(function (err) { |
||||
|
console.error(err); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
Object.defineProperty(obj, property.name, proto); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
var web3 = { |
||||
|
_callbacks: {}, |
||||
|
_events: {}, |
||||
|
providers: {}, |
||||
|
toHex: function(str) { |
||||
|
var hex = ""; |
||||
|
for(var i = 0; i < str.length; i++) { |
||||
|
var n = str.charCodeAt(i).toString(16); |
||||
|
hex += n.length < 2 ? '0' + n : n; |
||||
|
} |
||||
|
|
||||
|
return hex; |
||||
|
}, |
||||
|
|
||||
|
toAscii: function(hex) { |
||||
|
// Find termination
|
||||
|
var str = ""; |
||||
|
var i = 0, l = hex.length; |
||||
|
for(; i < l; i+=2) { |
||||
|
var code = hex.charCodeAt(i) |
||||
|
if(code == 0) { |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); |
||||
|
} |
||||
|
|
||||
|
return str; |
||||
|
}, |
||||
|
|
||||
|
toDecimal: function (val) { |
||||
|
return parseInt(val, 16); |
||||
|
}, |
||||
|
|
||||
|
fromAscii: function(str, pad) { |
||||
|
pad = pad === undefined ? 32 : pad; |
||||
|
var hex = this.toHex(str); |
||||
|
while(hex.length < pad*2) |
||||
|
hex += "00"; |
||||
|
return hex |
||||
|
}, |
||||
|
|
||||
|
eth: { |
||||
|
prototype: Object(), |
||||
|
watch: function (params) { |
||||
|
return new Filter(params, ethWatch); |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
db: { |
||||
|
prototype: Object() |
||||
|
}, |
||||
|
|
||||
|
shh: { |
||||
|
prototype: Object(), |
||||
|
watch: function (params) { |
||||
|
return new Filter(params, shhWatch); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
on: function(event, id, cb) { |
||||
|
if(web3._events[event] === undefined) { |
||||
|
web3._events[event] = {}; |
||||
|
} |
||||
|
|
||||
|
web3._events[event][id] = cb; |
||||
|
return this |
||||
|
}, |
||||
|
|
||||
|
off: function(event, id) { |
||||
|
if(web3._events[event] !== undefined) { |
||||
|
delete web3._events[event][id]; |
||||
|
} |
||||
|
|
||||
|
return this |
||||
|
}, |
||||
|
|
||||
|
trigger: function(event, id, data) { |
||||
|
var callbacks = web3._events[event]; |
||||
|
if (!callbacks || !callbacks[id]) { |
||||
|
return; |
||||
|
} |
||||
|
var cb = callbacks[id]; |
||||
|
cb(data); |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
var eth = web3.eth; |
||||
|
setupMethods(eth, ethMethods()); |
||||
|
setupProperties(eth, ethProperties()); |
||||
|
setupMethods(web3.db, dbMethods()); |
||||
|
setupMethods(web3.shh, shhMethods()); |
||||
|
|
||||
|
var ethWatch = { |
||||
|
changed: 'changed' |
||||
|
}; |
||||
|
setupMethods(ethWatch, ethWatchMethods()); |
||||
|
var shhWatch = { |
||||
|
changed: 'shhChanged' |
||||
|
}; |
||||
|
setupMethods(shhWatch, shhWatchMethods()); |
||||
|
|
||||
|
var ProviderManager = function() { |
||||
|
this.queued = []; |
||||
|
this.polls = []; |
||||
|
this.ready = false; |
||||
|
this.provider = undefined; |
||||
|
this.id = 1; |
||||
|
|
||||
|
var self = this; |
||||
|
var poll = function () { |
||||
|
if (self.provider && self.provider.poll) { |
||||
|
self.polls.forEach(function (data) { |
||||
|
data.data._id = self.id; |
||||
|
self.id++; |
||||
|
self.provider.poll(data.data, data.id); |
||||
|
}); |
||||
|
} |
||||
|
setTimeout(poll, 12000); |
||||
|
}; |
||||
|
poll(); |
||||
|
}; |
||||
|
|
||||
|
ProviderManager.prototype.send = function(data, cb) { |
||||
|
data._id = this.id; |
||||
|
if (cb) { |
||||
|
web3._callbacks[data._id] = cb; |
||||
|
} |
||||
|
|
||||
|
data.args = data.args || []; |
||||
|
this.id++; |
||||
|
|
||||
|
if(this.provider !== undefined) { |
||||
|
this.provider.send(data); |
||||
|
} else { |
||||
|
console.warn("provider is not set"); |
||||
|
this.queued.push(data); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
ProviderManager.prototype.set = function(provider) { |
||||
|
if(this.provider !== undefined && this.provider.unload !== undefined) { |
||||
|
this.provider.unload(); |
||||
|
} |
||||
|
|
||||
|
this.provider = provider; |
||||
|
this.ready = true; |
||||
|
}; |
||||
|
|
||||
|
ProviderManager.prototype.sendQueued = function() { |
||||
|
for(var i = 0; this.queued.length; i++) { |
||||
|
// Resend
|
||||
|
this.send(this.queued[i]); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
ProviderManager.prototype.installed = function() { |
||||
|
return this.provider !== undefined; |
||||
|
}; |
||||
|
|
||||
|
ProviderManager.prototype.startPolling = function (data, pollId) { |
||||
|
if (!this.provider || !this.provider.poll) { |
||||
|
return; |
||||
|
} |
||||
|
this.polls.push({data: data, id: pollId}); |
||||
|
}; |
||||
|
|
||||
|
ProviderManager.prototype.stopPolling = function (pollId) { |
||||
|
for (var i = this.polls.length; i--;) { |
||||
|
var poll = this.polls[i]; |
||||
|
if (poll.id === pollId) { |
||||
|
this.polls.splice(i, 1); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
web3.provider = new ProviderManager(); |
||||
|
|
||||
|
web3.setProvider = function(provider) { |
||||
|
provider.onmessage = messageHandler; |
||||
|
web3.provider.set(provider); |
||||
|
web3.provider.sendQueued(); |
||||
|
}; |
||||
|
|
||||
|
var Filter = function(options, impl) { |
||||
|
this.impl = impl; |
||||
|
this.callbacks = []; |
||||
|
|
||||
|
var self = this; |
||||
|
this.promise = impl.newFilter(options); |
||||
|
this.promise.then(function (id) { |
||||
|
self.id = id; |
||||
|
web3.on(impl.changed, id, self.trigger.bind(self)); |
||||
|
web3.provider.startPolling({call: impl.changed, args: [id]}, id); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
Filter.prototype.arrived = function(callback) { |
||||
|
this.changed(callback); |
||||
|
} |
||||
|
|
||||
|
Filter.prototype.changed = function(callback) { |
||||
|
var self = this; |
||||
|
this.promise.then(function(id) { |
||||
|
self.callbacks.push(callback); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
Filter.prototype.trigger = function(messages) { |
||||
|
for(var i = 0; i < this.callbacks.length; i++) { |
||||
|
this.callbacks[i].call(this, messages); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
Filter.prototype.uninstall = function() { |
||||
|
var self = this; |
||||
|
this.promise.then(function (id) { |
||||
|
self.impl.uninstallFilter(id); |
||||
|
web3.provider.stopPolling(id); |
||||
|
web3.off(impl.changed, id); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
Filter.prototype.messages = function() { |
||||
|
var self = this; |
||||
|
return this.promise.then(function (id) { |
||||
|
return self.impl.getMessages(id); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
function messageHandler(data) { |
||||
|
if(data._event !== undefined) { |
||||
|
web3.trigger(data._event, data._id, data.data); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if(data._id) { |
||||
|
var cb = web3._callbacks[data._id]; |
||||
|
if (cb) { |
||||
|
cb.call(this, data.data) |
||||
|
delete web3._callbacks[data._id]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
// Install default provider
|
||||
|
if(!web3.provider.installed()) { |
||||
|
var sock = new web3.WebSocket("ws://localhost:40404/eth"); |
||||
|
|
||||
|
web3.setProvider(sock); |
||||
|
} |
||||
|
*/ |
||||
|
|
||||
|
window.web3 = web3; |
||||
|
|
||||
|
})(this); |
@ -0,0 +1,49 @@ |
|||||
|
/* |
||||
|
This file is part of ethereum.js. |
||||
|
|
||||
|
ethereum.js 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. |
||||
|
|
||||
|
ethereum.js 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 ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file ethereum.js |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
(function() { |
||||
|
var QtProvider = function() { |
||||
|
this.handlers = []; |
||||
|
|
||||
|
var self = this; |
||||
|
navigator.qt.onmessage = function (message) { |
||||
|
self.handlers.forEach(function (handler) { |
||||
|
handler.call(self, JSON.parse(message.data)); |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
QtProvider.prototype.send = function(payload) { |
||||
|
navigator.qt.postMessage(JSON.stringify(payload)); |
||||
|
}; |
||||
|
|
||||
|
Object.defineProperty(QtProvider.prototype, "onmessage", { |
||||
|
set: function(handler) { |
||||
|
this.handlers.push(handler); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
if(typeof(web3) !== "undefined" && web3.providers !== undefined) { |
||||
|
web3.providers.QtProvider = QtProvider; |
||||
|
} |
||||
|
})(); |
||||
|
|
@ -0,0 +1,44 @@ |
|||||
|
/* |
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file QEthereum.cpp |
||||
|
* @authors: |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
navigator.qt = _web3; |
||||
|
|
||||
|
(function () { |
||||
|
navigator.qt.handlers = []; |
||||
|
Object.defineProperty(navigator.qt, 'onmessage', { |
||||
|
set: function (handler) { |
||||
|
navigator.qt.handlers.push(handler); |
||||
|
} |
||||
|
}); |
||||
|
})(); |
||||
|
|
||||
|
navigator.qt.response.connect(function (res) { |
||||
|
navigator.qt.handlers.forEach(function (handler) { |
||||
|
handler({data: res}); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
if (window.Promise === undefined) { |
||||
|
window.Promise = ES6Promise.Promise; |
||||
|
} |
||||
|
|
||||
|
web3.setProvider(new web3.providers.QtProvider()); |
@ -0,0 +1,401 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/**
|
||||
|
* @author Christian <c@ethdev.com> |
||||
|
* @date 2014 |
||||
|
* Solidity AST to EVM bytecode compiler. |
||||
|
*/ |
||||
|
|
||||
|
#include <cassert> |
||||
|
#include <utility> |
||||
|
#include <libsolidity/AST.h> |
||||
|
#include <libsolidity/Compiler.h> |
||||
|
|
||||
|
namespace dev { |
||||
|
namespace solidity { |
||||
|
|
||||
|
void CompilerContext::setLabelPosition(uint32_t _label, uint32_t _position) |
||||
|
{ |
||||
|
assert(m_labelPositions.find(_label) == m_labelPositions.end()); |
||||
|
m_labelPositions[_label] = _position; |
||||
|
} |
||||
|
|
||||
|
uint32_t CompilerContext::getLabelPosition(uint32_t _label) const |
||||
|
{ |
||||
|
auto iter = m_labelPositions.find(_label); |
||||
|
assert(iter != m_labelPositions.end()); |
||||
|
return iter->second; |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::compile(Expression& _expression) |
||||
|
{ |
||||
|
m_assemblyItems.clear(); |
||||
|
_expression.accept(*this); |
||||
|
} |
||||
|
|
||||
|
bytes ExpressionCompiler::getAssembledBytecode() const |
||||
|
{ |
||||
|
bytes assembled; |
||||
|
assembled.reserve(m_assemblyItems.size()); |
||||
|
|
||||
|
// resolve label references
|
||||
|
for (uint32_t pos = 0; pos < m_assemblyItems.size(); ++pos) |
||||
|
{ |
||||
|
AssemblyItem const& item = m_assemblyItems[pos]; |
||||
|
if (item.getType() == AssemblyItem::Type::LABEL) |
||||
|
m_context.setLabelPosition(item.getLabel(), pos + 1); |
||||
|
} |
||||
|
|
||||
|
for (AssemblyItem const& item: m_assemblyItems) |
||||
|
if (item.getType() == AssemblyItem::Type::LABELREF) |
||||
|
assembled.push_back(m_context.getLabelPosition(item.getLabel())); |
||||
|
else |
||||
|
assembled.push_back(item.getData()); |
||||
|
|
||||
|
return assembled; |
||||
|
} |
||||
|
|
||||
|
AssemblyItems ExpressionCompiler::compileExpression(CompilerContext& _context, |
||||
|
Expression& _expression) |
||||
|
{ |
||||
|
ExpressionCompiler compiler(_context); |
||||
|
compiler.compile(_expression); |
||||
|
return compiler.getAssemblyItems(); |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::endVisit(Assignment& _assignment) |
||||
|
{ |
||||
|
Expression& rightHandSide = _assignment.getRightHandSide(); |
||||
|
Token::Value op = _assignment.getAssignmentOperator(); |
||||
|
if (op != Token::ASSIGN) |
||||
|
{ |
||||
|
// compound assignment
|
||||
|
// @todo retrieve lvalue value
|
||||
|
rightHandSide.accept(*this); |
||||
|
Type const& resultType = *_assignment.getType(); |
||||
|
cleanHigherOrderBitsIfNeeded(*rightHandSide.getType(), resultType); |
||||
|
appendOrdinaryBinaryOperatorCode(Token::AssignmentToBinaryOp(op), resultType); |
||||
|
} |
||||
|
else |
||||
|
rightHandSide.accept(*this); |
||||
|
// @todo store value
|
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::endVisit(UnaryOperation& _unaryOperation) |
||||
|
{ |
||||
|
//@todo type checking and creating code for an operator should be in the same place:
|
||||
|
// the operator should know how to convert itself and to which types it applies, so
|
||||
|
// put this code together with "Type::acceptsBinary/UnaryOperator" into a class that
|
||||
|
// represents the operator
|
||||
|
switch (_unaryOperation.getOperator()) |
||||
|
{ |
||||
|
case Token::NOT: // !
|
||||
|
append(eth::Instruction::ISZERO); |
||||
|
break; |
||||
|
case Token::BIT_NOT: // ~
|
||||
|
append(eth::Instruction::NOT); |
||||
|
break; |
||||
|
case Token::DELETE: // delete
|
||||
|
// a -> a xor a (= 0).
|
||||
|
// @todo this should also be an assignment
|
||||
|
// @todo semantics change for complex types
|
||||
|
append(eth::Instruction::DUP1); |
||||
|
append(eth::Instruction::XOR); |
||||
|
break; |
||||
|
case Token::INC: // ++ (pre- or postfix)
|
||||
|
// @todo this should also be an assignment
|
||||
|
if (_unaryOperation.isPrefixOperation()) |
||||
|
{ |
||||
|
append(eth::Instruction::PUSH1); |
||||
|
append(1); |
||||
|
append(eth::Instruction::ADD); |
||||
|
} |
||||
|
break; |
||||
|
case Token::DEC: // -- (pre- or postfix)
|
||||
|
// @todo this should also be an assignment
|
||||
|
if (_unaryOperation.isPrefixOperation()) |
||||
|
{ |
||||
|
append(eth::Instruction::PUSH1); |
||||
|
append(1); |
||||
|
append(eth::Instruction::SWAP1); //@todo avoid this
|
||||
|
append(eth::Instruction::SUB); |
||||
|
} |
||||
|
break; |
||||
|
case Token::ADD: // +
|
||||
|
// unary add, so basically no-op
|
||||
|
break; |
||||
|
case Token::SUB: // -
|
||||
|
// unary -x translates into "0-x"
|
||||
|
append(eth::Instruction::PUSH1); |
||||
|
append(0); |
||||
|
append(eth::Instruction::SUB); |
||||
|
break; |
||||
|
default: |
||||
|
assert(false); // invalid operation
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool ExpressionCompiler::visit(BinaryOperation& _binaryOperation) |
||||
|
{ |
||||
|
Expression& leftExpression = _binaryOperation.getLeftExpression(); |
||||
|
Expression& rightExpression = _binaryOperation.getRightExpression(); |
||||
|
Type const& resultType = *_binaryOperation.getType(); |
||||
|
Token::Value const op = _binaryOperation.getOperator(); |
||||
|
|
||||
|
if (op == Token::AND || op == Token::OR) |
||||
|
{ |
||||
|
// special case: short-circuiting
|
||||
|
appendAndOrOperatorCode(_binaryOperation); |
||||
|
} |
||||
|
else if (Token::isCompareOp(op)) |
||||
|
{ |
||||
|
leftExpression.accept(*this); |
||||
|
rightExpression.accept(*this); |
||||
|
|
||||
|
// the types to compare have to be the same, but the resulting type is always bool
|
||||
|
assert(*leftExpression.getType() == *rightExpression.getType()); |
||||
|
appendCompareOperatorCode(op, *leftExpression.getType()); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
leftExpression.accept(*this); |
||||
|
cleanHigherOrderBitsIfNeeded(*leftExpression.getType(), resultType); |
||||
|
rightExpression.accept(*this); |
||||
|
cleanHigherOrderBitsIfNeeded(*rightExpression.getType(), resultType); |
||||
|
appendOrdinaryBinaryOperatorCode(op, resultType); |
||||
|
} |
||||
|
|
||||
|
// do not visit the child nodes, we already did that explicitly
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::endVisit(FunctionCall& _functionCall) |
||||
|
{ |
||||
|
if (_functionCall.isTypeConversion()) |
||||
|
{ |
||||
|
//@todo binary representation for all supported types (bool and int) is the same, so no-op
|
||||
|
// here for now.
|
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
//@todo
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::endVisit(MemberAccess&) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::endVisit(IndexAccess&) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::endVisit(Identifier&) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::endVisit(Literal& _literal) |
||||
|
{ |
||||
|
switch (_literal.getType()->getCategory()) |
||||
|
{ |
||||
|
case Type::Category::INTEGER: |
||||
|
case Type::Category::BOOL: |
||||
|
{ |
||||
|
bytes value = _literal.getType()->literalToBigEndian(_literal); |
||||
|
assert(value.size() <= 32); |
||||
|
assert(!value.empty()); |
||||
|
append(static_cast<byte>(eth::Instruction::PUSH1) + static_cast<byte>(value.size() - 1)); |
||||
|
append(value); |
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
assert(false); // @todo
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::cleanHigherOrderBitsIfNeeded(Type const& _typeOnStack, Type const& _targetType) |
||||
|
{ |
||||
|
// If the type of one of the operands is extended, we need to remove all
|
||||
|
// higher-order bits that we might have ignored in previous operations.
|
||||
|
// @todo: store in the AST whether the operand might have "dirty" higher
|
||||
|
// order bits
|
||||
|
|
||||
|
if (_typeOnStack == _targetType) |
||||
|
return; |
||||
|
if (_typeOnStack.getCategory() == Type::Category::INTEGER && |
||||
|
_targetType.getCategory() == Type::Category::INTEGER) |
||||
|
{ |
||||
|
//@todo
|
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// If we get here, there is either an implementation missing to clean higher oder bits
|
||||
|
// for non-integer types that are explicitly convertible or we got here in error.
|
||||
|
assert(!_typeOnStack.isExplicitlyConvertibleTo(_targetType)); |
||||
|
assert(false); // these types should not be convertible.
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation& _binaryOperation) |
||||
|
{ |
||||
|
Token::Value const op = _binaryOperation.getOperator(); |
||||
|
assert(op == Token::OR || op == Token::AND); |
||||
|
|
||||
|
_binaryOperation.getLeftExpression().accept(*this); |
||||
|
append(eth::Instruction::DUP1); |
||||
|
if (op == Token::AND) |
||||
|
append(eth::Instruction::NOT); |
||||
|
uint32_t endLabel = appendConditionalJump(); |
||||
|
_binaryOperation.getRightExpression().accept(*this); |
||||
|
appendLabel(endLabel); |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type const& _type) |
||||
|
{ |
||||
|
if (_operator == Token::EQ || _operator == Token::NE) |
||||
|
{ |
||||
|
append(eth::Instruction::EQ); |
||||
|
if (_operator == Token::NE) |
||||
|
append(eth::Instruction::NOT); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
IntegerType const* type = dynamic_cast<IntegerType const*>(&_type); |
||||
|
assert(type); |
||||
|
bool const isSigned = type->isSigned(); |
||||
|
|
||||
|
// note that EVM opcodes compare like "stack[0] < stack[1]",
|
||||
|
// but our left value is at stack[1], so everyhing is reversed.
|
||||
|
switch (_operator) |
||||
|
{ |
||||
|
case Token::GTE: |
||||
|
append(isSigned ? eth::Instruction::SGT : eth::Instruction::GT); |
||||
|
append(eth::Instruction::NOT); |
||||
|
break; |
||||
|
case Token::LTE: |
||||
|
append(isSigned ? eth::Instruction::SLT : eth::Instruction::LT); |
||||
|
append(eth::Instruction::NOT); |
||||
|
break; |
||||
|
case Token::GT: |
||||
|
append(isSigned ? eth::Instruction::SLT : eth::Instruction::LT); |
||||
|
break; |
||||
|
case Token::LT: |
||||
|
append(isSigned ? eth::Instruction::SGT : eth::Instruction::GT); |
||||
|
break; |
||||
|
default: |
||||
|
assert(false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::appendOrdinaryBinaryOperatorCode(Token::Value _operator, Type const& _type) |
||||
|
{ |
||||
|
if (Token::isArithmeticOp(_operator)) |
||||
|
appendArithmeticOperatorCode(_operator, _type); |
||||
|
else if (Token::isBitOp(_operator)) |
||||
|
appendBitOperatorCode(_operator); |
||||
|
else if (Token::isShiftOp(_operator)) |
||||
|
appendShiftOperatorCode(_operator); |
||||
|
else |
||||
|
assert(false); // unknown binary operator
|
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Type const& _type) |
||||
|
{ |
||||
|
IntegerType const* type = dynamic_cast<IntegerType const*>(&_type); |
||||
|
assert(type); |
||||
|
bool const isSigned = type->isSigned(); |
||||
|
|
||||
|
switch (_operator) |
||||
|
{ |
||||
|
case Token::ADD: |
||||
|
append(eth::Instruction::ADD); |
||||
|
break; |
||||
|
case Token::SUB: |
||||
|
append(eth::Instruction::SWAP1); |
||||
|
append(eth::Instruction::SUB); |
||||
|
break; |
||||
|
case Token::MUL: |
||||
|
append(eth::Instruction::MUL); |
||||
|
break; |
||||
|
case Token::DIV: |
||||
|
append(isSigned ? eth::Instruction::SDIV : eth::Instruction::DIV); |
||||
|
break; |
||||
|
case Token::MOD: |
||||
|
append(isSigned ? eth::Instruction::SMOD : eth::Instruction::MOD); |
||||
|
break; |
||||
|
default: |
||||
|
assert(false); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator) |
||||
|
{ |
||||
|
switch (_operator) |
||||
|
{ |
||||
|
case Token::BIT_OR: |
||||
|
append(eth::Instruction::OR); |
||||
|
break; |
||||
|
case Token::BIT_AND: |
||||
|
append(eth::Instruction::AND); |
||||
|
break; |
||||
|
case Token::BIT_XOR: |
||||
|
append(eth::Instruction::XOR); |
||||
|
break; |
||||
|
default: |
||||
|
assert(false); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator) |
||||
|
{ |
||||
|
switch (_operator) |
||||
|
{ |
||||
|
case Token::SHL: |
||||
|
assert(false); //@todo
|
||||
|
break; |
||||
|
case Token::SAR: |
||||
|
assert(false); //@todo
|
||||
|
break; |
||||
|
default: |
||||
|
assert(false); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
uint32_t ExpressionCompiler::appendConditionalJump() |
||||
|
{ |
||||
|
uint32_t label = m_context.dispenseNewLabel(); |
||||
|
append(eth::Instruction::PUSH1); |
||||
|
appendLabelref(label); |
||||
|
append(eth::Instruction::JUMPI); |
||||
|
return label; |
||||
|
} |
||||
|
|
||||
|
void ExpressionCompiler::append(bytes const& _data) |
||||
|
{ |
||||
|
m_assemblyItems.reserve(m_assemblyItems.size() + _data.size()); |
||||
|
for (byte b: _data) |
||||
|
append(b); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,146 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/**
|
||||
|
* @author Christian <c@ethdev.com> |
||||
|
* @date 2014 |
||||
|
* Solidity AST to EVM bytecode compiler. |
||||
|
*/ |
||||
|
|
||||
|
#include <libevmface/Instruction.h> |
||||
|
#include <libsolidity/ASTVisitor.h> |
||||
|
#include <libsolidity/Types.h> |
||||
|
#include <libsolidity/Token.h> |
||||
|
|
||||
|
namespace dev { |
||||
|
namespace solidity { |
||||
|
|
||||
|
/**
|
||||
|
* A single item of compiled code that can be assembled to a single byte value in the final |
||||
|
* bytecode. Its main purpose is to inject jump labels and label references into the opcode stream, |
||||
|
* which can be resolved in the final step. |
||||
|
*/ |
||||
|
class AssemblyItem |
||||
|
{ |
||||
|
public: |
||||
|
enum class Type |
||||
|
{ |
||||
|
CODE, ///< m_data is opcode, m_label is empty.
|
||||
|
DATA, ///< m_data is actual data, m_label is empty
|
||||
|
LABEL, ///< m_data is JUMPDEST opcode, m_label is id of label
|
||||
|
LABELREF ///< m_data is empty, m_label is id of label
|
||||
|
}; |
||||
|
|
||||
|
explicit AssemblyItem(eth::Instruction _instruction) : m_type(Type::CODE), m_data(byte(_instruction)) {} |
||||
|
explicit AssemblyItem(byte _data): m_type(Type::DATA), m_data(_data) {} |
||||
|
|
||||
|
/// Factory functions
|
||||
|
static AssemblyItem labelRef(uint32_t _label) { return AssemblyItem(Type::LABELREF, 0, _label); } |
||||
|
static AssemblyItem label(uint32_t _label) { return AssemblyItem(Type::LABEL, byte(eth::Instruction::JUMPDEST), _label); } |
||||
|
|
||||
|
Type getType() const { return m_type; } |
||||
|
byte getData() const { return m_data; } |
||||
|
uint32_t getLabel() const { return m_label; } |
||||
|
|
||||
|
private: |
||||
|
AssemblyItem(Type _type, byte _data, uint32_t _label): m_type(_type), m_data(_data), m_label(_label) {} |
||||
|
|
||||
|
Type m_type; |
||||
|
byte m_data; ///< data to be written to the bytecode stream (or filled by a label if this is a LABELREF)
|
||||
|
uint32_t m_label; ///< the id of a label either referenced or defined by this item
|
||||
|
}; |
||||
|
|
||||
|
using AssemblyItems = std::vector<AssemblyItem>; |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* Context to be shared by all units that compile the same contract. Its current usage only |
||||
|
* concerns dispensing unique jump label IDs and storing their actual positions in the bytecode |
||||
|
* stream. |
||||
|
*/ |
||||
|
class CompilerContext |
||||
|
{ |
||||
|
public: |
||||
|
CompilerContext(): m_nextLabel(0) {} |
||||
|
uint32_t dispenseNewLabel() { return m_nextLabel++; } |
||||
|
void setLabelPosition(uint32_t _label, uint32_t _position); |
||||
|
uint32_t getLabelPosition(uint32_t _label) const; |
||||
|
|
||||
|
private: |
||||
|
uint32_t m_nextLabel; |
||||
|
|
||||
|
std::map<uint32_t, uint32_t> m_labelPositions; |
||||
|
}; |
||||
|
|
||||
|
/**
|
||||
|
* Compiler for expressions, i.e. converts an AST tree whose root is an Expression into a stream |
||||
|
* of EVM instructions. It needs a compiler context that is the same for the whole compilation |
||||
|
* unit. |
||||
|
*/ |
||||
|
class ExpressionCompiler: public ASTVisitor |
||||
|
{ |
||||
|
public: |
||||
|
ExpressionCompiler(CompilerContext& _compilerContext): m_context(_compilerContext) {} |
||||
|
|
||||
|
/// Compile the given expression and (re-)populate the assembly item list.
|
||||
|
void compile(Expression& _expression); |
||||
|
AssemblyItems const& getAssemblyItems() const { return m_assemblyItems; } |
||||
|
bytes getAssembledBytecode() const; |
||||
|
|
||||
|
/// Compile the given expression and return the assembly items right away.
|
||||
|
static AssemblyItems compileExpression(CompilerContext& _context, Expression& _expression); |
||||
|
|
||||
|
private: |
||||
|
virtual void endVisit(Assignment& _assignment) override; |
||||
|
virtual void endVisit(UnaryOperation& _unaryOperation) override; |
||||
|
virtual bool visit(BinaryOperation& _binaryOperation) override; |
||||
|
virtual void endVisit(FunctionCall& _functionCall) override; |
||||
|
virtual void endVisit(MemberAccess& _memberAccess) override; |
||||
|
virtual void endVisit(IndexAccess& _indexAccess) override; |
||||
|
virtual void endVisit(Identifier& _identifier) override; |
||||
|
virtual void endVisit(Literal& _literal) override; |
||||
|
|
||||
|
/// Appends code to remove dirty higher order bits in case of an implicit promotion to a wider type.
|
||||
|
void cleanHigherOrderBitsIfNeeded(Type const& _typeOnStack, Type const& _targetType); |
||||
|
|
||||
|
///@{
|
||||
|
///@name Append code for various operator types
|
||||
|
void appendAndOrOperatorCode(BinaryOperation& _binaryOperation); |
||||
|
void appendCompareOperatorCode(Token::Value _operator, Type const& _type); |
||||
|
void appendOrdinaryBinaryOperatorCode(Token::Value _operator, Type const& _type); |
||||
|
|
||||
|
void appendArithmeticOperatorCode(Token::Value _operator, Type const& _type); |
||||
|
void appendBitOperatorCode(Token::Value _operator); |
||||
|
void appendShiftOperatorCode(Token::Value _operator); |
||||
|
/// @}
|
||||
|
|
||||
|
/// Appends a JUMPI instruction to a new label and returns the label
|
||||
|
uint32_t appendConditionalJump(); |
||||
|
|
||||
|
/// Append elements to the current instruction list.
|
||||
|
void append(eth::Instruction const& _instruction) { m_assemblyItems.push_back(AssemblyItem(_instruction)); } |
||||
|
void append(byte _value) { m_assemblyItems.push_back(AssemblyItem(_value)); } |
||||
|
void append(bytes const& _data); |
||||
|
void appendLabelref(byte _label) { m_assemblyItems.push_back(AssemblyItem::labelRef(_label)); } |
||||
|
void appendLabel(byte _label) { m_assemblyItems.push_back(AssemblyItem::label(_label)); } |
||||
|
|
||||
|
AssemblyItems m_assemblyItems; |
||||
|
CompilerContext& m_context; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,55 @@ |
|||||
|
cmake_policy(SET CMP0015 NEW) |
||||
|
|
||||
|
aux_source_directory(. SRC_LIST) |
||||
|
|
||||
|
include_directories(..) |
||||
|
link_directories(../libethcore) |
||||
|
link_directories(../libwebthree) |
||||
|
|
||||
|
set(EXECUTABLE web3jsonrpc) |
||||
|
file(GLOB HEADERS "*.h") |
||||
|
|
||||
|
if(ETH_STATIC) |
||||
|
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) |
||||
|
else() |
||||
|
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) |
||||
|
endif() |
||||
|
|
||||
|
target_link_libraries(${EXECUTABLE} webthree) |
||||
|
target_link_libraries(${EXECUTABLE} secp256k1) |
||||
|
target_link_libraries(${EXECUTABLE} gmp) |
||||
|
if(MINIUPNPC_LS) |
||||
|
target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) |
||||
|
endif() |
||||
|
target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) |
||||
|
target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) |
||||
|
target_link_libraries(${EXECUTABLE} ${JSONRPC_LS}) |
||||
|
target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) |
||||
|
if(READLINE_LS) |
||||
|
target_link_libraries(${EXECUTABLE} ${READLINE_LS}) |
||||
|
endif() |
||||
|
|
||||
|
if ("${TARGET_PLATFORM}" STREQUAL "w64") |
||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") |
||||
|
target_link_libraries(${EXECUTABLE} boost_system-mt-s) |
||||
|
target_link_libraries(${EXECUTABLE} boost_filesystem-mt-s) |
||||
|
target_link_libraries(${EXECUTABLE} boost_thread_win32-mt-s) |
||||
|
target_link_libraries(${EXECUTABLE} gcc) |
||||
|
target_link_libraries(${EXECUTABLE} gdi32) |
||||
|
target_link_libraries(${EXECUTABLE} ws2_32) |
||||
|
target_link_libraries(${EXECUTABLE} mswsock) |
||||
|
target_link_libraries(${EXECUTABLE} shlwapi) |
||||
|
target_link_libraries(${EXECUTABLE} iphlpapi) |
||||
|
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) |
||||
|
elseif (UNIX) |
||||
|
else () |
||||
|
target_link_libraries(${EXECUTABLE} boost_system) |
||||
|
target_link_libraries(${EXECUTABLE} boost_filesystem) |
||||
|
find_package(Threads REQUIRED) |
||||
|
target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) |
||||
|
endif () |
||||
|
|
||||
|
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) |
||||
|
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) |
||||
|
|
||||
|
|
@ -0,0 +1,42 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file CorsHttpServer.cpp
|
||||
|
* @author Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "CorsHttpServer.h" |
||||
|
|
||||
|
namespace jsonrpc |
||||
|
{ |
||||
|
|
||||
|
bool CorsHttpServer::SendResponse(std::string const& _response, void* _addInfo) |
||||
|
{ |
||||
|
struct mg_connection* conn = (struct mg_connection*) _addInfo; |
||||
|
if (mg_printf(conn, "HTTP/1.1 200 OK\r\n" |
||||
|
"Content-Type: application/json\r\n" |
||||
|
"Content-Length: %d\r\n" |
||||
|
"Access-Control-Allow-Origin: *\r\n" |
||||
|
"Access-Control-Allow-Headers: Content-Type\r\n" |
||||
|
"\r\n" |
||||
|
"%s",(int)_response.length(), _response.c_str()) > 0) |
||||
|
return true; |
||||
|
return false; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,35 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file CorsHttpServer.h
|
||||
|
* @author Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include <jsonrpc/connectors/httpserver.h> |
||||
|
|
||||
|
namespace jsonrpc |
||||
|
{ |
||||
|
|
||||
|
class CorsHttpServer : public HttpServer |
||||
|
{ |
||||
|
public: |
||||
|
using HttpServer::HttpServer; |
||||
|
bool virtual SendResponse(std::string const& _response, void* _addInfo = NULL); |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
|
@ -0,0 +1,657 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file WebThreeStubServer.cpp
|
||||
|
* @authors: |
||||
|
* Gav Wood <i@gavwood.com> |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "WebThreeStubServer.h" |
||||
|
#include <libevmface/Instruction.h> |
||||
|
#include <liblll/Compiler.h> |
||||
|
#include <libethereum/Client.h> |
||||
|
#include <libwebthree/WebThree.h> |
||||
|
#include <libdevcore/CommonJS.h> |
||||
|
#include <boost/filesystem.hpp> |
||||
|
#include <libdevcrypto/FileSystem.h> |
||||
|
#include <libwhisper/Message.h> |
||||
|
#include <libwhisper/WhisperHost.h> |
||||
|
|
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
|
||||
|
static Json::Value toJson(dev::eth::BlockInfo const& _bi) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["hash"] = boost::lexical_cast<string>(_bi.hash); |
||||
|
res["parentHash"] = toJS(_bi.parentHash); |
||||
|
res["sha3Uncles"] = toJS(_bi.sha3Uncles); |
||||
|
res["miner"] = toJS(_bi.coinbaseAddress); |
||||
|
res["stateRoot"] = toJS(_bi.stateRoot); |
||||
|
res["transactionsRoot"] = toJS(_bi.transactionsRoot); |
||||
|
res["difficulty"] = toJS(_bi.difficulty); |
||||
|
res["number"] = (int)_bi.number; |
||||
|
res["minGasPrice"] = toJS(_bi.minGasPrice); |
||||
|
res["gasLimit"] = (int)_bi.gasLimit; |
||||
|
res["timestamp"] = (int)_bi.timestamp; |
||||
|
res["extraData"] = jsFromBinary(_bi.extraData); |
||||
|
res["nonce"] = toJS(_bi.nonce); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
static Json::Value toJson(dev::eth::PastMessage const& _t) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["input"] = jsFromBinary(_t.input); |
||||
|
res["output"] = jsFromBinary(_t.output); |
||||
|
res["to"] = toJS(_t.to); |
||||
|
res["from"] = toJS(_t.from); |
||||
|
res["value"] = jsToDecimal(toJS(_t.value)); |
||||
|
res["origin"] = toJS(_t.origin); |
||||
|
res["timestamp"] = toJS(_t.timestamp); |
||||
|
res["coinbase"] = toJS(_t.coinbase); |
||||
|
res["block"] = toJS(_t.block); |
||||
|
Json::Value path; |
||||
|
for (int i: _t.path) |
||||
|
path.append(i); |
||||
|
res["path"] = path; |
||||
|
res["number"] = (int)_t.number; |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
static Json::Value toJson(dev::eth::PastMessages const& _pms) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
for (dev::eth::PastMessage const& t: _pms) |
||||
|
res.append(toJson(t)); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
static Json::Value toJson(dev::eth::Transaction const& _t) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["hash"] = toJS(_t.sha3()); |
||||
|
res["input"] = jsFromBinary(_t.data); |
||||
|
res["to"] = toJS(_t.receiveAddress); |
||||
|
res["from"] = toJS(_t.sender()); |
||||
|
res["gas"] = (int)_t.gas; |
||||
|
res["gasPrice"] = toJS(_t.gasPrice); |
||||
|
res["nonce"] = toJS(_t.nonce); |
||||
|
res["value"] = toJS(_t.value); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json) |
||||
|
{ |
||||
|
dev::eth::MessageFilter filter; |
||||
|
if (!_json.isObject() || _json.empty()) |
||||
|
return filter; |
||||
|
|
||||
|
if (!_json["earliest"].empty()) |
||||
|
filter.withEarliest(_json["earliest"].asInt()); |
||||
|
if (!_json["latest"].empty()) |
||||
|
filter.withLatest(_json["lastest"].asInt()); |
||||
|
if (!_json["max"].empty()) |
||||
|
filter.withMax(_json["max"].asInt()); |
||||
|
if (!_json["skip"].empty()) |
||||
|
filter.withSkip(_json["skip"].asInt()); |
||||
|
if (!_json["from"].empty()) |
||||
|
{ |
||||
|
if (_json["from"].isArray()) |
||||
|
for (auto i : _json["from"]) |
||||
|
filter.from(jsToAddress(i.asString())); |
||||
|
else |
||||
|
filter.from(jsToAddress(_json["from"].asString())); |
||||
|
} |
||||
|
if (!_json["to"].empty()) |
||||
|
{ |
||||
|
if (_json["to"].isArray()) |
||||
|
for (auto i : _json["to"]) |
||||
|
filter.from(jsToAddress(i.asString())); |
||||
|
else |
||||
|
filter.from(jsToAddress(_json["to"].asString())); |
||||
|
} |
||||
|
if (!_json["altered"].empty()) |
||||
|
{ |
||||
|
if (_json["altered"].isArray()) |
||||
|
for (auto i: _json["altered"]) |
||||
|
if (i.isObject()) |
||||
|
filter.altered(jsToAddress(i["id"].asString()), jsToU256(i["at"].asString())); |
||||
|
else |
||||
|
filter.altered((jsToAddress(i.asString()))); |
||||
|
else if (_json["altered"].isObject()) |
||||
|
filter.altered(jsToAddress(_json["altered"]["id"].asString()), jsToU256(_json["altered"]["at"].asString())); |
||||
|
else |
||||
|
filter.altered(jsToAddress(_json["altered"].asString())); |
||||
|
} |
||||
|
return filter; |
||||
|
} |
||||
|
|
||||
|
static shh::Message toMessage(Json::Value const& _json) |
||||
|
{ |
||||
|
shh::Message ret; |
||||
|
if (!_json["from"].empty()) |
||||
|
ret.setFrom(jsToPublic(_json["from"].asString())); |
||||
|
if (!_json["to"].empty()) |
||||
|
ret.setTo(jsToPublic(_json["to"].asString())); |
||||
|
if (!_json["payload"].empty()) |
||||
|
ret.setPayload(asBytes(_json["payload"].asString())); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, Secret _from) |
||||
|
{ |
||||
|
unsigned ttl = 50; |
||||
|
unsigned workToProve = 50; |
||||
|
shh::BuildTopic bt; |
||||
|
|
||||
|
if (!_json["ttl"].empty()) |
||||
|
ttl = _json["ttl"].asInt(); |
||||
|
if (!_json["workToProve"].empty()) |
||||
|
workToProve = _json["workToProve"].asInt(); |
||||
|
if (!_json["topic"].empty()) |
||||
|
{ |
||||
|
if (_json["topic"].isString()) |
||||
|
bt.shift(asBytes(jsPadded(_json["topic"].asString(), 32))); |
||||
|
else if (_json["topic"].isArray()) |
||||
|
for (auto i: _json["topic"]) |
||||
|
bt.shift(asBytes(jsPadded(i.asString(), 32))); |
||||
|
} |
||||
|
return _m.seal(_from, bt, ttl, workToProve); |
||||
|
} |
||||
|
|
||||
|
static pair<shh::TopicMask, Public> toWatch(Json::Value const& _json) |
||||
|
{ |
||||
|
shh::BuildTopicMask bt(shh::BuildTopicMask::Empty); |
||||
|
Public to; |
||||
|
|
||||
|
if (!_json["to"].empty()) |
||||
|
to = jsToPublic(_json["to"].asString()); |
||||
|
|
||||
|
if (!_json["topic"].empty()) |
||||
|
{ |
||||
|
if (_json["topic"].isString()) |
||||
|
bt.shift(asBytes(jsPadded(_json["topic"].asString(), 32))); |
||||
|
else if (_json["topic"].isArray()) |
||||
|
for (auto i: _json["topic"]) |
||||
|
{ |
||||
|
if (i.isString()) |
||||
|
bt.shift(asBytes(jsPadded(i.asString(), 32))); |
||||
|
else |
||||
|
bt.shift(); |
||||
|
} |
||||
|
} |
||||
|
return make_pair(bt.toTopicMask(), to); |
||||
|
} |
||||
|
|
||||
|
static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message const& _m) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["hash"] = toJS(_h); |
||||
|
res["expiry"] = (int)_e.expiry(); |
||||
|
res["sent"] = (int)_e.sent(); |
||||
|
res["ttl"] = (int)_e.ttl(); |
||||
|
res["workProved"] = (int)_e.workProved(); |
||||
|
res["topic"] = toJS(_e.topic()); |
||||
|
res["payload"] = asString(_m.payload()); |
||||
|
res["from"] = toJS(_m.from()); |
||||
|
res["to"] = toJS(_m.to()); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts): |
||||
|
AbstractWebThreeStubServer(_conn), |
||||
|
m_web3(_web3) |
||||
|
{ |
||||
|
setAccounts(_accounts); |
||||
|
auto path = getDataDir() + "/.web3"; |
||||
|
boost::filesystem::create_directories(path); |
||||
|
ldb::Options o; |
||||
|
o.create_if_missing = true; |
||||
|
ldb::DB::Open(o, path, &m_db); |
||||
|
} |
||||
|
|
||||
|
void WebThreeStubServer::setAccounts(std::vector<dev::KeyPair> const& _accounts) |
||||
|
{ |
||||
|
m_accounts.clear(); |
||||
|
for (auto i: _accounts) |
||||
|
m_accounts[i.address()] = i.secret(); |
||||
|
} |
||||
|
|
||||
|
void WebThreeStubServer::setIdentities(std::vector<dev::KeyPair> const& _ids) |
||||
|
{ |
||||
|
m_ids.clear(); |
||||
|
for (auto i: _ids) |
||||
|
m_ids[i.pub()] = i.secret(); |
||||
|
} |
||||
|
|
||||
|
dev::eth::Interface* WebThreeStubServer::client() const |
||||
|
{ |
||||
|
return m_web3.ethereum(); |
||||
|
} |
||||
|
|
||||
|
std::shared_ptr<dev::shh::Interface> WebThreeStubServer::face() const |
||||
|
{ |
||||
|
return m_web3.whisper(); |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::account() |
||||
|
{ |
||||
|
if (!m_accounts.empty()) |
||||
|
return toJS(m_accounts.begin()->first); |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::accounts() |
||||
|
{ |
||||
|
Json::Value ret(Json::arrayValue); |
||||
|
for (auto i: m_accounts) |
||||
|
ret.append(toJS(i.first)); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::addToGroup(std::string const& _group, std::string const& _who) |
||||
|
{ |
||||
|
(void)_group; |
||||
|
(void)_who; |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::balanceAt(string const& _address) |
||||
|
{ |
||||
|
int block = 0; |
||||
|
return toJS(client()->balanceAt(jsToAddress(_address), block)); |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::blockByHash(std::string const& _hash) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return ""; |
||||
|
return toJson(client()->blockInfo(jsToFixed<32>(_hash))); |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::blockByNumber(int const& _number) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return ""; |
||||
|
return toJson(client()->blockInfo(client()->hashFromNumber(_number))); |
||||
|
} |
||||
|
|
||||
|
static TransactionSkeleton toTransaction(Json::Value const& _json) |
||||
|
{ |
||||
|
TransactionSkeleton ret; |
||||
|
if (!_json.isObject() || _json.empty()) |
||||
|
return ret; |
||||
|
|
||||
|
if (!_json["from"].empty()) |
||||
|
ret.from = jsToAddress(_json["from"].asString()); |
||||
|
if (!_json["to"].empty()) |
||||
|
ret.to = jsToAddress(_json["to"].asString()); |
||||
|
if (!_json["value"].empty()) |
||||
|
ret.value = jsToU256(_json["value"].asString()); |
||||
|
if (!_json["gas"].empty()) |
||||
|
ret.gas = jsToU256(_json["gas"].asString()); |
||||
|
if (!_json["gasPrice"].empty()) |
||||
|
ret.gasPrice = jsToU256(_json["gasPrice"].asString()); |
||||
|
|
||||
|
if (!_json["data"].empty() || _json["code"].empty() || _json["dataclose"].empty()) |
||||
|
{ |
||||
|
if (_json["data"].isString()) |
||||
|
ret.data = jsToBytes(_json["data"].asString()); |
||||
|
else if (_json["code"].isString()) |
||||
|
ret.data = jsToBytes(_json["code"].asString()); |
||||
|
else if (_json["data"].isArray()) |
||||
|
for (auto i: _json["data"]) |
||||
|
dev::operator +=(ret.data, asBytes(jsPadded(i.asString(), 32))); |
||||
|
else if (_json["code"].isArray()) |
||||
|
for (auto i: _json["code"]) |
||||
|
dev::operator +=(ret.data, asBytes(jsPadded(i.asString(), 32))); |
||||
|
else if (_json["dataclose"].isArray()) |
||||
|
for (auto i: _json["dataclose"]) |
||||
|
dev::operator +=(ret.data, jsToBytes(i.asString())); |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::call(Json::Value const& _json) |
||||
|
{ |
||||
|
std::string ret; |
||||
|
if (!client()) |
||||
|
return ret; |
||||
|
TransactionSkeleton t = toTransaction(_json); |
||||
|
if (!t.from && m_accounts.size()) |
||||
|
{ |
||||
|
auto b = m_accounts.begin()->first; |
||||
|
for (auto a: m_accounts) |
||||
|
if (client()->balanceAt(a.first) > client()->balanceAt(b)) |
||||
|
b = a.first; |
||||
|
t.from = b; |
||||
|
} |
||||
|
if (!m_accounts.count(t.from)) |
||||
|
return ret; |
||||
|
if (!t.gasPrice) |
||||
|
t.gasPrice = 10 * dev::eth::szabo; |
||||
|
if (!t.gas) |
||||
|
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice); |
||||
|
ret = toJS(client()->call(m_accounts[t.from].secret(), t.value, t.to, t.data, t.gas, t.gasPrice)); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::changed(int const& _id) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return false; |
||||
|
return client()->checkWatch(_id); |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::codeAt(string const& _address) |
||||
|
{ |
||||
|
int block = 0; |
||||
|
return client() ? jsFromBinary(client()->codeAt(jsToAddress(_address), block)) : ""; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::coinbase() |
||||
|
{ |
||||
|
return client() ? toJS(client()->address()) : ""; |
||||
|
} |
||||
|
|
||||
|
double WebThreeStubServer::countAt(string const& _address) |
||||
|
{ |
||||
|
int block = 0; |
||||
|
return client() ? (double)(uint64_t)client()->countAt(jsToAddress(_address), block) : 0; |
||||
|
} |
||||
|
|
||||
|
int WebThreeStubServer::defaultBlock() |
||||
|
{ |
||||
|
return client() ? client()->getDefault() : 0; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::gasPrice() |
||||
|
{ |
||||
|
return toJS(10 * dev::eth::szabo); |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::get(std::string const& _name, std::string const& _key) |
||||
|
{ |
||||
|
bytes k = sha3(_name).asBytes() + sha3(_key).asBytes(); |
||||
|
string ret; |
||||
|
m_db->Get(m_readOptions, ldb::Slice((char const*)k.data(), k.size()), &ret); |
||||
|
return toJS(dev::asBytes(ret)); |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::getMessages(int const& _id) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return Json::Value(); |
||||
|
return toJson(client()->messages(_id)); |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::getString(std::string const& _name, std::string const& _key) |
||||
|
{ |
||||
|
bytes k = sha3(_name).asBytes() + sha3(_key).asBytes(); |
||||
|
string ret; |
||||
|
m_db->Get(m_readOptions, ldb::Slice((char const*)k.data(), k.size()), &ret); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::haveIdentity(std::string const& _id) |
||||
|
{ |
||||
|
return m_ids.count(jsToPublic(_id)) > 0; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::listening() |
||||
|
{ |
||||
|
return m_web3.isNetworkStarted(); |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::mining() |
||||
|
{ |
||||
|
return client() ? client()->isMining() : false; |
||||
|
} |
||||
|
|
||||
|
int WebThreeStubServer::newFilter(Json::Value const& _json) |
||||
|
{ |
||||
|
unsigned ret = -1; |
||||
|
if (!client()) |
||||
|
return ret; |
||||
|
ret = client()->installWatch(toMessageFilter(_json)); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int WebThreeStubServer::newFilterString(std::string const& _filter) |
||||
|
{ |
||||
|
unsigned ret = -1; |
||||
|
if (!client()) |
||||
|
return ret; |
||||
|
if (_filter.compare("chain") == 0) |
||||
|
ret = client()->installWatch(dev::eth::ChainChangedFilter); |
||||
|
else if (_filter.compare("pending") == 0) |
||||
|
ret = client()->installWatch(dev::eth::PendingChangedFilter); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::newGroup(std::string const& _id, std::string const& _who) |
||||
|
{ |
||||
|
(void)_id; |
||||
|
(void)_who; |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::newIdentity() |
||||
|
{ |
||||
|
KeyPair kp = KeyPair::create(); |
||||
|
m_ids[kp.pub()] = kp.secret(); |
||||
|
return toJS(kp.pub()); |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::compile(string const& _s) |
||||
|
{ |
||||
|
return toJS(dev::eth::compileLLL(_s)); |
||||
|
} |
||||
|
|
||||
|
int WebThreeStubServer::number() |
||||
|
{ |
||||
|
return client() ? client()->number() + 1 : 0; |
||||
|
} |
||||
|
|
||||
|
int WebThreeStubServer::peerCount() |
||||
|
{ |
||||
|
return m_web3.peerCount(); |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::post(Json::Value const& _json) |
||||
|
{ |
||||
|
shh::Message m = toMessage(_json); |
||||
|
Secret from; |
||||
|
|
||||
|
if (m.from() && m_ids.count(m.from())) |
||||
|
{ |
||||
|
cwarn << "Silently signing message from identity" << m.from().abridged() << ": User validation hook goes here."; |
||||
|
// TODO: insert validification hook here.
|
||||
|
from = m_ids[m.from()]; |
||||
|
} |
||||
|
|
||||
|
face()->inject(toSealed(_json, m, from)); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::put(std::string const& _name, std::string const& _key, std::string const& _value) |
||||
|
{ |
||||
|
bytes k = sha3(_name).asBytes() + sha3(_key).asBytes(); |
||||
|
bytes v = jsToBytes(_value); |
||||
|
m_db->Put(m_writeOptions, ldb::Slice((char const*)k.data(), k.size()), ldb::Slice((char const*)v.data(), v.size())); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::putString(std::string const& _name, std::string const& _key, std::string const& _value) |
||||
|
{ |
||||
|
bytes k = sha3(_name).asBytes() + sha3(_key).asBytes(); |
||||
|
string v = _value; |
||||
|
m_db->Put(m_writeOptions, ldb::Slice((char const*)k.data(), k.size()), ldb::Slice((char const*)v.data(), v.size())); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::setCoinbase(std::string const& _address) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return false; |
||||
|
client()->setAddress(jsToAddress(_address)); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::setDefaultBlock(int const& _block) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return false; |
||||
|
client()->setDefault(_block); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::setListening(bool const& _listening) |
||||
|
{ |
||||
|
if (_listening) |
||||
|
m_web3.startNetwork(); |
||||
|
else |
||||
|
m_web3.stopNetwork(); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::setMining(bool const& _mining) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return false; |
||||
|
|
||||
|
if (_mining) |
||||
|
client()->startMining(); |
||||
|
else |
||||
|
client()->stopMining(); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::shhChanged(int const& _id) |
||||
|
{ |
||||
|
Json::Value ret(Json::arrayValue); |
||||
|
auto pub = m_shhWatches[_id]; |
||||
|
if (!pub || m_ids.count(pub)) |
||||
|
for (h256 const& h: face()->checkWatch(_id)) |
||||
|
{ |
||||
|
auto e = face()->envelope(h); |
||||
|
shh::Message m; |
||||
|
if (pub) |
||||
|
{ |
||||
|
cwarn << "Silently decrypting message from identity" << pub.abridged() << ": User validation hook goes here."; |
||||
|
m = e.open(m_ids[pub]); |
||||
|
if (!m) |
||||
|
continue; |
||||
|
} |
||||
|
else |
||||
|
m = e.open(); |
||||
|
ret.append(toJson(h,e,m)); |
||||
|
} |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int WebThreeStubServer::shhNewFilter(Json::Value const& _json) |
||||
|
{ |
||||
|
auto w = toWatch(_json); |
||||
|
auto ret = face()->installWatch(w.first); |
||||
|
m_shhWatches.insert(make_pair(ret, w.second)); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::shhUninstallFilter(int const& _id) |
||||
|
{ |
||||
|
face()->uninstallWatch(_id); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::stateAt(string const& _address, string const& _storage) |
||||
|
{ |
||||
|
int block = 0; |
||||
|
return client() ? toJS(client()->stateAt(jsToAddress(_address), jsToU256(_storage), block)) : ""; |
||||
|
} |
||||
|
|
||||
|
std::string WebThreeStubServer::transact(Json::Value const& _json) |
||||
|
{ |
||||
|
std::string ret; |
||||
|
if (!client()) |
||||
|
return ret; |
||||
|
TransactionSkeleton t = toTransaction(_json); |
||||
|
if (!t.from && m_accounts.size()) |
||||
|
{ |
||||
|
auto b = m_accounts.begin()->first; |
||||
|
for (auto a: m_accounts) |
||||
|
if (client()->balanceAt(a.first) > client()->balanceAt(b)) |
||||
|
b = a.first; |
||||
|
t.from = b; |
||||
|
} |
||||
|
if (!m_accounts.count(t.from)) |
||||
|
return ret; |
||||
|
if (!t.gasPrice) |
||||
|
t.gasPrice = 10 * dev::eth::szabo; |
||||
|
if (!t.gas) |
||||
|
t.gas = min<u256>(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice); |
||||
|
cwarn << "Silently signing transaction from address" << t.from.abridged() << ": User validation hook goes here."; |
||||
|
if (t.to) |
||||
|
// TODO: from qethereum, insert validification hook here.
|
||||
|
client()->transact(m_accounts[t.from].secret(), t.value, t.to, t.data, t.gas, t.gasPrice); |
||||
|
else |
||||
|
ret = toJS(client()->transact(m_accounts[t.from].secret(), t.value, t.data, t.gas, t.gasPrice)); |
||||
|
client()->flushTransactions(); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::transactionByHash(std::string const& _hash, int const& _i) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return ""; |
||||
|
return toJson(client()->transaction(jsToFixed<32>(_hash), _i)); |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::transactionByNumber(int const& _number, int const& _i) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return ""; |
||||
|
return toJson(client()->transaction(client()->hashFromNumber(_number), _i)); |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::uncleByHash(std::string const& _hash, int const& _i) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return ""; |
||||
|
return toJson(client()->uncle(jsToFixed<32>(_hash), _i)); |
||||
|
} |
||||
|
|
||||
|
Json::Value WebThreeStubServer::uncleByNumber(int const& _number, int const& _i) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return ""; |
||||
|
return toJson(client()->uncle(client()->hashFromNumber(_number), _i)); |
||||
|
} |
||||
|
|
||||
|
bool WebThreeStubServer::uninstallFilter(int const& _id) |
||||
|
{ |
||||
|
if (!client()) |
||||
|
return false; |
||||
|
client()->uninstallWatch(_id); |
||||
|
return true; |
||||
|
} |
||||
|
|
@ -0,0 +1,124 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file WebThreeStubServer.h
|
||||
|
* @authors: |
||||
|
* Gav Wood <i@gavwood.com> |
||||
|
* Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#pragma warning(push) |
||||
|
#pragma warning(disable: 4100 4267) |
||||
|
#include <leveldb/db.h> |
||||
|
#pragma warning(pop) |
||||
|
|
||||
|
#include <iostream> |
||||
|
#include <jsonrpc/rpc.h> |
||||
|
#include <libdevcrypto/Common.h> |
||||
|
#pragma GCC diagnostic push |
||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter" |
||||
|
#include "abstractwebthreestubserver.h" |
||||
|
#pragma GCC diagnostic pop |
||||
|
|
||||
|
namespace ldb = leveldb; |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
class WebThreeDirect; |
||||
|
class KeyPair; |
||||
|
namespace eth |
||||
|
{ |
||||
|
class Interface; |
||||
|
} |
||||
|
namespace shh |
||||
|
{ |
||||
|
class Interface; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* @brief JSON-RPC api implementation |
||||
|
* @todo filters should work on unsigned instead of int |
||||
|
* unsigned are not supported in json-rpc-cpp and there are bugs with double in json-rpc-cpp version 0.2.1 |
||||
|
*/ |
||||
|
class WebThreeStubServer: public AbstractWebThreeStubServer |
||||
|
{ |
||||
|
public: |
||||
|
WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector<dev::KeyPair> const& _accounts); |
||||
|
|
||||
|
virtual std::string account(); |
||||
|
virtual Json::Value accounts(); |
||||
|
virtual std::string addToGroup(std::string const& _group, std::string const& _who); |
||||
|
virtual std::string balanceAt(std::string const& _address); |
||||
|
virtual Json::Value blockByHash(std::string const& _hash); |
||||
|
virtual Json::Value blockByNumber(int const& _number); |
||||
|
virtual std::string call(Json::Value const& _json); |
||||
|
virtual bool changed(int const& _id); |
||||
|
virtual std::string codeAt(std::string const& _address); |
||||
|
virtual std::string coinbase(); |
||||
|
virtual std::string compile(std::string const& _s); |
||||
|
virtual double countAt(std::string const& _address); |
||||
|
virtual int defaultBlock(); |
||||
|
virtual std::string gasPrice(); |
||||
|
virtual std::string get(std::string const& _name, std::string const& _key); |
||||
|
virtual Json::Value getMessages(int const& _id); |
||||
|
virtual std::string getString(std::string const& _name, std::string const& _key); |
||||
|
virtual bool haveIdentity(std::string const& _id); |
||||
|
virtual bool listening(); |
||||
|
virtual bool mining(); |
||||
|
virtual int newFilter(Json::Value const& _json); |
||||
|
virtual int newFilterString(std::string const& _filter); |
||||
|
virtual std::string newGroup(std::string const& _id, std::string const& _who); |
||||
|
virtual std::string newIdentity(); |
||||
|
virtual int number(); |
||||
|
virtual int peerCount(); |
||||
|
virtual bool post(Json::Value const& _json); |
||||
|
virtual bool put(std::string const& _name, std::string const& _key, std::string const& _value); |
||||
|
virtual bool putString(std::string const& _name, std::string const& _key, std::string const& _value); |
||||
|
virtual bool setCoinbase(std::string const& _address); |
||||
|
virtual bool setDefaultBlock(int const& _block); |
||||
|
virtual bool setListening(bool const& _listening); |
||||
|
virtual bool setMining(bool const& _mining); |
||||
|
virtual Json::Value shhChanged(int const& _id); |
||||
|
virtual int shhNewFilter(Json::Value const& _json); |
||||
|
virtual bool shhUninstallFilter(int const& _id); |
||||
|
virtual std::string stateAt(std::string const& _address, std::string const& _storage); |
||||
|
virtual std::string transact(Json::Value const& _json); |
||||
|
virtual Json::Value transactionByHash(std::string const& _hash, int const& _i); |
||||
|
virtual Json::Value transactionByNumber(int const& _number, int const& _i); |
||||
|
virtual Json::Value uncleByHash(std::string const& _hash, int const& _i); |
||||
|
virtual Json::Value uncleByNumber(int const& _number, int const& _i); |
||||
|
virtual bool uninstallFilter(int const& _id); |
||||
|
|
||||
|
void setAccounts(std::vector<dev::KeyPair> const& _accounts); |
||||
|
void setIdentities(std::vector<dev::KeyPair> const& _ids); |
||||
|
std::map<dev::Public, dev::Secret> const& ids() const { return m_ids; } |
||||
|
private: |
||||
|
dev::eth::Interface* client() const; |
||||
|
std::shared_ptr<dev::shh::Interface> face() const; |
||||
|
dev::WebThreeDirect& m_web3; |
||||
|
std::map<dev::Address, dev::KeyPair> m_accounts; |
||||
|
|
||||
|
ldb::ReadOptions m_readOptions; |
||||
|
ldb::WriteOptions m_writeOptions; |
||||
|
ldb::DB* m_db; |
||||
|
|
||||
|
std::map<dev::Public, dev::Secret> m_ids; |
||||
|
std::map<unsigned, dev::Public> m_shhWatches; |
||||
|
}; |
@ -0,0 +1,323 @@ |
|||||
|
/**
|
||||
|
* THIS FILE IS GENERATED BY jsonrpcstub, DO NOT CHANGE IT!!!!! |
||||
|
*/ |
||||
|
|
||||
|
#ifndef _ABSTRACTWEBTHREESTUBSERVER_H_ |
||||
|
#define _ABSTRACTWEBTHREESTUBSERVER_H_ |
||||
|
|
||||
|
#include <jsonrpc/rpc.h> |
||||
|
|
||||
|
class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThreeStubServer> |
||||
|
{ |
||||
|
public: |
||||
|
AbstractWebThreeStubServer(jsonrpc::AbstractServerConnector* conn) : |
||||
|
jsonrpc::AbstractServer<AbstractWebThreeStubServer>(conn) |
||||
|
{ |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("account", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::accountI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::accountsI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::addToGroupI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::balanceAtI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("blockByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::blockByHashI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("blockByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::blockByNumberI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::callI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::changedI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::codeAtI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::coinbaseI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("compile", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::compileI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::countAtI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::defaultBlockI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::gasPriceI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::getI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("getMessages", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::getMessagesI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("getString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::getStringI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("haveIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::haveIdentityI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::listeningI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::miningI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::newFilterI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newFilterStringI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("newGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newGroupI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("newIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::newIdentityI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("number", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::numberI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("peerCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::peerCountI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("post", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::postI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::putI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("putString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::putStringI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("setCoinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::setCoinbaseI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("setDefaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::setDefaultBlockI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("setListening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::setListeningI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("setMining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::setMiningI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("shhChanged", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shhChangedI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("shhNewFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shhNewFilterI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("shhUninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shhUninstallFilterI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("stateAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::stateAtI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("transact", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::transactI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("transactionByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::transactionByHashI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("transactionByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::transactionByNumberI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("uncleByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::uncleByHashI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("uncleByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::uncleByNumberI); |
||||
|
this->bindAndAddMethod(new jsonrpc::Procedure("uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::uninstallFilterI); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
inline virtual void accountI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->account(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void accountsI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->accounts(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void addToGroupI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->addToGroup(request[0u].asString(), request[1u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void balanceAtI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->balanceAt(request[0u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void blockByHashI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->blockByHash(request[0u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void blockByNumberI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->blockByNumber(request[0u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void callI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->call(request[0u]); |
||||
|
} |
||||
|
|
||||
|
inline virtual void changedI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->changed(request[0u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void codeAtI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->codeAt(request[0u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void coinbaseI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->coinbase(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void compileI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->compile(request[0u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void countAtI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->countAt(request[0u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void defaultBlockI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->defaultBlock(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void gasPriceI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->gasPrice(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void getI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->get(request[0u].asString(), request[1u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void getMessagesI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->getMessages(request[0u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void getStringI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->getString(request[0u].asString(), request[1u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void haveIdentityI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->haveIdentity(request[0u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void listeningI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->listening(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void miningI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->mining(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void newFilterI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->newFilter(request[0u]); |
||||
|
} |
||||
|
|
||||
|
inline virtual void newFilterStringI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->newFilterString(request[0u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void newGroupI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->newGroup(request[0u].asString(), request[1u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void newIdentityI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->newIdentity(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void numberI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->number(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void peerCountI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->peerCount(); |
||||
|
} |
||||
|
|
||||
|
inline virtual void postI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->post(request[0u]); |
||||
|
} |
||||
|
|
||||
|
inline virtual void putI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->put(request[0u].asString(), request[1u].asString(), request[2u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void putStringI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->putString(request[0u].asString(), request[1u].asString(), request[2u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void setCoinbaseI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->setCoinbase(request[0u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void setDefaultBlockI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->setDefaultBlock(request[0u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void setListeningI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->setListening(request[0u].asBool()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void setMiningI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->setMining(request[0u].asBool()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void shhChangedI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->shhChanged(request[0u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void shhNewFilterI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->shhNewFilter(request[0u]); |
||||
|
} |
||||
|
|
||||
|
inline virtual void shhUninstallFilterI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->shhUninstallFilter(request[0u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void stateAtI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->stateAt(request[0u].asString(), request[1u].asString()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void transactI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->transact(request[0u]); |
||||
|
} |
||||
|
|
||||
|
inline virtual void transactionByHashI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->transactionByHash(request[0u].asString(), request[1u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void transactionByNumberI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->transactionByNumber(request[0u].asInt(), request[1u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void uncleByHashI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->uncleByHash(request[0u].asString(), request[1u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void uncleByNumberI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->uncleByNumber(request[0u].asInt(), request[1u].asInt()); |
||||
|
} |
||||
|
|
||||
|
inline virtual void uninstallFilterI(const Json::Value& request, Json::Value& response) |
||||
|
{ |
||||
|
response = this->uninstallFilter(request[0u].asInt()); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
virtual std::string account() = 0; |
||||
|
virtual Json::Value accounts() = 0; |
||||
|
virtual std::string addToGroup(const std::string& param1, const std::string& param2) = 0; |
||||
|
virtual std::string balanceAt(const std::string& param1) = 0; |
||||
|
virtual Json::Value blockByHash(const std::string& param1) = 0; |
||||
|
virtual Json::Value blockByNumber(const int& param1) = 0; |
||||
|
virtual std::string call(const Json::Value& param1) = 0; |
||||
|
virtual bool changed(const int& param1) = 0; |
||||
|
virtual std::string codeAt(const std::string& param1) = 0; |
||||
|
virtual std::string coinbase() = 0; |
||||
|
virtual std::string compile(const std::string& param1) = 0; |
||||
|
virtual double countAt(const std::string& param1) = 0; |
||||
|
virtual int defaultBlock() = 0; |
||||
|
virtual std::string gasPrice() = 0; |
||||
|
virtual std::string get(const std::string& param1, const std::string& param2) = 0; |
||||
|
virtual Json::Value getMessages(const int& param1) = 0; |
||||
|
virtual std::string getString(const std::string& param1, const std::string& param2) = 0; |
||||
|
virtual bool haveIdentity(const std::string& param1) = 0; |
||||
|
virtual bool listening() = 0; |
||||
|
virtual bool mining() = 0; |
||||
|
virtual int newFilter(const Json::Value& param1) = 0; |
||||
|
virtual int newFilterString(const std::string& param1) = 0; |
||||
|
virtual std::string newGroup(const std::string& param1, const std::string& param2) = 0; |
||||
|
virtual std::string newIdentity() = 0; |
||||
|
virtual int number() = 0; |
||||
|
virtual int peerCount() = 0; |
||||
|
virtual bool post(const Json::Value& param1) = 0; |
||||
|
virtual bool put(const std::string& param1, const std::string& param2, const std::string& param3) = 0; |
||||
|
virtual bool putString(const std::string& param1, const std::string& param2, const std::string& param3) = 0; |
||||
|
virtual bool setCoinbase(const std::string& param1) = 0; |
||||
|
virtual bool setDefaultBlock(const int& param1) = 0; |
||||
|
virtual bool setListening(const bool& param1) = 0; |
||||
|
virtual bool setMining(const bool& param1) = 0; |
||||
|
virtual Json::Value shhChanged(const int& param1) = 0; |
||||
|
virtual int shhNewFilter(const Json::Value& param1) = 0; |
||||
|
virtual bool shhUninstallFilter(const int& param1) = 0; |
||||
|
virtual std::string stateAt(const std::string& param1, const std::string& param2) = 0; |
||||
|
virtual std::string transact(const Json::Value& param1) = 0; |
||||
|
virtual Json::Value transactionByHash(const std::string& param1, const int& param2) = 0; |
||||
|
virtual Json::Value transactionByNumber(const int& param1, const int& param2) = 0; |
||||
|
virtual Json::Value uncleByHash(const std::string& param1, const int& param2) = 0; |
||||
|
virtual Json::Value uncleByNumber(const int& param1, const int& param2) = 0; |
||||
|
virtual bool uninstallFilter(const int& param1) = 0; |
||||
|
|
||||
|
}; |
||||
|
#endif //_ABSTRACTWEBTHREESTUBSERVER_H_
|
@ -0,0 +1,55 @@ |
|||||
|
[ |
||||
|
{ "method": "coinbase", "params": [], "order": [], "returns" : "" }, |
||||
|
{ "method": "setCoinbase", "params": [""], "order": [], "returns" : true }, |
||||
|
{ "method": "listening", "params": [], "order": [], "returns" : false }, |
||||
|
{ "method": "setListening", "params": [false], "order" : [], "returns" : true }, |
||||
|
{ "method": "mining", "params": [], "order": [], "returns" : false }, |
||||
|
{ "method": "setMining", "params": [false], "order" : [], "returns" : true }, |
||||
|
{ "method": "gasPrice", "params": [], "order": [], "returns" : "" }, |
||||
|
{ "method": "account", "params": [], "order": [], "returns" : "" }, |
||||
|
{ "method": "accounts", "params": [], "order": [], "returns" : [] }, |
||||
|
{ "method": "peerCount", "params": [], "order": [], "returns" : 0 }, |
||||
|
{ "method": "defaultBlock", "params": [], "order": [], "returns" : 0}, |
||||
|
{ "method": "setDefaultBlock", "params": [0], "order": [], "returns" : true}, |
||||
|
{ "method": "number", "params": [], "order": [], "returns" : 0}, |
||||
|
|
||||
|
{ "method": "balanceAt", "params": [""], "order": [], "returns" : ""}, |
||||
|
{ "method": "stateAt", "params": ["", ""], "order": [], "returns": ""}, |
||||
|
{ "method": "countAt", "params": [""], "order": [], "returns" : 0.0}, |
||||
|
{ "method": "codeAt", "params": [""], "order": [], "returns": ""}, |
||||
|
|
||||
|
{ "method": "transact", "params": [{}], "order": [], "returns": ""}, |
||||
|
{ "method": "call", "params": [{}], "order": [], "returns": ""}, |
||||
|
|
||||
|
{ "method": "blockByHash", "params": [""],"order": [], "returns": {}}, |
||||
|
{ "method": "blockByNumber", "params": [0],"order": [], "returns": {}}, |
||||
|
{ "method": "transactionByHash", "params": ["", 0], "order": [], "returns": {}}, |
||||
|
{ "method": "transactionByNumber", "params": [0, 0], "order": [], "returns": {}}, |
||||
|
{ "method": "uncleByHash", "params": ["", 0], "order": [], "returns": {}}, |
||||
|
{ "method": "uncleByNumber", "params": [0, 0], "order": [], "returns": {}}, |
||||
|
|
||||
|
{ "method": "compile", "params": [""], "order": [], "returns": ""}, |
||||
|
|
||||
|
{ "method": "newFilter", "params": [{}], "order": [], "returns": 0}, |
||||
|
{ "method": "newFilterString", "params": [""], "order": [], "returns": 0}, |
||||
|
{ "method": "uninstallFilter", "params": [0], "order": [], "returns": true}, |
||||
|
{ "method": "changed", "params": [0], "order": [], "returns": false}, |
||||
|
{ "method": "getMessages", "params": [0], "order": [], "returns": []}, |
||||
|
|
||||
|
{ "method": "put", "params": ["", "", ""], "order": [], "returns": true}, |
||||
|
{ "method": "get", "params": ["", ""], "order": [], "returns": ""}, |
||||
|
{ "method": "putString", "params": ["", "", ""], "order": [], "returns": true}, |
||||
|
{ "method": "getString", "params": ["", ""], "order": [], "returns": ""}, |
||||
|
|
||||
|
{ "method": "post", "params": [{}], "order": [], "returns": true}, |
||||
|
{ "method": "newIdentity", "params": [], "order": [], "returns": ""}, |
||||
|
{ "method": "haveIdentity", "params": [""], "order": [], "returns": false}, |
||||
|
{ "method": "newGroup", "params": ["", ""], "order": [], "returns": ""}, |
||||
|
{ "method": "addToGroup", "params": ["", ""], "order": [], "returns": ""}, |
||||
|
|
||||
|
{ "method": "shhNewFilter", "params": [{}], "order": [], "returns": 0}, |
||||
|
{ "method": "shhUninstallFilter", "params": [0], "order": [], "returns": true}, |
||||
|
{ "method": "shhChanged", "params": [0], "order": [], "returns": []} |
||||
|
|
||||
|
] |
||||
|
|
@ -0,0 +1,250 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file jsonrpc.cpp
|
||||
|
* @author Marek Kotewicz <marek@ethdev.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#if ETH_JSONRPC |
||||
|
|
||||
|
#include <boost/test/unit_test.hpp> |
||||
|
#include <boost/lexical_cast.hpp> |
||||
|
#include <libdevcore/Log.h> |
||||
|
#include <libdevcore/CommonIO.h> |
||||
|
#include <libdevcore/CommonJS.h> |
||||
|
#include <libwebthree/WebThree.h> |
||||
|
#include <libweb3jsonrpc/WebThreeStubServer.h> |
||||
|
#include <libweb3jsonrpc/CorsHttpServer.h> |
||||
|
#include <jsonrpc/connectors/httpserver.h> |
||||
|
#include <jsonrpc/connectors/httpclient.h> |
||||
|
#include <set> |
||||
|
#include "JsonSpiritHeaders.h" |
||||
|
#include "TestHelper.h" |
||||
|
#include "webthreestubclient.h" |
||||
|
|
||||
|
BOOST_AUTO_TEST_SUITE(jsonrpc) |
||||
|
|
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
namespace js = json_spirit; |
||||
|
|
||||
|
namespace jsonrpc_tests |
||||
|
{ |
||||
|
|
||||
|
string name = "Ethereum(++) tests"; |
||||
|
string dbPath; |
||||
|
auto s = set<string>{"eth", "shh"}; |
||||
|
dev::p2p::NetworkPreferences np(30303, std::string(), false); |
||||
|
dev::WebThreeDirect web3(name, dbPath, true, s, np); |
||||
|
|
||||
|
unique_ptr<WebThreeStubServer> jsonrpcServer; |
||||
|
unique_ptr<WebThreeStubClient> jsonrpcClient; |
||||
|
|
||||
|
struct JsonrpcFixture { |
||||
|
JsonrpcFixture() |
||||
|
{ |
||||
|
cnote << "setup jsonrpc"; |
||||
|
|
||||
|
web3.setIdealPeerCount(5); |
||||
|
web3.ethereum()->setForceMining(true); |
||||
|
jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(new jsonrpc::CorsHttpServer(8080), web3, {})); |
||||
|
jsonrpcServer->setIdentities({}); |
||||
|
jsonrpcServer->StartListening(); |
||||
|
|
||||
|
jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(new jsonrpc::HttpClient("http://localhost:8080"))); |
||||
|
} |
||||
|
~JsonrpcFixture() |
||||
|
{ |
||||
|
cnote << "teardown jsonrpc"; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
BOOST_GLOBAL_FIXTURE(JsonrpcFixture) |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc defaultBlock..."; |
||||
|
int defaultBlock = jsonrpcClient->defaultBlock(); |
||||
|
BOOST_CHECK_EQUAL(defaultBlock, web3.ethereum()->getDefault()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc gasPrice..."; |
||||
|
string gasPrice = jsonrpcClient->gasPrice(); |
||||
|
BOOST_CHECK_EQUAL(gasPrice, toJS(10 * dev::eth::szabo)); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_isListening) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc isListening..."; |
||||
|
|
||||
|
web3.startNetwork(); |
||||
|
bool listeningOn = jsonrpcClient->listening(); |
||||
|
BOOST_CHECK_EQUAL(listeningOn, web3.isNetworkStarted()); |
||||
|
|
||||
|
web3.stopNetwork(); |
||||
|
bool listeningOff = jsonrpcClient->listening(); |
||||
|
BOOST_CHECK_EQUAL(listeningOff, web3.isNetworkStarted()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_isMining) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc isMining..."; |
||||
|
|
||||
|
web3.ethereum()->startMining(); |
||||
|
bool miningOn = jsonrpcClient->mining(); |
||||
|
BOOST_CHECK_EQUAL(miningOn, web3.ethereum()->isMining()); |
||||
|
|
||||
|
web3.ethereum()->stopMining(); |
||||
|
bool miningOff = jsonrpcClient->mining(); |
||||
|
BOOST_CHECK_EQUAL(miningOff, web3.ethereum()->isMining()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_accounts) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc accounts..."; |
||||
|
std::vector <dev::KeyPair> keys = {KeyPair::create(), KeyPair::create()}; |
||||
|
jsonrpcServer->setAccounts(keys); |
||||
|
Json::Value k = jsonrpcClient->accounts(); |
||||
|
jsonrpcServer->setAccounts({}); |
||||
|
BOOST_CHECK_EQUAL(k.isArray(), true); |
||||
|
BOOST_CHECK_EQUAL(k.size(), keys.size()); |
||||
|
for (auto &i:k) |
||||
|
{ |
||||
|
auto it = std::find_if(keys.begin(), keys.end(), [i](dev::KeyPair const& keyPair) |
||||
|
{ |
||||
|
return jsToAddress(i.asString()) == keyPair.address(); |
||||
|
}); |
||||
|
BOOST_CHECK_EQUAL(it != keys.end(), true); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_number) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc number2..."; |
||||
|
int number = jsonrpcClient->number(); |
||||
|
BOOST_CHECK_EQUAL(number, web3.ethereum()->number() + 1); |
||||
|
dev::eth::mine(*(web3.ethereum()), 1); |
||||
|
int numberAfter = jsonrpcClient->number(); |
||||
|
BOOST_CHECK_EQUAL(number + 1, numberAfter); |
||||
|
BOOST_CHECK_EQUAL(numberAfter, web3.ethereum()->number() + 1); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_peerCount) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc peerCount..."; |
||||
|
int peerCount = jsonrpcClient->peerCount(); |
||||
|
BOOST_CHECK_EQUAL(web3.peerCount(), peerCount); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_setListening) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc setListening..."; |
||||
|
|
||||
|
jsonrpcClient->setListening(true); |
||||
|
BOOST_CHECK_EQUAL(web3.isNetworkStarted(), true); |
||||
|
|
||||
|
jsonrpcClient->setListening(false); |
||||
|
BOOST_CHECK_EQUAL(web3.isNetworkStarted(), false); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_setMining) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc setMining..."; |
||||
|
|
||||
|
jsonrpcClient->setMining(true); |
||||
|
BOOST_CHECK_EQUAL(web3.ethereum()->isMining(), true); |
||||
|
|
||||
|
jsonrpcClient->setMining(false); |
||||
|
BOOST_CHECK_EQUAL(web3.ethereum()->isMining(), false); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_stateAt) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc stateAt..."; |
||||
|
dev::KeyPair key = KeyPair::create(); |
||||
|
auto address = key.address(); |
||||
|
string stateAt = jsonrpcClient->stateAt(toJS(address), "0"); |
||||
|
BOOST_CHECK_EQUAL(toJS(web3.ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(jsonrpc_transact) |
||||
|
{ |
||||
|
cnote << "Testing jsonrpc transact..."; |
||||
|
string coinbase = jsonrpcClient->coinbase(); |
||||
|
BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3.ethereum()->address()); |
||||
|
|
||||
|
dev::KeyPair key = KeyPair::create(); |
||||
|
auto address = key.address(); |
||||
|
auto receiver = KeyPair::create(); |
||||
|
web3.ethereum()->setAddress(address); |
||||
|
|
||||
|
coinbase = jsonrpcClient->coinbase(); |
||||
|
BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3.ethereum()->address()); |
||||
|
BOOST_CHECK_EQUAL(jsToAddress(coinbase), address); |
||||
|
|
||||
|
jsonrpcServer->setAccounts({key}); |
||||
|
auto balance = web3.ethereum()->balanceAt(address, 0); |
||||
|
string balanceString = jsonrpcClient->balanceAt(toJS(address)); |
||||
|
double countAt = jsonrpcClient->countAt(toJS(address)); |
||||
|
|
||||
|
BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3.ethereum()->countAt(address)); |
||||
|
BOOST_CHECK_EQUAL(countAt, 0); |
||||
|
BOOST_CHECK_EQUAL(toJS(balance), balanceString); |
||||
|
BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "0"); |
||||
|
|
||||
|
dev::eth::mine(*(web3.ethereum()), 1); |
||||
|
balance = web3.ethereum()->balanceAt(address, 0); |
||||
|
balanceString = jsonrpcClient->balanceAt(toJS(address)); |
||||
|
|
||||
|
BOOST_CHECK_EQUAL(toJS(balance), balanceString); |
||||
|
BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "1500000000000000000"); |
||||
|
|
||||
|
auto txAmount = balance / 2u; |
||||
|
auto gasPrice = 10 * dev::eth::szabo; |
||||
|
auto gas = dev::eth::c_txGas; |
||||
|
|
||||
|
Json::Value t; |
||||
|
t["from"] = toJS(address); |
||||
|
t["value"] = jsToDecimal(toJS(txAmount)); |
||||
|
t["to"] = toJS(receiver.address()); |
||||
|
t["data"] = toJS(bytes()); |
||||
|
t["gas"] = toJS(gas); |
||||
|
t["gasPrice"] = toJS(gasPrice); |
||||
|
|
||||
|
jsonrpcClient->transact(t); |
||||
|
jsonrpcServer->setAccounts({}); |
||||
|
dev::eth::mine(*(web3.ethereum()), 1); |
||||
|
|
||||
|
countAt = jsonrpcClient->countAt(toJS(address)); |
||||
|
auto balance2 = web3.ethereum()->balanceAt(receiver.address()); |
||||
|
string balanceString2 = jsonrpcClient->balanceAt(toJS(receiver.address())); |
||||
|
|
||||
|
BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3.ethereum()->countAt(address)); |
||||
|
BOOST_CHECK_EQUAL(countAt, 1); |
||||
|
BOOST_CHECK_EQUAL(toJS(balance2), balanceString2); |
||||
|
BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000"); |
||||
|
BOOST_CHECK_EQUAL(txAmount, balance2); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_SUITE_END() |
||||
|
|
||||
|
#endif |
@ -0,0 +1,229 @@ |
|||||
|
|
||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-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. |
||||
|
|
||||
|
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/**
|
||||
|
* @author Christian <c@ethdev.com> |
||||
|
* @date 2014 |
||||
|
* Unit tests for the name and type resolution of the solidity parser. |
||||
|
*/ |
||||
|
|
||||
|
#include <string> |
||||
|
|
||||
|
#include <libdevcore/Log.h> |
||||
|
#include <libsolidity/Scanner.h> |
||||
|
#include <libsolidity/Parser.h> |
||||
|
#include <libsolidity/NameAndTypeResolver.h> |
||||
|
#include <libsolidity/Compiler.h> |
||||
|
#include <libsolidity/AST.h> |
||||
|
#include <boost/test/unit_test.hpp> |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
namespace solidity |
||||
|
{ |
||||
|
namespace test |
||||
|
{ |
||||
|
|
||||
|
namespace |
||||
|
{ |
||||
|
|
||||
|
/**
|
||||
|
* Helper class that extracts the first expression in an AST. |
||||
|
*/ |
||||
|
class FirstExpressionExtractor: private ASTVisitor |
||||
|
{ |
||||
|
public: |
||||
|
FirstExpressionExtractor(ASTNode& _node): m_expression(nullptr) { _node.accept(*this); } |
||||
|
Expression* getExpression() const { return m_expression; } |
||||
|
private: |
||||
|
virtual bool visit(Expression& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(Assignment& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(FunctionCall& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(MemberAccess& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(IndexAccess& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(PrimaryExpression& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(Identifier& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); } |
||||
|
virtual bool visit(Literal& _expression) override { return checkExpression(_expression); } |
||||
|
bool checkExpression(Expression& _expression) |
||||
|
{ |
||||
|
if (m_expression == nullptr) |
||||
|
m_expression = &_expression; |
||||
|
return false; |
||||
|
} |
||||
|
private: |
||||
|
Expression* m_expression; |
||||
|
}; |
||||
|
|
||||
|
bytes compileFirstExpression(std::string const& _sourceCode) |
||||
|
{ |
||||
|
Parser parser; |
||||
|
ASTPointer<ContractDefinition> contract; |
||||
|
BOOST_REQUIRE_NO_THROW(contract = parser.parse(std::make_shared<Scanner>(CharStream(_sourceCode)))); |
||||
|
NameAndTypeResolver resolver; |
||||
|
BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); |
||||
|
FirstExpressionExtractor extractor(*contract); |
||||
|
BOOST_REQUIRE(extractor.getExpression() != nullptr); |
||||
|
|
||||
|
CompilerContext context; |
||||
|
ExpressionCompiler compiler(context); |
||||
|
compiler.compile(*extractor.getExpression()); |
||||
|
bytes instructions = compiler.getAssembledBytecode(); |
||||
|
// debug
|
||||
|
//std::cout << eth::disassemble(instructions) << std::endl;
|
||||
|
return instructions; |
||||
|
} |
||||
|
|
||||
|
} // end anonymous namespace
|
||||
|
|
||||
|
BOOST_AUTO_TEST_SUITE(SolidityExpressionCompiler) |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(literal_true) |
||||
|
{ |
||||
|
char const* sourceCode = "contract test {\n" |
||||
|
" function f() { var x = true; }" |
||||
|
"}\n"; |
||||
|
bytes code = compileFirstExpression(sourceCode); |
||||
|
|
||||
|
bytes expectation({byte(eth::Instruction::PUSH1), 0x1}); |
||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(literal_false) |
||||
|
{ |
||||
|
char const* sourceCode = "contract test {\n" |
||||
|
" function f() { var x = false; }" |
||||
|
"}\n"; |
||||
|
bytes code = compileFirstExpression(sourceCode); |
||||
|
|
||||
|
bytes expectation({byte(eth::Instruction::PUSH1), 0x0}); |
||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(int_literal) |
||||
|
{ |
||||
|
char const* sourceCode = "contract test {\n" |
||||
|
" function f() { var x = 0x12345678901234567890; }" |
||||
|
"}\n"; |
||||
|
bytes code = compileFirstExpression(sourceCode); |
||||
|
|
||||
|
bytes expectation({byte(eth::Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, |
||||
|
0x12, 0x34, 0x56, 0x78, 0x90}); |
||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(comparison) |
||||
|
{ |
||||
|
char const* sourceCode = "contract test {\n" |
||||
|
" function f() { var x = (0x10aa < 0x11aa) != true; }" |
||||
|
"}\n"; |
||||
|
bytes code = compileFirstExpression(sourceCode); |
||||
|
|
||||
|
bytes expectation({byte(eth::Instruction::PUSH2), 0x10, 0xaa, |
||||
|
byte(eth::Instruction::PUSH2), 0x11, 0xaa, |
||||
|
byte(eth::Instruction::GT), |
||||
|
byte(eth::Instruction::PUSH1), 0x1, |
||||
|
byte(eth::Instruction::EQ), |
||||
|
byte(eth::Instruction::NOT)}); |
||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(short_circuiting) |
||||
|
{ |
||||
|
char const* sourceCode = "contract test {\n" |
||||
|
" function f() { var x = (10 + 8 >= 4 || 2 != 9) != true; }" |
||||
|
"}\n"; |
||||
|
bytes code = compileFirstExpression(sourceCode); |
||||
|
|
||||
|
bytes expectation({byte(eth::Instruction::PUSH1), 0xa, |
||||
|
byte(eth::Instruction::PUSH1), 0x8, |
||||
|
byte(eth::Instruction::ADD), |
||||
|
byte(eth::Instruction::PUSH1), 0x4, |
||||
|
byte(eth::Instruction::GT), |
||||
|
byte(eth::Instruction::NOT), // after this we have 10 + 8 >= 4
|
||||
|
byte(eth::Instruction::DUP1), |
||||
|
byte(eth::Instruction::PUSH1), 0x14, |
||||
|
byte(eth::Instruction::JUMPI), // short-circuit if it is true
|
||||
|
byte(eth::Instruction::PUSH1), 0x2, |
||||
|
byte(eth::Instruction::PUSH1), 0x9, |
||||
|
byte(eth::Instruction::EQ), |
||||
|
byte(eth::Instruction::NOT), // after this we have 2 != 9
|
||||
|
byte(eth::Instruction::JUMPDEST), |
||||
|
byte(eth::Instruction::PUSH1), 0x1, |
||||
|
byte(eth::Instruction::EQ), |
||||
|
byte(eth::Instruction::NOT)}); |
||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(arithmetics) |
||||
|
{ |
||||
|
char const* sourceCode = "contract test {\n" |
||||
|
" function f() { var x = (1 * (2 / (3 % (4 + (5 - (6 | (7 & (8 ^ 9)))))))); }" |
||||
|
"}\n"; |
||||
|
bytes code = compileFirstExpression(sourceCode); |
||||
|
|
||||
|
bytes expectation({byte(eth::Instruction::PUSH1), 0x1, |
||||
|
byte(eth::Instruction::PUSH1), 0x2, |
||||
|
byte(eth::Instruction::PUSH1), 0x3, |
||||
|
byte(eth::Instruction::PUSH1), 0x4, |
||||
|
byte(eth::Instruction::PUSH1), 0x5, |
||||
|
byte(eth::Instruction::PUSH1), 0x6, |
||||
|
byte(eth::Instruction::PUSH1), 0x7, |
||||
|
byte(eth::Instruction::PUSH1), 0x8, |
||||
|
byte(eth::Instruction::PUSH1), 0x9, |
||||
|
byte(eth::Instruction::XOR), |
||||
|
byte(eth::Instruction::AND), |
||||
|
byte(eth::Instruction::OR), |
||||
|
byte(eth::Instruction::SWAP1), |
||||
|
byte(eth::Instruction::SUB), |
||||
|
byte(eth::Instruction::ADD), |
||||
|
byte(eth::Instruction::MOD), |
||||
|
byte(eth::Instruction::DIV), |
||||
|
byte(eth::Instruction::MUL)}); |
||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_CASE(unary_operators) |
||||
|
{ |
||||
|
char const* sourceCode = "contract test {\n" |
||||
|
" function f() { var x = !(~+-(--(++1++)--) == 2); }" |
||||
|
"}\n"; |
||||
|
bytes code = compileFirstExpression(sourceCode); |
||||
|
|
||||
|
bytes expectation({byte(eth::Instruction::PUSH1), 0x1, |
||||
|
byte(eth::Instruction::PUSH1), 0x1, |
||||
|
byte(eth::Instruction::ADD), |
||||
|
byte(eth::Instruction::PUSH1), 0x1, |
||||
|
byte(eth::Instruction::SWAP1), |
||||
|
byte(eth::Instruction::SUB), |
||||
|
byte(eth::Instruction::PUSH1), 0x0, |
||||
|
byte(eth::Instruction::SUB), |
||||
|
byte(eth::Instruction::NOT), |
||||
|
byte(eth::Instruction::PUSH1), 0x2, |
||||
|
byte(eth::Instruction::EQ), |
||||
|
byte(eth::Instruction::ISZERO)}); |
||||
|
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |
||||
|
} |
||||
|
|
||||
|
BOOST_AUTO_TEST_SUITE_END() |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} // end namespaces
|
||||
|
|
@ -0,0 +1,587 @@ |
|||||
|
/**
|
||||
|
* THIS FILE IS GENERATED BY jsonrpcstub, DO NOT CHANGE IT!!!!! |
||||
|
*/ |
||||
|
|
||||
|
#ifndef _WEBTHREESTUBCLIENT_H_ |
||||
|
#define _WEBTHREESTUBCLIENT_H_ |
||||
|
|
||||
|
#include <jsonrpc/rpc.h> |
||||
|
|
||||
|
class WebThreeStubClient |
||||
|
{ |
||||
|
public: |
||||
|
WebThreeStubClient(jsonrpc::AbstractClientConnector* conn) |
||||
|
{ |
||||
|
this->client = new jsonrpc::Client(conn); |
||||
|
} |
||||
|
~WebThreeStubClient() |
||||
|
{ |
||||
|
delete this->client; |
||||
|
} |
||||
|
|
||||
|
std::string account() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("account",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value accounts() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("accounts",p); |
||||
|
if (result.isArray()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string addToGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("addToGroup",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string balanceAt(const std::string& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("balanceAt",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("blockByHash",p); |
||||
|
if (result.isObject()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value blockByNumber(const int& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("blockByNumber",p); |
||||
|
if (result.isObject()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string call(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("call",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool changed(const int& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("changed",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string codeAt(const std::string& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("codeAt",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string coinbase() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("coinbase",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string compile(const std::string& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("compile",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
double countAt(const std::string& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("countAt",p); |
||||
|
if (result.isDouble()) |
||||
|
return result.asDouble(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
int defaultBlock() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("defaultBlock",p); |
||||
|
if (result.isInt()) |
||||
|
return result.asInt(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string gasPrice() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("gasPrice",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string get(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("get",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value getMessages(const int& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("getMessages",p); |
||||
|
if (result.isArray()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string getString(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("getString",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool haveIdentity(const std::string& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("haveIdentity",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool listening() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("listening",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool mining() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("mining",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
int newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("newFilter",p); |
||||
|
if (result.isInt()) |
||||
|
return result.asInt(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
int newFilterString(const std::string& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("newFilterString",p); |
||||
|
if (result.isInt()) |
||||
|
return result.asInt(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string newGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("newGroup",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string newIdentity() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("newIdentity",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
int number() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("number",p); |
||||
|
if (result.isInt()) |
||||
|
return result.asInt(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
int peerCount() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->client->CallMethod("peerCount",p); |
||||
|
if (result.isInt()) |
||||
|
return result.asInt(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool post(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("post",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
p.append(param3); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("put",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool putString(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
p.append(param3); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("putString",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("setCoinbase",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool setDefaultBlock(const int& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("setDefaultBlock",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool setListening(const bool& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("setListening",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool setMining(const bool& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("setMining",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value shhChanged(const int& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("shhChanged",p); |
||||
|
if (result.isArray()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
int shhNewFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("shhNewFilter",p); |
||||
|
if (result.isInt()) |
||||
|
return result.asInt(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool shhUninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("shhUninstallFilter",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string stateAt(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("stateAt",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
std::string transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("transact",p); |
||||
|
if (result.isString()) |
||||
|
return result.asString(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value transactionByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("transactionByHash",p); |
||||
|
if (result.isObject()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value transactionByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("transactionByNumber",p); |
||||
|
if (result.isObject()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value uncleByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("uncleByHash",p); |
||||
|
if (result.isObject()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Json::Value uncleByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("uncleByNumber",p); |
||||
|
if (result.isObject()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
|
||||
|
Json::Value result = this->client->CallMethod("uninstallFilter",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
jsonrpc::Client* client; |
||||
|
}; |
||||
|
#endif //_WEBTHREESTUBCLIENT_H_
|
Loading…
Reference in new issue