subtly
10 years ago
90 changed files with 6063 additions and 2690 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,190 @@ |
|||
/*
|
|||
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 Account.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/RLP.h> |
|||
#include <libdevcrypto/TrieDB.h> |
|||
#include <libdevcrypto/SHA3.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
|
|||
/**
|
|||
* Models the state of a single Ethereum account. |
|||
* Used to cache a portion of the full Ethereum state. State keeps a mapping of Address's to Accounts. |
|||
* |
|||
* Aside from storing the nonce and balance, the account may also be "dead" (where isAlive() returns false). |
|||
* This allows State to explicitly store the notion of a deleted account in it's cache. kill() can be used |
|||
* for this. |
|||
* |
|||
* For the account's storage, the class operates a cache. baseRoot() specifies the base state of the storage |
|||
* given as the Trie root to be looked up in the state database. Alterations beyond this base are specified |
|||
* in the overlay, stored in this class and retrieved with storageOverlay(). setStorage allows the overlay |
|||
* to be altered. |
|||
* |
|||
* The code handling explicitly supports a two-stage commit model needed for contract-creation. When creating |
|||
* a contract (running the initialisation code), the code of the account is considered empty. The attribute |
|||
* of emptiness can be retrieved with codeBearing(). After initialisation one must set the code accordingly; |
|||
* the code of the Account can be set with setCode(). To validate a setCode() call, this class records the |
|||
* state of being in contract-creation (and thus in a state where setCode may validly be called). It can be |
|||
* determined through isFreshCode(). |
|||
* |
|||
* The code can be retrieved through code(), and its hash through codeHash(). codeHash() is only valid when |
|||
* the account is not in the contract-creation phase (i.e. when isFreshCode() returns false). This class |
|||
* supports populating code on-demand from the state database. To determine if the code has been prepopulated |
|||
* call codeCacheValid(). To populate the code, look it up with codeHash() and populate with noteCode(). |
|||
* |
|||
* @todo: need to make a noteCodeCommitted(). |
|||
* |
|||
* The constructor allows you to create an one of a number of "types" of accounts. The default constructor |
|||
* makes a dead account (this is ignored by State when writing out the Trie). Another three allow a basic |
|||
* or contract account to be specified along with an initial balance. The fina two allow either a basic or |
|||
* a contract account to be created with arbitrary values. |
|||
*/ |
|||
class Account |
|||
{ |
|||
public: |
|||
/// Type of account to create.
|
|||
enum NewAccountType |
|||
{ |
|||
/// Normal account.
|
|||
NormalCreation, |
|||
/// Contract account - we place this object into the contract-creation state (and as such we
|
|||
/// expect setCode(), but codeHash() won't work).
|
|||
ContractConception |
|||
}; |
|||
|
|||
/// Construct a dead Account.
|
|||
Account() {} |
|||
|
|||
/// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a
|
|||
/// contract account in the
|
|||
/// conception phase, where the code is not yet known.
|
|||
Account(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? EmptySHA3 : c_contractConceptionCodeHash) {} |
|||
/// Explicit constructor for wierd cases of construction of a normal account.
|
|||
Account(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {} |
|||
|
|||
/// Explicit constructor for wierd cases of construction or a contract account.
|
|||
Account(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) { assert(_contractRoot); } |
|||
|
|||
|
|||
/// Kill this account. Useful for the suicide opcode. Following this call, isAlive() returns false.
|
|||
void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; } |
|||
|
|||
/// @returns true iff this object represents an account in the state. Returns false if this object
|
|||
/// represents an account that should no longer exist in the trie (an account that never existed or was
|
|||
/// suicided).
|
|||
bool isAlive() const { return m_isAlive; } |
|||
|
|||
|
|||
/// @returns the balance of this account. Can be altered in place.
|
|||
u256& balance() { return m_balance; } |
|||
|
|||
/// @returns the balance of this account.
|
|||
u256 const& balance() const { return m_balance; } |
|||
|
|||
/// Increments the balance of this account by the given amount. It's a bigint, so can be negative.
|
|||
void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } |
|||
|
|||
/// @returns the nonce of the account. Can be altered in place.
|
|||
u256& nonce() { return m_nonce; } |
|||
|
|||
/// @returns the nonce of the account.
|
|||
u256 const& nonce() const { return m_nonce; } |
|||
|
|||
/// Increment the nonce of the account by one.
|
|||
void incNonce() { m_nonce++; } |
|||
|
|||
|
|||
/// @returns the root of the trie (whose nodes are stored in the state db externally to this class)
|
|||
/// which encodes the base-state of the account's storage (upon which the storage is overlaid).
|
|||
h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } |
|||
|
|||
/// @returns the storage overlay as a simple map.
|
|||
std::map<u256, u256> const& storageOverlay() const { return m_storageOverlay; } |
|||
|
|||
/// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing
|
|||
/// to the trie later.
|
|||
void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } |
|||
|
|||
/// @returns true if we are in the contract-conception state and setCode is valid to call.
|
|||
bool isFreshCode() const { return m_codeHash == c_contractConceptionCodeHash; } |
|||
|
|||
/// @returns true if we are either in the contract-conception state or if the account's code is not
|
|||
/// empty.
|
|||
bool codeBearing() const { return m_codeHash != EmptySHA3; } |
|||
|
|||
/// @returns the hash of the account's code. Must only be called when isFreshCode() returns false.
|
|||
h256 codeHash() const { assert(!isFreshCode()); return m_codeHash; } |
|||
|
|||
/// Sets the code of the account. Must only be called when isFreshCode() returns true.
|
|||
void setCode(bytesConstRef _code) { assert(isFreshCode()); m_codeCache = _code.toBytes(); } |
|||
|
|||
/// @returns true if the account's code is available through code().
|
|||
bool codeCacheValid() const { return m_codeHash == EmptySHA3 || m_codeHash == c_contractConceptionCodeHash || m_codeCache.size(); } |
|||
|
|||
/// Specify to the object what the actual code is for the account. @a _code must have a SHA3 equal to
|
|||
/// codeHash() and must only be called when isFreshCode() returns false.
|
|||
void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); } |
|||
|
|||
/// @returns the account's code. Must only be called when codeCacheValid returns true.
|
|||
bytes const& code() const { assert(codeCacheValid()); return m_codeCache; } |
|||
|
|||
private: |
|||
/// Is this account existant? If not, it represents a deleted account.
|
|||
bool m_isAlive = false; |
|||
|
|||
/// Account's nonce.
|
|||
u256 m_nonce = 0; |
|||
|
|||
/// Account's balance.
|
|||
u256 m_balance = 0; |
|||
|
|||
/// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is
|
|||
/// overlaid on this and takes precedence for all values set.
|
|||
h256 m_storageRoot = EmptyTrie; |
|||
|
|||
/** If c_contractConceptionCodeHash then we're in the limbo where we're running the initialisation code.
|
|||
* We expect a setCode() at some point later. |
|||
* If EmptySHA3, then m_code, which should be empty, is valid. |
|||
* If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to |
|||
* be called with the correct args. |
|||
*/ |
|||
h256 m_codeHash = EmptySHA3; |
|||
|
|||
/// The map with is overlaid onto whatever storage is implied by the m_storageRoot in the trie.
|
|||
std::map<u256, u256> m_storageOverlay; |
|||
|
|||
/// The associated code for this account. The SHA3 of this should be equal to m_codeHash unless m_codeHash
|
|||
/// equals c_contractConceptionCodeHash.
|
|||
bytes m_codeCache; |
|||
|
|||
/// Value for m_codeHash when this account is having its code determined.
|
|||
static const h256 c_contractConceptionCodeHash; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
@ -1,94 +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 AddressState.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/RLP.h> |
|||
#include <libdevcrypto/TrieDB.h> |
|||
#include <libdevcrypto/SHA3.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
|
|||
// TODO: Document fully.
|
|||
|
|||
class AddressState |
|||
{ |
|||
public: |
|||
enum NewAccountType { NormalCreation, ContractConception }; |
|||
|
|||
/// Construct a dead AddressState.
|
|||
AddressState() {} |
|||
/// Construct an alive AddressState, with given endowment, for either a normal (non-contract) account or for a contract account in the
|
|||
/// conception phase, where the code is not yet known.
|
|||
AddressState(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? h256() : EmptySHA3) {} |
|||
/// Explicit constructor for wierd cases of construction of a normal account.
|
|||
AddressState(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {} |
|||
/// Explicit constructor for wierd cases of construction or a contract account.
|
|||
AddressState(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) {} |
|||
|
|||
void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; } |
|||
bool isAlive() const { return m_isAlive; } |
|||
|
|||
u256& balance() { return m_balance; } |
|||
u256 const& balance() const { return m_balance; } |
|||
void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } |
|||
|
|||
u256& nonce() { return m_nonce; } |
|||
u256 const& nonce() const { return m_nonce; } |
|||
void incNonce() { m_nonce++; } |
|||
|
|||
h256 baseRoot() const { return m_storageRoot; } |
|||
std::map<u256, u256> const& storage() const { return m_storageOverlay; } |
|||
void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } |
|||
|
|||
bool isFreshCode() const { return !m_codeHash; } |
|||
bool codeBearing() const { return m_codeHash != EmptySHA3; } |
|||
bool codeCacheValid() const { return m_codeHash == EmptySHA3 || !m_codeHash || m_codeCache.size(); } |
|||
h256 codeHash() const { assert(m_codeHash); return m_codeHash; } |
|||
bytes const& code() const { assert(m_codeHash == EmptySHA3 || !m_codeHash || m_codeCache.size()); return m_codeCache; } |
|||
void setCode(bytesConstRef _code) { assert(!m_codeHash); m_codeCache = _code.toBytes(); } |
|||
void noteCode(bytesConstRef _code) { assert(sha3(_code) == m_codeHash); m_codeCache = _code.toBytes(); } |
|||
|
|||
private: |
|||
bool m_isAlive = false; |
|||
u256 m_nonce = 0; |
|||
u256 m_balance = 0; |
|||
|
|||
/// The base storage root. Used with the state DB to give a base to the storage. m_storageOverlay is overlaid on this and takes precedence for all values set.
|
|||
h256 m_storageRoot = EmptyTrie; |
|||
|
|||
/// If 0 then we're in the limbo where we're running the initialisation code. We expect a setCode() at some point later.
|
|||
/// If EmptySHA3, then m_code, which should be empty, is valid.
|
|||
/// If anything else, then m_code is valid iff it's not empty, otherwise, State::ensureCached() needs to be called with the correct args.
|
|||
h256 m_codeHash = EmptySHA3; |
|||
|
|||
// TODO: change to unordered_map.
|
|||
std::map<u256, u256> m_storageOverlay; |
|||
bytes m_codeCache; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
@ -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