From e2f32c3632e51b58ec5f7811a9730982bac82738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 17:58:37 +0100 Subject: [PATCH 01/44] Fix compilation with Visual Studio --- libdevcrypto/EC.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index af6d0e65e..7bc17ab99 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,7 +134,7 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static size_t derMaxEncodingLength = 72; + static const size_t derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); @@ -155,8 +155,9 @@ Public crypto::recover(Signature _signature, bytesConstRef _message) { secp256k1_start(); - int pubkeylen = 65; - byte pubkey[pubkeylen]; + static const int c_pubkeylen = 65; + auto pubkeylen = c_pubkeylen; + byte pubkey[c_pubkeylen]; if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) return Public(); @@ -180,8 +181,9 @@ bool crypto::verifySecret(Secret const& _s, Public const& _p) if (!ok) return false; - int pubkeylen = 65; - byte pubkey[pubkeylen]; + static const int c_pubkeylen = 65; + auto pubkeylen = c_pubkeylen; + byte pubkey[c_pubkeylen]; ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0); if (!ok || pubkeylen != 65) return false; From de0c84c7df6ad668f0969d35475fe4608e99f072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 18:29:49 +0100 Subject: [PATCH 02/44] Replace auto with int --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 7bc17ab99..17304668b 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -182,7 +182,7 @@ bool crypto::verifySecret(Secret const& _s, Public const& _p) return false; static const int c_pubkeylen = 65; - auto pubkeylen = c_pubkeylen; + int pubkeylen = c_pubkeylen; byte pubkey[c_pubkeylen]; ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _s.data(), 0); if (!ok || pubkeylen != 65) From 30bb7c21607d4b9c11a47a94fcdd53d3ecd87a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 6 Nov 2014 18:30:42 +0100 Subject: [PATCH 03/44] Replace auto with int --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 17304668b..237acebc5 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -156,7 +156,7 @@ Public crypto::recover(Signature _signature, bytesConstRef _message) secp256k1_start(); static const int c_pubkeylen = 65; - auto pubkeylen = c_pubkeylen; + int pubkeylen = c_pubkeylen; byte pubkey[c_pubkeylen]; if (!secp256k1_ecdsa_recover_compact(_message.data(), 32, _signature.data(), pubkey, &pubkeylen, 0, (int)_signature[64])) return Public(); From c5927833ac583d39bc32975c2e6b4a6a502a3ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 7 Nov 2014 11:37:34 +0100 Subject: [PATCH 04/44] static const variable name fix --- libdevcrypto/EC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index 237acebc5..a54c0132d 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,7 +134,7 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static const size_t derMaxEncodingLength = 72; + static const size_t c_derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); From 79267006ce3072390ebab78114004a4eab32e4a5 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 10 Nov 2014 21:32:13 +0100 Subject: [PATCH 05/44] js abi connection --- libethereum/Client.cpp | 2 +- libjsqrc/main.js | 14 +++-- libweb3jsonrpc/CMakeLists.txt | 1 + libweb3jsonrpc/WebThreeStubServer.cpp | 67 ++++++++++++++++++-- libweb3jsonrpc/WebThreeStubServer.h | 6 +- libweb3jsonrpc/abstractwebthreestubserver.h | 36 +++++++++-- libweb3jsonrpc/spec.json | 6 +- test/webthreestubclient.h | 70 ++++++++++++++++----- 8 files changed, 170 insertions(+), 32 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index d87e9c33e..0be499541 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -341,7 +341,7 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat n = temp.transactionsFrom(toAddress(_secret)); } Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); - u256 gasUsed = temp.execute(t.data(), &out, false); + u256 gasUsed = temp.execute(t.rlp(), &out, false); (void)gasUsed; // TODO: do something with gasused which it returns. } catch (...) diff --git a/libjsqrc/main.js b/libjsqrc/main.js index eb1dd25b9..c07a938e4 100644 --- a/libjsqrc/main.js +++ b/libjsqrc/main.js @@ -87,7 +87,11 @@ { name: 'block', call: blockCall }, { name: 'transaction', call: transactionCall }, { name: 'uncle', call: uncleCall }, - { name: 'compile', call: 'compile' } + { name: 'compilers', call: 'compilers' }, + { name: 'lll', call: 'lll' }, + { name: 'solidity', call: 'solidity' }, + { name: 'contractCreate', call: 'contractCreate' }, + { name: 'contractCall', call: 'contractCall' } ]; return methods; }; @@ -414,10 +418,8 @@ }; Filter.prototype.trigger = function(messages) { - if (!(messages instanceof Array) || messages.length) { - for(var i = 0; i < this.callbacks.length; i++) { - this.callbacks[i].call(this, messages); - } + for(var i = 0; i < this.callbacks.length; i++) { + this.callbacks[i].call(this, messages); } }; @@ -446,7 +448,7 @@ if(data._id) { var cb = web3._callbacks[data._id]; if (cb) { - cb.call(this, data.error, data.data); + cb.call(this, data.error, data.data) delete web3._callbacks[data._id]; } } diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index b24a11196..2f2219461 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -18,6 +18,7 @@ endif() target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) +target_link_libraries(${EXECUTABLE} solidity) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 40ec744bd..6b1ab6d68 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -31,6 +31,8 @@ #include #include #include +#include +#include using namespace std; using namespace dev; @@ -373,13 +375,13 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) ret.data = jsToBytes(_json["code"].asString()); else if (_json["data"].isArray()) for (auto i: _json["data"]) - dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32))); + dev::operator +=(ret.data, asBytes(jsPadded(i.asString(), 32))); else if (_json["code"].isArray()) for (auto i: _json["code"]) - dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32))); + 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())); + dev::operator +=(ret.data, asBytes(i.asString())); } return ret; } @@ -516,9 +518,64 @@ std::string WebThreeStubServer::newIdentity() return toJS(kp.pub()); } -std::string WebThreeStubServer::compile(string const& _s) +Json::Value WebThreeStubServer::compilers() { - return toJS(dev::eth::compileLLL(_s)); + Json::Value ret(Json::arrayValue); + ret.append("lll"); + ret.append("solidity"); + return ret; +} + +static bytes paramsToBytes(Json::Value const& _params) +{ + bytes data; + if (_params.isArray()) + for (auto i: _params) +// data += asBytes(i.asString()); +// data += toBigEndian(jsToU256(i.asString())); + data += asBytes(jsPadded(i.asString(), 33)); + cwarn << data; + return data; +} + +std::string WebThreeStubServer::contractCall(std::string const& _address, std::string const& _value, Json::Value const& _params) +{ + auto from = m_accounts.begin()->first; + for (auto a: m_accounts) + if (client()->balanceAt(a.first) > client()->balanceAt(from)) + from = a.first; + + cwarn << "Silently signing transaction from address" << from.abridged() << ": User validation hook goes here."; + + auto gasPrice = 10 * dev::eth::szabo; + auto gas = min(client()->gasLimitRemaining(), client()->balanceAt(from) / gasPrice); + auto bytes = paramsToBytes(_params); + return toJS(client()->call(m_accounts[from].secret(), jsToU256(_value), jsToAddress(_address), paramsToBytes(_params), gas, gasPrice)); +} + +std::string WebThreeStubServer::contractCreate(std::string const& _bytecode, std::string const& _value) +{ + auto from = m_accounts.begin()->first; + for (auto a: m_accounts) + if (client()->balanceAt(a.first) > client()->balanceAt(from)) + from = a.first; + + cwarn << "Silently signing transaction from address" << from.abridged() << ": User validation hook goes here."; + + auto gasPrice = 10 * dev::eth::szabo; + auto gas = min(client()->gasLimitRemaining(), client()->balanceAt(from) / gasPrice); + return toJS(client()->transact(m_accounts[from].secret(), jsToU256(_value), jsToBytes(_bytecode), gas, gasPrice)); +} + +std::string WebThreeStubServer::lll(std::string const& _code) +{ + return toJS(dev::eth::compileLLL(_code)); +} + +std::string WebThreeStubServer::solidity(std::string const& _code) +{ + shared_ptr scanner = make_shared(); + return toJS(dev::solidity::CompilerStack::compile(_code, scanner)); } int WebThreeStubServer::number() diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 33163b75e..1ca77b497 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -73,7 +73,9 @@ public: 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 Json::Value compilers(); + virtual std::string contractCall(std::string const& _address, std::string const& _value, Json::Value const& _params); + virtual std::string contractCreate(std::string const& _bytecode, std::string const& _value); virtual double countAt(std::string const& _address); virtual int defaultBlock(); virtual std::string gasPrice(); @@ -82,6 +84,7 @@ public: virtual std::string getString(std::string const& _name, std::string const& _key); virtual bool haveIdentity(std::string const& _id); virtual bool listening(); + virtual std::string lll(std::string const& _code); virtual bool mining(); virtual int newFilter(Json::Value const& _json); virtual int newFilterString(std::string const& _filter); @@ -99,6 +102,7 @@ public: virtual Json::Value shhChanged(int const& _id); virtual int shhNewFilter(Json::Value const& _json); virtual bool shhUninstallFilter(int const& _id); + virtual std::string solidity(std::string const& _code); 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); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 66b9ff77d..97b7a219f 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -22,7 +22,9 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(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("compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::compilersI); + this->bindAndAddMethod(new jsonrpc::Procedure("contractCall", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::contractCallI); + this->bindAndAddMethod(new jsonrpc::Procedure("contractCreate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::contractCreateI); 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); @@ -31,6 +33,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(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("lll", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::lllI); 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); @@ -48,6 +51,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(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("solidity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::solidityI); 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); @@ -103,9 +107,19 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServercoinbase(); } - inline virtual void compileI(const Json::Value& request, Json::Value& response) + inline virtual void compilersI(const Json::Value& request, Json::Value& response) { - response = this->compile(request[0u].asString()); + response = this->compilers(); + } + + inline virtual void contractCallI(const Json::Value& request, Json::Value& response) + { + response = this->contractCall(request[0u].asString(), request[1u].asString(), request[2u]); + } + + inline virtual void contractCreateI(const Json::Value& request, Json::Value& response) + { + response = this->contractCreate(request[0u].asString(), request[1u].asString()); } inline virtual void countAtI(const Json::Value& request, Json::Value& response) @@ -148,6 +162,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerlistening(); } + inline virtual void lllI(const Json::Value& request, Json::Value& response) + { + response = this->lll(request[0u].asString()); + } + inline virtual void miningI(const Json::Value& request, Json::Value& response) { response = this->mining(); @@ -233,6 +252,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServershhUninstallFilter(request[0u].asInt()); } + inline virtual void solidityI(const Json::Value& request, Json::Value& response) + { + response = this->solidity(request[0u].asString()); + } + inline virtual void stateAtI(const Json::Value& request, Json::Value& response) { response = this->stateAt(request[0u].asString(), request[1u].asString()); @@ -278,7 +302,9 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerclient; } - 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; @@ -147,12 +135,40 @@ p.append(param2); } - std::string compile(const std::string& param1) throw (jsonrpc::JsonRpcException) + Json::Value compilers() throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p = Json::nullValue; + Json::Value result = this->client->CallMethod("compilers",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + + std::string contractCall(const std::string& param1, const std::string& param2, const Json::Value& param3) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); +p.append(param2); +p.append(param3); + + Json::Value result = this->client->CallMethod("contractCall",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + + std::string contractCreate(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("compile",p); + Json::Value result = this->client->CallMethod("contractCreate",p); if (result.isString()) return result.asString(); else @@ -263,6 +279,19 @@ p.append(param2); } + std::string lll(const std::string& param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + + Json::Value result = this->client->CallMethod("lll",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + bool mining() throw (jsonrpc::JsonRpcException) { Json::Value p; @@ -485,6 +514,19 @@ p.append(param3); } + std::string solidity(const std::string& param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + + Json::Value result = this->client->CallMethod("solidity",p); + if (result.isString()) + return result.asString(); + 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; From 6cc9e6952e5bf14b014e0da4d96868bac6806fc8 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 10 Nov 2014 22:51:10 +0100 Subject: [PATCH 06/44] merge --- alethzero/MainWin.cpp | 2 +- alethzero/OurWebThreeStubServer.cpp | 2 +- alethzero/OurWebThreeStubServer.h | 2 +- libethereum/Executive.cpp | 4 +- libevmcore/Assembly.cpp | 81 +- libevmcore/Assembly.h | 2 +- libevmcore/Instruction.cpp | 260 ++-- libevmcore/Instruction.h | 1 + libjsqrc/main.js | 80 +- libjsqrc/setup.js | 2 +- libqethereum/QEthereum.cpp | 29 +- libsolidity/Compiler.cpp | 9 +- libsolidity/Compiler.h | 4 +- libsolidity/CompilerContext.h | 2 +- libsolidity/CompilerStack.cpp | 5 +- libsolidity/CompilerStack.h | 2 +- libweb3jsonrpc/WebThreeStubServer.cpp | 94 +- libweb3jsonrpc/WebThreeStubServer.h | 96 +- libweb3jsonrpc/abstractwebthreestubserver.h | 368 ++--- libweb3jsonrpc/spec.json | 106 +- solc/main.cpp | 10 +- test/TestHelper.cpp | 43 +- test/TestHelper.h | 1 + test/jsonrpc.cpp | 46 +- test/stPreCompiledContractsFiller.json | 717 ++++++++++ test/stSystemOperationsTestFiller.json | 1334 +++++++++++++++++++ test/state.cpp | 11 +- test/vm.cpp | 35 +- test/vmArithmeticTestFiller.json | 14 +- test/webthreestubclient.h | 356 ++--- 30 files changed, 2956 insertions(+), 762 deletions(-) create mode 100644 test/stPreCompiledContractsFiller.json create mode 100644 test/stSystemOperationsTestFiller.json diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e43a61d37..8fe76e24b 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1605,7 +1605,7 @@ void Main::on_data_textChanged() shared_ptr scanner = make_shared(); try { - m_data = dev::solidity::CompilerStack::compile(src, scanner); + m_data = dev::solidity::CompilerStack::compile(src, scanner, m_enableOptimizer); } catch (dev::Exception const& exception) { diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index ca1b77649..a40727e1e 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -28,7 +28,7 @@ OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector* _ WebThreeStubServer(_conn, _web3, _accounts) {} -std::string OurWebThreeStubServer::newIdentity() +std::string OurWebThreeStubServer::shh_newIdentity() { dev::KeyPair kp = dev::KeyPair::create(); emit onNewId(QString::fromStdString(toJS(kp.sec()))); diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index be06da62d..b3492df5e 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -31,7 +31,7 @@ class OurWebThreeStubServer: public QObject, public WebThreeStubServer public: OurWebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); - virtual std::string newIdentity() override; + virtual std::string shh_newIdentity() override; signals: void onNewId(QString _s); diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 71fc12a8c..fb89eb21e 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -80,14 +80,14 @@ bool Executive::setup(bytesConstRef _rlp) if (m_s.balance(m_sender) < cost) { clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender); - BOOST_THROW_EXCEPTION(NotEnoughCash()); + BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((int)cost, (int)m_s.balance(m_sender))); } u256 startGasUsed = m_s.gasUsed(); if (startGasUsed + m_t.gas() > m_s.m_currentBlock.gasLimit) { clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas(); - BOOST_THROW_EXCEPTION(BlockGasLimitReached()); + BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((int)(m_s.m_currentBlock.gasLimit - startGasUsed), (int)m_t.gas())); } // Increment associated nonce for sender. diff --git a/libevmcore/Assembly.cpp b/libevmcore/Assembly.cpp index d4f6c0a73..4725c8c1a 100644 --- a/libevmcore/Assembly.cpp +++ b/libevmcore/Assembly.cpp @@ -70,7 +70,12 @@ unsigned Assembly::bytesRequired() const case PushData: case PushSub: ret += 1 + br; - default:; + break; + case NoOptimizeBegin: + case NoOptimizeEnd: + break; + default: + BOOST_THROW_EXCEPTION(InvalidOpcode()); } if (dev::bytesRequired(ret) <= br) return ret; @@ -140,9 +145,17 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i) case PushSubSize: _out << " PUSHss[" << hex << h256(i.data()).abridged() << "]"; break; + case NoOptimizeBegin: + _out << " DoNotOptimze{{"; + break; + case NoOptimizeEnd: + _out << " DoNotOptimze}}"; + break; case UndefinedItem: _out << " ???"; - default:; + break; + default: + BOOST_THROW_EXCEPTION(InvalidOpcode()); } return _out; } @@ -177,7 +190,14 @@ ostream& Assembly::streamRLP(ostream& _out, string const& _prefix) const case PushData: _out << _prefix << " PUSH [" << hex << (unsigned)i.m_data << "]" << endl; break; - default:; + case NoOptimizeBegin: + _out << _prefix << "DoNotOptimze{{" << endl; + break; + case NoOptimizeEnd: + _out << _prefix << "DoNotOptimze}}" << endl; + break; + default: + BOOST_THROW_EXCEPTION(InvalidOpcode()); } if (m_data.size() || m_subs.size()) @@ -217,6 +237,12 @@ inline bool matches(AssemblyItemsConstRef _a, AssemblyItemsConstRef _b) return true; } +inline bool popCountIncreased(AssemblyItemsConstRef _pre, AssemblyItems const& _post) +{ + auto isPop = [](AssemblyItem const& _item) -> bool { return _item.match(AssemblyItem(Instruction::POP)); }; + return count_if(begin(_post), end(_post), isPop) > count_if(begin(_pre), end(_pre), isPop); +} + struct OptimiserChannel: public LogChannel { static const char* name() { return "OPT"; } static const int verbosity = 12; }; #define copt dev::LogOutputStream() @@ -224,6 +250,14 @@ Assembly& Assembly::optimise(bool _enable) { if (!_enable) return *this; + auto signextend = [](u256 a, u256 b) -> u256 + { + if (a >= 31) + return b; + unsigned testBit = unsigned(a) * 8 + 7; + u256 mask = (u256(1) << testBit) - 1; + return boost::multiprecision::bit_test(b, testBit) ? b | ~mask : b & mask; + }; map> c_simple = { { Instruction::SUB, [](u256 a, u256 b)->u256{return a - b;} }, @@ -232,6 +266,7 @@ Assembly& Assembly::optimise(bool _enable) { Instruction::MOD, [](u256 a, u256 b)->u256{return a % b;} }, { Instruction::SMOD, [](u256 a, u256 b)->u256{return s2u(u2s(a) % u2s(b));} }, { Instruction::EXP, [](u256 a, u256 b)->u256{return (u256)boost::multiprecision::powm((bigint)a, (bigint)b, bigint(2) << 256);} }, + { Instruction::SIGNEXTEND, signextend }, { Instruction::LT, [](u256 a, u256 b)->u256{return a < b ? 1 : 0;} }, { Instruction::GT, [](u256 a, u256 b)->u256{return a > b ? 1 : 0;} }, { Instruction::SLT, [](u256 a, u256 b)->u256{return u2s(a) < u2s(b) ? 1 : 0;} }, @@ -242,6 +277,9 @@ Assembly& Assembly::optimise(bool _enable) { { Instruction::ADD, [](u256 a, u256 b)->u256{return a + b;} }, { Instruction::MUL, [](u256 a, u256 b)->u256{return a * b;} }, + { Instruction::AND, [](u256 a, u256 b)->u256{return a & b;} }, + { Instruction::OR, [](u256 a, u256 b)->u256{return a | b;} }, + { Instruction::XOR, [](u256 a, u256 b)->u256{return a ^ b;} }, }; std::vector>> rules = { @@ -260,8 +298,23 @@ Assembly& Assembly::optimise(bool _enable) { rules.push_back({ { Push, Push, i.first }, [&](AssemblyItemsConstRef m) -> AssemblyItems { return { i.second(m[1].data(), m[0].data()) }; } }); rules.push_back({ { Push, i.first, Push, i.first }, [&](AssemblyItemsConstRef m) -> AssemblyItems { return { i.second(m[2].data(), m[0].data()), i.first }; } }); - rules.push_back({ { PushTag, Instruction::JUMP, Tag }, [&](AssemblyItemsConstRef m) -> AssemblyItems { if (m[0].m_data == m[2].m_data) return {}; else return m.toVector(); }}); } + // jump to next instruction + rules.push_back({ { PushTag, Instruction::JUMP, Tag }, [&](AssemblyItemsConstRef m) -> AssemblyItems { if (m[0].m_data == m[2].m_data) return {m[2]}; else return m.toVector(); }}); + + // pop optimization, do not compute values that are popped again anyway + rules.push_back({ { AssemblyItem(UndefinedItem), Instruction::POP }, [](AssemblyItemsConstRef m) -> AssemblyItems + { + if (m[0].type() != Operation) + return m.toVector(); + Instruction instr = Instruction(byte(m[0].data())); + if (Instruction::DUP1 <= instr && instr <= Instruction::DUP16) + return {}; + InstructionInfo info = instructionInfo(instr); + if (info.sideEffects || info.additional != 0 || info.ret != 1) + return m.toVector(); + return AssemblyItems(info.args, Instruction::POP); + } }); copt << *this; @@ -269,16 +322,21 @@ Assembly& Assembly::optimise(bool _enable) for (unsigned count = 1; count > 0; total += count) { count = 0; - map tags; for (unsigned i = 0; i < m_items.size(); ++i) { + if (m_items[i].type() == NoOptimizeBegin) + { + while (i < m_items.size() && m_items[i].type() != NoOptimizeEnd) + ++i; + continue; + } for (auto const& r: rules) { auto vr = AssemblyItemsConstRef(&m_items).cropped(i, r.first.size()); - if (matches(&r.first, vr)) + if (matches(vr, &r.first)) { auto rw = r.second(vr); - if (rw.size() < vr.size()) + if (rw.size() < vr.size() || (rw.size() == vr.size() && popCountIncreased(vr, rw))) { copt << vr << "matches" << AssemblyItemsConstRef(&r.first) << "becomes..."; for (unsigned j = 0; j < vr.size(); ++j) @@ -297,6 +355,8 @@ Assembly& Assembly::optimise(bool _enable) bool o = false; while (m_items.size() > i + 1 && m_items[i + 1].type() != Tag) { + if (m_items[i + 1].type() == NoOptimizeBegin) + break; m_items.erase(m_items.begin() + i + 1); o = true; } @@ -308,6 +368,7 @@ Assembly& Assembly::optimise(bool _enable) } } + map tags; for (unsigned i = 0; i < m_items.size(); ++i) if (m_items[i].type() == Tag) tags.insert(make_pair(m_items[i].data(), i)); @@ -416,7 +477,11 @@ bytes Assembly::assemble() const tagPos[(unsigned)i.m_data] = ret.size(); ret.push_back((byte)Instruction::JUMPDEST); break; - default:; + case NoOptimizeBegin: + case NoOptimizeEnd: + break; + default: + BOOST_THROW_EXCEPTION(InvalidOpcode()); } for (auto const& i: tagRef) diff --git a/libevmcore/Assembly.h b/libevmcore/Assembly.h index ef5294a54..b8e59a474 100644 --- a/libevmcore/Assembly.h +++ b/libevmcore/Assembly.h @@ -32,7 +32,7 @@ namespace dev namespace eth { -enum AssemblyItemType { UndefinedItem, Operation, Push, PushString, PushTag, PushSub, PushSubSize, Tag, PushData }; +enum AssemblyItemType { UndefinedItem, Operation, Push, PushString, PushTag, PushSub, PushSubSize, Tag, PushData, NoOptimizeBegin, NoOptimizeEnd }; class Assembly; diff --git a/libevmcore/Instruction.cpp b/libevmcore/Instruction.cpp index ad27b28ef..2df77a3c5 100644 --- a/libevmcore/Instruction.cpp +++ b/libevmcore/Instruction.cpp @@ -162,136 +162,136 @@ const std::map dev::eth::c_instructions = }; static const std::map c_instructionInfo = -{ // Add, Args, Ret - { Instruction::STOP, { "STOP", 0, 0, 0 } }, - { Instruction::ADD, { "ADD", 0, 2, 1 } }, - { Instruction::SUB, { "SUB", 0, 2, 1 } }, - { Instruction::MUL, { "MUL", 0, 2, 1 } }, - { Instruction::DIV, { "DIV", 0, 2, 1 } }, - { Instruction::SDIV, { "SDIV", 0, 2, 1 } }, - { Instruction::MOD, { "MOD", 0, 2, 1 } }, - { Instruction::SMOD, { "SMOD", 0, 2, 1 } }, - { Instruction::EXP, { "EXP", 0, 2, 1 } }, - { Instruction::NOT, { "NOT", 0, 1, 1 } }, - { Instruction::LT, { "LT", 0, 2, 1 } }, - { Instruction::GT, { "GT", 0, 2, 1 } }, - { Instruction::SLT, { "SLT", 0, 2, 1 } }, - { Instruction::SGT, { "SGT", 0, 2, 1 } }, - { Instruction::EQ, { "EQ", 0, 2, 1 } }, - { Instruction::ISZERO, { "ISZERO", 0, 1, 1 } }, - { Instruction::AND, { "AND", 0, 2, 1 } }, - { Instruction::OR, { "OR", 0, 2, 1 } }, - { Instruction::XOR, { "XOR", 0, 2, 1 } }, - { Instruction::BYTE, { "BYTE", 0, 2, 1 } }, - { Instruction::ADDMOD, { "ADDMOD", 0, 3, 1 } }, - { Instruction::MULMOD, { "MULMOD", 0, 3, 1 } }, - { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1 } }, - { Instruction::SHA3, { "SHA3", 0, 2, 1 } }, - { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1 } }, - { Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, - { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1 } }, - { Instruction::CALLER, { "CALLER", 0, 0, 1 } }, - { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1 } }, - { Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1 } }, - { Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1 } }, - { Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0 } }, - { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1 } }, - { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0 } }, - { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1 } }, - { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1 } }, - { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0 } }, - { Instruction::PREVHASH, { "PREVHASH", 0, 0, 1 } }, - { Instruction::COINBASE, { "COINBASE", 0, 0, 1 } }, - { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1 } }, - { Instruction::NUMBER, { "NUMBER", 0, 0, 1 } }, - { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1 } }, - { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1 } }, - { Instruction::POP, { "POP", 0, 1, 0 } }, - { Instruction::MLOAD, { "MLOAD", 0, 1, 1 } }, - { Instruction::MSTORE, { "MSTORE", 0, 2, 0 } }, - { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0 } }, - { Instruction::SLOAD, { "SLOAD", 0, 1, 1 } }, - { Instruction::SSTORE, { "SSTORE", 0, 2, 0 } }, - { Instruction::JUMP, { "JUMP", 0, 1, 0 } }, - { Instruction::JUMPI, { "JUMPI", 0, 2, 0 } }, - { Instruction::PC, { "PC", 0, 0, 1 } }, - { Instruction::MSIZE, { "MSIZE", 0, 0, 1 } }, - { Instruction::GAS, { "GAS", 0, 0, 1 } }, - { Instruction::JUMPDEST, { "JUMPDEST", 0, 1, 0 } }, - { Instruction::PUSH1, { "PUSH1", 1, 0, 1 } }, - { Instruction::PUSH2, { "PUSH2", 2, 0, 1 } }, - { Instruction::PUSH3, { "PUSH3", 3, 0, 1 } }, - { Instruction::PUSH4, { "PUSH4", 4, 0, 1 } }, - { Instruction::PUSH5, { "PUSH5", 5, 0, 1 } }, - { Instruction::PUSH6, { "PUSH6", 6, 0, 1 } }, - { Instruction::PUSH7, { "PUSH7", 7, 0, 1 } }, - { Instruction::PUSH8, { "PUSH8", 8, 0, 1 } }, - { Instruction::PUSH9, { "PUSH9", 9, 0, 1 } }, - { Instruction::PUSH10, { "PUSH10", 10, 0, 1 } }, - { Instruction::PUSH11, { "PUSH11", 11, 0, 1 } }, - { Instruction::PUSH12, { "PUSH12", 12, 0, 1 } }, - { Instruction::PUSH13, { "PUSH13", 13, 0, 1 } }, - { Instruction::PUSH14, { "PUSH14", 14, 0, 1 } }, - { Instruction::PUSH15, { "PUSH15", 15, 0, 1 } }, - { Instruction::PUSH16, { "PUSH16", 16, 0, 1 } }, - { Instruction::PUSH17, { "PUSH17", 17, 0, 1 } }, - { Instruction::PUSH18, { "PUSH18", 18, 0, 1 } }, - { Instruction::PUSH19, { "PUSH19", 19, 0, 1 } }, - { Instruction::PUSH20, { "PUSH20", 20, 0, 1 } }, - { Instruction::PUSH21, { "PUSH21", 21, 0, 1 } }, - { Instruction::PUSH22, { "PUSH22", 22, 0, 1 } }, - { Instruction::PUSH23, { "PUSH23", 23, 0, 1 } }, - { Instruction::PUSH24, { "PUSH24", 24, 0, 1 } }, - { Instruction::PUSH25, { "PUSH25", 25, 0, 1 } }, - { Instruction::PUSH26, { "PUSH26", 26, 0, 1 } }, - { Instruction::PUSH27, { "PUSH27", 27, 0, 1 } }, - { Instruction::PUSH28, { "PUSH28", 28, 0, 1 } }, - { Instruction::PUSH29, { "PUSH29", 29, 0, 1 } }, - { Instruction::PUSH30, { "PUSH30", 30, 0, 1 } }, - { Instruction::PUSH31, { "PUSH31", 31, 0, 1 } }, - { Instruction::PUSH32, { "PUSH32", 32, 0, 1 } }, - { Instruction::DUP1, { "DUP1", 0, 1, 2 } }, - { Instruction::DUP2, { "DUP2", 0, 2, 3 } }, - { Instruction::DUP3, { "DUP3", 0, 3, 4 } }, - { Instruction::DUP4, { "DUP4", 0, 4, 5 } }, - { Instruction::DUP5, { "DUP5", 0, 5, 6 } }, - { Instruction::DUP6, { "DUP6", 0, 6, 7 } }, - { Instruction::DUP7, { "DUP7", 0, 7, 8 } }, - { Instruction::DUP8, { "DUP8", 0, 8, 9 } }, - { Instruction::DUP9, { "DUP9", 0, 9, 10 } }, - { Instruction::DUP10, { "DUP10", 0, 10, 11 } }, - { Instruction::DUP11, { "DUP11", 0, 11, 12 } }, - { Instruction::DUP12, { "DUP12", 0, 12, 13 } }, - { Instruction::DUP13, { "DUP13", 0, 13, 14 } }, - { Instruction::DUP14, { "DUP14", 0, 14, 15 } }, - { Instruction::DUP15, { "DUP15", 0, 15, 16 } }, - { Instruction::DUP16, { "DUP16", 0, 16, 17 } }, - { Instruction::SWAP1, { "SWAP1", 0, 2, 2 } }, - { Instruction::SWAP2, { "SWAP2", 0, 3, 3 } }, - { Instruction::SWAP3, { "SWAP3", 0, 4, 4 } }, - { Instruction::SWAP4, { "SWAP4", 0, 5, 5 } }, - { Instruction::SWAP5, { "SWAP5", 0, 6, 6 } }, - { Instruction::SWAP6, { "SWAP6", 0, 7, 7 } }, - { Instruction::SWAP7, { "SWAP7", 0, 8, 8 } }, - { Instruction::SWAP8, { "SWAP8", 0, 9, 9 } }, - { Instruction::SWAP9, { "SWAP9", 0, 10, 10 } }, - { Instruction::SWAP10, { "SWAP10", 0, 11, 11 } }, - { Instruction::SWAP11, { "SWAP11", 0, 12, 12 } }, - { Instruction::SWAP12, { "SWAP12", 0, 13, 13 } }, - { Instruction::SWAP13, { "SWAP13", 0, 14, 14 } }, - { Instruction::SWAP14, { "SWAP14", 0, 15, 15 } }, - { Instruction::SWAP15, { "SWAP15", 0, 16, 16 } }, - { Instruction::SWAP16, { "SWAP16", 0, 17, 17 } }, - { Instruction::LOG0, { "LOG0", 0, 1, 0 } }, - { Instruction::LOG1, { "LOG1", 0, 2, 0 } }, - { Instruction::LOG2, { "LOG2", 0, 3, 0 } }, - { Instruction::LOG3, { "LOG3", 0, 4, 0 } }, - { Instruction::LOG4, { "LOG4", 0, 5, 0 } }, - { Instruction::CREATE, { "CREATE", 0, 3, 1 } }, - { Instruction::CALL, { "CALL", 0, 7, 1 } }, - { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1 } }, - { Instruction::RETURN, { "RETURN", 0, 2, 0 } }, - { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } +{ // Add, Args, Ret, SideEffects + { Instruction::STOP, { "STOP", 0, 0, 0, true } }, + { Instruction::ADD, { "ADD", 0, 2, 1, false } }, + { Instruction::SUB, { "SUB", 0, 2, 1, false } }, + { Instruction::MUL, { "MUL", 0, 2, 1, false } }, + { Instruction::DIV, { "DIV", 0, 2, 1, false } }, + { Instruction::SDIV, { "SDIV", 0, 2, 1, false } }, + { Instruction::MOD, { "MOD", 0, 2, 1, false } }, + { Instruction::SMOD, { "SMOD", 0, 2, 1, false } }, + { Instruction::EXP, { "EXP", 0, 2, 1, false } }, + { Instruction::NOT, { "NOT", 0, 1, 1, false } }, + { Instruction::LT, { "LT", 0, 2, 1, false } }, + { Instruction::GT, { "GT", 0, 2, 1, false } }, + { Instruction::SLT, { "SLT", 0, 2, 1, false } }, + { Instruction::SGT, { "SGT", 0, 2, 1, false } }, + { Instruction::EQ, { "EQ", 0, 2, 1, false } }, + { Instruction::ISZERO, { "ISZERO", 0, 1, 1, false } }, + { Instruction::AND, { "AND", 0, 2, 1, false } }, + { Instruction::OR, { "OR", 0, 2, 1, false } }, + { Instruction::XOR, { "XOR", 0, 2, 1, false } }, + { Instruction::BYTE, { "BYTE", 0, 2, 1, false } }, + { Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false } }, + { Instruction::MULMOD, { "MULMOD", 0, 3, 1, false } }, + { Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false } }, + { Instruction::SHA3, { "SHA3", 0, 2, 1, false } }, + { Instruction::ADDRESS, { "ADDRESS", 0, 0, 1, false } }, + { Instruction::BALANCE, { "BALANCE", 0, 1, 1, false } }, + { Instruction::ORIGIN, { "ORIGIN", 0, 0, 1, false } }, + { Instruction::CALLER, { "CALLER", 0, 0, 1, false } }, + { Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1, false } }, + { Instruction::CALLDATALOAD,{ "CALLDATALOAD", 0, 1, 1, false } }, + { Instruction::CALLDATASIZE,{ "CALLDATASIZE", 0, 0, 1, false } }, + { Instruction::CALLDATACOPY,{ "CALLDATACOPY", 0, 3, 0, true } }, + { Instruction::CODESIZE, { "CODESIZE", 0, 0, 1, false } }, + { Instruction::CODECOPY, { "CODECOPY", 0, 3, 0, true } }, + { Instruction::GASPRICE, { "GASPRICE", 0, 0, 1, false } }, + { Instruction::EXTCODESIZE, { "EXTCODESIZE", 0, 1, 1, false } }, + { Instruction::EXTCODECOPY, { "EXTCODECOPY", 0, 4, 0, true } }, + { Instruction::PREVHASH, { "PREVHASH", 0, 0, 1, false } }, + { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false } }, + { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false } }, + { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false } }, + { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false } }, + { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false } }, + { Instruction::POP, { "POP", 0, 1, 0, false } }, + { Instruction::MLOAD, { "MLOAD", 0, 1, 1, false } }, + { Instruction::MSTORE, { "MSTORE", 0, 2, 0, true } }, + { Instruction::MSTORE8, { "MSTORE8", 0, 2, 0, true } }, + { Instruction::SLOAD, { "SLOAD", 0, 1, 1, false } }, + { Instruction::SSTORE, { "SSTORE", 0, 2, 0, true } }, + { Instruction::JUMP, { "JUMP", 0, 1, 0, true } }, + { Instruction::JUMPI, { "JUMPI", 0, 2, 0, true } }, + { Instruction::PC, { "PC", 0, 0, 1, false } }, + { Instruction::MSIZE, { "MSIZE", 0, 0, 1, false } }, + { Instruction::GAS, { "GAS", 0, 0, 1, false } }, + { Instruction::JUMPDEST, { "JUMPDEST", 0, 1, 0, true } }, + { Instruction::PUSH1, { "PUSH1", 1, 0, 1, false } }, + { Instruction::PUSH2, { "PUSH2", 2, 0, 1, false } }, + { Instruction::PUSH3, { "PUSH3", 3, 0, 1, false } }, + { Instruction::PUSH4, { "PUSH4", 4, 0, 1, false } }, + { Instruction::PUSH5, { "PUSH5", 5, 0, 1, false } }, + { Instruction::PUSH6, { "PUSH6", 6, 0, 1, false } }, + { Instruction::PUSH7, { "PUSH7", 7, 0, 1, false } }, + { Instruction::PUSH8, { "PUSH8", 8, 0, 1, false } }, + { Instruction::PUSH9, { "PUSH9", 9, 0, 1, false } }, + { Instruction::PUSH10, { "PUSH10", 10, 0, 1, false } }, + { Instruction::PUSH11, { "PUSH11", 11, 0, 1, false } }, + { Instruction::PUSH12, { "PUSH12", 12, 0, 1, false } }, + { Instruction::PUSH13, { "PUSH13", 13, 0, 1, false } }, + { Instruction::PUSH14, { "PUSH14", 14, 0, 1, false } }, + { Instruction::PUSH15, { "PUSH15", 15, 0, 1, false } }, + { Instruction::PUSH16, { "PUSH16", 16, 0, 1, false } }, + { Instruction::PUSH17, { "PUSH17", 17, 0, 1, false } }, + { Instruction::PUSH18, { "PUSH18", 18, 0, 1, false } }, + { Instruction::PUSH19, { "PUSH19", 19, 0, 1, false } }, + { Instruction::PUSH20, { "PUSH20", 20, 0, 1, false } }, + { Instruction::PUSH21, { "PUSH21", 21, 0, 1, false } }, + { Instruction::PUSH22, { "PUSH22", 22, 0, 1, false } }, + { Instruction::PUSH23, { "PUSH23", 23, 0, 1, false } }, + { Instruction::PUSH24, { "PUSH24", 24, 0, 1, false } }, + { Instruction::PUSH25, { "PUSH25", 25, 0, 1, false } }, + { Instruction::PUSH26, { "PUSH26", 26, 0, 1, false } }, + { Instruction::PUSH27, { "PUSH27", 27, 0, 1, false } }, + { Instruction::PUSH28, { "PUSH28", 28, 0, 1, false } }, + { Instruction::PUSH29, { "PUSH29", 29, 0, 1, false } }, + { Instruction::PUSH30, { "PUSH30", 30, 0, 1, false } }, + { Instruction::PUSH31, { "PUSH31", 31, 0, 1, false } }, + { Instruction::PUSH32, { "PUSH32", 32, 0, 1, false } }, + { Instruction::DUP1, { "DUP1", 0, 1, 2, false } }, + { Instruction::DUP2, { "DUP2", 0, 2, 3, false } }, + { Instruction::DUP3, { "DUP3", 0, 3, 4, false } }, + { Instruction::DUP4, { "DUP4", 0, 4, 5, false } }, + { Instruction::DUP5, { "DUP5", 0, 5, 6, false } }, + { Instruction::DUP6, { "DUP6", 0, 6, 7, false } }, + { Instruction::DUP7, { "DUP7", 0, 7, 8, false } }, + { Instruction::DUP8, { "DUP8", 0, 8, 9, false } }, + { Instruction::DUP9, { "DUP9", 0, 9, 10, false } }, + { Instruction::DUP10, { "DUP10", 0, 10, 11, false } }, + { Instruction::DUP11, { "DUP11", 0, 11, 12, false } }, + { Instruction::DUP12, { "DUP12", 0, 12, 13, false } }, + { Instruction::DUP13, { "DUP13", 0, 13, 14, false } }, + { Instruction::DUP14, { "DUP14", 0, 14, 15, false } }, + { Instruction::DUP15, { "DUP15", 0, 15, 16, false } }, + { Instruction::DUP16, { "DUP16", 0, 16, 17, false } }, + { Instruction::SWAP1, { "SWAP1", 0, 2, 2, false } }, + { Instruction::SWAP2, { "SWAP2", 0, 3, 3, false } }, + { Instruction::SWAP3, { "SWAP3", 0, 4, 4, false } }, + { Instruction::SWAP4, { "SWAP4", 0, 5, 5, false } }, + { Instruction::SWAP5, { "SWAP5", 0, 6, 6, false } }, + { Instruction::SWAP6, { "SWAP6", 0, 7, 7, false } }, + { Instruction::SWAP7, { "SWAP7", 0, 8, 8, false } }, + { Instruction::SWAP8, { "SWAP8", 0, 9, 9, false } }, + { Instruction::SWAP9, { "SWAP9", 0, 10, 10, false } }, + { Instruction::SWAP10, { "SWAP10", 0, 11, 11, false } }, + { Instruction::SWAP11, { "SWAP11", 0, 12, 12, false } }, + { Instruction::SWAP12, { "SWAP12", 0, 13, 13, false } }, + { Instruction::SWAP13, { "SWAP13", 0, 14, 14, false } }, + { Instruction::SWAP14, { "SWAP14", 0, 15, 15, false } }, + { Instruction::SWAP15, { "SWAP15", 0, 16, 16, false } }, + { Instruction::SWAP16, { "SWAP16", 0, 17, 17, false } }, + { Instruction::LOG0, { "LOG0", 0, 1, 0, true } }, + { Instruction::LOG1, { "LOG1", 0, 2, 0, true } }, + { Instruction::LOG2, { "LOG2", 0, 3, 0, true } }, + { Instruction::LOG3, { "LOG3", 0, 4, 0, true } }, + { Instruction::LOG4, { "LOG4", 0, 5, 0, true } }, + { Instruction::CREATE, { "CREATE", 0, 3, 1, true } }, + { Instruction::CALL, { "CALL", 0, 7, 1, true } }, + { Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true } }, + { Instruction::RETURN, { "RETURN", 0, 2, 0, true } }, + { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0, true } } }; string dev::eth::disassemble(bytes const& _mem) diff --git a/libevmcore/Instruction.h b/libevmcore/Instruction.h index 0892c50dc..eb85c0610 100644 --- a/libevmcore/Instruction.h +++ b/libevmcore/Instruction.h @@ -204,6 +204,7 @@ struct InstructionInfo int additional; ///< Additional items required in memory for this instructions (only for PUSH). int args; ///< Number of items required on the stack for this instruction (and, for the purposes of ret, the number taken from the stack). int ret; ///< Number of items placed (back) on the stack by this instruction, assuming args items were removed. + bool sideEffects; ///< false if the only effect on the execution environment (apart from gas usage) is a change to a topmost segment of the stack }; /// Information on all the instructions. diff --git a/libjsqrc/main.js b/libjsqrc/main.js index c07a938e4..6abffb195 100644 --- a/libjsqrc/main.js +++ b/libjsqrc/main.js @@ -66,86 +66,86 @@ var ethMethods = function () { var blockCall = function (args) { - return typeof args[0] === "string" ? "blockByHash" : "blockByNumber"; + return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; }; var transactionCall = function (args) { - return typeof args[0] === "string" ? 'transactionByHash' : 'transactionByNumber'; + return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; }; var uncleCall = function (args) { - return typeof args[0] === "string" ? 'uncleByHash' : 'uncleByNumber'; + return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_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: 'balanceAt', call: 'eth_balanceAt' }, + { name: 'stateAt', call: 'eth_stateAt' }, + { name: 'countAt', call: 'eth_countAt'}, + { name: 'codeAt', call: 'eth_codeAt' }, + { name: 'transact', call: 'eth_transact' }, + { name: 'call', call: 'eth_call' }, { name: 'block', call: blockCall }, { name: 'transaction', call: transactionCall }, { name: 'uncle', call: uncleCall }, - { name: 'compilers', call: 'compilers' }, - { name: 'lll', call: 'lll' }, - { name: 'solidity', call: 'solidity' }, - { name: 'contractCreate', call: 'contractCreate' }, - { name: 'contractCall', call: 'contractCall' } + { name: 'compilers', call: 'eth_compilers' }, + { name: 'lll', call: 'eth_lll' }, + { name: 'solidity', call: 'eth_solidity' }, + { name: 'contractCreate', call: 'eth_contractCreate' }, + { name: 'contractCall', call: 'eth_contractCall' } ]; 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'} + { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, + { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, + { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, + { name: 'gasPrice', getter: 'eth_gasPrice' }, + { name: 'account', getter: 'eth_account' }, + { name: 'accounts', getter: 'eth_accounts' }, + { name: 'peerCount', getter: 'eth_peerCount' }, + { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, + { name: 'number', getter: 'eth_number'} ]; }; var dbMethods = function () { return [ - { name: 'put', call: 'put' }, - { name: 'get', call: 'get' }, - { name: 'putString', call: 'putString' }, - { name: 'getString', call: 'getString' } + { name: 'put', call: 'db_put' }, + { name: 'get', call: 'db_get' }, + { name: 'putString', call: 'db_putString' }, + { name: 'getString', call: 'db_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' } + { name: 'post', call: 'shh_post' }, + { name: 'newIdentity', call: 'shh_newIdentity' }, + { name: 'haveIdentity', call: 'shh_haveIdentity' }, + { name: 'newGroup', call: 'shh_newGroup' }, + { name: 'addToGroup', call: 'shh_addToGroup' } ]; }; var ethWatchMethods = function () { var newFilter = function (args) { - return typeof args[0] === 'string' ? 'newFilterString' : 'newFilter'; + return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; }; return [ { name: 'newFilter', call: newFilter }, - { name: 'uninstallFilter', call: 'uninstallFilter' }, - { name: 'getMessages', call: 'getMessages' } + { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, + { name: 'getMessages', call: 'eth_getMessages' } ]; }; var shhWatchMethods = function () { return [ - { name: 'newFilter', call: 'shhNewFilter' }, - { name: 'uninstallFilter', call: 'shhUninstallFilter' }, - { name: 'getMessage', call: 'shhGetMessages' } + { name: 'newFilter', call: 'shh_newFilter' }, + { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, + { name: 'getMessage', call: 'shh_getMessages' } ]; }; @@ -303,11 +303,11 @@ setupMethods(web3.shh, shhMethods()); var ethWatch = { - changed: 'changed' + changed: 'eth_changed' }; setupMethods(ethWatch, ethWatchMethods()); var shhWatch = { - changed: 'shhChanged' + changed: 'shh_changed' }; setupMethods(shhWatch, shhWatchMethods()); diff --git a/libjsqrc/setup.js b/libjsqrc/setup.js index 549222119..5142412a6 100644 --- a/libjsqrc/setup.js +++ b/libjsqrc/setup.js @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file QEthereum.cpp +/** @file setup.js * @authors: * Marek Kotewicz * @date 2014 diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index 42e00958a..5e5253829 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -59,13 +59,13 @@ void QWebThree::poll() { if (m_watches.size() > 0) { - QString batch = toJsonRpcBatch(m_watches, "changed"); - emit processData(batch, "changed"); + QString batch = toJsonRpcBatch(m_watches, "eth_changed"); + emit processData(batch, "eth_changed"); } if (m_shhWatches.size() > 0) { - QString batch = toJsonRpcBatch(m_shhWatches, "shhChanged"); - emit processData(batch, "shhChanged"); + QString batch = toJsonRpcBatch(m_shhWatches, "shh_changed"); + emit processData(batch, "shh_changed"); } } @@ -73,13 +73,13 @@ void QWebThree::clearWatches() { if (m_watches.size() > 0) { - QString batch = toJsonRpcBatch(m_watches, "uninstallFilter"); + QString batch = toJsonRpcBatch(m_watches, "eth_uninstallFilter"); m_watches.clear(); emit processData(batch, "internal"); } if (m_shhWatches.size() > 0) { - QString batch = toJsonRpcBatch(m_shhWatches, "shhUninstallFilter"); + QString batch = toJsonRpcBatch(m_shhWatches, "shh_uninstallFilter"); m_shhWatches.clear(); emit processData(batch, "internal"); } @@ -106,7 +106,12 @@ void QWebThree::postMessage(QString _json) QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object(); QString method = f["call"].toString(); - if (!method.compare("uninstallFilter") && f["args"].isArray() && f["args"].toArray().size()) + if (!method.compare("eth_uninstallFilter") && f["args"].isArray() && f["args"].toArray().size()) + { + int idToRemove = f["args"].toArray()[0].toInt(); + m_watches.erase(std::remove(m_watches.begin(), m_watches.end(), idToRemove), m_watches.end()); + } + else if (!method.compare("eth_uninstallFilter") && f["args"].isArray() && f["args"].toArray().size()) { int idToRemove = f["args"].toArray()[0].toInt(); m_watches.erase(std::remove(m_watches.begin(), m_watches.end(), idToRemove), m_watches.end()); @@ -129,7 +134,7 @@ void QWebThree::onDataProcessed(QString _json, QString _addInfo) if (!_addInfo.compare("internal")) return; - if (!_addInfo.compare("changed")) + if (!_addInfo.compare("eth_changed")) { QJsonArray resultsArray = QJsonDocument::fromJson(_json.toUtf8()).array(); for (int i = 0; i < resultsArray.size(); i++) @@ -146,7 +151,7 @@ void QWebThree::onDataProcessed(QString _json, QString _addInfo) return; } - if (!_addInfo.compare("shhChanged")) + if (!_addInfo.compare("shh_changed")) { QJsonArray resultsArray = QJsonDocument::fromJson(_json.toUtf8()).array(); for (int i = 0; i < resultsArray.size(); i++) @@ -165,11 +170,11 @@ void QWebThree::onDataProcessed(QString _json, QString _addInfo) QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object(); - if ((!_addInfo.compare("newFilter") || !_addInfo.compare("newFilterString")) && f.contains("result")) + if ((!_addInfo.compare("eth_newFilter") || !_addInfo.compare("eth_newFilterString")) && f.contains("result")) m_watches.push_back(f["result"].toInt()); - if (!_addInfo.compare("shhNewFilter") && f.contains("result")) + else if (!_addInfo.compare("shh_newFilter") && f.contains("result")) m_shhWatches.push_back(f["result"].toInt()); - if (!_addInfo.compare("newIdentity") && f.contains("result")) + else if (!_addInfo.compare("shh_newIdentity") && f.contains("result")) emit onNewId(f["result"].toString()); response(formatOutput(f)); diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index ce87f7bb0..ed2b1f45f 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -32,11 +32,11 @@ using namespace std; namespace dev { namespace solidity { -bytes Compiler::compile(ContractDefinition& _contract) +bytes Compiler::compile(ContractDefinition& _contract, bool _optimize) { Compiler compiler; compiler.compileContract(_contract); - return compiler.m_context.getAssembledBytecode(); + return compiler.m_context.getAssembledBytecode(_optimize); } void Compiler::compileContract(ContractDefinition& _contract) @@ -93,10 +93,11 @@ void Compiler::appendFunctionSelector(vector> con eth::AssemblyItem jumpTableStart = m_context.pushNewTag(); m_context << eth::Instruction::ADD << eth::Instruction::JUMP; - // jump table @todo it could be that the optimizer destroys this - m_context << jumpTableStart; + // jump table, tell the optimizer not to remove the JUMPDESTs + m_context << eth::AssemblyItem(eth::NoOptimizeBegin) << jumpTableStart; for (pair> const& f: publicFunctions) m_context.appendJumpTo(f.second.second) << eth::Instruction::JUMPDEST; + m_context << eth::AssemblyItem(eth::NoOptimizeEnd); m_context << returnTag << eth::Instruction::STOP; diff --git a/libsolidity/Compiler.h b/libsolidity/Compiler.h index 4e4d90d45..d931f5359 100644 --- a/libsolidity/Compiler.h +++ b/libsolidity/Compiler.h @@ -33,11 +33,11 @@ public: Compiler(): m_returnTag(m_context.newTag()) {} void compileContract(ContractDefinition& _contract); - bytes getAssembledBytecode() { return m_context.getAssembledBytecode(); } + bytes getAssembledBytecode(bool _optimize = false) { return m_context.getAssembledBytecode(_optimize); } void streamAssembly(std::ostream& _stream) const { m_context.streamAssembly(_stream); } /// Compile the given contract and return the EVM bytecode. - static bytes compile(ContractDefinition& _contract); + static bytes compile(ContractDefinition& _contract, bool _optimize); private: /// Creates a new compiler context / assembly and packs the current code into the data part. diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index 9f8658c3d..562c29321 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -84,7 +84,7 @@ public: eth::Assembly const& getAssembly() const { return m_asm; } void streamAssembly(std::ostream& _stream) const { _stream << m_asm; } - bytes getAssembledBytecode() const { return m_asm.assemble(); } + bytes getAssembledBytecode(bool _optimize = false) { return m_asm.optimise(_optimize).assemble(); } private: eth::Assembly m_asm; diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index bbd693ae5..c991171a5 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -34,7 +34,8 @@ namespace dev namespace solidity { -bytes CompilerStack::compile(std::string const& _sourceCode, shared_ptr _scanner) +bytes CompilerStack::compile(std::string const& _sourceCode, shared_ptr _scanner, + bool _optimize) { if (!_scanner) _scanner = make_shared(); @@ -42,7 +43,7 @@ bytes CompilerStack::compile(std::string const& _sourceCode, shared_ptr ASTPointer contract = Parser().parse(_scanner); NameAndTypeResolver().resolveNamesAndTypes(*contract); - return Compiler::compile(*contract); + return Compiler::compile(*contract, _optimize); } } diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index 9f3f81c04..b003745d2 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -36,7 +36,7 @@ class CompilerStack public: /// Compile the given @a _sourceCode to bytecode. If a scanner is provided, it is used for /// scanning the source code - this is useful for printing exception information. - static bytes compile(std::string const& _sourceCode, std::shared_ptr _scanner = std::shared_ptr()); + static bytes compile(std::string const& _sourceCode, std::shared_ptr _scanner = std::shared_ptr(), bool _optimize = false); }; } diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 6b1ab6d68..f9017026b 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -196,9 +196,11 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json) if (!_json["topics"].empty()) { if (_json["topics"].isArray()) + { for (auto i: _json["topics"]) if (i.isString()) filter.topic(jsToU256(i.asString())); + } else if(_json["topics"].isString()) filter.topic(jsToU256(_json["topics"].asString())); } @@ -315,7 +317,7 @@ std::shared_ptr WebThreeStubServer::face() const return m_web3.whisper(); } -Json::Value WebThreeStubServer::accounts() +Json::Value WebThreeStubServer::eth_accounts() { Json::Value ret(Json::arrayValue); for (auto i: m_accounts) @@ -323,27 +325,27 @@ Json::Value WebThreeStubServer::accounts() return ret; } -std::string WebThreeStubServer::addToGroup(std::string const& _group, std::string const& _who) +std::string WebThreeStubServer::shh_addToGroup(std::string const& _group, std::string const& _who) { (void)_group; (void)_who; return ""; } -std::string WebThreeStubServer::balanceAt(string const& _address) +std::string WebThreeStubServer::eth_balanceAt(string const& _address) { int block = 0; return toJS(client()->balanceAt(jsToAddress(_address), block)); } -Json::Value WebThreeStubServer::blockByHash(std::string const& _hash) +Json::Value WebThreeStubServer::eth_blockByHash(std::string const& _hash) { if (!client()) return ""; return toJson(client()->blockInfo(jsToFixed<32>(_hash))); } -Json::Value WebThreeStubServer::blockByNumber(int const& _number) +Json::Value WebThreeStubServer::eth_blockByNumber(int const& _number) { if (!client()) return ""; @@ -386,7 +388,7 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) return ret; } -std::string WebThreeStubServer::call(Json::Value const& _json) +std::string WebThreeStubServer::eth_call(Json::Value const& _json) { std::string ret; if (!client()) @@ -410,41 +412,41 @@ std::string WebThreeStubServer::call(Json::Value const& _json) return ret; } -bool WebThreeStubServer::changed(int const& _id) +bool WebThreeStubServer::eth_changed(int const& _id) { if (!client()) return false; return client()->checkWatch(_id); } -std::string WebThreeStubServer::codeAt(string const& _address) +std::string WebThreeStubServer::eth_codeAt(string const& _address) { int block = 0; return client() ? jsFromBinary(client()->codeAt(jsToAddress(_address), block)) : ""; } -std::string WebThreeStubServer::coinbase() +std::string WebThreeStubServer::eth_coinbase() { return client() ? toJS(client()->address()) : ""; } -double WebThreeStubServer::countAt(string const& _address) +double WebThreeStubServer::eth_countAt(string const& _address) { int block = 0; return client() ? (double)(uint64_t)client()->countAt(jsToAddress(_address), block) : 0; } -int WebThreeStubServer::defaultBlock() +int WebThreeStubServer::eth_defaultBlock() { return client() ? client()->getDefault() : 0; } -std::string WebThreeStubServer::gasPrice() +std::string WebThreeStubServer::eth_gasPrice() { return toJS(10 * dev::eth::szabo); } -std::string WebThreeStubServer::get(std::string const& _name, std::string const& _key) +std::string WebThreeStubServer::db_get(std::string const& _name, std::string const& _key) { bytes k = sha3(_name).asBytes() + sha3(_key).asBytes(); string ret; @@ -452,14 +454,14 @@ std::string WebThreeStubServer::get(std::string const& _name, std::string const& return toJS(dev::asBytes(ret)); } -Json::Value WebThreeStubServer::getMessages(int const& _id) +Json::Value WebThreeStubServer::eth_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) +std::string WebThreeStubServer::db_getString(std::string const& _name, std::string const& _key) { bytes k = sha3(_name).asBytes() + sha3(_key).asBytes(); string ret; @@ -467,22 +469,22 @@ std::string WebThreeStubServer::getString(std::string const& _name, std::string return ret; } -bool WebThreeStubServer::haveIdentity(std::string const& _id) +bool WebThreeStubServer::shh_haveIdentity(std::string const& _id) { return m_ids.count(jsToPublic(_id)) > 0; } -bool WebThreeStubServer::listening() +bool WebThreeStubServer::eth_listening() { return m_web3.isNetworkStarted(); } -bool WebThreeStubServer::mining() +bool WebThreeStubServer::eth_mining() { return client() ? client()->isMining() : false; } -int WebThreeStubServer::newFilter(Json::Value const& _json) +int WebThreeStubServer::eth_newFilter(Json::Value const& _json) { unsigned ret = -1; if (!client()) @@ -491,7 +493,7 @@ int WebThreeStubServer::newFilter(Json::Value const& _json) return ret; } -int WebThreeStubServer::newFilterString(std::string const& _filter) +int WebThreeStubServer::eth_newFilterString(std::string const& _filter) { unsigned ret = -1; if (!client()) @@ -503,14 +505,14 @@ int WebThreeStubServer::newFilterString(std::string const& _filter) return ret; } -std::string WebThreeStubServer::newGroup(std::string const& _id, std::string const& _who) +std::string WebThreeStubServer::shh_newGroup(std::string const& _id, std::string const& _who) { (void)_id; (void)_who; return ""; } -std::string WebThreeStubServer::newIdentity() +std::string WebThreeStubServer::shh_newIdentity() { cnote << this << m_ids; KeyPair kp = KeyPair::create(); @@ -518,7 +520,7 @@ std::string WebThreeStubServer::newIdentity() return toJS(kp.pub()); } -Json::Value WebThreeStubServer::compilers() +Json::Value WebThreeStubServer::eth_compilers() { Json::Value ret(Json::arrayValue); ret.append("lll"); @@ -538,7 +540,7 @@ static bytes paramsToBytes(Json::Value const& _params) return data; } -std::string WebThreeStubServer::contractCall(std::string const& _address, std::string const& _value, Json::Value const& _params) +std::string WebThreeStubServer::eth_contractCall(std::string const& _address, std::string const& _value, Json::Value const& _params) { auto from = m_accounts.begin()->first; for (auto a: m_accounts) @@ -553,7 +555,7 @@ std::string WebThreeStubServer::contractCall(std::string const& _address, std::s return toJS(client()->call(m_accounts[from].secret(), jsToU256(_value), jsToAddress(_address), paramsToBytes(_params), gas, gasPrice)); } -std::string WebThreeStubServer::contractCreate(std::string const& _bytecode, std::string const& _value) +std::string WebThreeStubServer::eth_contractCreate(std::string const& _bytecode, std::string const& _value) { auto from = m_accounts.begin()->first; for (auto a: m_accounts) @@ -567,28 +569,28 @@ std::string WebThreeStubServer::contractCreate(std::string const& _bytecode, std return toJS(client()->transact(m_accounts[from].secret(), jsToU256(_value), jsToBytes(_bytecode), gas, gasPrice)); } -std::string WebThreeStubServer::lll(std::string const& _code) +std::string WebThreeStubServer::eth_lll(std::string const& _code) { return toJS(dev::eth::compileLLL(_code)); } -std::string WebThreeStubServer::solidity(std::string const& _code) +std::string WebThreeStubServer::eth_solidity(std::string const& _code) { shared_ptr scanner = make_shared(); return toJS(dev::solidity::CompilerStack::compile(_code, scanner)); } -int WebThreeStubServer::number() +int WebThreeStubServer::eth_number() { return client() ? client()->number() + 1 : 0; } -int WebThreeStubServer::peerCount() +int WebThreeStubServer::eth_peerCount() { return m_web3.peerCount(); } -bool WebThreeStubServer::post(Json::Value const& _json) +bool WebThreeStubServer::shh_post(Json::Value const& _json) { cnote << this << m_ids; shh::Message m = toMessage(_json); @@ -605,7 +607,7 @@ bool WebThreeStubServer::post(Json::Value const& _json) return true; } -bool WebThreeStubServer::put(std::string const& _name, std::string const& _key, std::string const& _value) +bool WebThreeStubServer::db_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); @@ -613,7 +615,7 @@ bool WebThreeStubServer::put(std::string const& _name, std::string const& _key, return true; } -bool WebThreeStubServer::putString(std::string const& _name, std::string const& _key, std::string const& _value) +bool WebThreeStubServer::db_putString(std::string const& _name, std::string const& _key, std::string const& _value) { bytes k = sha3(_name).asBytes() + sha3(_key).asBytes(); string v = _value; @@ -621,7 +623,7 @@ bool WebThreeStubServer::putString(std::string const& _name, std::string const& return true; } -bool WebThreeStubServer::setCoinbase(std::string const& _address) +bool WebThreeStubServer::eth_setCoinbase(std::string const& _address) { if (!client()) return false; @@ -629,7 +631,7 @@ bool WebThreeStubServer::setCoinbase(std::string const& _address) return true; } -bool WebThreeStubServer::setDefaultBlock(int const& _block) +bool WebThreeStubServer::eth_setDefaultBlock(int const& _block) { if (!client()) return false; @@ -637,7 +639,7 @@ bool WebThreeStubServer::setDefaultBlock(int const& _block) return true; } -bool WebThreeStubServer::setListening(bool const& _listening) +bool WebThreeStubServer::eth_setListening(bool const& _listening) { if (_listening) m_web3.startNetwork(); @@ -646,7 +648,7 @@ bool WebThreeStubServer::setListening(bool const& _listening) return true; } -bool WebThreeStubServer::setMining(bool const& _mining) +bool WebThreeStubServer::eth_setMining(bool const& _mining) { if (!client()) return false; @@ -658,7 +660,7 @@ bool WebThreeStubServer::setMining(bool const& _mining) return true; } -Json::Value WebThreeStubServer::shhChanged(int const& _id) +Json::Value WebThreeStubServer::shh_changed(int const& _id) { Json::Value ret(Json::arrayValue); auto pub = m_shhWatches[_id]; @@ -682,7 +684,7 @@ Json::Value WebThreeStubServer::shhChanged(int const& _id) return ret; } -int WebThreeStubServer::shhNewFilter(Json::Value const& _json) +int WebThreeStubServer::shh_newFilter(Json::Value const& _json) { auto w = toWatch(_json); auto ret = face()->installWatch(w.first); @@ -690,19 +692,19 @@ int WebThreeStubServer::shhNewFilter(Json::Value const& _json) return ret; } -bool WebThreeStubServer::shhUninstallFilter(int const& _id) +bool WebThreeStubServer::shh_uninstallFilter(int const& _id) { face()->uninstallWatch(_id); return true; } -std::string WebThreeStubServer::stateAt(string const& _address, string const& _storage) +std::string WebThreeStubServer::eth_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 WebThreeStubServer::eth_transact(Json::Value const& _json) { std::string ret; if (!client()) @@ -732,35 +734,35 @@ std::string WebThreeStubServer::transact(Json::Value const& _json) return ret; } -Json::Value WebThreeStubServer::transactionByHash(std::string const& _hash, int const& _i) +Json::Value WebThreeStubServer::eth_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) +Json::Value WebThreeStubServer::eth_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) +Json::Value WebThreeStubServer::eth_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) +Json::Value WebThreeStubServer::eth_uncleByNumber(int const& _number, int const& _i) { if (!client()) return ""; return toJson(client()->uncle(client()->hashFromNumber(_number), _i)); } -bool WebThreeStubServer::uninstallFilter(int const& _id) +bool WebThreeStubServer::eth_uninstallFilter(int const& _id) { if (!client()) return false; diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 1ca77b497..2b26f9acf 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -64,53 +64,55 @@ class WebThreeStubServer: public AbstractWebThreeStubServer public: WebThreeStubServer(jsonrpc::AbstractServerConnector* _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); - 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 Json::Value compilers(); - virtual std::string contractCall(std::string const& _address, std::string const& _value, Json::Value const& _params); - virtual std::string contractCreate(std::string const& _bytecode, std::string const& _value); - 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 std::string lll(std::string const& _code); - 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 solidity(std::string const& _code); - 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); - + virtual Json::Value eth_accounts(); + virtual std::string eth_balanceAt(std::string const& _address); + virtual Json::Value eth_blockByHash(std::string const& _hash); + virtual Json::Value eth_blockByNumber(int const& _number); + virtual std::string eth_call(Json::Value const& _json); + virtual bool eth_changed(int const& _id); + virtual std::string eth_codeAt(std::string const& _address); + virtual std::string eth_coinbase(); + virtual Json::Value eth_compilers(); + virtual std::string eth_contractCall(std::string const& _address, std::string const& _value, Json::Value const& _params); + virtual std::string eth_contractCreate(std::string const& _bytecode, std::string const& _value); + virtual double eth_countAt(std::string const& _address); + virtual int eth_defaultBlock(); + virtual std::string eth_gasPrice(); + virtual Json::Value eth_getMessages(int const& _id); + virtual bool eth_listening(); + virtual bool eth_mining(); + virtual int eth_newFilter(Json::Value const& _json); + virtual int eth_newFilterString(std::string const& _filter); + virtual int eth_number(); + virtual int eth_peerCount(); + virtual bool eth_setCoinbase(std::string const& _address); + virtual bool eth_setDefaultBlock(int const& _block); + virtual bool eth_setListening(bool const& _listening); + virtual std::string eth_lll(std::string const& _s); + virtual bool eth_setMining(bool const& _mining); + virtual std::string eth_solidity(std::string const& _code); + virtual std::string eth_stateAt(std::string const& _address, std::string const& _storage); + virtual std::string eth_transact(Json::Value const& _json); + virtual Json::Value eth_transactionByHash(std::string const& _hash, int const& _i); + virtual Json::Value eth_transactionByNumber(int const& _number, int const& _i); + virtual Json::Value eth_uncleByHash(std::string const& _hash, int const& _i); + virtual Json::Value eth_uncleByNumber(int const& _number, int const& _i); + virtual bool eth_uninstallFilter(int const& _id); + + virtual std::string db_get(std::string const& _name, std::string const& _key); + virtual std::string db_getString(std::string const& _name, std::string const& _key); + virtual bool db_put(std::string const& _name, std::string const& _key, std::string const& _value); + virtual bool db_putString(std::string const& _name, std::string const& _key, std::string const& _value); + + virtual std::string shh_addToGroup(std::string const& _group, std::string const& _who); + virtual Json::Value shh_changed(int const& _id); + virtual bool shh_haveIdentity(std::string const& _id); + virtual int shh_newFilter(Json::Value const& _json); + virtual std::string shh_newGroup(std::string const& _id, std::string const& _who); + virtual std::string shh_newIdentity(); + virtual bool shh_post(Json::Value const& _json); + virtual bool shh_uninstallFilter(int const& _id); + void setAccounts(std::vector const& _accounts); void setIdentities(std::vector const& _ids); std::map const& ids() const { return m_ids; } diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 97b7a219f..e7d8b22ed 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -13,332 +13,332 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer(conn) { - 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("compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::compilersI); - this->bindAndAddMethod(new jsonrpc::Procedure("contractCall", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::contractCallI); - this->bindAndAddMethod(new jsonrpc::Procedure("contractCreate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::contractCreateI); - 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("lll", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::lllI); - 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("solidity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::solidityI); - 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); + this->bindAndAddMethod(new jsonrpc::Procedure("db_get", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getI); + this->bindAndAddMethod(new jsonrpc::Procedure("db_getString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_getStringI); + this->bindAndAddMethod(new jsonrpc::Procedure("db_put", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putI); + this->bindAndAddMethod(new jsonrpc::Procedure("db_putString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::db_putStringI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_accounts", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_accountsI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_balanceAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_balanceAtI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_blockByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_blockByHashI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_blockByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_blockByNumberI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_callI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_changedI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_codeAtI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_coinbaseI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_compilersI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCall", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_contractCallI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCreate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_contractCreateI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_getMessages", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_getMessagesI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_listeningI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_lll", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_lllI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_miningI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_newFilterI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newFilterStringI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_number", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_numberI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_peerCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_peerCountI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_setCoinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_setCoinbaseI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_setDefaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_setDefaultBlockI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_setListening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_setListeningI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_setMining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_setMiningI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_solidity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_solidityI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_stateAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_stateAtI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_transact", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_transactI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_transactionByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionByHashI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_transactionByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionByNumberI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_uncleByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uncleByHashI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_uncleByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uncleByNumberI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uninstallFilterI); + this->bindAndAddMethod(new jsonrpc::Procedure("shh_addToGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_addToGroupI); + this->bindAndAddMethod(new jsonrpc::Procedure("shh_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_changedI); + this->bindAndAddMethod(new jsonrpc::Procedure("shh_haveIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_haveIdentityI); + this->bindAndAddMethod(new jsonrpc::Procedure("shh_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_newFilterI); + this->bindAndAddMethod(new jsonrpc::Procedure("shh_newGroup", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_newGroupI); + this->bindAndAddMethod(new jsonrpc::Procedure("shh_newIdentity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::shh_newIdentityI); + this->bindAndAddMethod(new jsonrpc::Procedure("shh_post", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_postI); + this->bindAndAddMethod(new jsonrpc::Procedure("shh_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_uninstallFilterI); } - inline virtual void accountsI(const Json::Value& request, Json::Value& response) + inline virtual void db_getI(const Json::Value& request, Json::Value& response) { - response = this->accounts(); + response = this->db_get(request[0u].asString(), request[1u].asString()); } - inline virtual void addToGroupI(const Json::Value& request, Json::Value& response) + inline virtual void db_getStringI(const Json::Value& request, Json::Value& response) { - response = this->addToGroup(request[0u].asString(), request[1u].asString()); + response = this->db_getString(request[0u].asString(), request[1u].asString()); } - inline virtual void balanceAtI(const Json::Value& request, Json::Value& response) + inline virtual void db_putI(const Json::Value& request, Json::Value& response) { - response = this->balanceAt(request[0u].asString()); + response = this->db_put(request[0u].asString(), request[1u].asString(), request[2u].asString()); } - inline virtual void blockByHashI(const Json::Value& request, Json::Value& response) + inline virtual void db_putStringI(const Json::Value& request, Json::Value& response) { - response = this->blockByHash(request[0u].asString()); + response = this->db_putString(request[0u].asString(), request[1u].asString(), request[2u].asString()); } - inline virtual void blockByNumberI(const Json::Value& request, Json::Value& response) + inline virtual void eth_accountsI(const Json::Value& request, Json::Value& response) { - response = this->blockByNumber(request[0u].asInt()); + response = this->eth_accounts(); } - inline virtual void callI(const Json::Value& request, Json::Value& response) + inline virtual void eth_balanceAtI(const Json::Value& request, Json::Value& response) { - response = this->call(request[0u]); + response = this->eth_balanceAt(request[0u].asString()); } - inline virtual void changedI(const Json::Value& request, Json::Value& response) + inline virtual void eth_blockByHashI(const Json::Value& request, Json::Value& response) { - response = this->changed(request[0u].asInt()); + response = this->eth_blockByHash(request[0u].asString()); } - inline virtual void codeAtI(const Json::Value& request, Json::Value& response) + inline virtual void eth_blockByNumberI(const Json::Value& request, Json::Value& response) { - response = this->codeAt(request[0u].asString()); + response = this->eth_blockByNumber(request[0u].asInt()); } - inline virtual void coinbaseI(const Json::Value& request, Json::Value& response) + inline virtual void eth_callI(const Json::Value& request, Json::Value& response) { - response = this->coinbase(); + response = this->eth_call(request[0u]); } - inline virtual void compilersI(const Json::Value& request, Json::Value& response) + inline virtual void eth_changedI(const Json::Value& request, Json::Value& response) { - response = this->compilers(); + response = this->eth_changed(request[0u].asInt()); } - inline virtual void contractCallI(const Json::Value& request, Json::Value& response) + inline virtual void eth_codeAtI(const Json::Value& request, Json::Value& response) { - response = this->contractCall(request[0u].asString(), request[1u].asString(), request[2u]); + response = this->eth_codeAt(request[0u].asString()); } - inline virtual void contractCreateI(const Json::Value& request, Json::Value& response) + inline virtual void eth_coinbaseI(const Json::Value& request, Json::Value& response) { - response = this->contractCreate(request[0u].asString(), request[1u].asString()); + response = this->eth_coinbase(); } - inline virtual void countAtI(const Json::Value& request, Json::Value& response) + inline virtual void eth_compilersI(const Json::Value& request, Json::Value& response) { - response = this->countAt(request[0u].asString()); + response = this->eth_compilers(); } - inline virtual void defaultBlockI(const Json::Value& request, Json::Value& response) + inline virtual void eth_contractCallI(const Json::Value& request, Json::Value& response) { - response = this->defaultBlock(); + response = this->eth_contractCall(request[0u].asString(), request[1u].asString(), request[2u]); } - inline virtual void gasPriceI(const Json::Value& request, Json::Value& response) + inline virtual void eth_contractCreateI(const Json::Value& request, Json::Value& response) { - response = this->gasPrice(); + response = this->eth_contractCreate(request[0u].asString(), request[1u].asString()); } - inline virtual void getI(const Json::Value& request, Json::Value& response) + inline virtual void eth_countAtI(const Json::Value& request, Json::Value& response) { - response = this->get(request[0u].asString(), request[1u].asString()); + response = this->eth_countAt(request[0u].asString()); } - inline virtual void getMessagesI(const Json::Value& request, Json::Value& response) + inline virtual void eth_defaultBlockI(const Json::Value& request, Json::Value& response) { - response = this->getMessages(request[0u].asInt()); + response = this->eth_defaultBlock(); } - inline virtual void getStringI(const Json::Value& request, Json::Value& response) + inline virtual void eth_gasPriceI(const Json::Value& request, Json::Value& response) { - response = this->getString(request[0u].asString(), request[1u].asString()); + response = this->eth_gasPrice(); } - inline virtual void haveIdentityI(const Json::Value& request, Json::Value& response) + inline virtual void eth_getMessagesI(const Json::Value& request, Json::Value& response) { - response = this->haveIdentity(request[0u].asString()); + response = this->eth_getMessages(request[0u].asInt()); } - inline virtual void listeningI(const Json::Value& request, Json::Value& response) + inline virtual void eth_listeningI(const Json::Value& request, Json::Value& response) { - response = this->listening(); + response = this->eth_listening(); } - inline virtual void lllI(const Json::Value& request, Json::Value& response) + inline virtual void eth_lllI(const Json::Value& request, Json::Value& response) { - response = this->lll(request[0u].asString()); + response = this->eth_lll(request[0u].asString()); } - inline virtual void miningI(const Json::Value& request, Json::Value& response) + inline virtual void eth_miningI(const Json::Value& request, Json::Value& response) { - response = this->mining(); + response = this->eth_mining(); } - inline virtual void newFilterI(const Json::Value& request, Json::Value& response) + inline virtual void eth_newFilterI(const Json::Value& request, Json::Value& response) { - response = this->newFilter(request[0u]); + response = this->eth_newFilter(request[0u]); } - inline virtual void newFilterStringI(const Json::Value& request, Json::Value& response) + inline virtual void eth_newFilterStringI(const Json::Value& request, Json::Value& response) { - response = this->newFilterString(request[0u].asString()); + response = this->eth_newFilterString(request[0u].asString()); } - inline virtual void newGroupI(const Json::Value& request, Json::Value& response) + inline virtual void eth_numberI(const Json::Value& request, Json::Value& response) { - response = this->newGroup(request[0u].asString(), request[1u].asString()); + response = this->eth_number(); } - inline virtual void newIdentityI(const Json::Value& request, Json::Value& response) + inline virtual void eth_peerCountI(const Json::Value& request, Json::Value& response) { - response = this->newIdentity(); + response = this->eth_peerCount(); } - inline virtual void numberI(const Json::Value& request, Json::Value& response) + inline virtual void eth_setCoinbaseI(const Json::Value& request, Json::Value& response) { - response = this->number(); + response = this->eth_setCoinbase(request[0u].asString()); } - inline virtual void peerCountI(const Json::Value& request, Json::Value& response) + inline virtual void eth_setDefaultBlockI(const Json::Value& request, Json::Value& response) { - response = this->peerCount(); + response = this->eth_setDefaultBlock(request[0u].asInt()); } - inline virtual void postI(const Json::Value& request, Json::Value& response) + inline virtual void eth_setListeningI(const Json::Value& request, Json::Value& response) { - response = this->post(request[0u]); + response = this->eth_setListening(request[0u].asBool()); } - inline virtual void putI(const Json::Value& request, Json::Value& response) + inline virtual void eth_setMiningI(const Json::Value& request, Json::Value& response) { - response = this->put(request[0u].asString(), request[1u].asString(), request[2u].asString()); + response = this->eth_setMining(request[0u].asBool()); } - inline virtual void putStringI(const Json::Value& request, Json::Value& response) + inline virtual void eth_solidityI(const Json::Value& request, Json::Value& response) { - response = this->putString(request[0u].asString(), request[1u].asString(), request[2u].asString()); + response = this->eth_solidity(request[0u].asString()); } - inline virtual void setCoinbaseI(const Json::Value& request, Json::Value& response) + inline virtual void eth_stateAtI(const Json::Value& request, Json::Value& response) { - response = this->setCoinbase(request[0u].asString()); + response = this->eth_stateAt(request[0u].asString(), request[1u].asString()); } - inline virtual void setDefaultBlockI(const Json::Value& request, Json::Value& response) + inline virtual void eth_transactI(const Json::Value& request, Json::Value& response) { - response = this->setDefaultBlock(request[0u].asInt()); + response = this->eth_transact(request[0u]); } - inline virtual void setListeningI(const Json::Value& request, Json::Value& response) + inline virtual void eth_transactionByHashI(const Json::Value& request, Json::Value& response) { - response = this->setListening(request[0u].asBool()); + response = this->eth_transactionByHash(request[0u].asString(), request[1u].asInt()); } - inline virtual void setMiningI(const Json::Value& request, Json::Value& response) + inline virtual void eth_transactionByNumberI(const Json::Value& request, Json::Value& response) { - response = this->setMining(request[0u].asBool()); + response = this->eth_transactionByNumber(request[0u].asInt(), request[1u].asInt()); } - inline virtual void shhChangedI(const Json::Value& request, Json::Value& response) + inline virtual void eth_uncleByHashI(const Json::Value& request, Json::Value& response) { - response = this->shhChanged(request[0u].asInt()); + response = this->eth_uncleByHash(request[0u].asString(), request[1u].asInt()); } - inline virtual void shhNewFilterI(const Json::Value& request, Json::Value& response) + inline virtual void eth_uncleByNumberI(const Json::Value& request, Json::Value& response) { - response = this->shhNewFilter(request[0u]); + response = this->eth_uncleByNumber(request[0u].asInt(), request[1u].asInt()); } - inline virtual void shhUninstallFilterI(const Json::Value& request, Json::Value& response) + inline virtual void eth_uninstallFilterI(const Json::Value& request, Json::Value& response) { - response = this->shhUninstallFilter(request[0u].asInt()); + response = this->eth_uninstallFilter(request[0u].asInt()); } - inline virtual void solidityI(const Json::Value& request, Json::Value& response) + inline virtual void shh_addToGroupI(const Json::Value& request, Json::Value& response) { - response = this->solidity(request[0u].asString()); + response = this->shh_addToGroup(request[0u].asString(), request[1u].asString()); } - inline virtual void stateAtI(const Json::Value& request, Json::Value& response) + inline virtual void shh_changedI(const Json::Value& request, Json::Value& response) { - response = this->stateAt(request[0u].asString(), request[1u].asString()); + response = this->shh_changed(request[0u].asInt()); } - inline virtual void transactI(const Json::Value& request, Json::Value& response) + inline virtual void shh_haveIdentityI(const Json::Value& request, Json::Value& response) { - response = this->transact(request[0u]); + response = this->shh_haveIdentity(request[0u].asString()); } - inline virtual void transactionByHashI(const Json::Value& request, Json::Value& response) + inline virtual void shh_newFilterI(const Json::Value& request, Json::Value& response) { - response = this->transactionByHash(request[0u].asString(), request[1u].asInt()); + response = this->shh_newFilter(request[0u]); } - inline virtual void transactionByNumberI(const Json::Value& request, Json::Value& response) + inline virtual void shh_newGroupI(const Json::Value& request, Json::Value& response) { - response = this->transactionByNumber(request[0u].asInt(), request[1u].asInt()); + response = this->shh_newGroup(request[0u].asString(), request[1u].asString()); } - inline virtual void uncleByHashI(const Json::Value& request, Json::Value& response) + inline virtual void shh_newIdentityI(const Json::Value& request, Json::Value& response) { - response = this->uncleByHash(request[0u].asString(), request[1u].asInt()); + response = this->shh_newIdentity(); } - inline virtual void uncleByNumberI(const Json::Value& request, Json::Value& response) + inline virtual void shh_postI(const Json::Value& request, Json::Value& response) { - response = this->uncleByNumber(request[0u].asInt(), request[1u].asInt()); + response = this->shh_post(request[0u]); } - inline virtual void uninstallFilterI(const Json::Value& request, Json::Value& response) + inline virtual void shh_uninstallFilterI(const Json::Value& request, Json::Value& response) { - response = this->uninstallFilter(request[0u].asInt()); + response = this->shh_uninstallFilter(request[0u].asInt()); } - 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 Json::Value compilers() = 0; - virtual std::string contractCall(const std::string& param1, const std::string& param2, const Json::Value& param3) = 0; - virtual std::string contractCreate(const std::string& param1, const std::string& param2) = 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 std::string lll(const std::string& param1) = 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 solidity(const std::string& 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; + virtual std::string db_get(const std::string& param1, const std::string& param2) = 0; + virtual std::string db_getString(const std::string& param1, const std::string& param2) = 0; + virtual bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) = 0; + virtual bool db_putString(const std::string& param1, const std::string& param2, const std::string& param3) = 0; + virtual Json::Value eth_accounts() = 0; + virtual std::string eth_balanceAt(const std::string& param1) = 0; + virtual Json::Value eth_blockByHash(const std::string& param1) = 0; + virtual Json::Value eth_blockByNumber(const int& param1) = 0; + virtual std::string eth_call(const Json::Value& param1) = 0; + virtual bool eth_changed(const int& param1) = 0; + virtual std::string eth_codeAt(const std::string& param1) = 0; + virtual std::string eth_coinbase() = 0; + virtual Json::Value eth_compilers() = 0; + virtual std::string eth_contractCall(const std::string& param1, const std::string& param2, const Json::Value& param3) = 0; + virtual std::string eth_contractCreate(const std::string& param1, const std::string& param2) = 0; + virtual double eth_countAt(const std::string& param1) = 0; + virtual int eth_defaultBlock() = 0; + virtual std::string eth_gasPrice() = 0; + virtual Json::Value eth_getMessages(const int& param1) = 0; + virtual bool eth_listening() = 0; + virtual std::string eth_lll(const std::string& param1) = 0; + virtual bool eth_mining() = 0; + virtual int eth_newFilter(const Json::Value& param1) = 0; + virtual int eth_newFilterString(const std::string& param1) = 0; + virtual int eth_number() = 0; + virtual int eth_peerCount() = 0; + virtual bool eth_setCoinbase(const std::string& param1) = 0; + virtual bool eth_setDefaultBlock(const int& param1) = 0; + virtual bool eth_setListening(const bool& param1) = 0; + virtual bool eth_setMining(const bool& param1) = 0; + virtual std::string eth_solidity(const std::string& param1) = 0; + virtual std::string eth_stateAt(const std::string& param1, const std::string& param2) = 0; + virtual std::string eth_transact(const Json::Value& param1) = 0; + virtual Json::Value eth_transactionByHash(const std::string& param1, const int& param2) = 0; + virtual Json::Value eth_transactionByNumber(const int& param1, const int& param2) = 0; + virtual Json::Value eth_uncleByHash(const std::string& param1, const int& param2) = 0; + virtual Json::Value eth_uncleByNumber(const int& param1, const int& param2) = 0; + virtual bool eth_uninstallFilter(const int& param1) = 0; + virtual std::string shh_addToGroup(const std::string& param1, const std::string& param2) = 0; + virtual Json::Value shh_changed(const int& param1) = 0; + virtual bool shh_haveIdentity(const std::string& param1) = 0; + virtual int shh_newFilter(const Json::Value& param1) = 0; + virtual std::string shh_newGroup(const std::string& param1, const std::string& param2) = 0; + virtual std::string shh_newIdentity() = 0; + virtual bool shh_post(const Json::Value& param1) = 0; + virtual bool shh_uninstallFilter(const int& param1) = 0; }; #endif //_ABSTRACTWEBTHREESTUBSERVER_H_ diff --git a/libweb3jsonrpc/spec.json b/libweb3jsonrpc/spec.json index a96336f7b..8660b9221 100644 --- a/libweb3jsonrpc/spec.json +++ b/libweb3jsonrpc/spec.json @@ -1,58 +1,58 @@ [ - { "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": "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": "compilers", "params": [], "order": [], "returns": []}, - { "method": "lll", "params": [""], "order": [], "returns": ""}, - { "method": "solidity", "params": [""], "order": [], "returns": ""}, - { "method": "contractCreate", "params": ["", ""], "order": [], "returns": ""}, - { "method": "contractCall", "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": "eth_coinbase", "params": [], "order": [], "returns" : "" }, + { "method": "eth_setCoinbase", "params": [""], "order": [], "returns" : true }, + { "method": "eth_listening", "params": [], "order": [], "returns" : false }, + { "method": "eth_setListening", "params": [false], "order" : [], "returns" : true }, + { "method": "eth_mining", "params": [], "order": [], "returns" : false }, + { "method": "eth_setMining", "params": [false], "order" : [], "returns" : true }, + { "method": "eth_gasPrice", "params": [], "order": [], "returns" : "" }, + { "method": "eth_accounts", "params": [], "order": [], "returns" : [] }, + { "method": "eth_peerCount", "params": [], "order": [], "returns" : 0 }, + { "method": "eth_defaultBlock", "params": [], "order": [], "returns" : 0}, + { "method": "eth_setDefaultBlock", "params": [0], "order": [], "returns" : true}, + { "method": "eth_number", "params": [], "order": [], "returns" : 0}, + + { "method": "eth_balanceAt", "params": [""], "order": [], "returns" : ""}, + { "method": "eth_stateAt", "params": ["", ""], "order": [], "returns": ""}, + { "method": "eth_countAt", "params": [""], "order": [], "returns" : 0.0}, + { "method": "eth_codeAt", "params": [""], "order": [], "returns": ""}, + + { "method": "eth_transact", "params": [{}], "order": [], "returns": ""}, + { "method": "eth_call", "params": [{}], "order": [], "returns": ""}, + + { "method": "eth_blockByHash", "params": [""],"order": [], "returns": {}}, + { "method": "eth_blockByNumber", "params": [0],"order": [], "returns": {}}, + { "method": "eth_transactionByHash", "params": ["", 0], "order": [], "returns": {}}, + { "method": "eth_transactionByNumber", "params": [0, 0], "order": [], "returns": {}}, + { "method": "eth_uncleByHash", "params": ["", 0], "order": [], "returns": {}}, + { "method": "eth_uncleByNumber", "params": [0, 0], "order": [], "returns": {}}, + + { "method": "eth_compilers", "params": [], "order": [], "returns": []}, + { "method": "eth_lll", "params": [""], "order": [], "returns": ""}, + { "method": "eth_solidity", "params": [""], "order": [], "returns": ""}, + { "method": "eth_contractCreate", "params": ["", ""], "order": [], "returns": ""}, + { "method": "eth_contractCall", "params": ["", "", []], "order": [], "returns": ""}, + + { "method": "eth_newFilter", "params": [{}], "order": [], "returns": 0}, + { "method": "eth_newFilterString", "params": [""], "order": [], "returns": 0}, + { "method": "eth_uninstallFilter", "params": [0], "order": [], "returns": true}, + { "method": "eth_changed", "params": [0], "order": [], "returns": false}, + { "method": "eth_getMessages", "params": [0], "order": [], "returns": []}, + + { "method": "db_put", "params": ["", "", ""], "order": [], "returns": true}, + { "method": "db_get", "params": ["", ""], "order": [], "returns": ""}, + { "method": "db_putString", "params": ["", "", ""], "order": [], "returns": true}, + { "method": "db_getString", "params": ["", ""], "order": [], "returns": ""}, + + { "method": "shh_post", "params": [{}], "order": [], "returns": true}, + { "method": "shh_newIdentity", "params": [], "order": [], "returns": ""}, + { "method": "shh_haveIdentity", "params": [""], "order": [], "returns": false}, + { "method": "shh_newGroup", "params": ["", ""], "order": [], "returns": ""}, + { "method": "shh_addToGroup", "params": ["", ""], "order": [], "returns": ""}, - { "method": "shhNewFilter", "params": [{}], "order": [], "returns": 0}, - { "method": "shhUninstallFilter", "params": [0], "order": [], "returns": true}, - { "method": "shhChanged", "params": [0], "order": [], "returns": []} + { "method": "shh_newFilter", "params": [{}], "order": [], "returns": 0}, + { "method": "shh_uninstallFilter", "params": [0], "order": [], "returns": true}, + { "method": "shh_changed", "params": [0], "order": [], "returns": []} ] diff --git a/solc/main.cpp b/solc/main.cpp index 04fee2905..04fdc0ee1 100644 --- a/solc/main.cpp +++ b/solc/main.cpp @@ -42,7 +42,8 @@ void help() { cout << "Usage solc [OPTIONS] " << endl << "Options:" << endl - << " -h,--help Show this help message and exit." << endl + << " -o,--optimize Optimize the bytecode for size." << endl + << " -h,--help Show this help message and exit." << endl << " -V,--version Show the version and exit." << endl; exit(0); } @@ -58,10 +59,13 @@ void version() int main(int argc, char** argv) { string infile; + bool optimize = false; for (int i = 1; i < argc; ++i) { string arg = argv[i]; - if (arg == "-h" || arg == "--help") + if (arg == "-o" || arg == "--optimize") + optimize = true; + else if (arg == "-h" || arg == "--help") help(); else if (arg == "-V" || arg == "--version") version(); @@ -98,7 +102,7 @@ int main(int argc, char** argv) printer.print(cout); compiler.compileContract(*ast); - instructions = compiler.getAssembledBytecode(); + instructions = compiler.getAssembledBytecode(optimize); } catch (ParserError const& exception) { diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index ca46c2ca2..c1a141abb 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -253,7 +253,7 @@ bytes importCode(json_spirit::mObject& _o) code.clear(); for (auto const& j: _o["code"].get_array()) code.push_back(toByte(j)); - } + } return code; } @@ -305,6 +305,47 @@ std::string getTestPath() return testPath; } +void userDefinedTest(string testTypeFlag, std::function doTests) +{ + for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) + { + string arg = boost::unit_test::framework::master_test_suite().argv[i]; + if (arg == testTypeFlag) + { + if (i + 1 >= boost::unit_test::framework::master_test_suite().argc) + { + cnote << "Missing filename\nUsage: testeth " << testTypeFlag << " \n"; + return; + } + string filename = boost::unit_test::framework::master_test_suite().argv[i + 1]; + int currentVerbosity = g_logVerbosity; + g_logVerbosity = 12; + try + { + cnote << "Testing user defined test: " << filename; + json_spirit::mValue v; + string s = asString(contents(filename)); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); + json_spirit::read_string(s, v); + doTests(v, false); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); + g_logVerbosity = currentVerbosity; + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed Test with Exception: " << _e.what()); + g_logVerbosity = currentVerbosity; + } + g_logVerbosity = currentVerbosity; + } + else + continue; + } +} + void executeTests(const string& _name, const string& _testPathAppendix, std::function doTests) { string testPath = getTestPath(); diff --git a/test/TestHelper.h b/test/TestHelper.h index a4eb64d84..ef67d52fb 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -71,6 +71,7 @@ void checkOutput(bytes const& _output, json_spirit::mObject& _o); void checkStorage(std::map _expectedStore, std::map _resultStore, Address _expectedAddr); void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function doTests); std::string getTestPath(); +void userDefinedTest(std::string testTypeFlag, std::function doTests); template void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index 68c30734a..4c748a954 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -74,14 +74,14 @@ BOOST_FIXTURE_TEST_SUITE(environment, Setup) BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock) { cnote << "Testing jsonrpc defaultBlock..."; - int defaultBlock = jsonrpcClient->defaultBlock(); + int defaultBlock = jsonrpcClient->eth_defaultBlock(); BOOST_CHECK_EQUAL(defaultBlock, web3->ethereum()->getDefault()); } BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice) { cnote << "Testing jsonrpc gasPrice..."; - string gasPrice = jsonrpcClient->gasPrice(); + string gasPrice = jsonrpcClient->eth_gasPrice(); BOOST_CHECK_EQUAL(gasPrice, toJS(10 * dev::eth::szabo)); } @@ -90,11 +90,11 @@ BOOST_AUTO_TEST_CASE(jsonrpc_isListening) cnote << "Testing jsonrpc isListening..."; web3->startNetwork(); - bool listeningOn = jsonrpcClient->listening(); + bool listeningOn = jsonrpcClient->eth_listening(); BOOST_CHECK_EQUAL(listeningOn, web3->isNetworkStarted()); web3->stopNetwork(); - bool listeningOff = jsonrpcClient->listening(); + bool listeningOff = jsonrpcClient->eth_listening(); BOOST_CHECK_EQUAL(listeningOff, web3->isNetworkStarted()); } @@ -103,11 +103,11 @@ BOOST_AUTO_TEST_CASE(jsonrpc_isMining) cnote << "Testing jsonrpc isMining..."; web3->ethereum()->startMining(); - bool miningOn = jsonrpcClient->mining(); + bool miningOn = jsonrpcClient->eth_mining(); BOOST_CHECK_EQUAL(miningOn, web3->ethereum()->isMining()); web3->ethereum()->stopMining(); - bool miningOff = jsonrpcClient->mining(); + bool miningOff = jsonrpcClient->eth_mining(); BOOST_CHECK_EQUAL(miningOff, web3->ethereum()->isMining()); } @@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(jsonrpc_accounts) cnote << "Testing jsonrpc accounts..."; std::vector keys = {KeyPair::create(), KeyPair::create()}; jsonrpcServer->setAccounts(keys); - Json::Value k = jsonrpcClient->accounts(); + Json::Value k = jsonrpcClient->eth_accounts(); jsonrpcServer->setAccounts({}); BOOST_CHECK_EQUAL(k.isArray(), true); BOOST_CHECK_EQUAL(k.size(), keys.size()); @@ -133,10 +133,10 @@ BOOST_AUTO_TEST_CASE(jsonrpc_accounts) BOOST_AUTO_TEST_CASE(jsonrpc_number) { cnote << "Testing jsonrpc number2..."; - int number = jsonrpcClient->number(); + int number = jsonrpcClient->eth_number(); BOOST_CHECK_EQUAL(number, web3->ethereum()->number() + 1); dev::eth::mine(*(web3->ethereum()), 1); - int numberAfter = jsonrpcClient->number(); + int numberAfter = jsonrpcClient->eth_number(); BOOST_CHECK_EQUAL(number + 1, numberAfter); BOOST_CHECK_EQUAL(numberAfter, web3->ethereum()->number() + 1); } @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(jsonrpc_number) BOOST_AUTO_TEST_CASE(jsonrpc_peerCount) { cnote << "Testing jsonrpc peerCount..."; - int peerCount = jsonrpcClient->peerCount(); + int peerCount = jsonrpcClient->eth_peerCount(); BOOST_CHECK_EQUAL(web3->peerCount(), peerCount); } @@ -152,10 +152,10 @@ BOOST_AUTO_TEST_CASE(jsonrpc_setListening) { cnote << "Testing jsonrpc setListening..."; - jsonrpcClient->setListening(true); + jsonrpcClient->eth_setListening(true); BOOST_CHECK_EQUAL(web3->isNetworkStarted(), true); - jsonrpcClient->setListening(false); + jsonrpcClient->eth_setListening(false); BOOST_CHECK_EQUAL(web3->isNetworkStarted(), false); } @@ -163,10 +163,10 @@ BOOST_AUTO_TEST_CASE(jsonrpc_setMining) { cnote << "Testing jsonrpc setMining..."; - jsonrpcClient->setMining(true); + jsonrpcClient->eth_setMining(true); BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), true); - jsonrpcClient->setMining(false); + jsonrpcClient->eth_setMining(false); BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), false); } @@ -175,14 +175,14 @@ 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"); + string stateAt = jsonrpcClient->eth_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(); + string coinbase = jsonrpcClient->eth_coinbase(); BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address()); dev::KeyPair key = KeyPair::create(); @@ -190,14 +190,14 @@ BOOST_AUTO_TEST_CASE(jsonrpc_transact) auto receiver = KeyPair::create(); web3->ethereum()->setAddress(address); - coinbase = jsonrpcClient->coinbase(); + coinbase = jsonrpcClient->eth_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)); + string balanceString = jsonrpcClient->eth_balanceAt(toJS(address)); + double countAt = jsonrpcClient->eth_countAt(toJS(address)); BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address)); BOOST_CHECK_EQUAL(countAt, 0); @@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE(jsonrpc_transact) dev::eth::mine(*(web3->ethereum()), 1); balance = web3->ethereum()->balanceAt(address, 0); - balanceString = jsonrpcClient->balanceAt(toJS(address)); + balanceString = jsonrpcClient->eth_balanceAt(toJS(address)); BOOST_CHECK_EQUAL(toJS(balance), balanceString); BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "1500000000000000000"); @@ -223,13 +223,13 @@ BOOST_AUTO_TEST_CASE(jsonrpc_transact) t["gas"] = toJS(gas); t["gasPrice"] = toJS(gasPrice); - jsonrpcClient->transact(t); + jsonrpcClient->eth_transact(t); jsonrpcServer->setAccounts({}); dev::eth::mine(*(web3->ethereum()), 1); - countAt = jsonrpcClient->countAt(toJS(address)); + countAt = jsonrpcClient->eth_countAt(toJS(address)); auto balance2 = web3->ethereum()->balanceAt(receiver.address()); - string balanceString2 = jsonrpcClient->balanceAt(toJS(receiver.address())); + string balanceString2 = jsonrpcClient->eth_balanceAt(toJS(receiver.address())); BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address)); BOOST_CHECK_EQUAL(countAt, 1); diff --git a/test/stPreCompiledContractsFiller.json b/test/stPreCompiledContractsFiller.json new file mode 100644 index 000000000..8975f1aea --- /dev/null +++ b/test/stPreCompiledContractsFiller.json @@ -0,0 +1,717 @@ +{ + "CallEcrecover0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallEcrecover0_gas500": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 500 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallEcrecover0_Gas499": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 499 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallEcrecover0_0input": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code": "{ (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallEcrecover1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallEcrecover2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) (CALL 1000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallEcrecover3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallSha256_0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "0x600160005260206000602060006000600260fff1600051600055", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallSha256_1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallSha256_2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 5 0xf34578907f) (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallSha256_3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xf34578907f) (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallSha256_4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallSha256_4_gas99": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallSha256_5": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 500 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRipemd160_0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "0x600160005260206000602060006000600360fff1600051600055", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRipemd160_1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (CALL 500 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRipemd160_2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 5 0xf34578907f) (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRipemd160_3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xf34578907f) (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRipemd160_4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 100 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRipemd160_4_gas99": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 99 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRipemd160_5": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (CALL 500 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + +} + diff --git a/test/stSystemOperationsTestFiller.json b/test/stSystemOperationsTestFiller.json new file mode 100644 index 000000000..e62753089 --- /dev/null +++ b/test/stSystemOperationsTestFiller.json @@ -0,0 +1,1334 @@ +{ + "createNameRegistrator": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 28) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createNameRegistratorValueTooHigh": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 1000 4 28) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createNameRegistratorOutOfMemoryBonds0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 0xfffffffffff 28) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createNameRegistratorOutOfMemoryBonds1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0x601080600c6000396000f20060003554156009570060203560003555) [[ 0 ]] (CREATE 23 4 0xfffffffffff) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallToNameRegistrator0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 64 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallToReturn1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 0 2) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x6001600155603760005360026000f2", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "PostToReturn1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) (POST 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 ) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x603760005360026000f2", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "callstatelessToReturn1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALLSTATELESS 500 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 0 2 ) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x6001600155603760005360026000f2", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "callcodeToReturn1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALLCODE 500 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 0 2 ) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x6001600155603760005360026000f2", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + + "CallToNameRegistratorOutOfGas": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 100 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 64 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallToNameRegistratorTooMuchMemory0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 500 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 987654321 64 64 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallToNameRegistratorTooMuchMemory1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 500 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 9865432 64 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallToNameRegistratorTooMuchMemory2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 500 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 987654 1) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + + "CallToNameRegistratorNotMuchMemory0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 500 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 987654 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallToNameRegistratorNotMuchMemory1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xeeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALL 500 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 987654 0 64 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRecursiveBomb0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ (CALL 100000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) } ", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRecursiveBomb1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365223", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRecursiveBomb2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallRecursiveBomb3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "suicideCaller": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[0]] (CALLER) (SUICIDE (CALLER))}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "suicideOrigin": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[0]] (ORIGIN) (SUICIDE (ORIGIN))}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "suicideAddress": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[0]] (ADDRESS) (SUICIDE (ADDRESS))}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "suicideNotExistingAccount": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (SUICIDE 0xaa1722f3947def4cf144679da39c4c32bdc35681 )}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "suicideSendEtherToMe": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (SUICIDE (ADDRESS) )}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "return0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "23", + "code" : "{ (MSTORE8 0 55) (RETURN 0 1)}", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "return1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "23", + "code" : "{ (MSTORE8 0 55) (RETURN 0 2)}", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "return2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "23", + "code" : "{ (MSTORE8 0 55) (RETURN 0 33)}", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "callcodeToNameRegistrator0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (MSTORE 32 0xaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa ) [[ 0 ]] (CALLCODE 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 23 0 64 64 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "0x60003554156009570060203560003555", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "TestNameRegistrator": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "0x60003554156009570060203560003555", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffafffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa" + } + }, + + "ABAcalls0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ (PC) ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 24 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : " { [[ (PC) ]] (ADD 1 (CALL 500 0x095e7baea6a6c7c4c2dfeb977efac326af552d87 23 0 0 0 0)) } ", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "ABAcalls1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ (PC) ]] (CALL (- (GAS) 1000) 0x945304eb96065b2a98b57a48a06ae28d285a71b5 24 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : " { [[ (PC) ]] (ADD 1 (CALL (- (GAS) 1000) 0x095e7baea6a6c7c4c2dfeb977efac326af552d87 23 0 0 0 0)) } ", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "1000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "ABAcalls2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x945304eb96065b2a98b57a48a06ae28d285a71b5 1 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "0", + "code" : " { [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x095e7baea6a6c7c4c2dfeb977efac326af552d87 0 0 0 0 0) } ", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "ABAcalls3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1025000", + "nonce" : 0, + "code" : "{ [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x945304eb96065b2a98b57a48a06ae28d285a71b5 1 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "0", + "code" : " { [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x095e7baea6a6c7c4c2dfeb977efac326af552d87 0 0 0 0 0) } ", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "ABAcallsSuicide0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ (PC) ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 24 0 0 0 0) (SUICIDE 0x945304eb96065b2a98b57a48a06ae28d285a71b5) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "{ [[ (PC) ]] (ADD 1 (CALL 500 0x095e7baea6a6c7c4c2dfeb977efac326af552d87 23 0 0 0 0)) } ", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "ABAcallsSuicide1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ (PC) ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 24 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "{ [[ (PC) ]] (ADD 1 (CALL 500 0x095e7baea6a6c7c4c2dfeb977efac326af552d87 23 0 0 0 0)) (SUICIDE 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6) } ", + "nonce" : "0", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + } +} diff --git a/test/state.cpp b/test/state.cpp index 935869058..91d9f3e51 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -43,7 +43,6 @@ namespace dev { namespace test { void doStateTests(json_spirit::mValue& v, bool _fillin) { - cout << "start state test\n"; for (auto& i: v.get_obj()) { cnote << i.first; @@ -118,4 +117,14 @@ BOOST_AUTO_TEST_CASE(stSystemOperationsTest) dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests); } +BOOST_AUTO_TEST_CASE(stPreCompiledContracts) +{ + dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests); +} + +BOOST_AUTO_TEST_CASE(userDefinedFileState) +{ + dev::test::userDefinedTest("--statetest", dev::test::doStateTests); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/vm.cpp b/test/vm.cpp index 93cf121de..b36d3dc2b 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -20,6 +20,7 @@ * vm test functions. */ +#include #include "vm.h" using namespace std; @@ -423,32 +424,42 @@ BOOST_AUTO_TEST_CASE(vmPushDupSwapTest) dev::test::executeTests("vmPushDupSwapTest", "/VMTests", dev::test::doVMTests); } -BOOST_AUTO_TEST_CASE(userDefinedFile) +BOOST_AUTO_TEST_CASE(vmRandom) { - if (boost::unit_test::framework::master_test_suite().argc == 2) + string testPath = getTestPath(); + testPath += "/VMTests/RandomTests"; + + vector testFiles; + boost::filesystem::directory_iterator iterator(testPath); + for(; iterator != boost::filesystem::directory_iterator(); ++iterator) + if (boost::filesystem::is_regular_file(iterator->path()) && iterator->path().extension() == ".json") + testFiles.push_back(iterator->path()); + + for (auto& path: testFiles) { - string filename = boost::unit_test::framework::master_test_suite().argv[1]; - int currentVerbosity = g_logVerbosity; - g_logVerbosity = 12; try { - cnote << "Testing VM..." << "user defined test"; + cnote << "Testing ..." << path.filename(); json_spirit::mValue v; - string s = asString(contents(filename)); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); + string s = asString(dev::contents(path.string())); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); json_spirit::read_string(s, v); - dev::test::doVMTests(v, false); + doVMTests(v, false); } catch (Exception const& _e) { - BOOST_ERROR("Failed VM Test with Exception: " << diagnostic_information(_e)); + BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); } catch (std::exception const& _e) { - BOOST_ERROR("Failed VM Test with Exception: " << _e.what()); + BOOST_ERROR("Failed test with Exception: " << _e.what()); } - g_logVerbosity = currentVerbosity; } } +BOOST_AUTO_TEST_CASE(userDefinedFileVM) +{ + dev::test::userDefinedTest("--vmtest", dev::test::doVMTests); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/vmArithmeticTestFiller.json b/test/vmArithmeticTestFiller.json index 29d523a36..b93694575 100644 --- a/test/vmArithmeticTestFiller.json +++ b/test/vmArithmeticTestFiller.json @@ -1725,7 +1725,7 @@ "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "0x62122ff4600016600057", + "code" : "0x62122ff460000b600055", "storage": {} } }, @@ -1753,7 +1753,7 @@ "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "0x62122f6a600016600057", + "code" : "0x62122f6a60000b600055", "storage": {} } }, @@ -1781,7 +1781,7 @@ "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "0x6212faf4600116600057", + "code" : "0x6212faf460010b600055", "storage": {} } }, @@ -1809,7 +1809,7 @@ "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "0x62126af4600116600057", + "code" : "0x62126af460010b600055", "storage": {} } }, @@ -1837,7 +1837,7 @@ "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "0x62126af4605016600057", + "code" : "0x62126af460500b600055", "storage": {} } }, @@ -2005,7 +2005,7 @@ "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "0x66f000000000000161ffff16600057", + "code" : "0x66f000000000000161ffff0b600055", "storage": {} } }, @@ -2033,7 +2033,7 @@ "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "1000000000000000000", "nonce" : 0, - "code" : "0x60ff68f0000000000000000116600057", + "code" : "0x60ff68f000000000000000010b600055", "storage": {} } }, diff --git a/test/webthreestubclient.h b/test/webthreestubclient.h index c494c1bae..cf749aac7 100644 --- a/test/webthreestubclient.h +++ b/test/webthreestubclient.h @@ -19,25 +19,27 @@ class WebThreeStubClient delete this->client; } - Json::Value accounts() throw (jsonrpc::JsonRpcException) + std::string db_get(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("accounts",p); - if (result.isArray()) - return result; + p.append(param1); +p.append(param2); + + Json::Value result = this->client->CallMethod("db_get",p); + if (result.isString()) + return result.asString(); 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) + std::string db_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("addToGroup",p); + Json::Value result = this->client->CallMethod("db_getString",p); if (result.isString()) return result.asString(); else @@ -45,12 +47,54 @@ p.append(param2); } - std::string balanceAt(const std::string& param1) throw (jsonrpc::JsonRpcException) + bool db_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("db_put",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + + bool db_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("db_putString",p); + if (result.isBool()) + return result.asBool(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + + Json::Value eth_accounts() throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p = Json::nullValue; + Json::Value result = this->client->CallMethod("eth_accounts",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + + std::string eth_balanceAt(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("balanceAt",p); + Json::Value result = this->client->CallMethod("eth_balanceAt",p); if (result.isString()) return result.asString(); else @@ -58,12 +102,12 @@ p.append(param2); } - Json::Value blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) + Json::Value eth_blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("blockByHash",p); + Json::Value result = this->client->CallMethod("eth_blockByHash",p); if (result.isObject()) return result; else @@ -71,12 +115,12 @@ p.append(param2); } - Json::Value blockByNumber(const int& param1) throw (jsonrpc::JsonRpcException) + Json::Value eth_blockByNumber(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("blockByNumber",p); + Json::Value result = this->client->CallMethod("eth_blockByNumber",p); if (result.isObject()) return result; else @@ -84,12 +128,12 @@ p.append(param2); } - std::string call(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + std::string eth_call(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("call",p); + Json::Value result = this->client->CallMethod("eth_call",p); if (result.isString()) return result.asString(); else @@ -97,12 +141,12 @@ p.append(param2); } - bool changed(const int& param1) throw (jsonrpc::JsonRpcException) + bool eth_changed(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("changed",p); + Json::Value result = this->client->CallMethod("eth_changed",p); if (result.isBool()) return result.asBool(); else @@ -110,12 +154,12 @@ p.append(param2); } - std::string codeAt(const std::string& param1) throw (jsonrpc::JsonRpcException) + std::string eth_codeAt(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("codeAt",p); + Json::Value result = this->client->CallMethod("eth_codeAt",p); if (result.isString()) return result.asString(); else @@ -123,11 +167,11 @@ p.append(param2); } - std::string coinbase() throw (jsonrpc::JsonRpcException) + std::string eth_coinbase() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("coinbase",p); + Json::Value result = this->client->CallMethod("eth_coinbase",p); if (result.isString()) return result.asString(); else @@ -135,11 +179,11 @@ p.append(param2); } - Json::Value compilers() throw (jsonrpc::JsonRpcException) + Json::Value eth_compilers() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("compilers",p); + Json::Value result = this->client->CallMethod("eth_compilers",p); if (result.isArray()) return result; else @@ -147,14 +191,14 @@ p.append(param2); } - std::string contractCall(const std::string& param1, const std::string& param2, const Json::Value& param3) throw (jsonrpc::JsonRpcException) + std::string eth_contractCall(const std::string& param1, const std::string& param2, const Json::Value& param3) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); p.append(param2); p.append(param3); - Json::Value result = this->client->CallMethod("contractCall",p); + Json::Value result = this->client->CallMethod("eth_contractCall",p); if (result.isString()) return result.asString(); else @@ -162,13 +206,13 @@ p.append(param3); } - std::string contractCreate(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + std::string eth_contractCreate(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("contractCreate",p); + Json::Value result = this->client->CallMethod("eth_contractCreate",p); if (result.isString()) return result.asString(); else @@ -176,12 +220,12 @@ p.append(param2); } - double countAt(const std::string& param1) throw (jsonrpc::JsonRpcException) + double eth_countAt(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("countAt",p); + Json::Value result = this->client->CallMethod("eth_countAt",p); if (result.isDouble()) return result.asDouble(); else @@ -189,11 +233,11 @@ p.append(param2); } - int defaultBlock() throw (jsonrpc::JsonRpcException) + int eth_defaultBlock() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("defaultBlock",p); + Json::Value result = this->client->CallMethod("eth_defaultBlock",p); if (result.isInt()) return result.asInt(); else @@ -201,25 +245,11 @@ p.append(param2); } - std::string gasPrice() throw (jsonrpc::JsonRpcException) + std::string eth_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); + Json::Value result = this->client->CallMethod("eth_gasPrice",p); if (result.isString()) return result.asString(); else @@ -227,12 +257,12 @@ p.append(param2); } - Json::Value getMessages(const int& param1) throw (jsonrpc::JsonRpcException) + Json::Value eth_getMessages(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("getMessages",p); + Json::Value result = this->client->CallMethod("eth_getMessages",p); if (result.isArray()) return result; else @@ -240,38 +270,11 @@ p.append(param2); } - 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) + bool eth_listening() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("listening",p); + Json::Value result = this->client->CallMethod("eth_listening",p); if (result.isBool()) return result.asBool(); else @@ -279,12 +282,12 @@ p.append(param2); } - std::string lll(const std::string& param1) throw (jsonrpc::JsonRpcException) + std::string eth_lll(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("lll",p); + Json::Value result = this->client->CallMethod("eth_lll",p); if (result.isString()) return result.asString(); else @@ -292,11 +295,11 @@ p.append(param2); } - bool mining() throw (jsonrpc::JsonRpcException) + bool eth_mining() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("mining",p); + Json::Value result = this->client->CallMethod("eth_mining",p); if (result.isBool()) return result.asBool(); else @@ -304,12 +307,12 @@ p.append(param2); } - int newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + int eth_newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("newFilter",p); + Json::Value result = this->client->CallMethod("eth_newFilter",p); if (result.isInt()) return result.asInt(); else @@ -317,12 +320,12 @@ p.append(param2); } - int newFilterString(const std::string& param1) throw (jsonrpc::JsonRpcException) + int eth_newFilterString(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("newFilterString",p); + Json::Value result = this->client->CallMethod("eth_newFilterString",p); if (result.isInt()) return result.asInt(); else @@ -330,62 +333,62 @@ p.append(param2); } - std::string newGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + int eth_number() 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(); + p = Json::nullValue; + Json::Value result = this->client->CallMethod("eth_number",p); + if (result.isInt()) + return result.asInt(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - std::string newIdentity() throw (jsonrpc::JsonRpcException) + int eth_peerCount() throw (jsonrpc::JsonRpcException) { Json::Value p; p = Json::nullValue; - Json::Value result = this->client->CallMethod("newIdentity",p); - if (result.isString()) - return result.asString(); + Json::Value result = this->client->CallMethod("eth_peerCount",p); + if (result.isInt()) + return result.asInt(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - int number() throw (jsonrpc::JsonRpcException) + bool eth_setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("number",p); - if (result.isInt()) - return result.asInt(); + p.append(param1); + + Json::Value result = this->client->CallMethod("eth_setCoinbase",p); + if (result.isBool()) + return result.asBool(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - int peerCount() throw (jsonrpc::JsonRpcException) + bool eth_setDefaultBlock(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; - p = Json::nullValue; - Json::Value result = this->client->CallMethod("peerCount",p); - if (result.isInt()) - return result.asInt(); + p.append(param1); + + Json::Value result = this->client->CallMethod("eth_setDefaultBlock",p); + if (result.isBool()) + return result.asBool(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - bool post(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + bool eth_setListening(const bool& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("post",p); + Json::Value result = this->client->CallMethod("eth_setListening",p); if (result.isBool()) return result.asBool(); else @@ -393,14 +396,12 @@ p.append(param2); } - bool put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) + bool eth_setMining(const bool& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); -p.append(param2); -p.append(param3); - Json::Value result = this->client->CallMethod("put",p); + Json::Value result = this->client->CallMethod("eth_setMining",p); if (result.isBool()) return result.asBool(); else @@ -408,105 +409,108 @@ p.append(param3); } - bool putString(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) + std::string eth_solidity(const std::string& param1) 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(); + Json::Value result = this->client->CallMethod("eth_solidity",p); + if (result.isString()) + return result.asString(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - bool setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException) + std::string eth_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("setCoinbase",p); - if (result.isBool()) - return result.asBool(); + Json::Value result = this->client->CallMethod("eth_stateAt",p); + if (result.isString()) + return result.asString(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - bool setDefaultBlock(const int& param1) throw (jsonrpc::JsonRpcException) + std::string eth_transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("setDefaultBlock",p); - if (result.isBool()) - return result.asBool(); + Json::Value result = this->client->CallMethod("eth_transact",p); + if (result.isString()) + return result.asString(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - bool setListening(const bool& param1) throw (jsonrpc::JsonRpcException) + Json::Value eth_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("setListening",p); - if (result.isBool()) - return result.asBool(); + Json::Value result = this->client->CallMethod("eth_transactionByHash",p); + if (result.isObject()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - bool setMining(const bool& param1) throw (jsonrpc::JsonRpcException) + Json::Value eth_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("setMining",p); - if (result.isBool()) - return result.asBool(); + Json::Value result = this->client->CallMethod("eth_transactionByNumber",p); + if (result.isObject()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - Json::Value shhChanged(const int& param1) throw (jsonrpc::JsonRpcException) + Json::Value eth_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("shhChanged",p); - if (result.isArray()) + Json::Value result = this->client->CallMethod("eth_uncleByHash",p); + if (result.isObject()) 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 eth_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("shhNewFilter",p); - if (result.isInt()) - return result.asInt(); + Json::Value result = this->client->CallMethod("eth_uncleByNumber",p); + if (result.isObject()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - bool shhUninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) + bool eth_uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("shhUninstallFilter",p); + Json::Value result = this->client->CallMethod("eth_uninstallFilter",p); if (result.isBool()) return result.asBool(); else @@ -514,12 +518,13 @@ p.append(param3); } - std::string solidity(const std::string& param1) throw (jsonrpc::JsonRpcException) + std::string shh_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("solidity",p); + Json::Value result = this->client->CallMethod("shh_addToGroup",p); if (result.isString()) return result.asString(); else @@ -527,95 +532,90 @@ p.append(param3); } - std::string stateAt(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) + Json::Value shh_changed(const int& param1) 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(); + Json::Value result = this->client->CallMethod("shh_changed",p); + if (result.isArray()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - std::string transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + bool shh_haveIdentity(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("transact",p); - if (result.isString()) - return result.asString(); + Json::Value result = this->client->CallMethod("shh_haveIdentity",p); + if (result.isBool()) + return result.asBool(); 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) + int shh_newFilter(const Json::Value& param1) 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; + Json::Value result = this->client->CallMethod("shh_newFilter",p); + if (result.isInt()) + return result.asInt(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - Json::Value transactionByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) + std::string shh_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("transactionByNumber",p); - if (result.isObject()) - return result; + Json::Value result = this->client->CallMethod("shh_newGroup",p); + if (result.isString()) + return result.asString(); 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) + std::string shh_newIdentity() 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; + p = Json::nullValue; + Json::Value result = this->client->CallMethod("shh_newIdentity",p); + if (result.isString()) + return result.asString(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - Json::Value uncleByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) + bool shh_post(const Json::Value& param1) 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; + Json::Value result = this->client->CallMethod("shh_post",p); + if (result.isBool()) + return result.asBool(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - bool uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) + bool shh_uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; p.append(param1); - Json::Value result = this->client->CallMethod("uninstallFilter",p); + Json::Value result = this->client->CallMethod("shh_uninstallFilter",p); if (result.isBool()) return result.asBool(); else From a2349ba485ce97205846f916819facf7ae5c908f Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 11 Nov 2014 09:06:35 +0100 Subject: [PATCH 07/44] contract create and contract call working --- libweb3jsonrpc/WebThreeStubServer.cpp | 18 ++++++++---------- libweb3jsonrpc/WebThreeStubServer.h | 4 ++-- libweb3jsonrpc/abstractwebthreestubserver.h | 12 ++++++------ libweb3jsonrpc/spec.json | 4 ++-- test/webthreestubclient.h | 5 ++--- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index f9017026b..87cd3c22b 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -528,19 +528,17 @@ Json::Value WebThreeStubServer::eth_compilers() return ret; } -static bytes paramsToBytes(Json::Value const& _params) +static bytes toMethodCall(int const& _index, Json::Value const& _params) { - bytes data; + bytes data(1, _index); if (_params.isArray()) for (auto i: _params) -// data += asBytes(i.asString()); -// data += toBigEndian(jsToU256(i.asString())); - data += asBytes(jsPadded(i.asString(), 33)); + data += asBytes(jsPadded(i.asString(), 32)); cwarn << data; return data; } -std::string WebThreeStubServer::eth_contractCall(std::string const& _address, std::string const& _value, Json::Value const& _params) +std::string WebThreeStubServer::eth_contractCall(std::string const& _address, int const& _index, Json::Value const& _params) { auto from = m_accounts.begin()->first; for (auto a: m_accounts) @@ -551,11 +549,11 @@ std::string WebThreeStubServer::eth_contractCall(std::string const& _address, st auto gasPrice = 10 * dev::eth::szabo; auto gas = min(client()->gasLimitRemaining(), client()->balanceAt(from) / gasPrice); - auto bytes = paramsToBytes(_params); - return toJS(client()->call(m_accounts[from].secret(), jsToU256(_value), jsToAddress(_address), paramsToBytes(_params), gas, gasPrice)); + auto bytes = toMethodCall(_index, _params); + return toJS(client()->call(m_accounts[from].secret(), 0, jsToAddress(_address), toMethodCall(_index, _params), gas, gasPrice)); } -std::string WebThreeStubServer::eth_contractCreate(std::string const& _bytecode, std::string const& _value) +std::string WebThreeStubServer::eth_contractCreate(std::string const& _bytecode) { auto from = m_accounts.begin()->first; for (auto a: m_accounts) @@ -566,7 +564,7 @@ std::string WebThreeStubServer::eth_contractCreate(std::string const& _bytecode, auto gasPrice = 10 * dev::eth::szabo; auto gas = min(client()->gasLimitRemaining(), client()->balanceAt(from) / gasPrice); - return toJS(client()->transact(m_accounts[from].secret(), jsToU256(_value), jsToBytes(_bytecode), gas, gasPrice)); + return toJS(client()->transact(m_accounts[from].secret(), 0, jsToBytes(_bytecode), gas, gasPrice)); } std::string WebThreeStubServer::eth_lll(std::string const& _code) diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 2b26f9acf..3318214f1 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -73,8 +73,8 @@ public: virtual std::string eth_codeAt(std::string const& _address); virtual std::string eth_coinbase(); virtual Json::Value eth_compilers(); - virtual std::string eth_contractCall(std::string const& _address, std::string const& _value, Json::Value const& _params); - virtual std::string eth_contractCreate(std::string const& _bytecode, std::string const& _value); + virtual std::string eth_contractCall(std::string const& _address, int const& _index, Json::Value const& _params); + virtual std::string eth_contractCreate(std::string const& _bytecode); virtual double eth_countAt(std::string const& _address); virtual int eth_defaultBlock(); virtual std::string eth_gasPrice(); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index e7d8b22ed..43a81c1cc 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -26,8 +26,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_codeAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_coinbaseI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_compilersI); - this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCall", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING,"param3",jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_contractCallI); - this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCreate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_contractCreateI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCall", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER,"param3",jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_contractCallI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCreate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_contractCreateI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI); @@ -129,12 +129,12 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_contractCall(request[0u].asString(), request[1u].asString(), request[2u]); + response = this->eth_contractCall(request[0u].asString(), request[1u].asInt(), request[2u]); } inline virtual void eth_contractCreateI(const Json::Value& request, Json::Value& response) { - response = this->eth_contractCreate(request[0u].asString(), request[1u].asString()); + response = this->eth_contractCreate(request[0u].asString()); } inline virtual void eth_countAtI(const Json::Value& request, Json::Value& response) @@ -306,8 +306,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerclient->CallMethod("eth_contractCreate",p); if (result.isString()) From 2f50d919ce9d94c011918a5f649c15bc2d449945 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 11 Nov 2014 09:14:50 +0100 Subject: [PATCH 08/44] revert unnecessary changes in main.js --- libjsqrc/main.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libjsqrc/main.js b/libjsqrc/main.js index 6abffb195..da95e7e53 100644 --- a/libjsqrc/main.js +++ b/libjsqrc/main.js @@ -418,8 +418,10 @@ }; Filter.prototype.trigger = function(messages) { - for(var i = 0; i < this.callbacks.length; i++) { - this.callbacks[i].call(this, messages); + if (!(messages instanceof Array) || messages.length) { + for(var i = 0; i < this.callbacks.length; i++) { + this.callbacks[i].call(this, messages); + } } }; @@ -448,7 +450,7 @@ if(data._id) { var cb = web3._callbacks[data._id]; if (cb) { - cb.call(this, data.error, data.data) + cb.call(this, data.error, data.data); delete web3._callbacks[data._id]; } } From 489fb2b430a24eb6b7e2617db3bb7b8646481ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 11 Nov 2014 18:00:49 +0100 Subject: [PATCH 09/44] static const variable name fix --- libdevcrypto/EC.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libdevcrypto/EC.cpp b/libdevcrypto/EC.cpp index a54c0132d..a3438ede1 100644 --- a/libdevcrypto/EC.cpp +++ b/libdevcrypto/EC.cpp @@ -134,15 +134,15 @@ bool crypto::verify(Signature const& _signature, bytesConstRef _message) bool crypto::verify(Public const& _p, Signature const& _sig, bytesConstRef _message, bool _hashed) { - static const size_t c_derMaxEncodingLength = 72; if (_hashed) { assert(_message.size() == 32); byte encpub[65] = {0x04}; memcpy(&encpub[1], _p.data(), 64); - byte dersig[derMaxEncodingLength]; - size_t cssz = DSAConvertSignatureFormat(dersig, derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363); - assert(cssz <= derMaxEncodingLength); + static const size_t c_derMaxEncodingLength = 72; + byte dersig[c_derMaxEncodingLength]; + size_t cssz = DSAConvertSignatureFormat(dersig, c_derMaxEncodingLength, DSA_DER, _sig.data(), 64, DSA_P1363); + assert(cssz <= c_derMaxEncodingLength); return (1 == secp256k1_ecdsa_verify(_message.data(), _message.size(), dersig, cssz, encpub, 65)); } From ed7cbeaacdac4def4478cc9bfb768ebfc01bb200 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 12 Nov 2014 20:47:05 +0100 Subject: [PATCH 10/44] contract calls working from js --- libweb3jsonrpc/WebThreeStubServer.cpp | 6 +++--- libweb3jsonrpc/WebThreeStubServer.h | 2 +- libweb3jsonrpc/abstractwebthreestubserver.h | 6 +++--- libweb3jsonrpc/spec.json | 2 +- test/webthreestubclient.h | 3 +-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 87cd3c22b..6f7963c1d 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -538,7 +538,7 @@ static bytes toMethodCall(int const& _index, Json::Value const& _params) return data; } -std::string WebThreeStubServer::eth_contractCall(std::string const& _address, int const& _index, Json::Value const& _params) +std::string WebThreeStubServer::eth_contractCall(std::string const& _address, std::string const& _bytes) { auto from = m_accounts.begin()->first; for (auto a: m_accounts) @@ -549,8 +549,8 @@ std::string WebThreeStubServer::eth_contractCall(std::string const& _address, in auto gasPrice = 10 * dev::eth::szabo; auto gas = min(client()->gasLimitRemaining(), client()->balanceAt(from) / gasPrice); - auto bytes = toMethodCall(_index, _params); - return toJS(client()->call(m_accounts[from].secret(), 0, jsToAddress(_address), toMethodCall(_index, _params), gas, gasPrice)); + auto bytes = jsToBytes(_bytes); + return toJS(client()->call(m_accounts[from].secret(), 0, jsToAddress(_address), bytes, gas, gasPrice)); } std::string WebThreeStubServer::eth_contractCreate(std::string const& _bytecode) diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 3318214f1..bb4f258f6 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -73,7 +73,7 @@ public: virtual std::string eth_codeAt(std::string const& _address); virtual std::string eth_coinbase(); virtual Json::Value eth_compilers(); - virtual std::string eth_contractCall(std::string const& _address, int const& _index, Json::Value const& _params); + virtual std::string eth_contractCall(std::string const& _address, std::string const& _bytes); virtual std::string eth_contractCreate(std::string const& _bytecode); virtual double eth_countAt(std::string const& _address); virtual int eth_defaultBlock(); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 43a81c1cc..0ae4193fa 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -26,7 +26,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_codeAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_coinbaseI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_compilersI); - this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCall", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER,"param3",jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_contractCallI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCall", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_contractCallI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCreate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_contractCreateI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI); @@ -129,7 +129,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_contractCall(request[0u].asString(), request[1u].asInt(), request[2u]); + response = this->eth_contractCall(request[0u].asString(), request[1u].asString()); } inline virtual void eth_contractCreateI(const Json::Value& request, Json::Value& response) @@ -306,7 +306,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerclient->CallMethod("eth_contractCall",p); if (result.isString()) From 0b236057d8d1ff54bc49b45a6e16d38b224b800c Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 12 Nov 2014 20:55:23 +0100 Subject: [PATCH 11/44] minified ethereum.js --- libjsqrc/ethereum.min.js | 1 + libjsqrc/js.qrc | 3 +- libjsqrc/main.js | 470 --------------------------------------- libjsqrc/qt.js | 49 ---- libjsqrc/setup.js | 2 + libqethereum/QEthereum.h | 3 +- 6 files changed, 5 insertions(+), 523 deletions(-) create mode 100644 libjsqrc/ethereum.min.js delete mode 100644 libjsqrc/main.js delete mode 100644 libjsqrc/qt.js diff --git a/libjsqrc/ethereum.min.js b/libjsqrc/ethereum.min.js new file mode 100644 index 000000000..1befc1804 --- /dev/null +++ b/libjsqrc/ethereum.min.js @@ -0,0 +1 @@ +require=function t(e,n,r){function i(a,s){if(!n[a]){if(!e[a]){var c="function"==typeof require&&require;if(!s&&c)return c(a,!0);if(o)return o(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[a]={exports:{}};e[a][0].call(u.exports,function(t){var n=e[a][1][t];return i(n?n:t)},u,u.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;ar&&(e=t.charCodeAt(r),0!==e);r+=2)n+=String.fromCharCode(parseInt(t.substr(r,2),16));return n},toDecimal:function(t){return parseInt(t,16)},fromAscii:function(t,e){e=void 0===e?32:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},eth:{prototype:Object(),watch:function(t){return new s(t,i)}},db:{prototype:Object()},shh:{prototype:Object(),watch:function(t){return new s(t,o)}},on:function(t,e,n){return void 0===g._events[t]&&(g._events[t]={}),g._events[t][e]=n,this},off:function(t,e){return void 0!==g._events[t]&&delete g._events[t][e],this},trigger:function(t,e,n){var r,i=g._events[t];i&&i[e]&&(r=i[e])(n)}},m=g.eth;p(m,c()),v(m,l()),p(g.db,u()),p(g.shh,h()),i={changed:"eth_changed"},p(i,f()),o={changed:"shh_changed"},p(o,d()),a=function(){var t,e;this.queued=[],this.polls=[],this.ready=!1,this.provider=void 0,this.id=1,t=this,(e=function(){t.provider&&t.provider.poll&&t.polls.forEach(function(e){e.data._id=t.id,t.id++,t.provider.poll(e.data,e.id)}),setTimeout(e,12e3)})()},a.prototype.send=function(t,e){t._id=this.id,e&&(g._callbacks[t._id]=e),t.args=t.args||[],this.id++,void 0!==this.provider?this.provider.send(t):(console.warn("provider is not set"),this.queued.push(t))},a.prototype.set=function(t){void 0!==this.provider&&void 0!==this.provider.unload&&this.provider.unload(),this.provider=t,this.ready=!0},a.prototype.sendQueued=function(){for(var t=0;this.queued.length;t++)this.send(this.queued[t])},a.prototype.installed=function(){return void 0!==this.provider},a.prototype.startPolling=function(t,e){this.provider&&this.provider.poll&&this.polls.push({data:t,id:e})},a.prototype.stopPolling=function(t){var e,n;for(e=this.polls.length;e--;)n=this.polls[e],n.id===t&&this.polls.splice(e,1)},g.provider=new a,g.setProvider=function(t){t.onmessage=r,g.provider.set(t),g.provider.sendQueued()},g.haveProvider=function(){return!!g.provider.provider},s=function(t,e){this.impl=e,this.callbacks=[];var n=this;this.promise=e.newFilter(t),this.promise.then(function(t){n.id=t,g.on(e.changed,t,n.trigger.bind(n)),g.provider.startPolling({call:e.changed,args:[t]},t)})},s.prototype.arrived=function(t){this.changed(t)},s.prototype.changed=function(t){var e=this;this.promise.then(function(){e.callbacks.push(t)})},s.prototype.trigger=function(t){for(var e=0;e es6-promise-2.0.0.js setup.js - main.js - qt.js + ethereum.min.js diff --git a/libjsqrc/main.js b/libjsqrc/main.js deleted file mode 100644 index da95e7e53..000000000 --- a/libjsqrc/main.js +++ /dev/null @@ -1,470 +0,0 @@ -/* - 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 Lesser 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see . -*/ -/** @file main.js - * @authors: - * Marek Kotewicz - * @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" ? "eth_blockByHash" : "eth_blockByNumber"; - }; - - var transactionCall = function (args) { - return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; - }; - - var uncleCall = function (args) { - return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; - }; - - var methods = [ - { name: 'balanceAt', call: 'eth_balanceAt' }, - { name: 'stateAt', call: 'eth_stateAt' }, - { name: 'countAt', call: 'eth_countAt'}, - { name: 'codeAt', call: 'eth_codeAt' }, - { name: 'transact', call: 'eth_transact' }, - { name: 'call', call: 'eth_call' }, - { name: 'block', call: blockCall }, - { name: 'transaction', call: transactionCall }, - { name: 'uncle', call: uncleCall }, - { name: 'compilers', call: 'eth_compilers' }, - { name: 'lll', call: 'eth_lll' }, - { name: 'solidity', call: 'eth_solidity' }, - { name: 'contractCreate', call: 'eth_contractCreate' }, - { name: 'contractCall', call: 'eth_contractCall' } - ]; - return methods; - }; - - var ethProperties = function () { - return [ - { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, - { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, - { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, - { name: 'gasPrice', getter: 'eth_gasPrice' }, - { name: 'account', getter: 'eth_account' }, - { name: 'accounts', getter: 'eth_accounts' }, - { name: 'peerCount', getter: 'eth_peerCount' }, - { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, - { name: 'number', getter: 'eth_number'} - ]; - }; - - var dbMethods = function () { - return [ - { name: 'put', call: 'db_put' }, - { name: 'get', call: 'db_get' }, - { name: 'putString', call: 'db_putString' }, - { name: 'getString', call: 'db_getString' } - ]; - }; - - var shhMethods = function () { - return [ - { name: 'post', call: 'shh_post' }, - { name: 'newIdentity', call: 'shh_newIdentity' }, - { name: 'haveIdentity', call: 'shh_haveIdentity' }, - { name: 'newGroup', call: 'shh_newGroup' }, - { name: 'addToGroup', call: 'shh_addToGroup' } - ]; - }; - - var ethWatchMethods = function () { - var newFilter = function (args) { - return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; - }; - - return [ - { name: 'newFilter', call: newFilter }, - { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, - { name: 'getMessages', call: 'eth_getMessages' } - ]; - }; - - var shhWatchMethods = function () { - return [ - { name: 'newFilter', call: 'shh_newFilter' }, - { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, - { name: 'getMessage', call: 'shh_getMessages' } - ]; - }; - - 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 (err, result) { - if (!err) { - resolve(result); - return; - } - reject(err); - }); - }); - }).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(err, result) { - if (!err) { - resolve(result); - return; - } - reject(err); - }); - }); - }; - 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 (err, result) { - if (!err) { - resolve(result); - return; - } - reject(err); - }); - }); - }).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; - if (hex.substring(0, 2) == '0x') - i = 2; - 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 "0x" + 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: 'eth_changed' - }; - setupMethods(ethWatch, ethWatchMethods()); - var shhWatch = { - changed: 'shh_changed' - }; - 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) { - if (!(messages instanceof Array) || messages.length) { - 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.error, 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); diff --git a/libjsqrc/qt.js b/libjsqrc/qt.js deleted file mode 100644 index aedd34236..000000000 --- a/libjsqrc/qt.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - 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 Lesser 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see . -*/ -/** @file qt.js - * @authors: - * Marek Kotewicz - * @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; - } -})(); - diff --git a/libjsqrc/setup.js b/libjsqrc/setup.js index 5142412a6..b83745c33 100644 --- a/libjsqrc/setup.js +++ b/libjsqrc/setup.js @@ -41,4 +41,6 @@ if (window.Promise === undefined) { window.Promise = ES6Promise.Promise; } +var web3 = require('web3'); web3.setProvider(new web3.providers.QtProvider()); + diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index 4f276b7e1..ec7eadaf6 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -84,8 +84,7 @@ private: _frame->disconnect(); \ _frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/es6-promise-2.0.0.js")); \ - _frame->evaluateJavaScript(contentsOfQResource(":/js/main.js")); \ - _frame->evaluateJavaScript(contentsOfQResource(":/js/qt.js")); \ + _frame->evaluateJavaScript(contentsOfQResource(":/js/ethereum.min.js")); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/setup.js")); \ } From 7bdc646dccdba745726382c57feaa0f37e4c39ff Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 13 Nov 2014 12:25:49 +0100 Subject: [PATCH 12/44] removed unnecessary methods from jsonrpc and added contract call tests --- libjsqrc/ethereum.min.js | 2 +- libweb3jsonrpc/WebThreeStubServer.cpp | 60 ++------------------- libweb3jsonrpc/WebThreeStubServer.h | 2 - libweb3jsonrpc/abstractwebthreestubserver.h | 14 ----- libweb3jsonrpc/spec.json | 2 - test/jsonrpc.cpp | 28 ++++++++++ test/webthreestubclient.h | 27 ---------- 7 files changed, 34 insertions(+), 101 deletions(-) diff --git a/libjsqrc/ethereum.min.js b/libjsqrc/ethereum.min.js index 1befc1804..5b1ff1c6f 100644 --- a/libjsqrc/ethereum.min.js +++ b/libjsqrc/ethereum.min.js @@ -1 +1 @@ -require=function t(e,n,r){function i(a,s){if(!n[a]){if(!e[a]){var c="function"==typeof require&&require;if(!s&&c)return c(a,!0);if(o)return o(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[a]={exports:{}};e[a][0].call(u.exports,function(t){var n=e[a][1][t];return i(n?n:t)},u,u.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;ar&&(e=t.charCodeAt(r),0!==e);r+=2)n+=String.fromCharCode(parseInt(t.substr(r,2),16));return n},toDecimal:function(t){return parseInt(t,16)},fromAscii:function(t,e){e=void 0===e?32:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},eth:{prototype:Object(),watch:function(t){return new s(t,i)}},db:{prototype:Object()},shh:{prototype:Object(),watch:function(t){return new s(t,o)}},on:function(t,e,n){return void 0===g._events[t]&&(g._events[t]={}),g._events[t][e]=n,this},off:function(t,e){return void 0!==g._events[t]&&delete g._events[t][e],this},trigger:function(t,e,n){var r,i=g._events[t];i&&i[e]&&(r=i[e])(n)}},m=g.eth;p(m,c()),v(m,l()),p(g.db,u()),p(g.shh,h()),i={changed:"eth_changed"},p(i,f()),o={changed:"shh_changed"},p(o,d()),a=function(){var t,e;this.queued=[],this.polls=[],this.ready=!1,this.provider=void 0,this.id=1,t=this,(e=function(){t.provider&&t.provider.poll&&t.polls.forEach(function(e){e.data._id=t.id,t.id++,t.provider.poll(e.data,e.id)}),setTimeout(e,12e3)})()},a.prototype.send=function(t,e){t._id=this.id,e&&(g._callbacks[t._id]=e),t.args=t.args||[],this.id++,void 0!==this.provider?this.provider.send(t):(console.warn("provider is not set"),this.queued.push(t))},a.prototype.set=function(t){void 0!==this.provider&&void 0!==this.provider.unload&&this.provider.unload(),this.provider=t,this.ready=!0},a.prototype.sendQueued=function(){for(var t=0;this.queued.length;t++)this.send(this.queued[t])},a.prototype.installed=function(){return void 0!==this.provider},a.prototype.startPolling=function(t,e){this.provider&&this.provider.poll&&this.polls.push({data:t,id:e})},a.prototype.stopPolling=function(t){var e,n;for(e=this.polls.length;e--;)n=this.polls[e],n.id===t&&this.polls.splice(e,1)},g.provider=new a,g.setProvider=function(t){t.onmessage=r,g.provider.set(t),g.provider.sendQueued()},g.haveProvider=function(){return!!g.provider.provider},s=function(t,e){this.impl=e,this.callbacks=[];var n=this;this.promise=e.newFilter(t),this.promise.then(function(t){n.id=t,g.on(e.changed,t,n.trigger.bind(n)),g.provider.startPolling({call:e.changed,args:[t]},t)})},s.prototype.arrived=function(t){this.changed(t)},s.prototype.changed=function(t){var e=this;this.promise.then(function(){e.callbacks.push(t)})},s.prototype.trigger=function(t){for(var e=0;er&&(t=e.charCodeAt(r),0!==t);r+=2)n+=String.fromCharCode(parseInt(e.substr(r,2),16));return n},toDecimal:function(e){return parseInt(e,16)},fromAscii:function(e,t){t=void 0===t?32:t;for(var n=this.toHex(e);n.length<2*t;)n+="00";return"0x"+n},eth:{prototype:Object(),watch:function(e){return new a(e,o)}},db:{prototype:Object()},shh:{prototype:Object(),watch:function(e){return new a(e,i)}},on:function(e,t,n){return void 0===g._events[e]&&(g._events[e]={}),g._events[e][t]=n,this},off:function(e,t){return void 0!==g._events[e]&&delete g._events[e][t],this},trigger:function(e,t,n){var r,o=g._events[e];o&&o[t]&&(r=o[t])(n)}},m=g.eth;f(m,c()),v(m,u()),f(g.db,l()),f(g.shh,h()),o={changed:"eth_changed"},f(o,d()),i={changed:"shh_changed"},f(i,p()),s=function(){var e,t;this.queued=[],this.polls=[],this.ready=!1,this.provider=void 0,this.id=1,e=this,(t=function(){e.provider&&e.provider.poll&&e.polls.forEach(function(t){t.data._id=e.id,e.id++,e.provider.poll(t.data,t.id)}),setTimeout(t,12e3)})()},s.prototype.send=function(e,t){e._id=this.id,t&&(g._callbacks[e._id]=t),e.args=e.args||[],this.id++,void 0!==this.provider?this.provider.send(e):(console.warn("provider is not set"),this.queued.push(e))},s.prototype.set=function(e){void 0!==this.provider&&void 0!==this.provider.unload&&this.provider.unload(),this.provider=e,this.ready=!0},s.prototype.sendQueued=function(){for(var e=0;this.queued.length;e++)this.send(this.queued[e])},s.prototype.installed=function(){return void 0!==this.provider},s.prototype.startPolling=function(e,t){this.provider&&this.provider.poll&&this.polls.push({data:e,id:t})},s.prototype.stopPolling=function(e){var t,n;for(t=this.polls.length;t--;)n=this.polls[t],n.id===e&&this.polls.splice(t,1)},g.provider=new s,g.setProvider=function(e){e.onmessage=r,g.provider.set(e),g.provider.sendQueued()},g.haveProvider=function(){return!!g.provider.provider},a=function(e,t){this.impl=t,this.callbacks=[];var n=this;this.promise=t.newFilter(e),this.promise.then(function(e){n.id=e,g.on(t.changed,e,n.trigger.bind(n)),g.provider.startPolling({call:t.changed,args:[e]},e)})},a.prototype.arrived=function(e){this.changed(e)},a.prototype.changed=function(e){var t=this;this.promise.then(function(){t.callbacks.push(e)})},a.prototype.trigger=function(e){for(var t=0;tfirst; - for (auto a: m_accounts) - if (client()->balanceAt(a.first) > client()->balanceAt(from)) - from = a.first; - - cwarn << "Silently signing transaction from address" << from.abridged() << ": User validation hook goes here."; - - auto gasPrice = 10 * dev::eth::szabo; - auto gas = min(client()->gasLimitRemaining(), client()->balanceAt(from) / gasPrice); - auto bytes = jsToBytes(_bytes); - return toJS(client()->call(m_accounts[from].secret(), 0, jsToAddress(_address), bytes, gas, gasPrice)); -} - -std::string WebThreeStubServer::eth_contractCreate(std::string const& _bytecode) -{ - auto from = m_accounts.begin()->first; - for (auto a: m_accounts) - if (client()->balanceAt(a.first) > client()->balanceAt(from)) - from = a.first; - - cwarn << "Silently signing transaction from address" << from.abridged() << ": User validation hook goes here."; - - auto gasPrice = 10 * dev::eth::szabo; - auto gas = min(client()->gasLimitRemaining(), client()->balanceAt(from) / gasPrice); - return toJS(client()->transact(m_accounts[from].secret(), 0, jsToBytes(_bytecode), gas, gasPrice)); -} - std::string WebThreeStubServer::eth_lll(std::string const& _code) { return toJS(dev::eth::compileLLL(_code)); diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index bb4f258f6..e358e110c 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -73,8 +73,6 @@ public: virtual std::string eth_codeAt(std::string const& _address); virtual std::string eth_coinbase(); virtual Json::Value eth_compilers(); - virtual std::string eth_contractCall(std::string const& _address, std::string const& _bytes); - virtual std::string eth_contractCreate(std::string const& _bytecode); virtual double eth_countAt(std::string const& _address); virtual int eth_defaultBlock(); virtual std::string eth_gasPrice(); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 0ae4193fa..dba6e02cd 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -26,8 +26,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_codeAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_coinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_coinbaseI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_compilersI); - this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCall", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_contractCallI); - this->bindAndAddMethod(new jsonrpc::Procedure("eth_contractCreate", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_contractCreateI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI); @@ -127,16 +125,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_compilers(); } - inline virtual void eth_contractCallI(const Json::Value& request, Json::Value& response) - { - response = this->eth_contractCall(request[0u].asString(), request[1u].asString()); - } - - inline virtual void eth_contractCreateI(const Json::Value& request, Json::Value& response) - { - response = this->eth_contractCreate(request[0u].asString()); - } - inline virtual void eth_countAtI(const Json::Value& request, Json::Value& response) { response = this->eth_countAt(request[0u].asString()); @@ -306,8 +294,6 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerethereum()->setAddress(kp.address()); + jsonrpcServer->setAccounts({kp}); + + dev::eth::mine(*(web3->ethereum()), 1); + char const* sourceCode = "contract test {\n" + " function f(uint a) returns(uint d) { return a * 7; }\n" + "}\n"; + + string compiled = jsonrpcClient->eth_solidity(sourceCode); + + Json::Value create; + create["code"] = compiled; + string contractAddress = jsonrpcClient->eth_transact(create); + dev::eth::mine(*(web3->ethereum()), 1); + + Json::Value call; + call["to"] = contractAddress; + call["data"] = "0x00000000000000000000000000000000000000000000000000000000000000001"; + string result = jsonrpcClient->eth_call(call); + BOOST_CHECK_EQUAL(result, "0x0000000000000000000000000000000000000000000000000000000000000007"); +} + BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END() diff --git a/test/webthreestubclient.h b/test/webthreestubclient.h index 6d844de8e..66c4bef35 100644 --- a/test/webthreestubclient.h +++ b/test/webthreestubclient.h @@ -191,33 +191,6 @@ p.append(param3); } - std::string eth_contractCall(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("eth_contractCall",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - - } - - std::string eth_contractCreate(const std::string& param1) throw (jsonrpc::JsonRpcException) - { - Json::Value p; - p.append(param1); - - Json::Value result = this->client->CallMethod("eth_contractCreate",p); - if (result.isString()) - return result.asString(); - else - throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); - - } - double eth_countAt(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; From 47434e62c328907338d77b27af3c31b77cc76bae Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 13 Nov 2014 18:29:01 +0100 Subject: [PATCH 13/44] added storageAt which dumps contract storage --- libjsqrc/ethereum.min.js | 2 +- libweb3jsonrpc/WebThreeStubServer.cpp | 15 +++++++++++++++ libweb3jsonrpc/WebThreeStubServer.h | 1 + libweb3jsonrpc/abstractwebthreestubserver.h | 7 +++++++ libweb3jsonrpc/spec.json | 1 + test/webthreestubclient.h | 13 +++++++++++++ 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/libjsqrc/ethereum.min.js b/libjsqrc/ethereum.min.js index 5b1ff1c6f..125523290 100644 --- a/libjsqrc/ethereum.min.js +++ b/libjsqrc/ethereum.min.js @@ -1 +1 @@ -require=function e(t,n,r){function o(s,a){if(!n[s]){if(!t[s]){var c="function"==typeof require&&require;if(!a&&c)return c(s,!0);if(i)return i(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var l=n[s]={exports:{}};t[s][0].call(l.exports,function(e){var n=t[s][1][e];return o(n?n:e)},l,l.exports,e,t,n,r)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;sr&&(t=e.charCodeAt(r),0!==t);r+=2)n+=String.fromCharCode(parseInt(e.substr(r,2),16));return n},toDecimal:function(e){return parseInt(e,16)},fromAscii:function(e,t){t=void 0===t?32:t;for(var n=this.toHex(e);n.length<2*t;)n+="00";return"0x"+n},eth:{prototype:Object(),watch:function(e){return new a(e,o)}},db:{prototype:Object()},shh:{prototype:Object(),watch:function(e){return new a(e,i)}},on:function(e,t,n){return void 0===g._events[e]&&(g._events[e]={}),g._events[e][t]=n,this},off:function(e,t){return void 0!==g._events[e]&&delete g._events[e][t],this},trigger:function(e,t,n){var r,o=g._events[e];o&&o[t]&&(r=o[t])(n)}},m=g.eth;f(m,c()),v(m,u()),f(g.db,l()),f(g.shh,h()),o={changed:"eth_changed"},f(o,d()),i={changed:"shh_changed"},f(i,p()),s=function(){var e,t;this.queued=[],this.polls=[],this.ready=!1,this.provider=void 0,this.id=1,e=this,(t=function(){e.provider&&e.provider.poll&&e.polls.forEach(function(t){t.data._id=e.id,e.id++,e.provider.poll(t.data,t.id)}),setTimeout(t,12e3)})()},s.prototype.send=function(e,t){e._id=this.id,t&&(g._callbacks[e._id]=t),e.args=e.args||[],this.id++,void 0!==this.provider?this.provider.send(e):(console.warn("provider is not set"),this.queued.push(e))},s.prototype.set=function(e){void 0!==this.provider&&void 0!==this.provider.unload&&this.provider.unload(),this.provider=e,this.ready=!0},s.prototype.sendQueued=function(){for(var e=0;this.queued.length;e++)this.send(this.queued[e])},s.prototype.installed=function(){return void 0!==this.provider},s.prototype.startPolling=function(e,t){this.provider&&this.provider.poll&&this.polls.push({data:e,id:t})},s.prototype.stopPolling=function(e){var t,n;for(t=this.polls.length;t--;)n=this.polls[t],n.id===e&&this.polls.splice(t,1)},g.provider=new s,g.setProvider=function(e){e.onmessage=r,g.provider.set(e),g.provider.sendQueued()},g.haveProvider=function(){return!!g.provider.provider},a=function(e,t){this.impl=t,this.callbacks=[];var n=this;this.promise=t.newFilter(e),this.promise.then(function(e){n.id=e,g.on(t.changed,e,n.trigger.bind(n)),g.provider.startPolling({call:t.changed,args:[e]},e)})},a.prototype.arrived=function(e){this.changed(e)},a.prototype.changed=function(e){var t=this;this.promise.then(function(){t.callbacks.push(e)})},a.prototype.trigger=function(e){for(var t=0;tr&&(t=e.charCodeAt(r),0!==t);r+=2)n+=String.fromCharCode(parseInt(e.substr(r,2),16));return n},toDecimal:function(e){return parseInt(e,16)},fromAscii:function(e,t){t=void 0===t?32:t;for(var n=this.toHex(e);n.length<2*t;)n+="00";return"0x"+n},eth:{prototype:Object(),watch:function(e){return new a(e,o)}},db:{prototype:Object()},shh:{prototype:Object(),watch:function(e){return new a(e,i)}},on:function(e,t,n){return void 0===g._events[e]&&(g._events[e]={}),g._events[e][t]=n,this},off:function(e,t){return void 0!==g._events[e]&&delete g._events[e][t],this},trigger:function(e,t,n){var r,o=g._events[e];o&&o[t]&&(r=o[t])(n)}},m=g.eth;f(m,c()),v(m,u()),f(g.db,l()),f(g.shh,h()),o={changed:"eth_changed"},f(o,d()),i={changed:"shh_changed"},f(i,p()),s=function(){var e,t;this.queued=[],this.polls=[],this.ready=!1,this.provider=void 0,this.id=1,e=this,(t=function(){e.provider&&e.provider.poll&&e.polls.forEach(function(t){t.data._id=e.id,e.id++,e.provider.poll(t.data,t.id)}),setTimeout(t,12e3)})()},s.prototype.send=function(e,t){e._id=this.id,t&&(g._callbacks[e._id]=t),e.args=e.args||[],this.id++,void 0!==this.provider?this.provider.send(e):(console.warn("provider is not set"),this.queued.push(e))},s.prototype.set=function(e){void 0!==this.provider&&void 0!==this.provider.unload&&this.provider.unload(),this.provider=e,this.ready=!0},s.prototype.sendQueued=function(){for(var e=0;this.queued.length;e++)this.send(this.queued[e])},s.prototype.installed=function(){return void 0!==this.provider},s.prototype.startPolling=function(e,t){this.provider&&this.provider.poll&&this.polls.push({data:e,id:t})},s.prototype.stopPolling=function(e){var t,n;for(t=this.polls.length;t--;)n=this.polls[t],n.id===e&&this.polls.splice(t,1)},g.provider=new s,g.setProvider=function(e){e.onmessage=r,g.provider.set(e),g.provider.sendQueued()},g.haveProvider=function(){return!!g.provider.provider},a=function(e,t){this.impl=t,this.callbacks=[];var n=this;this.promise=t.newFilter(e),this.promise.then(function(e){n.id=e,g.on(t.changed,e,n.trigger.bind(n)),g.provider.startPolling({call:t.changed,args:[e]},e)})},a.prototype.arrived=function(e){this.changed(e)},a.prototype.changed=function(e){var t=this;this.promise.then(function(){t.callbacks.push(e)})},a.prototype.trigger=function(e){for(var t=0;t const& _storage) +{ + Json::Value res(Json::objectValue); + for (auto i: _storage) + res[toJS(i.first)] = toJS(i.second); + return res; +} + /*static*/ Json::Value toJson(dev::eth::LogEntries const& _es) // commented to avoid warning. Uncomment once in use @ poC-7. { Json::Value res; @@ -651,6 +659,13 @@ std::string WebThreeStubServer::eth_stateAt(string const& _address, string const return client() ? toJS(client()->stateAt(jsToAddress(_address), jsToU256(_storage), block)) : ""; } +Json::Value WebThreeStubServer::eth_storageAt(string const& _address) +{ + if (!client()) + return Json::Value(Json::objectValue); + return toJson(client()->storageAt(jsToAddress(_address))); +} + std::string WebThreeStubServer::eth_transact(Json::Value const& _json) { std::string ret; diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index e358e110c..5207ed1df 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -90,6 +90,7 @@ public: virtual bool eth_setMining(bool const& _mining); virtual std::string eth_solidity(std::string const& _code); virtual std::string eth_stateAt(std::string const& _address, std::string const& _storage); + virtual Json::Value eth_storageAt(std::string const& _address); virtual std::string eth_transact(Json::Value const& _json); virtual Json::Value eth_transactionByHash(std::string const& _hash, int const& _i); virtual Json::Value eth_transactionByNumber(int const& _number, int const& _i); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index dba6e02cd..5fb548103 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -43,6 +43,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_setMining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_setMiningI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_solidity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_solidityI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_stateAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_stateAtI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_storageAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_storageAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_transact", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_transactI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_transactionByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionByHashI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_transactionByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_INTEGER,"param2",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionByNumberI); @@ -210,6 +211,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_stateAt(request[0u].asString(), request[1u].asString()); } + inline virtual void eth_storageAtI(const Json::Value& request, Json::Value& response) + { + response = this->eth_storageAt(request[0u].asString()); + } + inline virtual void eth_transactI(const Json::Value& request, Json::Value& response) { response = this->eth_transact(request[0u]); @@ -311,6 +317,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerclient->CallMethod("eth_storageAt",p); + if (result.isObject()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + std::string eth_transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; From 0e02c79b801133b8c880615994e5d3c58077aa7b Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 13 Nov 2014 18:52:21 +0100 Subject: [PATCH 14/44] storage dump test --- test/jsonrpc.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/jsonrpc.cpp b/test/jsonrpc.cpp index 3f552d47d..d17c5a594 100644 --- a/test/jsonrpc.cpp +++ b/test/jsonrpc.cpp @@ -266,6 +266,44 @@ BOOST_AUTO_TEST_CASE(simple_contract) BOOST_CHECK_EQUAL(result, "0x0000000000000000000000000000000000000000000000000000000000000007"); } +BOOST_AUTO_TEST_CASE(contract_storage) +{ + cnote << "Testing jsonrpc contract storage..."; + KeyPair kp = KeyPair::create(); + web3->ethereum()->setAddress(kp.address()); + jsonrpcServer->setAccounts({kp}); + + dev::eth::mine(*(web3->ethereum()), 1); + + char const* sourceCode = R"( + contract test { + uint hello; + function writeHello(uint value) returns(bool d){ + hello = value; + return true; + } + } + )"; + + string compiled = jsonrpcClient->eth_solidity(sourceCode); + + Json::Value create; + create["code"] = compiled; + string contractAddress = jsonrpcClient->eth_transact(create); + dev::eth::mine(*(web3->ethereum()), 1); + + Json::Value transact; + transact["to"] = contractAddress; + transact["data"] = "0x00000000000000000000000000000000000000000000000000000000000000003"; + jsonrpcClient->eth_transact(transact); + dev::eth::mine(*(web3->ethereum()), 1); + + Json::Value storage = jsonrpcClient->eth_storageAt(contractAddress); + BOOST_CHECK_EQUAL(storage.getMemberNames().size(), 1); + for (auto name: storage.getMemberNames()) + BOOST_CHECK_EQUAL(storage[name].asString(), "0x03"); +} + BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END() From d2427082fa2971922432097aa17f260374826103 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 14 Nov 2014 13:13:06 +0100 Subject: [PATCH 15/44] improved js interface for contract calling --- libjsqrc/ethereum.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libjsqrc/ethereum.min.js b/libjsqrc/ethereum.min.js index 125523290..b23886cab 100644 --- a/libjsqrc/ethereum.min.js +++ b/libjsqrc/ethereum.min.js @@ -1 +1 @@ -require=function e(t,n,r){function o(s,a){if(!n[s]){if(!t[s]){var c="function"==typeof require&&require;if(!a&&c)return c(s,!0);if(i)return i(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var l=n[s]={exports:{}};t[s][0].call(l.exports,function(e){var n=t[s][1][e];return o(n?n:e)},l,l.exports,e,t,n,r)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;sr&&(t=e.charCodeAt(r),0!==t);r+=2)n+=String.fromCharCode(parseInt(e.substr(r,2),16));return n},toDecimal:function(e){return parseInt(e,16)},fromAscii:function(e,t){t=void 0===t?32:t;for(var n=this.toHex(e);n.length<2*t;)n+="00";return"0x"+n},eth:{prototype:Object(),watch:function(e){return new a(e,o)}},db:{prototype:Object()},shh:{prototype:Object(),watch:function(e){return new a(e,i)}},on:function(e,t,n){return void 0===g._events[e]&&(g._events[e]={}),g._events[e][t]=n,this},off:function(e,t){return void 0!==g._events[e]&&delete g._events[e][t],this},trigger:function(e,t,n){var r,o=g._events[e];o&&o[t]&&(r=o[t])(n)}},m=g.eth;f(m,c()),v(m,u()),f(g.db,l()),f(g.shh,h()),o={changed:"eth_changed"},f(o,d()),i={changed:"shh_changed"},f(i,p()),s=function(){var e,t;this.queued=[],this.polls=[],this.ready=!1,this.provider=void 0,this.id=1,e=this,(t=function(){e.provider&&e.provider.poll&&e.polls.forEach(function(t){t.data._id=e.id,e.id++,e.provider.poll(t.data,t.id)}),setTimeout(t,12e3)})()},s.prototype.send=function(e,t){e._id=this.id,t&&(g._callbacks[e._id]=t),e.args=e.args||[],this.id++,void 0!==this.provider?this.provider.send(e):(console.warn("provider is not set"),this.queued.push(e))},s.prototype.set=function(e){void 0!==this.provider&&void 0!==this.provider.unload&&this.provider.unload(),this.provider=e,this.ready=!0},s.prototype.sendQueued=function(){for(var e=0;this.queued.length;e++)this.send(this.queued[e])},s.prototype.installed=function(){return void 0!==this.provider},s.prototype.startPolling=function(e,t){this.provider&&this.provider.poll&&this.polls.push({data:e,id:t})},s.prototype.stopPolling=function(e){var t,n;for(t=this.polls.length;t--;)n=this.polls[t],n.id===e&&this.polls.splice(t,1)},g.provider=new s,g.setProvider=function(e){e.onmessage=r,g.provider.set(e),g.provider.sendQueued()},g.haveProvider=function(){return!!g.provider.provider},a=function(e,t){this.impl=t,this.callbacks=[];var n=this;this.promise=t.newFilter(e),this.promise.then(function(e){n.id=e,g.on(t.changed,e,n.trigger.bind(n)),g.provider.startPolling({call:t.changed,args:[e]},e)})},a.prototype.arrived=function(e){this.changed(e)},a.prototype.changed=function(e){var t=this;this.promise.then(function(){t.callbacks.push(e)})},a.prototype.trigger=function(e){for(var t=0;tr&&(e=t.charCodeAt(r),0!==e);r+=2)n+=String.fromCharCode(parseInt(t.substr(r,2),16));return n},toDecimal:function(t){return parseInt(t,16)},fromAscii:function(t,e){e=void 0===e?32:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},eth:{prototype:Object(),watch:function(t){return new a(t,o)}},db:{prototype:Object()},shh:{prototype:Object(),watch:function(t){return new a(t,i)}},on:function(t,e,n){return void 0===m._events[t]&&(m._events[t]={}),m._events[t][e]=n,this},off:function(t,e){return void 0!==m._events[t]&&delete m._events[t][e],this},trigger:function(t,e,n){var r,o=m._events[t];o&&o[e]&&(r=o[e])(n)}};v(m.eth,c()),g(m.eth,l()),v(m.db,h()),v(m.shh,p()),o={changed:"eth_changed"},v(o,d()),i={changed:"shh_changed"},v(i,f()),s=function(){var t,e;this.queued=[],this.polls=[],this.ready=!1,this.provider=void 0,this.id=1,t=this,(e=function(){t.provider&&t.provider.poll&&t.polls.forEach(function(e){e.data._id=t.id,t.id++,t.provider.poll(e.data,e.id)}),setTimeout(e,12e3)})()},s.prototype.send=function(t,e){t._id=this.id,e&&(m._callbacks[t._id]=e),t.args=t.args||[],this.id++,void 0!==this.provider?this.provider.send(t):(console.warn("provider is not set"),this.queued.push(t))},s.prototype.set=function(t){void 0!==this.provider&&void 0!==this.provider.unload&&this.provider.unload(),this.provider=t,this.ready=!0},s.prototype.sendQueued=function(){for(var t=0;this.queued.length;t++)this.send(this.queued[t])},s.prototype.installed=function(){return void 0!==this.provider},s.prototype.startPolling=function(t,e){this.provider&&this.provider.poll&&this.polls.push({data:t,id:e})},s.prototype.stopPolling=function(t){var e,n;for(e=this.polls.length;e--;)n=this.polls[e],n.id===t&&this.polls.splice(e,1)},m.provider=new s,m.setProvider=function(t){t.onmessage=r,m.provider.set(t),m.provider.sendQueued()},m.haveProvider=function(){return!!m.provider.provider},a=function(t,e){this.impl=e,this.callbacks=[];var n=this;this.promise=e.newFilter(t),this.promise.then(function(t){n.id=t,m.on(e.changed,t,n.trigger.bind(n)),m.provider.startPolling({call:e.changed,args:[t]},t)})},a.prototype.arrived=function(t){this.changed(t)},a.prototype.changed=function(t){var e=this;this.promise.then(function(){e.callbacks.push(t)})},a.prototype.trigger=function(t){for(var e=0;e Date: Fri, 14 Nov 2014 13:42:07 +0100 Subject: [PATCH 16/44] Update Visual Studio project files --- windows/LibEthereum.vcxproj | 7 ++++--- windows/LibEthereum.vcxproj.filters | 17 ++++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 35ca956d3..0578a8f16 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -125,8 +125,8 @@ - + true true @@ -341,7 +341,8 @@ - + + true @@ -567,4 +568,4 @@ - + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index 514320472..114364008 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -40,9 +40,6 @@ libevmcore - - liblll - liblll @@ -202,6 +199,9 @@ libethereum + + libevmcore + @@ -248,9 +248,6 @@ liblll - - - libevmcore liblll @@ -435,6 +432,12 @@ libethereum + + libevmcore + + + libevmcore + @@ -471,4 +474,4 @@ {d838fece-fc20-42f6-bff5-97c236159b80} - + \ No newline at end of file From ec2b0100472b9509bb3a964c1d5894fa5495c15a Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 10 Nov 2014 17:31:09 +0100 Subject: [PATCH 17/44] Mapping types. --- libsolidity/AST.cpp | 40 +++++-- libsolidity/AST.h | 26 +++- libsolidity/Compiler.cpp | 2 +- libsolidity/CompilerContext.h | 4 +- libsolidity/ExpressionCompiler.cpp | 177 ++++++++++++++++++---------- libsolidity/ExpressionCompiler.h | 77 +++++++----- libsolidity/NameAndTypeResolver.cpp | 5 +- libsolidity/Types.cpp | 6 +- libsolidity/Types.h | 15 ++- test/solidityCompiler.cpp | 2 - test/solidityEndToEndTest.cpp | 167 ++++++++++++++++++++++++++ 11 files changed, 412 insertions(+), 109 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 70af8f98e..d5f856dfc 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -278,6 +278,15 @@ vector ContractDefinition::getInterfaceFunctions() co return exportedFunctions; } +void FunctionDefinition::checkTypeRequirements() +{ + for (ASTPointer const& var: getParameters() + getReturnParameters()) + if (!var->getType()->canLiveOutsideStorage()) + BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage.")); + + m_body->checkTypeRequirements(); +} + void Block::checkTypeRequirements() { for (shared_ptr const& statement: m_statements) @@ -315,7 +324,7 @@ void Return::checkTypeRequirements() void VariableDefinition::checkTypeRequirements() { // Variables can be declared without type (with "var"), in which case the first assignment - // setsthe type. + // sets the type. // Note that assignments before the first declaration are legal because of the special scoping // rules inherited from JavaScript. if (m_value) @@ -329,13 +338,14 @@ void VariableDefinition::checkTypeRequirements() m_variable->setType(m_value->getType()); } } + if (m_variable->getType() && !m_variable->getType()->canLiveOutsideStorage()) + BOOST_THROW_EXCEPTION(m_variable->createTypeError("Type is required to live outside storage.")); } void Assignment::checkTypeRequirements() { m_leftHandSide->checkTypeRequirements(); - if (!m_leftHandSide->isLvalue()) - BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); + m_leftHandSide->requireLValue(); m_rightHandSide->expectType(*m_leftHandSide->getType()); m_type = m_leftHandSide->getType(); if (m_assigmentOperator != Token::ASSIGN) @@ -359,13 +369,19 @@ void Expression::expectType(Type const& _expectedType) + _expectedType.toString() + ".")); } +void Expression::requireLValue() +{ + if (!isLvalue()) + BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); + m_lvalueRequested = true; +} + void UnaryOperation::checkTypeRequirements() { // INC, DEC, ADD, SUB, NOT, BIT_NOT, DELETE m_subExpression->checkTypeRequirements(); if (m_operator == Token::Value::INC || m_operator == Token::Value::DEC || m_operator == Token::Value::DELETE) - if (!m_subExpression->isLvalue()) - BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); + m_subExpression->requireLValue(); m_type = m_subExpression->getType(); if (!m_type->acceptsUnaryOperator(m_operator)) BOOST_THROW_EXCEPTION(createTypeError("Unary operator not compatible with type.")); @@ -416,6 +432,8 @@ void FunctionCall::checkTypeRequirements() } else { + m_expression->requireLValue(); + //@todo would be nice to create a struct type from the arguments // and then ask if that is implicitly convertible to the struct represented by the // function parameters @@ -448,8 +466,15 @@ void MemberAccess::checkTypeRequirements() void IndexAccess::checkTypeRequirements() { - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Index access not yet implemented.")); - // m_type = ; + m_base->checkTypeRequirements(); + m_base->requireLValue(); + if (m_base->getType()->getCategory() != Type::Category::MAPPING) + BOOST_THROW_EXCEPTION(m_base->createTypeError("Indexed expression has to be a mapping (is " + + m_base->getType()->toString() + ")")); + MappingType const& type = dynamic_cast(*m_base->getType()); + m_index->expectType(*type.getKeyType()); + m_type = type.getValueType(); + m_isLvalue = true; } void Identifier::checkTypeRequirements() @@ -481,6 +506,7 @@ void Identifier::checkTypeRequirements() // Calling a function (e.g. function(12), otherContract.function(34)) does not do a type // conversion. m_type = make_shared(*functionDef); + m_isLvalue = true; return; } ContractDefinition* contractDef = dynamic_cast(m_referencedDeclaration); diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 7b266f132..31ca56f76 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -186,6 +186,8 @@ public: void addLocalVariable(VariableDeclaration const& _localVariable) { m_localVariables.push_back(&_localVariable); } std::vector const& getLocalVariables() const { return m_localVariables; } + /// Checks that all parameters have allowed types and calls checkTypeRequirements on the body. + void checkTypeRequirements(); private: bool m_isPublic; ASTPointer m_parameters; @@ -236,7 +238,7 @@ public: /// Retrieve the element of the type hierarchy this node refers to. Can return an empty shared /// pointer until the types have been resolved using the @ref NameAndTypeResolver. - virtual std::shared_ptr toType() = 0; + virtual std::shared_ptr toType() const = 0; }; /** @@ -252,7 +254,7 @@ public: if (asserts(Token::isElementaryTypeName(_type))) BOOST_THROW_EXCEPTION(InternalCompilerError()); } virtual void accept(ASTVisitor& _visitor) override; - virtual std::shared_ptr toType() override { return Type::fromElementaryTypeName(m_type); } + virtual std::shared_ptr toType() const override { return Type::fromElementaryTypeName(m_type); } Token::Value getTypeName() const { return m_type; } @@ -270,7 +272,7 @@ public: UserDefinedTypeName(Location const& _location, ASTPointer const& _name): TypeName(_location), m_name(_name) {} virtual void accept(ASTVisitor& _visitor) override; - virtual std::shared_ptr toType() override { return Type::fromUserDefinedTypeName(*this); } + virtual std::shared_ptr toType() const override { return Type::fromUserDefinedTypeName(*this); } ASTString const& getName() const { return *m_name; } void setReferencedStruct(StructDefinition& _referencedStruct) { m_referencedStruct = &_referencedStruct; } @@ -292,7 +294,10 @@ public: ASTPointer const& _valueType): TypeName(_location), m_keyType(_keyType), m_valueType(_valueType) {} virtual void accept(ASTVisitor& _visitor) override; - virtual std::shared_ptr toType() override { return Type::fromMapping(*this); } + virtual std::shared_ptr toType() const override { return Type::fromMapping(*this); } + + ElementaryTypeName const& getKeyType() const { return *m_keyType; } + TypeName const& getValueType() const { return *m_valueType; } private: ASTPointer m_keyType; @@ -481,7 +486,7 @@ private: class Expression: public ASTNode { public: - Expression(Location const& _location): ASTNode(_location), m_isLvalue(false) {} + Expression(Location const& _location): ASTNode(_location), m_isLvalue(false), m_lvalueRequested(false) {} virtual void checkTypeRequirements() = 0; std::shared_ptr const& getType() const { return m_type; } @@ -490,6 +495,12 @@ public: /// Helper function, infer the type via @ref checkTypeRequirements and then check that it /// is implicitly convertible to @a _expectedType. If not, throw exception. void expectType(Type const& _expectedType); + /// Checks that this expression is an lvalue and also registers that an address and + /// not a value is generated during compilation. Can be called after checkTypeRequirements() + /// by an enclosing expression. + void requireLValue(); + /// Returns true if @a requireLValue was previously called on this expression. + bool lvalueRequested() const { return m_lvalueRequested; } protected: //! Inferred type of the expression, only filled after a call to checkTypeRequirements(). @@ -497,6 +508,8 @@ protected: //! Whether or not this expression is an lvalue, i.e. something that can be assigned to. //! This is set during calls to @a checkTypeRequirements() bool m_isLvalue; + //! Whether the outer expression requested the address (true) or the value (false) of this expression. + bool m_lvalueRequested; }; /// Assignment, can also be a compound assignment. @@ -543,6 +556,7 @@ public: Token::Value getOperator() const { return m_operator; } bool isPrefixOperation() const { return m_isPrefix; } + Expression& getSubExpression() const { return *m_subExpression; } private: Token::Value m_operator; @@ -635,6 +649,8 @@ public: virtual void accept(ASTVisitor& _visitor) override; virtual void checkTypeRequirements() override; + Expression& getBaseExpression() const { return *m_base; } + Expression& getIndexExpression() const { return *m_index; } private: ASTPointer m_base; ASTPointer m_index; diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index da28ba8a3..eed886783 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -225,7 +225,7 @@ bool Compiler::visit(IfStatement& _ifStatement) eth::AssemblyItem trueTag = m_context.appendConditionalJump(); if (_ifStatement.getFalseStatement()) _ifStatement.getFalseStatement()->accept(*this); - eth::AssemblyItem endTag = m_context.appendJump(); + eth::AssemblyItem endTag = m_context.appendJumpToNew(); m_context << trueTag; _ifStatement.getTrueStatement().accept(*this); m_context << endTag; diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index 562c29321..e624222dd 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -65,7 +65,9 @@ public: /// Appends a JUMPI instruction to @a _tag CompilerContext& appendConditionalJumpTo(eth::AssemblyItem const& _tag) { m_asm.appendJumpI(_tag); return *this; } /// Appends a JUMP to a new tag and @returns the tag - eth::AssemblyItem appendJump() { return m_asm.appendJump().tag(); } + eth::AssemblyItem appendJumpToNew() { return m_asm.appendJump().tag(); } + /// Appends a JUMP to a tag already on the stack + CompilerContext& appendJump() { return *this << eth::Instruction::JUMP; } /// Appends a JUMP to a specific tag CompilerContext& appendJumpTo(eth::AssemblyItem const& _tag) { m_asm.appendJump(_tag); return *this; } /// Appends pushing of a new tag and @returns the new tag. diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 05bbb0916..d80b42b35 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -50,14 +51,19 @@ bool ExpressionCompiler::visit(Assignment& _assignment) appendTypeConversion(*_assignment.getRightHandSide().getType(), *_assignment.getType()); m_currentLValue.reset(); _assignment.getLeftHandSide().accept(*this); + if (asserts(m_currentLValue.isValid())) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("LValue not retrieved.")); Token::Value op = _assignment.getAssignmentOperator(); if (op != Token::ASSIGN) // compound assignment + { + if (m_currentLValue.storesReferenceOnStack()) + m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; + m_currentLValue.retrieveValue(_assignment, true); appendOrdinaryBinaryOperatorCode(Token::AssignmentToBinaryOp(op), *_assignment.getType()); - else - m_context << eth::Instruction::POP; + } + m_currentLValue.storeValue(_assignment); - storeInLValue(_assignment); return false; } @@ -76,23 +82,37 @@ void ExpressionCompiler::endVisit(UnaryOperation& _unaryOperation) m_context << eth::Instruction::NOT; break; case Token::DELETE: // delete - { - // a -> a xor a (= 0). // @todo semantics change for complex types - m_context << eth::Instruction::DUP1 << eth::Instruction::XOR; - storeInLValue(_unaryOperation); + if (asserts(m_currentLValue.isValid())) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("LValue not retrieved.")); + + m_context << u256(0); + if (m_currentLValue.storesReferenceOnStack()) + m_context << eth::Instruction::SWAP1; + m_currentLValue.storeValue(_unaryOperation); break; - } case Token::INC: // ++ (pre- or postfix) case Token::DEC: // -- (pre- or postfix) + if (asserts(m_currentLValue.isValid())) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("LValue not retrieved.")); + m_currentLValue.retrieveValue(_unaryOperation); if (!_unaryOperation.isPrefixOperation()) - m_context << eth::Instruction::DUP1; + { + if (m_currentLValue.storesReferenceOnStack()) + m_context << eth::Instruction::SWAP1 << eth::Instruction::DUP2; + else + m_context << eth::Instruction::DUP1; + } m_context << u256(1); if (_unaryOperation.getOperator() == Token::INC) m_context << eth::Instruction::ADD; else m_context << eth::Instruction::SWAP1 << eth::Instruction::SUB; // @todo avoid the swap - storeInLValue(_unaryOperation, !_unaryOperation.isPrefixOperation()); + // Stack for prefix: [ref] (*ref)+-1 + // Stack for postfix: *ref [ref] (*ref)+-1 + if (m_currentLValue.storesReferenceOnStack()) + m_context << eth::Instruction::SWAP1; + m_currentLValue.storeValue(_unaryOperation, !_unaryOperation.isPrefixOperation()); break; case Token::ADD: // + // unary add, so basically no-op @@ -151,12 +171,6 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) { // Calling convention: Caller pushes return address and arguments // Callee removes them and pushes return values - m_currentLValue.reset(); - _functionCall.getExpression().accept(*this); - if (asserts(m_currentLValue.isInCode())) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Code reference expected.")); - eth::AssemblyItem functionTag(eth::PushTag, m_currentLValue.location); - FunctionDefinition const& function = dynamic_cast(*_functionCall.getExpression().getType()).getFunction(); eth::AssemblyItem returnLabel = m_context.pushNewTag(); @@ -168,8 +182,12 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) arguments[i]->accept(*this); appendTypeConversion(*arguments[i]->getType(), *function.getParameters()[i]->getType()); } + m_currentLValue.reset(); + _functionCall.getExpression().accept(*this); + if (asserts(m_currentLValue.isInCode())) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Code reference expected.")); - m_context.appendJumpTo(functionTag); + m_context.appendJump(); m_context << returnLabel; // callee adds return parameters, but removes arguments and return label @@ -185,30 +203,33 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) void ExpressionCompiler::endVisit(MemberAccess&) { - + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access not yet implemented.")); } -void ExpressionCompiler::endVisit(IndexAccess&) +bool ExpressionCompiler::visit(IndexAccess& _indexAccess) { + m_currentLValue.reset(); + _indexAccess.getBaseExpression().accept(*this); + if (asserts(m_currentLValue.isInStorage())) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Index access to a non-storage value.")); + _indexAccess.getIndexExpression().accept(*this); + appendTypeConversion(*_indexAccess.getIndexExpression().getType(), + *dynamic_cast(*_indexAccess.getBaseExpression().getType()).getKeyType(), + true); + // @todo move this once we actually use memory + m_context << u256(32) << eth::Instruction::MSTORE << u256(0) << eth::Instruction::MSTORE; + m_context << u256(64) << u256(0) << eth::Instruction::SHA3; + + m_currentLValue = LValue(m_context, LValue::STORAGE); + m_currentLValue.retrieveValueIfLValueNotRequested(_indexAccess); + return false; } void ExpressionCompiler::endVisit(Identifier& _identifier) { - Declaration const* declaration = _identifier.getReferencedDeclaration(); - if (m_context.isLocalVariable(declaration)) - m_currentLValue = LValueLocation(LValueLocation::STACK, - m_context.getBaseStackOffsetOfVariable(*declaration)); - else if (m_context.isStateVariable(declaration)) - m_currentLValue = LValueLocation(LValueLocation::STORAGE, - m_context.getStorageLocationOfVariable(*declaration)); - else if (m_context.isFunctionDefinition(declaration)) - m_currentLValue = LValueLocation(LValueLocation::CODE, - m_context.getFunctionEntryLabel(dynamic_cast(*declaration)).data()); - else - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not supported or identifier not found.")); - - retrieveLValueValue(_identifier); + m_currentLValue.fromDeclaration(_identifier, *_identifier.getReferencedDeclaration()); + m_currentLValue.retrieveValueIfLValueNotRequested(_identifier); } void ExpressionCompiler::endVisit(Literal& _literal) @@ -371,66 +392,104 @@ void ExpressionCompiler::appendHighBitsCleanup(IntegerType const& _typeOnStack) m_context << ((u256(1) << _typeOnStack.getNumBits()) - 1) << eth::Instruction::AND; } -void ExpressionCompiler::retrieveLValueValue(Expression const& _expression) +void ExpressionCompiler::LValue::retrieveValue(Expression const& _expression, bool _remove) const { - switch (m_currentLValue.locationType) + switch (m_type) { - case LValueLocation::CODE: - // not stored on the stack + case CODE: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Tried to retrieve value of a function.")); break; - case LValueLocation::STACK: + case STACK: { - unsigned stackPos = m_context.baseToCurrentStackOffset(unsigned(m_currentLValue.location)); + unsigned stackPos = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)); if (stackPos >= 15) //@todo correct this by fetching earlier or moving to memory BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation()) << errinfo_comment("Stack too deep.")); - m_context << eth::dupInstruction(stackPos + 1); + *m_context << eth::dupInstruction(stackPos + 1); break; } - case LValueLocation::STORAGE: - m_context << m_currentLValue.location << eth::Instruction::SLOAD; + case STORAGE: + if (!_remove) + *m_context << eth::Instruction::DUP1; + *m_context << eth::Instruction::SLOAD; break; - case LValueLocation::MEMORY: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Location type not yet implemented.")); + case MEMORY: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Location type not yet implemented.")); break; default: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unsupported location type.")); + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Unsupported location type.")); break; } } -void ExpressionCompiler::storeInLValue(Expression const& _expression, bool _move) +void ExpressionCompiler::LValue::storeValue(Expression const& _expression, bool _move) const { - switch (m_currentLValue.locationType) + switch (m_type) { - case LValueLocation::STACK: + case STACK: { - unsigned stackPos = m_context.baseToCurrentStackOffset(unsigned(m_currentLValue.location)); + unsigned stackPos = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)); if (stackPos > 16) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_expression.getLocation()) << errinfo_comment("Stack too deep.")); else if (stackPos > 0) - m_context << eth::swapInstruction(stackPos) << eth::Instruction::POP; + *m_context << eth::swapInstruction(stackPos) << eth::Instruction::POP; if (!_move) - retrieveLValueValue(_expression); + retrieveValue(_expression); break; } - case LValueLocation::STORAGE: + case LValue::STORAGE: if (!_move) - m_context << eth::Instruction::DUP1; - m_context << m_currentLValue.location << eth::Instruction::SSTORE; + *m_context << eth::Instruction::DUP2 << eth::Instruction::SWAP1; + *m_context << eth::Instruction::SSTORE; break; - case LValueLocation::CODE: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Location type does not support assignment.")); + case LValue::CODE: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Location type does not support assignment.")); break; - case LValueLocation::MEMORY: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Location type not yet implemented.")); + case LValue::MEMORY: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Location type not yet implemented.")); break; default: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unsupported location type.")); + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Unsupported location type.")); break; } } +void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(const Expression& _expression) +{ + if (!_expression.lvalueRequested()) + { + retrieveValue(_expression, true); + reset(); + } +} + +void ExpressionCompiler::LValue::fromDeclaration( Expression const& _expression, Declaration const& _declaration) +{ + if (m_context->isLocalVariable(&_declaration)) + { + m_type = STACK; + m_baseStackOffset = m_context->getBaseStackOffsetOfVariable(_declaration); + } + else if (m_context->isStateVariable(&_declaration)) + { + m_type = STORAGE; + *m_context << m_context->getStorageLocationOfVariable(_declaration); + } + else if (m_context->isFunctionDefinition(&_declaration)) + { + m_type = CODE; + *m_context << m_context->getFunctionEntryLabel(dynamic_cast(_declaration)).pushTag(); + } + else + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_sourceLocation(_expression.getLocation()) + << errinfo_comment("Identifier type not supported or identifier not found.")); +} + } } diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index bd5a9f866..f52da29ec 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -20,6 +20,7 @@ * Solidity AST to EVM bytecode compiler for expressions. */ +#include #include #include @@ -49,14 +50,15 @@ public: static void appendTypeConversion(CompilerContext& _context, Type const& _typeOnStack, Type const& _targetType); private: - ExpressionCompiler(CompilerContext& _compilerContext): m_context(_compilerContext) {} + ExpressionCompiler(CompilerContext& _compilerContext): + m_context(_compilerContext), m_currentLValue(m_context) {} virtual bool visit(Assignment& _assignment) override; virtual void endVisit(UnaryOperation& _unaryOperation) override; virtual bool visit(BinaryOperation& _binaryOperation) override; virtual bool visit(FunctionCall& _functionCall) override; virtual void endVisit(MemberAccess& _memberAccess) override; - virtual void endVisit(IndexAccess& _indexAccess) override; + virtual bool visit(IndexAccess& _indexAccess) override; virtual void endVisit(Identifier& _identifier) override; virtual void endVisit(Literal& _literal) override; @@ -79,37 +81,58 @@ private: //// Appends code that cleans higher-order bits for integer types. void appendHighBitsCleanup(IntegerType const& _typeOnStack); - /// Copies the value of the current lvalue to the top of the stack. - void retrieveLValueValue(Expression const& _expression); - /// Stores the value on top of the stack in the current lvalue. Removes it from the stack if - /// @a _move is true. - void storeInLValue(Expression const& _expression, bool _move = false); - /** - * Location of an lvalue, either in code (for a function) on the stack, in the storage or memory. + * Helper class to store and retrieve lvalues to and from various locations. + * All types except STACK store a reference in a slot on the stack, STACK just stores the + * base stack offset of the variable in @a m_baseStackOffset. */ - struct LValueLocation + class LValue { - enum LocationType { INVALID, CODE, STACK, MEMORY, STORAGE }; - - LValueLocation() { reset(); } - LValueLocation(LocationType _type, u256 const& _location): locationType(_type), location(_location) {} - void reset() { locationType = INVALID; location = 0; } - bool isValid() const { return locationType != INVALID; } - bool isInCode() const { return locationType == CODE; } - bool isInOnStack() const { return locationType == STACK; } - bool isInMemory() const { return locationType == MEMORY; } - bool isInStorage() const { return locationType == STORAGE; } - - LocationType locationType; - /// Depending on the type, this is the id of a tag (code), the base offset of a stack - /// variable (@see CompilerContext::getBaseStackOffsetOfVariable) or the offset in - /// storage or memory. - u256 location; + public: + enum LValueType { NONE, CODE, STACK, MEMORY, STORAGE }; + + explicit LValue(CompilerContext& _compilerContext): m_context(&_compilerContext) { reset(); } + LValue(CompilerContext& _compilerContext, LValueType _type, unsigned _baseStackOffset = 0): + m_context(&_compilerContext), m_type(_type), m_baseStackOffset(_baseStackOffset) {} + + /// Set type according to the declaration and retrieve the reference. + /// @a _expression is the current expression, used for error reporting. + void fromDeclaration(Expression const& _expression, Declaration const& _declaration); + void reset() { m_type = NONE; m_baseStackOffset = 0; } + + bool isValid() const { return m_type != NONE; } + bool isInCode() const { return m_type == CODE; } + bool isInOnStack() const { return m_type == STACK; } + bool isInMemory() const { return m_type == MEMORY; } + bool isInStorage() const { return m_type == STORAGE; } + + /// @returns true if this lvalue reference type occupies a slot on the stack. + bool storesReferenceOnStack() const { return m_type == STORAGE || m_type == MEMORY || m_type == CODE; } + + /// Copies the value of the current lvalue to the top of the stack and, if @a _remove is true, + /// also removes the reference from the stack (note that is does not reset the type to @a NONE). + /// @a _expression is the current expression, used for error reporting. + void retrieveValue(Expression const& _expression, bool _remove = false) const; + /// Stores a value (from the stack directly beneath the reference, which is assumed to + /// be on the top of the stack, if any) in the lvalue and removes the reference. + /// Also removes the stored value from the stack if @a _move is + /// true. @a _expression is the current expression, used for error reporting. + void storeValue(Expression const& _expression, bool _move = false) const; + + /// Convenience function to convert the stored reference to a value and reset type to NONE if + /// the reference was not requested by @a _expression. + void retrieveValueIfLValueNotRequested(Expression const& _expression); + + private: + CompilerContext* m_context; + LValueType m_type; + /// If m_type is STACK, this is base stack offset (@see + /// CompilerContext::getBaseStackOffsetOfVariable) of a local variable. + unsigned m_baseStackOffset; }; - LValueLocation m_currentLValue; CompilerContext& m_context; + LValue m_currentLValue; }; diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 0578e5996..4a15fe794 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -52,7 +52,7 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) for (ASTPointer const& function: _contract.getDefinedFunctions()) { m_currentScope = &m_scopes[function.get()]; - function->getBody().checkTypeRequirements(); + function->checkTypeRequirements(); } m_currentScope = &m_scopes[nullptr]; } @@ -186,9 +186,8 @@ bool ReferencesResolver::visit(Return& _return) return true; } -bool ReferencesResolver::visit(Mapping&) +bool ReferencesResolver::visit(Mapping& _mapping) { - // @todo return true; } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 3a4112c45..e37ed3e5b 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -63,9 +63,11 @@ shared_ptr Type::fromUserDefinedTypeName(UserDefinedTypeName const& _typeN return make_shared(*_typeName.getReferencedStruct()); } -shared_ptr Type::fromMapping(Mapping const&) +shared_ptr Type::fromMapping(Mapping const& _typeName) { - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Mapping types not yet implemented.")); + shared_ptr keyType = _typeName.getKeyType().toType(); + shared_ptr valueType = _typeName.getValueType().toType(); + return make_shared(keyType, valueType); } shared_ptr Type::forLiteral(Literal const& _literal) diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 607ee3a6f..b9bb74dbb 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -35,7 +35,7 @@ namespace dev namespace solidity { -// @todo realMxN, string, mapping +// @todo realMxN, string /** * Abstract base class that forms the root of the type hierarchy. @@ -78,6 +78,8 @@ public: /// @returns number of bytes required to hold this value in storage. /// For dynamically "allocated" types, it returns the size of the statically allocated head, virtual u256 getStorageSize() const { return 1; } + /// Returns false if the type cannot live outside the storage, i.e. if it includes some mapping. + virtual bool canLiveOutsideStorage() const { return true; } virtual std::string toString() const = 0; virtual u256 literalValue(Literal const&) const @@ -182,6 +184,8 @@ public: virtual bool operator==(Type const& _other) const override; virtual u256 getStorageSize() const; + //@todo it can, if its members can + virtual bool canLiveOutsideStorage() const { return false; } virtual std::string toString() const override { return "struct{...}"; } private: @@ -202,6 +206,7 @@ public: virtual bool operator==(Type const& _other) const override; virtual std::string toString() const override { return "function(...)returns(...)"; } virtual u256 getStorageSize() const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable function type requested.")); } + virtual bool canLiveOutsideStorage() const { return false; } private: FunctionDefinition const& m_function; @@ -214,11 +219,15 @@ class MappingType: public Type { public: virtual Category getCategory() const override { return Category::MAPPING; } - MappingType() {} + MappingType(std::shared_ptr _keyType, std::shared_ptr _valueType): + m_keyType(_keyType), m_valueType(_valueType) {} virtual bool operator==(Type const& _other) const override; virtual std::string toString() const override { return "mapping(...=>...)"; } + virtual bool canLiveOutsideStorage() const { return false; } + std::shared_ptr getKeyType() const { return m_keyType; } + std::shared_ptr getValueType() const { return m_valueType; } private: std::shared_ptr m_keyType; std::shared_ptr m_valueType; @@ -236,6 +245,7 @@ public: virtual std::string toString() const override { return "void"; } virtual u256 getStorageSize() const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable void type requested.")); } + virtual bool canLiveOutsideStorage() const { return false; } }; /** @@ -252,6 +262,7 @@ public: virtual bool operator==(Type const& _other) const override; virtual u256 getStorageSize() const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable type type requested.")); } + virtual bool canLiveOutsideStorage() const { return false; } virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; } private: diff --git a/test/solidityCompiler.cpp b/test/solidityCompiler.cpp index 054ad3297..e0635b6ae 100644 --- a/test/solidityCompiler.cpp +++ b/test/solidityCompiler.cpp @@ -128,8 +128,6 @@ BOOST_AUTO_TEST_CASE(different_argument_numbers) byte(Instruction::JUMP), byte(Instruction::JUMPDEST), // stack here: ret e h f(1,2,3) - byte(Instruction::DUP2), - byte(Instruction::POP), byte(Instruction::SWAP1), // stack here: ret e f(1,2,3) h byte(Instruction::POP), diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index d905646cb..5e6631df6 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -32,6 +32,9 @@ using namespace std; namespace dev { +/// Provider another overload for toBigEndian to encode arguments and return values. +inline bytes toBigEndian(bool _value) { return bytes({byte(_value)}); } + namespace solidity { namespace test @@ -137,6 +140,7 @@ private: m_output = executive.out().toVector(); } +protected: Address m_contractAddress; eth::State m_state; u256 const m_gasPrice = 100 * eth::szabo; @@ -496,6 +500,169 @@ BOOST_AUTO_TEST_CASE(state_smoke_test) BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3))); } +BOOST_AUTO_TEST_CASE(simple_mapping) +{ + char const* sourceCode = "contract test {\n" + " mapping(uint8 => uint8) table;\n" + " function get(uint8 k) returns (uint8 v) {\n" + " return table[k];\n" + " }\n" + " function set(uint8 k, uint8 v) {\n" + " table[k] = v;\n" + " }\n" + "}"; + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0x00})); + BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0x00})); + BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); + callContractFunction(1, bytes({0x01, 0xa1})); + BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0x00})); + BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0xa1})); + BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); + callContractFunction(1, bytes({0x00, 0xef})); + BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0xef})); + BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0xa1})); + BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); + callContractFunction(1, bytes({0x01, 0x05})); + BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0xef})); + BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0x05})); + BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); +} + +BOOST_AUTO_TEST_CASE(mapping_state) +{ + char const* sourceCode = "contract Ballot {\n" + " mapping(address => bool) canVote;\n" + " mapping(address => uint) voteCount;\n" + " mapping(address => bool) voted;\n" + " function getVoteCount(address addr) returns (uint retVoteCount) {\n" + " return voteCount[addr];\n" + " }\n" + " function grantVoteRight(address addr) {\n" + " canVote[addr] = true;\n" + " }\n" + " function vote(address voter, address vote) returns (bool success) {\n" + " if (!canVote[voter] || voted[voter]) return false;\n" + " voted[voter] = true;\n" + " voteCount[vote] = voteCount[vote] + 1;\n" + " return true;\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + class Ballot + { + public: + u256 getVoteCount(u160 _address) { return m_voteCount[_address]; } + void grantVoteRight(u160 _address) { m_canVote[_address] = true; } + bool vote(u160 _voter, u160 _vote) + { + if (!m_canVote[_voter] || m_voted[_voter]) return false; + m_voted[_voter] = true; + m_voteCount[_vote]++; + return true; + } + private: + map m_canVote; + map m_voteCount; + map m_voted; + } ballot; + + auto getVoteCount = bind(&Ballot::getVoteCount, &ballot, _1); + auto grantVoteRight = bind(&Ballot::grantVoteRight, &ballot, _1); + auto vote = bind(&Ballot::vote, &ballot, _1, _2); + testSolidityAgainstCpp(0, getVoteCount, u160(0)); + testSolidityAgainstCpp(0, getVoteCount, u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(2)); + // voting without vote right shourd be rejected + testSolidityAgainstCpp(2, vote, u160(0), u160(2)); + testSolidityAgainstCpp(0, getVoteCount, u160(0)); + testSolidityAgainstCpp(0, getVoteCount, u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(2)); + // grant vote rights + testSolidityAgainstCpp(1, grantVoteRight, u160(0)); + testSolidityAgainstCpp(1, grantVoteRight, u160(1)); + // vote, should increase 2's vote count + testSolidityAgainstCpp(2, vote, u160(0), u160(2)); + testSolidityAgainstCpp(0, getVoteCount, u160(0)); + testSolidityAgainstCpp(0, getVoteCount, u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(2)); + // vote again, should be rejected + testSolidityAgainstCpp(2, vote, u160(0), u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(0)); + testSolidityAgainstCpp(0, getVoteCount, u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(2)); + // vote without right to vote + testSolidityAgainstCpp(2, vote, u160(2), u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(0)); + testSolidityAgainstCpp(0, getVoteCount, u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(2)); + // grant vote right and now vote again + testSolidityAgainstCpp(1, grantVoteRight, u160(2)); + testSolidityAgainstCpp(2, vote, u160(2), u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(0)); + testSolidityAgainstCpp(0, getVoteCount, u160(1)); + testSolidityAgainstCpp(0, getVoteCount, u160(2)); +} + +BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) +{ + char const* sourceCode = "contract test {\n" + " uint value;\n" + " mapping(uint => uint) table;\n" + " function f(uint x) returns (uint y) {\n" + " value = x;\n" + " if (x > 0) table[++value] = 8;\n" + " if (x > 1) value--;\n" + " if (x > 2) table[value]++;\n" + " return --table[value++];\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + + u256 value = 0; + map table; + auto f = [&](u256 const& _x) -> u256 + { + value = _x; + if (_x > 0) + table[++value] = 8; + if (_x > 1) + value --; + if (_x > 2) + table[value]++; + return --table[value++]; + }; + testSolidityAgainstCppOnRange(0, f, 0, 5); +} + +BOOST_AUTO_TEST_CASE(multi_level_mapping) +{ + char const* sourceCode = "contract test {\n" + " mapping(uint => mapping(uint => uint)) table;\n" + " function f(uint x, uint y, uint z) returns (uint w) {\n" + " if (z == 0) return table[x][y];\n" + " else return table[x][y] = z;\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + + map> table; + auto f = [&](u256 const& _x, u256 const& _y, u256 const& _z) -> u256 + { + if (_z == 0) return table[_x][_y]; + else return table[_x][_y] = _z; + }; + testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0)); + testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0)); + testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(9)); + testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0)); + testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0)); + testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(7)); + testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0)); + testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0)); +} + BOOST_AUTO_TEST_SUITE_END() } From bbc3a1b37e72d9d27a70c5d82eda219836017d3d Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 13 Nov 2014 01:12:57 +0100 Subject: [PATCH 18/44] Struct types. --- libsolidity/AST.cpp | 13 +++++- libsolidity/AST.h | 5 ++- libsolidity/ExpressionCompiler.cpp | 17 ++++++-- libsolidity/NameAndTypeResolver.cpp | 29 ++++++++++++-- libsolidity/NameAndTypeResolver.h | 11 ++++-- libsolidity/Types.cpp | 55 +++++++++++++++++++++++++- libsolidity/Types.h | 16 +++++--- test/solidityEndToEndTest.cpp | 37 +++++++++++++++++ test/solidityNameAndTypeResolution.cpp | 38 ++++++++++++++++++ 9 files changed, 201 insertions(+), 20 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index d5f856dfc..e8bdecf31 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -460,8 +460,17 @@ bool FunctionCall::isTypeConversion() const void MemberAccess::checkTypeRequirements() { - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access not yet implemented.")); - // m_type = ; + m_expression->checkTypeRequirements(); + m_expression->requireLValue(); + if (m_expression->getType()->getCategory() != Type::Category::STRUCT) + BOOST_THROW_EXCEPTION(createTypeError("Member access to a non-struct (is " + + m_expression->getType()->toString() + ")")); + StructType const& type = dynamic_cast(*m_expression->getType()); + unsigned memberIndex = type.memberNameToIndex(*m_memberName); + if (memberIndex >= type.getMemberCount()) + BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found in " + type.toString())); + m_type = type.getMemberByIndex(memberIndex).getType(); + m_isLvalue = true; } void IndexAccess::checkTypeRequirements() diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 31ca56f76..80c7dd198 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -146,7 +146,7 @@ private: /** * Parameter list, used as function parameter list and return list. * None of the parameters is allowed to contain mappings (not even recursively - * inside structs), but (@todo) this is not yet enforced. + * inside structs). */ class ParameterList: public ASTNode { @@ -368,7 +368,6 @@ private: /** * Statement in which a break statement is legal. - * @todo actually check this requirement. */ class BreakableStatement: public Statement { @@ -629,6 +628,7 @@ public: ASTPointer const& _memberName): Expression(_location), m_expression(_expression), m_memberName(_memberName) {} virtual void accept(ASTVisitor& _visitor) override; + Expression& getExpression() const { return *m_expression; } ASTString const& getMemberName() const { return *m_memberName; } virtual void checkTypeRequirements() override; @@ -651,6 +651,7 @@ public: Expression& getBaseExpression() const { return *m_base; } Expression& getIndexExpression() const { return *m_index; } + private: ASTPointer m_base; ASTPointer m_index; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index d80b42b35..f37ce39ce 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -49,7 +49,6 @@ bool ExpressionCompiler::visit(Assignment& _assignment) { _assignment.getRightHandSide().accept(*this); appendTypeConversion(*_assignment.getRightHandSide().getType(), *_assignment.getType()); - m_currentLValue.reset(); _assignment.getLeftHandSide().accept(*this); if (asserts(m_currentLValue.isValid())) BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("LValue not retrieved.")); @@ -63,6 +62,7 @@ bool ExpressionCompiler::visit(Assignment& _assignment) appendOrdinaryBinaryOperatorCode(Token::AssignmentToBinaryOp(op), *_assignment.getType()); } m_currentLValue.storeValue(_assignment); + m_currentLValue.reset(); return false; } @@ -90,6 +90,7 @@ void ExpressionCompiler::endVisit(UnaryOperation& _unaryOperation) if (m_currentLValue.storesReferenceOnStack()) m_context << eth::Instruction::SWAP1; m_currentLValue.storeValue(_unaryOperation); + m_currentLValue.reset(); break; case Token::INC: // ++ (pre- or postfix) case Token::DEC: // -- (pre- or postfix) @@ -113,6 +114,7 @@ void ExpressionCompiler::endVisit(UnaryOperation& _unaryOperation) if (m_currentLValue.storesReferenceOnStack()) m_context << eth::Instruction::SWAP1; m_currentLValue.storeValue(_unaryOperation, !_unaryOperation.isPrefixOperation()); + m_currentLValue.reset(); break; case Token::ADD: // + // unary add, so basically no-op @@ -182,10 +184,10 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) arguments[i]->accept(*this); appendTypeConversion(*arguments[i]->getType(), *function.getParameters()[i]->getType()); } - m_currentLValue.reset(); _functionCall.getExpression().accept(*this); if (asserts(m_currentLValue.isInCode())) BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Code reference expected.")); + m_currentLValue.reset(); m_context.appendJump(); m_context << returnLabel; @@ -201,9 +203,16 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall) return false; } -void ExpressionCompiler::endVisit(MemberAccess&) +void ExpressionCompiler::endVisit(MemberAccess& _memberAccess) { - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access not yet implemented.")); + if (asserts(m_currentLValue.isInStorage())) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to a non-storage value.")); + StructType const& type = dynamic_cast(*_memberAccess.getExpression().getType()); + unsigned memberIndex = type.memberNameToIndex(_memberAccess.getMemberName()); + if (asserts(memberIndex <= type.getMemberCount())) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member not found in struct during compilation.")); + m_context << type.getStorageOffsetOfMember(memberIndex) << eth::Instruction::ADD; + m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess); } bool ExpressionCompiler::visit(IndexAccess& _indexAccess) diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 4a15fe794..5bc406855 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -37,7 +37,10 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) reset(); DeclarationRegistrationHelper registrar(m_scopes, _contract); m_currentScope = &m_scopes[&_contract]; - //@todo structs + for (ASTPointer const& structDef: _contract.getDefinedStructs()) + ReferencesResolver resolver(*structDef, *this, nullptr); + for (ASTPointer const& structDef: _contract.getDefinedStructs()) + checkForRecursion(*structDef); for (ASTPointer const& variable: _contract.getStateVariables()) ReferencesResolver resolver(*variable, *this, nullptr); for (ASTPointer const& function: _contract.getDefinedFunctions()) @@ -70,6 +73,24 @@ Declaration* NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name return m_currentScope->resolveName(_name, _recursive); } +void NameAndTypeResolver::checkForRecursion(StructDefinition const& _struct) +{ + set definitionsSeen; + vector queue = {&_struct}; + while (!queue.empty()) + { + StructDefinition const* def = queue.back(); + queue.pop_back(); + if (definitionsSeen.count(def)) + BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation()) + << errinfo_comment("Recursive struct definition.")); + definitionsSeen.insert(def); + for (ASTPointer const& member: def->getMembers()) + if (member->getType()->getCategory() == Type::Category::STRUCT) + queue.push_back(dynamic_cast(*member->getTypeName()).getReferencedStruct()); + } +} + void NameAndTypeResolver::reset() { m_scopes.clear(); @@ -163,8 +184,8 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio } ReferencesResolver::ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver, - ParameterList* _returnParameters): - m_resolver(_resolver), m_returnParameters(_returnParameters) + ParameterList* _returnParameters, bool _allowLazyTypes): + m_resolver(_resolver), m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes) { _root.accept(*this); } @@ -175,6 +196,8 @@ void ReferencesResolver::endVisit(VariableDeclaration& _variable) // or mapping if (_variable.getTypeName()) _variable.setType(_variable.getTypeName()->toType()); + else if (!m_allowLazyTypes) + BOOST_THROW_EXCEPTION(_variable.createTypeError("Explicit type needed.")); // otherwise we have a "var"-declaration whose type is resolved by the first assignment } diff --git a/libsolidity/NameAndTypeResolver.h b/libsolidity/NameAndTypeResolver.h index 909024942..d335807e5 100644 --- a/libsolidity/NameAndTypeResolver.h +++ b/libsolidity/NameAndTypeResolver.h @@ -55,10 +55,13 @@ public: Declaration* getNameFromCurrentScope(ASTString const& _name, bool _recursive = true); private: + /// Throws if @a _struct contains a recursive loop. Note that recursion via mappings is fine. + void checkForRecursion(StructDefinition const& _struct); void reset(); - /// Maps nodes declaring a scope to scopes, i.e. ContractDefinition, FunctionDeclaration and - /// StructDefinition (@todo not yet implemented), where nullptr denotes the global scope. + /// Maps nodes declaring a scope to scopes, i.e. ContractDefinition and FunctionDeclaration, + /// where nullptr denotes the global scope. Note that structs are not scope since they do + /// not contain code. std::map m_scopes; Scope* m_currentScope; @@ -99,7 +102,8 @@ private: class ReferencesResolver: private ASTVisitor { public: - ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver, ParameterList* _returnParameters); + ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver, + ParameterList* _returnParameters, bool _allowLazyTypes = true); private: virtual void endVisit(VariableDeclaration& _variable) override; @@ -110,6 +114,7 @@ private: NameAndTypeResolver& m_resolver; ParameterList* m_returnParameters; + bool m_allowLazyTypes; }; } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index e37ed3e5b..63bad5d61 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -80,7 +80,7 @@ shared_ptr Type::forLiteral(Literal const& _literal) case Token::NUMBER: return IntegerType::smallestTypeForLiteral(_literal.getValue()); case Token::STRING_LITERAL: - return shared_ptr(); // @todo + return shared_ptr(); // @todo add string literals default: return shared_ptr(); } @@ -231,6 +231,48 @@ u256 StructType::getStorageSize() const return max(1, size); } +bool StructType::canLiveOutsideStorage() const +{ + for (unsigned i = 0; i < getMemberCount(); ++i) + if (!getMemberByIndex(i).getType()->canLiveOutsideStorage()) + return false; + return true; +} + +string StructType::toString() const +{ + return string("struct ") + m_struct.getName(); +} + +unsigned StructType::getMemberCount() const +{ + return m_struct.getMembers().size(); +} + +unsigned StructType::memberNameToIndex(string const& _name) const +{ + vector> const& members = m_struct.getMembers(); + for (unsigned index = 0; index < members.size(); ++index) + if (members[index]->getName() == _name) + return index; + return unsigned(-1); +} + +VariableDeclaration const& StructType::getMemberByIndex(unsigned _index) const +{ + return *m_struct.getMembers()[_index]; +} + +u256 StructType::getStorageOffsetOfMember(unsigned _index) const +{ + //@todo cache member offset? + u256 offset; + vector> const& members = m_struct.getMembers(); + for (unsigned index = 0; index < _index; ++index) + offset += getMemberByIndex(index).getType()->getStorageSize(); + return offset; +} + bool FunctionType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) @@ -239,6 +281,12 @@ bool FunctionType::operator==(Type const& _other) const return other.m_function == m_function; } +string FunctionType::toString() const +{ + //@todo nice string for function types + return "function(...)returns(...)"; +} + bool MappingType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) @@ -247,6 +295,11 @@ bool MappingType::operator==(Type const& _other) const return *other.m_keyType == *m_keyType && *other.m_valueType == *m_valueType; } +string MappingType::toString() const +{ + return "mapping(" + getKeyType()->toString() + " => " + getValueType()->toString() + ")"; +} + bool TypeType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) diff --git a/libsolidity/Types.h b/libsolidity/Types.h index b9bb74dbb..726470172 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -184,9 +184,14 @@ public: virtual bool operator==(Type const& _other) const override; virtual u256 getStorageSize() const; - //@todo it can, if its members can - virtual bool canLiveOutsideStorage() const { return false; } - virtual std::string toString() const override { return "struct{...}"; } + virtual bool canLiveOutsideStorage() const; + virtual std::string toString() const override; + + unsigned getMemberCount() const; + /// Returns the index of the member with name @a _name or unsigned(-1) if it does not exist. + unsigned memberNameToIndex(std::string const& _name) const; + VariableDeclaration const& getMemberByIndex(unsigned _index) const; + u256 getStorageOffsetOfMember(unsigned _index) const; private: StructDefinition const& m_struct; @@ -204,7 +209,7 @@ public: FunctionDefinition const& getFunction() const { return m_function; } virtual bool operator==(Type const& _other) const override; - virtual std::string toString() const override { return "function(...)returns(...)"; } + virtual std::string toString() const override; virtual u256 getStorageSize() const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable function type requested.")); } virtual bool canLiveOutsideStorage() const { return false; } @@ -223,11 +228,12 @@ public: m_keyType(_keyType), m_valueType(_valueType) {} virtual bool operator==(Type const& _other) const override; - virtual std::string toString() const override { return "mapping(...=>...)"; } + virtual std::string toString() const override; virtual bool canLiveOutsideStorage() const { return false; } std::shared_ptr getKeyType() const { return m_keyType; } std::shared_ptr getValueType() const { return m_valueType; } + private: std::shared_ptr m_keyType; std::shared_ptr m_valueType; diff --git a/test/solidityEndToEndTest.cpp b/test/solidityEndToEndTest.cpp index 5e6631df6..617cbabc9 100644 --- a/test/solidityEndToEndTest.cpp +++ b/test/solidityEndToEndTest.cpp @@ -663,6 +663,43 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0)); } +BOOST_AUTO_TEST_CASE(structs) +{ + char const* sourceCode = "contract test {\n" + " struct s1 {\n" + " uint8 x;\n" + " bool y;\n" + " }\n" + " struct s2 {\n" + " uint32 z;\n" + " s1 s1data;\n" + " mapping(uint8 => s2) recursive;\n" + " }\n" + " s2 data;\n" + " function check() returns (bool ok) {\n" + " return data.z == 1 && data.s1data.x == 2 && \n" + " data.s1data.y == true && \n" + " data.recursive[3].recursive[4].z == 5 && \n" + " data.recursive[4].recursive[3].z == 6 && \n" + " data.recursive[0].s1data.y == false && \n" + " data.recursive[4].z == 9;\n" + " }\n" + " function set() {\n" + " data.z = 1;\n" + " data.s1data.x = 2;\n" + " data.s1data.y = true;\n" + " data.recursive[3].recursive[4].z = 5;\n" + " data.recursive[4].recursive[3].z = 6;\n" + " data.recursive[0].s1data.y = false;\n" + " data.recursive[4].z = 9;\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction(0) == bytes({0x00})); + BOOST_CHECK(callContractFunction(1) == bytes()); + BOOST_CHECK(callContractFunction(0) == bytes({0x01})); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/solidityNameAndTypeResolution.cpp b/test/solidityNameAndTypeResolution.cpp index f46ad6733..930bba0e3 100644 --- a/test/solidityNameAndTypeResolution.cpp +++ b/test/solidityNameAndTypeResolution.cpp @@ -121,6 +121,44 @@ BOOST_AUTO_TEST_CASE(reference_to_later_declaration) BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } +BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive) +{ + char const* text = "contract test {\n" + " struct MyStructName {\n" + " address addr;\n" + " MyStructName x;\n" + " }\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError); +} + +BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) +{ + char const* text = "contract test {\n" + " struct MyStructName1 {\n" + " address addr;\n" + " uint256 count;\n" + " MyStructName2 x;\n" + " }\n" + " struct MyStructName2 {\n" + " MyStructName1 x;\n" + " }\n" + "}\n"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError); +} + +BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping) +{ + char const* text = "contract test {\n" + " struct MyStructName1 {\n" + " address addr;\n" + " uint256 count;\n" + " mapping(uint => MyStructName1) x;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_CASE(type_inference_smoke_test) { char const* text = "contract test {\n" From 64044e71a5ecc26f767e683540b82fbcd87e11eb Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Fri, 14 Nov 2014 14:21:02 +0100 Subject: [PATCH 19/44] common changes after merge --- libweb3jsonrpc/WebThreeStubServer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 22e871559..c0c50f9bd 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -531,8 +531,7 @@ std::string WebThreeStubServer::eth_lll(std::string const& _code) std::string WebThreeStubServer::eth_solidity(std::string const& _code) { - shared_ptr scanner = make_shared(); - return toJS(dev::solidity::CompilerStack::compile(_code, scanner)); + return toJS(dev::solidity::CompilerStack::staticCompile(_code, false)); } int WebThreeStubServer::eth_number() From 7dfd83e8f5bfe8ef084e9afd23890b2e1b11bc9e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 12:59:16 +0100 Subject: [PATCH 20/44] Whisper API change for topics. Don't keep dead nodes. --- libp2p/Host.cpp | 6 +++--- libwhisper/Common.cpp | 2 +- libwhisper/Common.h | 7 +------ 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 4b28a63a3..be9f2f7ae 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -778,7 +778,7 @@ bytes Host::saveNodes() const { Node const& n = *(i.second); // TODO: PoC-7: Figure out why it ever shares these ports.//n.address.port() >= 30300 && n.address.port() <= 30305 && - if (!n.dead && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address())) + if (!n.dead && chrono::system_clock::now() - n.lastConnected < chrono::seconds(3600 * 48) && n.address.port() > 0 && n.address.port() < /*49152*/32768 && n.id != id() && !isPrivateAddress(n.address.address())) { nodes.appendList(10); if (n.address.address().is_v4()) @@ -786,8 +786,8 @@ bytes Host::saveNodes() const else nodes << n.address.address().to_v6().to_bytes(); nodes << n.address.port() << n.id << (int)n.idOrigin - << std::chrono::duration_cast(n.lastConnected.time_since_epoch()).count() - << std::chrono::duration_cast(n.lastAttempted.time_since_epoch()).count() + << chrono::duration_cast(n.lastConnected.time_since_epoch()).count() + << chrono::duration_cast(n.lastAttempted.time_since_epoch()).count() << n.failedAttempts << (unsigned)n.lastDisconnect << n.score << n.rating; count++; } diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index 83f289875..0d54af089 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -69,7 +69,7 @@ TopicMask BuildTopicMask::toTopicMask() const TopicMask ret; ret.reserve(m_parts.size()); for (auto const& h: m_parts) - ret.push_back(make_pair(TopicPart(h), h ? ~TopicPart() : TopicPart())); + ret.push_back(make_pair(TopicPart(h), ~TopicPart())); return ret; } diff --git a/libwhisper/Common.h b/libwhisper/Common.h index 312cbf6d3..a704a2896 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -114,17 +114,12 @@ private: class BuildTopicMask: BuildTopic { public: - enum EmptyType { Empty }; - - BuildTopicMask() { shift(); } - BuildTopicMask(EmptyType) {} + template BuildTopicMask() {} template BuildTopicMask(T const& _t) { shift(_t); } template BuildTopicMask& shift(T const& _r) { BuildTopic::shift(_r); return *this; } BuildTopicMask& shiftRaw(h256 const& _h) { BuildTopic::shiftRaw(_h); return *this; } - BuildTopic& shift() { m_parts.push_back(h256()); return *this; } - BuildTopicMask& operator()() { shift(); return *this; } template BuildTopicMask& operator()(T const& _t) { shift(_t); return *this; } operator TopicMask() const { return toTopicMask(); } From 3b17797b4604c7ad6614c62edab5d7f2475f92b6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 14:50:45 +0100 Subject: [PATCH 21/44] Build fixes. --- libweb3jsonrpc/WebThreeStubServer.cpp | 6 +----- libwhisper/Common.h | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 092faae09..73c938ce2 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -240,7 +240,7 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, static pair toWatch(Json::Value const& _json) { - shh::BuildTopicMask bt(shh::BuildTopicMask::Empty); + shh::BuildTopicMask bt; Public to; if (!_json["to"].empty()) @@ -252,12 +252,8 @@ static pair toWatch(Json::Value const& _json) bt.shift(jsToBytes(_json["topic"].asString())); else if (_json["topic"].isArray()) for (auto i: _json["topic"]) - { if (i.isString()) bt.shift(jsToBytes(i.asString())); - else - bt.shift(); - } } return make_pair(bt.toTopicMask(), to); } diff --git a/libwhisper/Common.h b/libwhisper/Common.h index a704a2896..5ce7d3b1c 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -114,7 +114,7 @@ private: class BuildTopicMask: BuildTopic { public: - template BuildTopicMask() {} + BuildTopicMask() {} template BuildTopicMask(T const& _t) { shift(_t); } template BuildTopicMask& shift(T const& _r) { BuildTopic::shift(_r); return *this; } From c0b3f93e8e8a61df944a3bbbb5b1b01931be05c1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 15:14:40 +0100 Subject: [PATCH 22/44] Fix first part of stdserv.js. Still much to do. --- stdserv.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/stdserv.js b/stdserv.js index 55ae90d86..887586874 100644 --- a/stdserv.js +++ b/stdserv.js @@ -1,7 +1,9 @@ eth = web3.eth; +env = web3.env; env.note('Creating Config...') -var configCode = eth.lll(" +var config; +eth.lll(" { [[69]] (caller) (returnlll { @@ -12,13 +14,19 @@ var configCode = eth.lll(" ) (return @@ $0) }) -} -") -env.note('Config code: ' + configCode) -var config; -eth.transact({ 'code': configCode }, function(a) { config = a; }); +}" +).then(function(configCode) +{ + console.log('Config code: ' + configCode); + return eth.transact({ 'code': configCode }); +}).then(function(configAddress) +{ + config = configAddress; + console.log('Config at address ' + configAddress); +}); -env.note('Config at address ' + config) +// marek: TODO +/* var nameRegCode = eth.lll(" { @@ -306,7 +314,7 @@ eth.transact({ 'to': exchange, 'data': [web3.fromAscii('new'), gavCoin, '5000', env.note('Register gav.eth...') eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] }); - +*/ env.note('All done.') // env.load('/home/gav/Eth/cpp-ethereum/stdserv.js') From e2b3925683ff58beaa2b7a0f7c0d8fa00e7bc80a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 15:38:30 +0100 Subject: [PATCH 23/44] More fixing for std serv --- alethzero/MainWin.cpp | 5 ++++- stdserv.js | 40 +++++++++++++++++----------------------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 0ad5ba938..e10d01efc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -355,6 +355,9 @@ void Main::on_enableOptimizer_triggered() void Main::load(QString _s) { + QString contents = QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); + ui->webView->page()->currentFrame()->evaluateJavaScript(contents); + /* QFile fin(_s); if (!fin.open(QFile::ReadOnly)) return; @@ -375,7 +378,7 @@ void Main::load(QString _s) //eval(line); line.clear(); } - } + }*/ } void Main::on_loadJS_triggered() diff --git a/stdserv.js b/stdserv.js index 887586874..375a8379f 100644 --- a/stdserv.js +++ b/stdserv.js @@ -1,29 +1,23 @@ eth = web3.eth; env = web3.env; -env.note('Creating Config...') -var config; -eth.lll(" -{ - [[69]] (caller) - (returnlll { - (when (&& (= (calldatasize) 64) (= (caller) @@69)) - (for {} (< @i (calldatasize)) [i](+ @i 64) - [[ (calldataload @i) ]] (calldataload (+ @i 32)) - ) - ) - (return @@ $0) - }) -}" -).then(function(configCode) -{ - console.log('Config code: ' + configCode); - return eth.transact({ 'code': configCode }); -}).then(function(configAddress) -{ - config = configAddress; - console.log('Config at address ' + configAddress); -}); +var configSource = +"{"+ +" [[69]] (caller)"+ +" (returnlll {"+ +" (when (&& (= (calldatasize) 64) (= (caller) @@69))"+ +" (for {} (< @i (calldatasize)) [i](+ @i 64)"+ +" [[ (calldataload @i) ]] (calldataload (+ @i 32))"+ +" )"+ +" )"+ +" (return @@ $0)"+ +" })"+ +"}"; + +console.log('Creating Config...') +var config = eth.lll(configSource); +config = config.then(function (configCode) { console.log('Config code: ' + configCode); return eth.transact({ 'code': configCode }); }); +config.then(function(configAddress) { console.log('Config at address ' + configAddress); config = configAddress; return configAddress; }); // marek: TODO /* From c80fe4728988f66ef0bdaadbdf4d51ce8aec235f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 21:07:47 +0100 Subject: [PATCH 24/44] Fix std services except DNS Reg whose contract needs rewriting. --- alethzero/MainWin.cpp | 7 +- alethzero/MainWin.h | 1 + libdevcore/CommonJS.cpp | 31 +-- libdevcore/CommonJS.h | 11 +- libdevcore/Exceptions.h | 4 +- libethereum/Executive.cpp | 6 +- libevm/VM.h | 2 +- libqethereum/QEthereum.h | 1 + libweb3jsonrpc/WebThreeStubServer.cpp | 4 +- stdserv.js | 324 +++----------------------- 10 files changed, 62 insertions(+), 329 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e10d01efc..dc5b326bc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -353,6 +353,11 @@ void Main::on_enableOptimizer_triggered() on_data_textChanged(); } +QString Main::contents(QString _s) +{ + return QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); +} + void Main::load(QString _s) { QString contents = QString::fromStdString(dev::asString(dev::contents(_s.toStdString()))); @@ -682,7 +687,7 @@ void Main::on_importKeyFile_triggered() try { js::mValue val; - json_spirit::read_string(asString(contents(s.toStdString())), val); + json_spirit::read_string(asString(dev::contents(s.toStdString())), val); auto obj = val.get_obj(); if (obj["encseed"].type() == js::str_type) { diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 9f7ad97de..14877f610 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -85,6 +85,7 @@ public slots: void note(QString _entry); void debug(QString _entry); void warn(QString _entry); + QString contents(QString _file); void onKeysChanged(); diff --git a/libdevcore/CommonJS.cpp b/libdevcore/CommonJS.cpp index 96f4b1896..c09a5b565 100644 --- a/libdevcore/CommonJS.cpp +++ b/libdevcore/CommonJS.cpp @@ -38,31 +38,20 @@ bytes jsToBytes(std::string const& _s) return bytes(); } -std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r) +bytes padded(bytes _b, unsigned _l) { - bytes b = jsToBytes(_s); - while (b.size() < _l) - b.insert(b.begin(), 0); - while (b.size() < _r) - b.push_back(0); - return asString(b).substr(b.size() - std::max(_l, _r)); + while (_b.size() < _l) + _b.insert(_b.begin(), 0); + while (_b.size() < _l) + _b.push_back(0); + return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l))); } -std::string jsPadded(std::string const& _s, unsigned _l) +bytes unpadded(bytes _b) { - if (_s.substr(0, 2) == "0x" || _s.find_first_not_of("0123456789") == std::string::npos) - // Numeric: pad to right - return jsPadded(_s, _l, _l); - else - // Text: pad to the left - return jsPadded(_s, 0, _l); -} - -std::string jsUnpadded(std::string _s) -{ - auto p = _s.find_last_not_of((char)0); - _s.resize(p == std::string::npos ? 0 : (p + 1)); - return _s; + auto p = asString(_b).find_last_not_of((char)0); + _b.resize(p == std::string::npos ? 0 : (p + 1)); + return _b; } } diff --git a/libdevcore/CommonJS.h b/libdevcore/CommonJS.h index be98c2372..80e1a9ca1 100644 --- a/libdevcore/CommonJS.h +++ b/libdevcore/CommonJS.h @@ -47,9 +47,8 @@ inline std::string toJS(dev::bytes const& _n) } bytes jsToBytes(std::string const& _s); -std::string jsPadded(std::string const& _s, unsigned _l, unsigned _r); -std::string jsPadded(std::string const& _s, unsigned _l); -std::string jsUnpadded(std::string _s); +bytes padded(bytes _b, unsigned _l); +bytes unpadded(bytes _s); template FixedHash jsToFixed(std::string const& _s) { @@ -61,7 +60,7 @@ template FixedHash jsToFixed(std::string const& _s) return (typename FixedHash::Arith)(_s); else // Binary - return FixedHash(asBytes(jsPadded(_s, N))); + return FixedHash(); // FAIL } inline std::string jsToFixed(double _s) @@ -79,7 +78,7 @@ template boost::multiprecision::number>(_s); else // Binary - return fromBigEndian>>(asBytes(jsPadded(_s, N))); + return 0; // FAIL } inline Address jsToAddress(std::string const& _s) { return jsToFixed(_s); } @@ -89,7 +88,7 @@ inline u256 jsToU256(std::string const& _s) { return jsToInt<32>(_s); } inline std::string jsToBinary(std::string const& _s) { - return jsUnpadded(dev::toString(jsToBytes(_s))); + return dev::toString(unpadded(jsToBytes(_s))); } inline std::string jsToDecimal(std::string const& _s) diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h index bbc928da4..5d03c195f 100644 --- a/libdevcore/Exceptions.h +++ b/libdevcore/Exceptions.h @@ -45,7 +45,7 @@ struct FileError: virtual Exception {}; typedef boost::error_info errinfo_invalidSymbol; typedef boost::error_info errinfo_wrongAddress; typedef boost::error_info errinfo_comment; -typedef boost::error_info errinfo_required; -typedef boost::error_info errinfo_got; +typedef boost::error_info errinfo_required; +typedef boost::error_info errinfo_got; typedef boost::tuple RequirementError; } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index f8c526ac7..c3a8b2a80 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -71,7 +71,7 @@ bool Executive::setup(bytesConstRef _rlp) if (m_t.gas() < gasCost) { clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas(); - BOOST_THROW_EXCEPTION(OutOfGas()); + BOOST_THROW_EXCEPTION(OutOfGas() << RequirementError((bigint)gasCost, (bigint)m_t.gas())); } u256 cost = m_t.value() + m_t.gas() * m_t.gasPrice(); @@ -80,14 +80,14 @@ bool Executive::setup(bytesConstRef _rlp) if (m_s.balance(m_sender) < cost) { clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender); - BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((int)cost, (int)m_s.balance(m_sender))); + BOOST_THROW_EXCEPTION(NotEnoughCash() << RequirementError((bigint)cost, (bigint)m_s.balance(m_sender))); } u256 startGasUsed = m_s.gasUsed(); if (startGasUsed + m_t.gas() > m_s.m_currentBlock.gasLimit) { clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas(); - BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((int)(m_s.m_currentBlock.gasLimit - startGasUsed), (int)m_t.gas())); + BOOST_THROW_EXCEPTION(BlockGasLimitReached() << RequirementError((bigint)(m_s.m_currentBlock.gasLimit - startGasUsed), (bigint)m_t.gas())); } // Increment associated nonce for sender. diff --git a/libevm/VM.h b/libevm/VM.h index 52149a9a1..487c8cd1a 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -71,7 +71,7 @@ public: template bytesConstRef go(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); - void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError(int(_n), m_stack.size())); } + void require(u256 _n) { if (m_stack.size() < _n) BOOST_THROW_EXCEPTION(StackTooSmall() << RequirementError((bigint)_n, (bigint)m_stack.size())); } void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } } u256 gas() const { return m_gas; } u256 curPC() const { return m_curPC; } diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index 4f276b7e1..0824b0139 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -83,6 +83,7 @@ private: { \ _frame->disconnect(); \ _frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \ + _frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/es6-promise-2.0.0.js")); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/main.js")); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/qt.js")); \ diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 73c938ce2..03c2a37ac 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -370,10 +370,10 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) ret.data = jsToBytes(_json["code"].asString()); else if (_json["data"].isArray()) for (auto i: _json["data"]) - dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32))); + dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32)); else if (_json["code"].isArray()) for (auto i: _json["code"]) - dev::operator +=(ret.data, jsToBytes(jsPadded(i.asString(), 32))); + dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32)); else if (_json["dataclose"].isArray()) for (auto i: _json["dataclose"]) dev::operator +=(ret.data, jsToBytes(i.asString())); diff --git a/stdserv.js b/stdserv.js index 375a8379f..fe681414e 100644 --- a/stdserv.js +++ b/stdserv.js @@ -1,69 +1,41 @@ -eth = web3.eth; -env = web3.env; - -var configSource = -"{"+ -" [[69]] (caller)"+ -" (returnlll {"+ -" (when (&& (= (calldatasize) 64) (= (caller) @@69))"+ -" (for {} (< @i (calldatasize)) [i](+ @i 64)"+ -" [[ (calldataload @i) ]] (calldataload (+ @i 32))"+ -" )"+ -" )"+ -" (return @@ $0)"+ -" })"+ -"}"; - -console.log('Creating Config...') -var config = eth.lll(configSource); -config = config.then(function (configCode) { console.log('Config code: ' + configCode); return eth.transact({ 'code': configCode }); }); -config.then(function(configAddress) { console.log('Config at address ' + configAddress); config = configAddress; return configAddress; }); - -// marek: TODO +var compile = function(name) { return web3.eth.lll(env.contents("../../dapp-bin/" + name + "/" + name + ".lll")); }; +var create = function(code) { return web3.eth.transact({ 'code': code }); }; +var send = function(from, val, to) { return web3.eth.transact({ 'from': from, 'value': val, 'to': to }); }; +var initService = function(name, index, dep) { return dep.then(function(){ var ret = compile(name).then(create); register(ret, index); return ret; }); }; + +var config = compile("config").then(create); +var register = function(address, index) { return web3.eth.transact({ 'to': config, 'gas': '10000', 'data': [index + '', address] }); }; +var nameReg = initService("namereg", 0, config); +var regName = function(account, name) { return web3.eth.transact({ 'from': account, 'to': nameReg, 'gas': '10000', 'data': [ web3.fromAscii('register'), web3.fromAscii(name) ] }); }; +var coins = initService("coins", 1, nameReg); +var coin = initService("coin", 2, coins); +var approve = function(account, approvedAddress) { web3.eth.transact({ 'from': account, 'to': coin, 'gas': '10000', 'data': [ web3.fromAscii('approve'), approvedAddress ] }); }; +var exchange = initService("exchange", 3, coin); +var offer = function(account, haveCoin, haveVal, wantCoin, wantVal) { web3.eth.transact({ 'from': account, 'to': exchange, 'gas': '10000', 'data': [web3.fromAscii('new'), haveCoin, haveVal, wantCoin, wantVal] }); }; + +config.then(function() { + web3.eth.accounts.then(function(accounts) + { + var funded = send(accounts[0], '100000000000000000000', accounts[1]); + funded.then(function(){ env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); regName(accounts[1], 'Gav Would'); env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); approve(accounts[1], exchange); }); + regName(accounts[0], 'Gav'); + approve(accounts[0], exchange).then(function(){ offer(accounts[0], coin, '5000', '0', '5000000000000000000'); }); + + // TODO: once we have a new implementation of DNSReg. + // env.note('Register gav.eth...') + // eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] }); + }); +}); + +// TODO /* - -var nameRegCode = eth.lll(" -{ - [[(address)]] 'NameReg - [['NameReg]] (address) - [[config]] 'Config - [['Config]] config - [[69]] (caller) - (returnlll { - (when (= $0 'register) { - (when @@ $32 (stop)) - (when @@(caller) [[@@(caller)]] 0) - [[$32]] (caller) - [[(caller)]] $32 - (stop) - }) - (when (&& (= $0 'unregister) @@(caller)) { - [[@@(caller)]] 0 - [[(caller)]] 0 - (stop) - }) - (when (&& (= $0 'kill) (= (caller) @@69)) (suicide (caller))) - (return @@ $0) - }) -} -"); -env.note('NameReg code: ' + nameRegCode) - -var nameReg; - -env.note('Create NameReg...') -eth.transact({ 'code': nameRegCode }, function(a) { nameReg = a; }); - -env.note('Register NameReg...') -eth.transact({ 'to': config, 'data': ['0', nameReg] }); - var nameRegJeff; env.note('Create NameRegJeff...') eth.transact({ 'code': nameRegCode }, function(a) { nameRegJeff = a; }); env.note('Register NameRegJeff...') -eth.transact({ 'to': config, 'data': ['4', nameReg] }); +eth.transact({ 'to': config, 'data': ['4', nameRegJeff] }); var dnsRegCode = '0x60006000546000600053602001546000600053604001546020604060206020600073661005d2720d855f1d9976f88bb10c1a3398c77f6103e8f17f7265676973746572000000000000000000000000000000000000000000000000600053606001600060200201547f446e735265670000000000000000000000000000000000000000000000000000600053606001600160200201546000600060006000604060606000600053604001536103e8f1327f6f776e65720000000000000000000000000000000000000000000000000000005761011663000000e46000396101166000f20060006000547f72656769737465720000000000000000000000000000000000000000000000006000602002350e0f630000006d596000600160200235560e0f630000006c59600032560e0f0f6300000057596000325657600260200235600160200235576001602002353257007f64657265676973746572000000000000000000000000000000000000000000006000602002350e0f63000000b95960016020023532560e0f63000000b959600032576000600160200235577f6b696c6c000000000000000000000000000000000000000000000000000000006000602002350e0f630000011559327f6f776e6572000000000000000000000000000000000000000000000000000000560e0f63000001155932ff00'; @@ -75,240 +47,6 @@ env.note('DnsReg at address ' + dnsReg) env.note('Register DnsReg...') eth.transact({ 'to': config, 'data': ['4', dnsReg] }); - -var coinRegCode = eth.lll(" -{ -(regname 'CoinReg) -(returnlll { - (def 'name $0) - (def 'denom $32) - (def 'address (caller)) - (when (|| (& 0xffffffffffffffffffffffffff name) @@name) (stop)) - (set 'n (+ @@0 1)) - [[0]] @n - [[@n]] name - [[name]] address - [[(sha3 name)]] denom -}) -} -"); - -var coinReg; -env.note('Create CoinReg...') -eth.transact({ 'code': coinRegCode }, function(a) { coinReg = a; }); - -env.note('Register CoinReg...') -eth.transact({ 'to': config, 'data': ['1', coinReg] }); - -var gavCoinCode = eth.lll(" -{ -[[ (caller) ]] 0x1000000 -[[ 0x69 ]] (caller) -[[ 0x42 ]] (number) - -(regname 'GavCoin) -(regcoin 'GAV 1000) - -(returnlll { - (when (&& (= $0 'kill) (= (caller) @@0x69)) (suicide (caller))) - (when (= $0 'balance) (return @@$32)) - (when (= $0 'approved) (return @@ (sha3pair (if (= (calldatasize) 64) (caller) $64) $32)) ) - - (when (= $0 'approve) { - [[(sha3pair (caller) $32)]] $32 - (stop) - }) - - (when (= $0 'send) { - (set 'fromVar (if (= (calldatasize) 96) - (caller) - { - (when (! @@ (sha3pair (origin) (caller))) (return 0)) - (origin) - } - )) - (def 'to $32) - (def 'value $64) - (def 'from (get 'fromVar)) - (set 'fromBal @@from) - (when (< @fromBal value) (return 0)) - [[ from ]]: (- @fromBal value) - [[ to ]]: (+ @@to value) - (return 1) - }) - - (set 'n @@0x42) - (when (&& (|| (= $0 'mine) (! (calldatasize))) (> (number) @n)) { - (set 'b (- (number) @n)) - [[(coinbase)]] (+ @@(coinbase) (* 1000 @b)) - [[(caller)]] (+ @@(caller) (* 1000 @b)) - [[0x42]] (number) - (return @b) - }) - - (return @@ $0) -}) -} -"); - -var gavCoin; -env.note('Create GavCoin...') -eth.transact({ 'code': gavCoinCode }, function(a) { gavCoin = a; }); - -env.note('Register GavCoin...') -eth.transact({ 'to': config, 'data': ['2', gavCoin] }); - - -var exchangeCode = eth.lll(" -{ -(regname 'Exchange) - -(def 'min (a b) (if (< a b) a b)) - -(def 'head (_list) @@ _list) -(def 'next (_item) @@ _item) -(def 'inc (itemref) [itemref]: (next @itemref)) -(def 'rateof (_item) @@ (+ _item 1)) -(def 'idof (_item) @@ (+ _item 2)) -(def 'wantof (_item) @@ (+ _item 3)) -(def 'newitem (rate who want list) { - (set 'pos (sha3trip rate who list)) - [[ (+ @pos 1) ]] rate - [[ (+ @pos 2) ]] who - [[ (+ @pos 3) ]] want - @pos -}) -(def 'stitchitem (parent pos) { - [[ pos ]] @@ parent - [[ parent ]] pos -}) -(def 'addwant (_item amount) [[ (+ _item 3) ]] (+ @@ (+ _item 3) amount)) -(def 'deductwant (_item amount) [[ (+ _item 3) ]] (- @@ (+ _item 3) amount)) - -(def 'xfer (contract to amount) - (if contract { - [0] 'send - [32] to - [64] amount - (msg allgas contract 0 0 96) - } - (send to amount) - ) -) - -(def 'fpdiv (a b) (/ (+ (/ b 2) (* a (exp 2 128))) b)) -(def 'fpmul (a b) (/ (* a b) (exp 2 128)) ) - -(returnlll { - (when (= $0 'new) { - (set 'offer $32) - (set 'xoffer (if @offer $64 (callvalue))) - (set 'want $96) - (set 'xwant $128) - (set 'rate (fpdiv @xoffer @xwant)) - (set 'irate (fpdiv @xwant @xoffer)) - - (unless (&& @rate @irate @xoffer @xwant) (stop)) - - (when @offer { - (set 'arg1 'send) - (set 'arg2 (address)) - (set 'arg3 @xoffer) - (set 'arg4 (caller)) - (unless (msg allgas @offer 0 arg1 128) (stop)) - }) - (set 'list (sha3pair @offer @want)) - (set 'ilist (sha3pair @want @offer)) - - (set 'last @ilist) - (set 'item @@ @last) - - (for {} (&& @item (>= (rateof @item) @irate)) {} { - (set 'offerA (min @xoffer (wantof @item))) - (set 'wantA (fpmul @offerA (rateof @item))) - - (set 'xoffer (- @xoffer @offerA)) - (set 'xwant (- @xwant @wantA)) - - (deductwant @item @offerA) - - (xfer @offer (idof @item) @offerA) - (xfer @want (caller) @wantA) - - (unless @xoffer (stop)) - - (set 'item @@ @item) - [[ @last ]] @item - }) - - (set 'last @list) - (set 'item @@ @last) - - (set 'newpos (newitem @rate (caller) @xwant @list)) - - (for {} (&& @item (!= @item @newpos) (>= (rateof @item) @rate)) { (set 'last @item) (inc item) } {}) - (if (= @item @newpos) - (addwant @item @wantx) - (stitchitem @last @newpos) - ) - (stop) - }) - (when (= $0 'delete) { - (set 'offer $32) - (set 'want $64) - (set 'rate $96) - (set 'list (sha3pair @offer @want)) - (set 'last @list) - (set 'item @@ @last) - (for {} (&& @item (!= (idof @item) (caller)) (!= (rateof @item) @rate)) { (set 'last @item) (inc item) } {}) - (when @item { - (set 'xoffer (fpmul (wantof @item) (rateof @item))) - [[ @last ]] @@ @item - (xfer @offer (caller) @xoffer) - }) - (stop) - }) - (when (= $0 'price) { - (set 'offer $32) - (set 'want $96) - (set 'item (head (sha3pair @offer @want))) - (return (if @item (rateof @list) 0)) - }) -}) -} -"); - -var exchange; -env.note('Create Exchange...') -eth.transact({ 'code': exchangeCode }, function(a) { exchange = a; }); - -env.note('Register Exchange...') -eth.transact({ 'to': config, 'data': ['3', exchange] }); - - - - -env.note('Register my name...') -eth.transact({ 'to': nameReg, 'data': [ web3.fromAscii('register'), web3.fromAscii('Gav') ] }); - -env.note('Dole out ETH to other address...') -eth.transact({ 'value': '100000000000000000000', 'to': eth.accounts[1] }); - -env.note('Register my other name...') -eth.transact({ 'from': eth.keys[1], 'to': nameReg, 'data': [ web3.fromAscii('register'), web3.fromAscii("Gav Would") ] }); - -env.note('Approve Exchange...') -eth.transact({ 'to': gavCoin, 'data': [ web3.fromAscii('approve'), exchange ] }); - -env.note('Approve Exchange on other address...') -eth.transact({ 'from': eth.keys[1], 'to': gavCoin, 'data': [ web3.fromAscii('approve'), exchange ] }); - -env.note('Make offer 5000GAV/5ETH...') -eth.transact({ 'to': exchange, 'data': [web3.fromAscii('new'), gavCoin, '5000', '0', '5000000000000000000'] }); - -env.note('Register gav.eth...') -eth.transact({ 'to': dnsReg, 'data': [web3.fromAscii('register'), web3.fromAscii('gav'), web3.fromAscii('opensecrecy.com')] }); */ -env.note('All done.') // env.load('/home/gav/Eth/cpp-ethereum/stdserv.js') From d7972e726dccccdcecc826944dba49de731ef9b1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 21:26:39 +0100 Subject: [PATCH 25/44] Minor UI changes and reduction of verbosity. --- alethzero/MainWin.cpp | 2 +- libethereum/State.cpp | 4 ++-- libp2p/Host.cpp | 2 +- libweb3jsonrpc/WebThreeStubServer.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index dc5b326bc..280a70fe1 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -956,7 +956,7 @@ void Main::refreshBlockCount() cwatch << "refreshBlockCount()"; auto d = ethereum()->blockChain().details(); auto diff = BlockInfo(ethereum()->blockChain().block()).difficulty; - ui->blockCount->setText(QString("%6 #%1 @%3 T%2 N%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); + ui->blockCount->setText(QString("%6 #%1 @%3 T%2 PV%4 D%5").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)).arg(dev::eth::c_protocolVersion).arg(dev::eth::c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet")); } static bool blockMatch(string const& _f, dev::eth::BlockDetails const& _b, h256 _h, BlockChain const& _bc) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index ee93fdc55..69faf983c 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -322,8 +322,8 @@ StateDiff State::diff(State const& _c) const for (auto i: _c.m_cache) ads.insert(i.first); - cnote << *this; - cnote << _c; +// cnote << *this; +// cnote << _c; for (auto i: ads) { diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index be9f2f7ae..996e219db 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -385,7 +385,7 @@ void Host::populateAddresses() shared_ptr Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId) { RecursiveGuard l(x_peers); - if (_a.port() < 30300 || _a.port() > 30303) + if (_a.port() < 30300 || _a.port() > 30305) cwarn << "Weird port being recorded: " << _a.port(); if (_a.port() >= /*49152*/32768) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 03c2a37ac..5b362cde5 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -507,7 +507,7 @@ std::string WebThreeStubServer::shh_newGroup(std::string const& _id, std::string std::string WebThreeStubServer::shh_newIdentity() { - cnote << this << m_ids; +// cnote << this << m_ids; KeyPair kp = KeyPair::create(); m_ids[kp.pub()] = kp.secret(); return toJS(kp.pub()); @@ -535,7 +535,7 @@ int WebThreeStubServer::eth_peerCount() bool WebThreeStubServer::shh_post(Json::Value const& _json) { - cnote << this << m_ids; +// cnote << this << m_ids; shh::Message m = toMessage(_json); Secret from; From ecf4ede0308a3bb7cc8a970e638c16b4dafc5aef Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 22:00:41 +0100 Subject: [PATCH 26/44] Clean up Alex's Windows mess :-P --- windows/LibEthereum.vcxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 0578a8f16..06f868023 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -68,14 +68,14 @@ true + - + - @@ -568,4 +568,4 @@ - \ No newline at end of file + From 0f7e159df48eea17819fda72471d4c416ce132d8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 22:35:14 +0100 Subject: [PATCH 27/44] Brain-dead MSVC strikes again. --- libdevcrypto/ECDHE.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index dd72e8176..deae3bc6d 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -76,7 +76,7 @@ void ECDHEKeyExchange::exchange(bytes& o_exchange) memcpy(&exchange[exchange.size() - sizeof(p)], p.data(), sizeof(p)); // protocol parameters; should be fixed size - bytes v({0x80}); + bytes v(1, 0x80); exchange.resize(exchange.size() + v.size()); memcpy(&exchange[exchange.size() - v.size()], v.data(), v.size()); From 6af670af27f74e9cb5c8566d1e5a226adbd7bfb6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 16 Nov 2014 23:02:53 +0100 Subject: [PATCH 28/44] Windows build fix. --- test/crypto.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/crypto.cpp b/test/crypto.cpp index d8bd25035..08236135a 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) Secret secret(sha3(sbytes)); KeyPair key(secret); - bytes m({0xFF}); + bytes m(1, 0xff); int tests = 2; while (m[0]++, tests--) { From 3ba250c61ff3a5755c8433362a8f93792fbce1ad Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 17 Nov 2014 13:13:18 +0100 Subject: [PATCH 29/44] fixed #502 --- libweb3jsonrpc/WebThreeStubServer.cpp | 83 +++++++++++++++++---------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 256f6d564..9526b2f9b 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -131,28 +131,34 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json) if (!_json.isObject() || _json.empty()) return filter; - if (!_json["earliest"].empty()) + if (_json["earliest"].isInt()) filter.withEarliest(_json["earliest"].asInt()); - if (!_json["latest"].empty()) + if (_json["latest"].isInt()) filter.withLatest(_json["lastest"].asInt()); - if (!_json["max"].empty()) + if (_json["max"].isInt()) filter.withMax(_json["max"].asInt()); - if (!_json["skip"].empty()) + if (_json["skip"].isInt()) filter.withSkip(_json["skip"].asInt()); if (!_json["from"].empty()) { if (_json["from"].isArray()) + { for (auto i : _json["from"]) - filter.from(jsToAddress(i.asString())); - else + if (i.isString()) + filter.from(jsToAddress(i.asString())); + } + else if (_json["from"].isString()) filter.from(jsToAddress(_json["from"].asString())); } if (!_json["to"].empty()) { if (_json["to"].isArray()) + { for (auto i : _json["to"]) - filter.to(jsToAddress(i.asString())); - else + if (i.isString()) + filter.to(jsToAddress(i.asString())); + } + else if (_json["to"].isString()) filter.to(jsToAddress(_json["to"].asString())); } if (!_json["altered"].empty()) @@ -177,28 +183,34 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json) if (!_json.isObject() || _json.empty()) return filter; - if (!_json["earliest"].empty()) + if (_json["earliest"].isInt()) filter.withEarliest(_json["earliest"].asInt()); - if (!_json["latest"].empty()) + if (_json["latest"].isInt()) filter.withLatest(_json["lastest"].asInt()); - if (!_json["max"].empty()) + if (_json["max"].isInt()) filter.withMax(_json["max"].asInt()); - if (!_json["skip"].empty()) + if (_json["skip"].isInt()) filter.withSkip(_json["skip"].asInt()); if (!_json["from"].empty()) { if (_json["from"].isArray()) + { for (auto i : _json["from"]) - filter.from(jsToAddress(i.asString())); - else + if (i.isString()) + filter.from(jsToAddress(i.asString())); + } + else if (_json["from"].isString()) filter.from(jsToAddress(_json["from"].asString())); } if (!_json["address"].empty()) { if (_json["address"].isArray()) + { for (auto i : _json["address"]) - filter.address(jsToAddress(i.asString())); - else + if (i.isString()) + filter.address(jsToAddress(i.asString())); + } + else if (_json["address"].isString()) filter.from(jsToAddress(_json["address"].asString())); } if (!_json["topics"].empty()) @@ -218,11 +230,11 @@ static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json) static shh::Message toMessage(Json::Value const& _json) { shh::Message ret; - if (!_json["from"].empty()) + if (_json["from"].isString()) ret.setFrom(jsToPublic(_json["from"].asString())); - if (!_json["to"].empty()) + if (_json["to"].isString()) ret.setTo(jsToPublic(_json["to"].asString())); - if (!_json["payload"].empty()) + if (_json["payload"].isString()) ret.setPayload(jsToBytes(_json["payload"].asString())); return ret; } @@ -233,9 +245,9 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, unsigned workToProve = 50; shh::BuildTopic bt; - if (!_json["ttl"].empty()) + if (_json["ttl"].isInt()) ttl = _json["ttl"].asInt(); - if (!_json["workToProve"].empty()) + if (_json["workToProve"].isInt()) workToProve = _json["workToProve"].asInt(); if (!_json["topic"].empty()) { @@ -243,7 +255,8 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, bt.shift(jsToBytes(_json["topic"].asString())); else if (_json["topic"].isArray()) for (auto i: _json["topic"]) - bt.shift(jsToBytes(i.asString())); + if (i.isString()) + bt.shift(jsToBytes(i.asString())); } return _m.seal(_from, bt, ttl, workToProve); } @@ -253,7 +266,7 @@ static pair toWatch(Json::Value const& _json) shh::BuildTopicMask bt; Public to; - if (!_json["to"].empty()) + if (_json["to"].isString()) to = jsToPublic(_json["to"].asString()); if (!_json["topic"].empty()) @@ -361,19 +374,29 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) if (!_json.isObject() || _json.empty()) return ret; - if (!_json["from"].empty()) + if (_json["from"].isString()) ret.from = jsToAddress(_json["from"].asString()); - if (!_json["to"].empty()) + if (_json["to"].isString()) ret.to = jsToAddress(_json["to"].asString()); - if (!_json["value"].empty()) + if (_json["value"].isString()) ret.value = jsToU256(_json["value"].asString()); if (!_json["gas"].empty()) - ret.gas = jsToU256(_json["gas"].asString()); + { + if (_json["gas"].isString()) + ret.gas = jsToU256(_json["gas"].asString()); + else if (_json["gas"].isInt()) + ret.gas = u256(_json["gas"].asInt()); + } if (!_json["gasPrice"].empty()) - ret.gasPrice = jsToU256(_json["gasPrice"].asString()); - if (!_json["data"].empty() && _json["data"].isString()) + { + if (_json["gasPrice"].isString()) + ret.gasPrice = jsToU256(_json["gasPrice"].asString()); + else if (_json["gasPrice"].isInt()) + ret.gas = u256(_json["gas"].asInt()); + } + if (_json["data"].isString()) ret.data = jsToBytes(_json["data"].asString()); - else if (!_json["code"].empty() && _json["code"].isString()) + else if (_json["code"].isString()) ret.data = jsToBytes(_json["code"].asString()); return ret; } From 4c4dd302f27404997f0b7b2c62e994d65fb843f1 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 17 Nov 2014 14:04:57 +0100 Subject: [PATCH 30/44] ethereum.js not minified, serpent compiler, jsonrpc handles compilers exceptions --- libjsqrc/ethereum.js | 1034 +++++++++++++++++++ libjsqrc/ethereum.min.js | 1 - libjsqrc/js.qrc | 2 +- libweb3jsonrpc/CMakeLists.txt | 1 + libweb3jsonrpc/WebThreeStubServer.cpp | 45 +- libweb3jsonrpc/WebThreeStubServer.h | 1 + libweb3jsonrpc/abstractwebthreestubserver.h | 7 + libweb3jsonrpc/spec.json | 1 + test/webthreestubclient.h | 13 + 9 files changed, 1101 insertions(+), 4 deletions(-) create mode 100644 libjsqrc/ethereum.js delete mode 100644 libjsqrc/ethereum.min.js diff --git a/libjsqrc/ethereum.js b/libjsqrc/ethereum.js new file mode 100644 index 000000000..e65489a66 --- /dev/null +++ b/libjsqrc/ethereum.js @@ -0,0 +1,1034 @@ +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o. +*/ +/** @file abi.js + * @authors: + * Marek Kotewicz + * @date 2014 + */ + +var findIndex = function (array, callback) { + var end = false; + var i = 0; + for (; i < array.length && !end; i++) { + end = callback(array[i]); + } + return end ? i - 1 : -1; +}; + +var findMethodIndex = function (json, methodName) { + return findIndex(json, function (method) { + return method.name === methodName; + }); +}; + +var padLeft = function (number, n) { + return (new Array(n * 2 - number.toString().length + 1)).join("0") + number; +}; + +var setupInputTypes = function () { + var prefixedType = function (prefix) { + return function (type, value) { + var expected = prefix; + if (type.indexOf(expected) !== 0) { + return false; + } + + var padding = parseInt(type.slice(expected.length)) / 8; + return padLeft(value, padding); + }; + }; + + var namedType = function (name, padding, formatter) { + return function (type, value) { + if (type !== name) { + return false; + } + + return padLeft(formatter ? value : formatter(value), padding); + }; + }; + + var formatBool = function (value) { + return value ? '1' : '0'; + }; + + return [ + prefixedType('uint'), + prefixedType('int'), + namedType('address', 20), + namedType('bool', 1, formatBool), + ]; +}; + +var inputTypes = setupInputTypes(); + +var toAbiInput = function (json, methodName, params) { + var bytes = ""; + var index = findMethodIndex(json, methodName); + + if (index === -1) { + return; + } + + // it needs to be checked in WebThreeStubServer + // something wrong might be with this additional zero + bytes = bytes + index + 'x' + '0'; + var method = json[index]; + + for (var i = 0; i < method.inputs.length; i++) { + var found = false; + for (var j = 0; j < inputTypes.length && !found; j++) { + var val = parseInt(params[i]).toString(16); + found = inputTypes[j](method.inputs[i].type, val); + } + if (!found) { + console.error('unsupported json type: ' + method.inputs[i].type); + } + bytes += found; + } + return bytes; +}; + +var setupOutputTypes = function () { + var prefixedType = function (prefix) { + return function (type) { + var expected = prefix; + if (type.indexOf(expected) !== 0) { + return -1; + } + + var padding = parseInt(type.slice(expected.length)) / 8; + return padding * 2; + }; + }; + + var namedType = function (name, padding) { + return function (type) { + return name === type ? padding * 2: -1; + }; + }; + + var formatInt = function (value) { + return parseInt(value, 16); + }; + + var formatBool = function (value) { + return value === '1' ? true : false; + }; + + return [ + { padding: prefixedType('uint'), format: formatInt }, + { padding: prefixedType('int'), format: formatInt }, + { padding: namedType('address', 20) }, + { padding: namedType('bool', 1), format: formatBool } + ]; +}; + +var outputTypes = setupOutputTypes(); + +var fromAbiOutput = function (json, methodName, output) { + var index = findMethodIndex(json, methodName); + + if (index === -1) { + return; + } + + output = output.slice(2); + + var result = []; + var method = json[index]; + for (var i = 0; i < method.outputs.length; i++) { + var padding = -1; + for (var j = 0; j < outputTypes.length && padding === -1; j++) { + padding = outputTypes[j].padding(method.outputs[i].type); + } + + if (padding === -1) { + // not found output parsing + continue; + } + var res = output.slice(0, padding); + var formatter = outputTypes[j - 1].format; + result.push(formatter ? formatter(res): res); + output = output.slice(padding); + } + + return result; +}; + +var inputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + parser[method.name] = function () { + var params = Array.prototype.slice.call(arguments); + return toAbiInput(json, method.name, params); + }; + }); + + return parser; +}; + +var outputParser = function (json) { + var parser = {}; + json.forEach(function (method) { + parser[method.name] = function (output) { + return fromAbiOutput(json, method.name, output); + }; + }); + + return parser; +}; + +module.exports = { + inputParser: inputParser, + outputParser: outputParser +}; + + +},{}],2:[function(require,module,exports){ +/* + 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file websocket.js + * @authors: + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +/* + * @brief if qt object is available, uses QtProvider, + * if not tries to connect over websockets + * if it fails, it uses HttpRpcProvider + */ +if ("build" !== 'build') {/* + var WebSocket = require('ws'); // jshint ignore:line + var web3 = require('./web3'); // jshint ignore:line +*/} + +var AutoProvider = function (userOptions) { + if (web3.haveProvider()) { + return; + } + + // before we determine what provider we are, we have to cache request + this.sendQueue = []; + this.onmessageQueue = []; + + if (navigator.qt) { + this.provider = new web3.providers.QtProvider(); + return; + } + + userOptions = userOptions || {}; + var options = { + httprpc: userOptions.httprpc || 'http://localhost:8080', + websockets: userOptions.websockets || 'ws://localhost:40404/eth' + }; + + var self = this; + var closeWithSuccess = function (success) { + ws.close(); + if (success) { + self.provider = new web3.providers.WebSocketProvider(options.websockets); + } else { + self.provider = new web3.providers.HttpRpcProvider(options.httprpc); + self.poll = self.provider.poll.bind(self.provider); + } + self.sendQueue.forEach(function (payload) { + self.provider(payload); + }); + self.onmessageQueue.forEach(function (handler) { + self.provider.onmessage = handler; + }); + }; + + var ws = new WebSocket(options.websockets); + + ws.onopen = function() { + closeWithSuccess(true); + }; + + ws.onerror = function() { + closeWithSuccess(false); + }; +}; + +AutoProvider.prototype.send = function (payload) { + if (this.provider) { + this.provider.send(payload); + return; + } + this.sendQueue.push(payload); +}; + +Object.defineProperty(AutoProvider.prototype, 'onmessage', { + set: function (handler) { + if (this.provider) { + this.provider.onmessage = handler; + return; + } + this.onmessageQueue.push(handler); + } +}); + +module.exports = AutoProvider; + +},{}],3:[function(require,module,exports){ +/* + 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file httprpc.js + * @authors: + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +if ("build" !== "build") {/* + var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line +*/} + +var HttpRpcProvider = function (host) { + this.handlers = []; + this.host = host; +}; + +function formatJsonRpcObject(object) { + return { + jsonrpc: '2.0', + method: object.call, + params: object.args, + id: object._id + }; +} + +function formatJsonRpcMessage(message) { + var object = JSON.parse(message); + + return { + _id: object.id, + data: object.result, + error: object.error + }; +} + +HttpRpcProvider.prototype.sendRequest = function (payload, cb) { + var data = formatJsonRpcObject(payload); + + var request = new XMLHttpRequest(); + request.open("POST", this.host, true); + request.send(JSON.stringify(data)); + request.onreadystatechange = function () { + if (request.readyState === 4 && cb) { + cb(request); + } + }; +}; + +HttpRpcProvider.prototype.send = function (payload) { + var self = this; + this.sendRequest(payload, function (request) { + self.handlers.forEach(function (handler) { + handler.call(self, formatJsonRpcMessage(request.responseText)); + }); + }); +}; + +HttpRpcProvider.prototype.poll = function (payload, id) { + var self = this; + this.sendRequest(payload, function (request) { + var parsed = JSON.parse(request.responseText); + if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) { + return; + } + self.handlers.forEach(function (handler) { + handler.call(self, {_event: payload.call, _id: id, data: parsed.result}); + }); + }); +}; + +Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { + set: function (handler) { + this.handlers.push(handler); + } +}); + +module.exports = HttpRpcProvider; + +},{}],4:[function(require,module,exports){ +/* + 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file main.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +var abi = require('./abi'); + +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" ? "eth_blockByHash" : "eth_blockByNumber"; + }; + + var transactionCall = function (args) { + return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; + }; + + var uncleCall = function (args) { + return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; + }; + + var methods = [ + { name: 'balanceAt', call: 'eth_balanceAt' }, + { name: 'stateAt', call: 'eth_stateAt' }, + { name: 'storageAt', call: 'eth_storageAt' }, + { name: 'countAt', call: 'eth_countAt'}, + { name: 'codeAt', call: 'eth_codeAt' }, + { name: 'transact', call: 'eth_transact' }, + { name: 'call', call: 'eth_call' }, + { name: 'block', call: blockCall }, + { name: 'transaction', call: transactionCall }, + { name: 'uncle', call: uncleCall }, + { name: 'compilers', call: 'eth_compilers' }, + { name: 'lll', call: 'eth_lll' }, + { name: 'solidity', call: 'eth_solidity' }, + { name: 'serpent', call: 'eth_serpent' } + ]; + return methods; +}; + +var ethProperties = function () { + return [ + { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, + { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, + { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, + { name: 'gasPrice', getter: 'eth_gasPrice' }, + { name: 'account', getter: 'eth_account' }, + { name: 'accounts', getter: 'eth_accounts' }, + { name: 'peerCount', getter: 'eth_peerCount' }, + { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, + { name: 'number', getter: 'eth_number'} + ]; +}; + +var dbMethods = function () { + return [ + { name: 'put', call: 'db_put' }, + { name: 'get', call: 'db_get' }, + { name: 'putString', call: 'db_putString' }, + { name: 'getString', call: 'db_getString' } + ]; +}; + +var shhMethods = function () { + return [ + { name: 'post', call: 'shh_post' }, + { name: 'newIdentity', call: 'shh_newIdentity' }, + { name: 'haveIdentity', call: 'shh_haveIdentity' }, + { name: 'newGroup', call: 'shh_newGroup' }, + { name: 'addToGroup', call: 'shh_addToGroup' } + ]; +}; + +var ethWatchMethods = function () { + var newFilter = function (args) { + return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; + }; + + return [ + { name: 'newFilter', call: newFilter }, + { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, + { name: 'getMessages', call: 'eth_getMessages' } + ]; +}; + +var shhWatchMethods = function () { + return [ + { name: 'newFilter', call: 'shh_newFilter' }, + { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, + { name: 'getMessage', call: 'shh_getMessages' } + ]; +}; + +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 (err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }).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(err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }; + 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 (err, result) { + if (!err) { + resolve(result); + return; + } + reject(err); + }); + }); + }).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; + if (hex.substring(0, 2) === '0x') + i = 2; + 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 "0x" + hex; + }, + + eth: { + prototype: Object(), // jshint ignore:line + watch: function (params) { + return new Filter(params, ethWatch); + } + }, + + db: { + prototype: Object() // jshint ignore:line + }, + + shh: { + prototype: Object(), // jshint ignore:line + 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); + } +}; + +setupMethods(web3.eth, ethMethods()); +setupProperties(web3.eth, ethProperties()); +setupMethods(web3.db, dbMethods()); +setupMethods(web3.shh, shhMethods()); + +var ethWatch = { + changed: 'eth_changed' +}; +setupMethods(ethWatch, ethWatchMethods()); +var shhWatch = { + changed: 'shh_changed' +}; +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(); +}; + +web3.haveProvider = function() { + return !!web3.provider.provider; +}; + +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.error, data.data); + delete web3._callbacks[data._id]; + } + } +} + +web3.contract = function (address, desc) { + var inputParser = abi.inputParser(desc); + var outputParser = abi.outputParser(desc); + + var contract = {}; + + desc.forEach(function (method) { + contract[method.name] = function () { + var params = Array.prototype.slice.call(arguments); + var parsed = inputParser[method.name].apply(null, params); + + var onSuccess = function (result) { + return outputParser[method.name](result); + }; + + return { + call: function (extra) { + extra = extra || {}; + extra.to = address; + extra.data = parsed; + return web3.eth.call(extra).then(onSuccess); + }, + transact: function (extra) { + extra = extra || {}; + extra.to = address; + extra.data = parsed; + return web3.eth.transact(extra).then(onSuccess); + } + }; + }; + }); + + return contract; +}; + +module.exports = web3; + + +},{"./abi":1}],5:[function(require,module,exports){ +/* + 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file qt.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * @date 2014 + */ + +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); + } +}); + +module.exports = QtProvider; + +},{}],6:[function(require,module,exports){ +/* + 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** @file websocket.js + * @authors: + * Jeffrey Wilcke + * Marek Kotewicz + * Marian Oancea + * @date 2014 + */ + +if ("build" !== "build") {/* + var WebSocket = require('ws'); // jshint ignore:line +*/} + +var WebSocketProvider = function(host) { + // onmessage handlers + this.handlers = []; + // queue will be filled with messages if send is invoked before the ws is ready + this.queued = []; + this.ready = false; + + this.ws = new WebSocket(host); + + var self = this; + this.ws.onmessage = function(event) { + for(var i = 0; i < self.handlers.length; i++) { + self.handlers[i].call(self, JSON.parse(event.data), event); + } + }; + + this.ws.onopen = function() { + self.ready = true; + + for(var i = 0; i < self.queued.length; i++) { + // Resend + self.send(self.queued[i]); + } + }; +}; + +WebSocketProvider.prototype.send = function(payload) { + if(this.ready) { + var data = JSON.stringify(payload); + + this.ws.send(data); + } else { + this.queued.push(payload); + } +}; + +WebSocketProvider.prototype.onMessage = function(handler) { + this.handlers.push(handler); +}; + +WebSocketProvider.prototype.unload = function() { + this.ws.close(); +}; +Object.defineProperty(WebSocketProvider.prototype, "onmessage", { + set: function(provider) { this.onMessage(provider); } +}); + +module.exports = WebSocketProvider; + +},{}],"web3":[function(require,module,exports){ +var web3 = require('./lib/main'); +web3.providers.WebSocketProvider = require('./lib/websocket'); +web3.providers.HttpRpcProvider = require('./lib/httprpc'); +web3.providers.QtProvider = require('./lib/qt'); +web3.providers.AutoProvider = require('./lib/autoprovider'); + +module.exports = web3; + +},{"./lib/autoprovider":2,"./lib/httprpc":3,"./lib/main":4,"./lib/qt":5,"./lib/websocket":6}]},{},[]) + + +//# sourceMappingURL=ethereum.js.map \ No newline at end of file diff --git a/libjsqrc/ethereum.min.js b/libjsqrc/ethereum.min.js deleted file mode 100644 index b23886cab..000000000 --- a/libjsqrc/ethereum.min.js +++ /dev/null @@ -1 +0,0 @@ -require=function t(e,n,r){function o(s,a){if(!n[s]){if(!e[s]){var u="function"==typeof require&&require;if(!a&&u)return u(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[s]={exports:{}};e[s][0].call(l.exports,function(t){var n=e[s][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;sr&&(e=t.charCodeAt(r),0!==e);r+=2)n+=String.fromCharCode(parseInt(t.substr(r,2),16));return n},toDecimal:function(t){return parseInt(t,16)},fromAscii:function(t,e){e=void 0===e?32:e;for(var n=this.toHex(t);n.length<2*e;)n+="00";return"0x"+n},eth:{prototype:Object(),watch:function(t){return new a(t,o)}},db:{prototype:Object()},shh:{prototype:Object(),watch:function(t){return new a(t,i)}},on:function(t,e,n){return void 0===m._events[t]&&(m._events[t]={}),m._events[t][e]=n,this},off:function(t,e){return void 0!==m._events[t]&&delete m._events[t][e],this},trigger:function(t,e,n){var r,o=m._events[t];o&&o[e]&&(r=o[e])(n)}};v(m.eth,c()),g(m.eth,l()),v(m.db,h()),v(m.shh,p()),o={changed:"eth_changed"},v(o,d()),i={changed:"shh_changed"},v(i,f()),s=function(){var t,e;this.queued=[],this.polls=[],this.ready=!1,this.provider=void 0,this.id=1,t=this,(e=function(){t.provider&&t.provider.poll&&t.polls.forEach(function(e){e.data._id=t.id,t.id++,t.provider.poll(e.data,e.id)}),setTimeout(e,12e3)})()},s.prototype.send=function(t,e){t._id=this.id,e&&(m._callbacks[t._id]=e),t.args=t.args||[],this.id++,void 0!==this.provider?this.provider.send(t):(console.warn("provider is not set"),this.queued.push(t))},s.prototype.set=function(t){void 0!==this.provider&&void 0!==this.provider.unload&&this.provider.unload(),this.provider=t,this.ready=!0},s.prototype.sendQueued=function(){for(var t=0;this.queued.length;t++)this.send(this.queued[t])},s.prototype.installed=function(){return void 0!==this.provider},s.prototype.startPolling=function(t,e){this.provider&&this.provider.poll&&this.polls.push({data:t,id:e})},s.prototype.stopPolling=function(t){var e,n;for(e=this.polls.length;e--;)n=this.polls[e],n.id===t&&this.polls.splice(e,1)},m.provider=new s,m.setProvider=function(t){t.onmessage=r,m.provider.set(t),m.provider.sendQueued()},m.haveProvider=function(){return!!m.provider.provider},a=function(t,e){this.impl=e,this.callbacks=[];var n=this;this.promise=e.newFilter(t),this.promise.then(function(t){n.id=t,m.on(e.changed,t,n.trigger.bind(n)),m.provider.startPolling({call:e.changed,args:[t]},t)})},a.prototype.arrived=function(t){this.changed(t)},a.prototype.changed=function(t){var e=this;this.promise.then(function(){e.callbacks.push(t)})},a.prototype.trigger=function(t){for(var e=0;e es6-promise-2.0.0.js setup.js - ethereum.min.js + ethereum.js diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 2f2219461..0c6afd2b1 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -19,6 +19,7 @@ target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) target_link_libraries(${EXECUTABLE} gmp) target_link_libraries(${EXECUTABLE} solidity) +target_link_libraries(${EXECUTABLE} serpent) if(MINIUPNPC_LS) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LS}) endif() diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 9526b2f9b..ecbbacba7 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include using namespace std; using namespace dev; @@ -538,17 +540,56 @@ Json::Value WebThreeStubServer::eth_compilers() Json::Value ret(Json::arrayValue); ret.append("lll"); ret.append("solidity"); + ret.append("serpent"); return ret; } std::string WebThreeStubServer::eth_lll(std::string const& _code) { - return toJS(dev::eth::compileLLL(_code)); + string res; + vector errors; + res = toJS(dev::eth::compileLLL(_code, true, &errors)); + cwarn << "LLL compilation errors: " << errors; + return res; +} + +std::string WebThreeStubServer::eth_serpent(std::string const& _code) +{ + string res; + try + { + res = toJS(dev::asBytes(::compile(_code))); + } + catch (string err) + { + cwarn << "Solidity compilation error: " << err; + } + catch (...) + { + cwarn << "Uncought serpent compilation exception"; + } + return res; } std::string WebThreeStubServer::eth_solidity(std::string const& _code) { - return toJS(dev::solidity::CompilerStack::staticCompile(_code, false)); + string res; + dev::solidity::CompilerStack compiler; + try + { + res = toJS(compiler.compile(_code, true)); + } + catch (dev::Exception const& exception) + { + ostringstream error; + solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler.getScanner()); + cwarn << "Solidity compilation error: " << error.str(); + } + catch (...) + { + cwarn << "Uncought solidity compilation exception"; + } + return res; } int WebThreeStubServer::eth_number() diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 5207ed1df..7d25f5954 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -87,6 +87,7 @@ public: virtual bool eth_setDefaultBlock(int const& _block); virtual bool eth_setListening(bool const& _listening); virtual std::string eth_lll(std::string const& _s); + virtual std::string eth_serpent(std::string const& _s); virtual bool eth_setMining(bool const& _mining); virtual std::string eth_solidity(std::string const& _code); virtual std::string eth_stateAt(std::string const& _address, std::string const& _storage); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 5fb548103..b86576572 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -37,6 +37,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newFilterStringI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_number", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_numberI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_peerCount", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_peerCountI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_serpent", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_serpentI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_setCoinbase", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_setCoinbaseI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_setDefaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_setDefaultBlockI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_setListening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_setListeningI); @@ -181,6 +182,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_peerCount(); } + inline virtual void eth_serpentI(const Json::Value& request, Json::Value& response) + { + response = this->eth_serpent(request[0u].asString()); + } + inline virtual void eth_setCoinbaseI(const Json::Value& request, Json::Value& response) { response = this->eth_setCoinbase(request[0u].asString()); @@ -311,6 +317,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerclient->CallMethod("eth_serpent",p); + if (result.isString()) + return result.asString(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + bool eth_setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; From 5d55344f3a121fbe08644a50a11e63ad71dd630d Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 17 Nov 2014 16:01:48 +0100 Subject: [PATCH 31/44] common changes in ethereum.js --- libjsqrc/ethereum.js | 111 ++++++++++++++++++++++++--------------- libqethereum/QEthereum.h | 2 +- 2 files changed, 71 insertions(+), 42 deletions(-) diff --git a/libjsqrc/ethereum.js b/libjsqrc/ethereum.js index e65489a66..bd5b4fb4e 100644 --- a/libjsqrc/ethereum.js +++ b/libjsqrc/ethereum.js @@ -319,6 +319,71 @@ module.exports = AutoProvider; You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ +/** @file contract.js + * @authors: + * Marek Kotewicz + * @date 2014 + */ + +if ("build" !== 'build') {/* + var web3 = require('./web3'); // jshint ignore:line +*/} +var abi = require('./abi'); + +var contract = function (address, desc) { + var inputParser = abi.inputParser(desc); + var outputParser = abi.outputParser(desc); + + var contract = {}; + + desc.forEach(function (method) { + contract[method.name] = function () { + var params = Array.prototype.slice.call(arguments); + var parsed = inputParser[method.name].apply(null, params); + + var onSuccess = function (result) { + return outputParser[method.name](result); + }; + + return { + call: function (extra) { + extra = extra || {}; + extra.to = address; + extra.data = parsed; + return web3.eth.call(extra).then(onSuccess); + }, + transact: function (extra) { + extra = extra || {}; + extra.to = address; + extra.data = parsed; + return web3.eth.transact(extra).then(onSuccess); + } + }; + }; + }); + + return contract; +}; + +module.exports = contract; + +},{"./abi":1}],4:[function(require,module,exports){ +/* + 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ /** @file httprpc.js * @authors: * Marek Kotewicz @@ -397,7 +462,7 @@ Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { module.exports = HttpRpcProvider; -},{}],4:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -422,8 +487,6 @@ module.exports = HttpRpcProvider; * @date 2014 */ -var abi = require('./abi'); - function flattenPromise (obj) { if (obj instanceof Promise) { return Promise.resolve(obj); @@ -856,45 +919,10 @@ function messageHandler(data) { } } -web3.contract = function (address, desc) { - var inputParser = abi.inputParser(desc); - var outputParser = abi.outputParser(desc); - - var contract = {}; - - desc.forEach(function (method) { - contract[method.name] = function () { - var params = Array.prototype.slice.call(arguments); - var parsed = inputParser[method.name].apply(null, params); - - var onSuccess = function (result) { - return outputParser[method.name](result); - }; - - return { - call: function (extra) { - extra = extra || {}; - extra.to = address; - extra.data = parsed; - return web3.eth.call(extra).then(onSuccess); - }, - transact: function (extra) { - extra = extra || {}; - extra.to = address; - extra.data = parsed; - return web3.eth.transact(extra).then(onSuccess); - } - }; - }; - }); - - return contract; -}; - module.exports = web3; -},{"./abi":1}],5:[function(require,module,exports){ +},{}],6:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -941,7 +969,7 @@ Object.defineProperty(QtProvider.prototype, "onmessage", { module.exports = QtProvider; -},{}],6:[function(require,module,exports){ +},{}],7:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1025,10 +1053,11 @@ web3.providers.WebSocketProvider = require('./lib/websocket'); web3.providers.HttpRpcProvider = require('./lib/httprpc'); web3.providers.QtProvider = require('./lib/qt'); web3.providers.AutoProvider = require('./lib/autoprovider'); +web3.contract = require('./lib/contract'); module.exports = web3; -},{"./lib/autoprovider":2,"./lib/httprpc":3,"./lib/main":4,"./lib/qt":5,"./lib/websocket":6}]},{},[]) +},{"./lib/autoprovider":2,"./lib/contract":3,"./lib/httprpc":4,"./lib/main":5,"./lib/qt":6,"./lib/websocket":7}]},{},[]) //# sourceMappingURL=ethereum.js.map \ No newline at end of file diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index 7644152de..6a4e640e5 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -85,7 +85,7 @@ private: _frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \ _frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/es6-promise-2.0.0.js")); \ - _frame->evaluateJavaScript(contentsOfQResource(":/js/ethereum.min.js")); \ + _frame->evaluateJavaScript(contentsOfQResource(":/js/ethereum.js")); \ _frame->evaluateJavaScript(contentsOfQResource(":/js/setup.js")); \ } From 9cf1fb0dc7cfadd985c359110b429b39fe5ccdc1 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 17 Nov 2014 20:16:40 +0100 Subject: [PATCH 32/44] transact value may be int --- libweb3jsonrpc/WebThreeStubServer.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index ecbbacba7..c83d3f763 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -380,8 +380,13 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) ret.from = jsToAddress(_json["from"].asString()); if (_json["to"].isString()) ret.to = jsToAddress(_json["to"].asString()); - if (_json["value"].isString()) - ret.value = jsToU256(_json["value"].asString()); + if (!_json["value"].empty()) + { + if (_json["value"].isString()) + ret.value = jsToU256(_json["value"].asString()); + else if (_json["value"].isInt()) + ret.value = u256(_json["value"].asInt()); + } if (!_json["gas"].empty()) { if (_json["gas"].isString()) From 3a1b83538bf43401f6269e055afd3b8ffbbf2e8a Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 18 Nov 2014 10:45:40 +0100 Subject: [PATCH 33/44] migration to log filters, not finished --- alethzero/MainWin.cpp | 17 ++++- alethzero/MainWin.h | 1 + libethereum/Client.cpp | 92 ++++++++++-------------- libethereum/Client.h | 14 ++-- libethereum/Interface.h | 20 ++++-- libethereum/State.cpp | 6 +- libethereum/State.h | 2 +- libweb3jsonrpc/WebThreeStubServer.cpp | 100 +++----------------------- 8 files changed, 89 insertions(+), 163 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 280a70fe1..6bad7ea75 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -241,13 +241,22 @@ void Main::onKeysChanged() installBalancesWatch(); } -unsigned Main::installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f) +unsigned Main::installWatch(dev::eth::LogFilter const& _tf, std::function const& _f) { auto ret = ethereum()->installWatch(_tf); m_handlers[ret] = _f; return ret; } +unsigned Main::installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f) +{ +// auto ret = ethereum()->installWatch(_tf); +// m_handlers[ret] = _f; +// return ret; +} + + + unsigned Main::installWatch(dev::h256 _tf, std::function const& _f) { auto ret = ethereum()->installWatch(_tf); @@ -263,8 +272,10 @@ void Main::uninstallWatch(unsigned _w) void Main::installWatches() { - installWatch(dev::eth::MessageFilter().altered(c_config, 0), [=](){ installNameRegWatch(); }); - installWatch(dev::eth::MessageFilter().altered(c_config, 1), [=](){ installCurrenciesWatch(); }); + installWatch(dev::eth::LogFilter().address(c_config), [=]() { installNameRegWatch(); }); + installWatch(dev::eth::LogFilter().address(c_config), [=]() { installCurrenciesWatch(); }); +// installWatch(dev::eth::MessageFilter().altered(c_config, 0), [=](){ installNameRegWatch(); }); +// installWatch(dev::eth::MessageFilter().altered(c_config, 1), [=](){ installCurrenciesWatch(); }); installWatch(dev::eth::PendingChangedFilter, [=](){ onNewPending(); }); installWatch(dev::eth::ChainChangedFilter, [=](){ onNewBlock(); }); } diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 14877f610..a401333a5 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -189,6 +189,7 @@ private: dev::u256 value() const; dev::u256 gasPrice() const; + unsigned installWatch(dev::eth::LogFilter const& _tf, std::function const& _f); unsigned installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f); unsigned installWatch(dev::h256 _tf, std::function const& _f); void uninstallWatch(unsigned _w); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 0be499541..71638ce8f 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -159,7 +159,7 @@ void Client::clearPending() if (!m_postMine.pending().size()) return; for (unsigned i = 0; i < m_postMine.pending().size(); ++i) - appendFromNewPending(m_postMine.oldBloom(i), changeds); + appendFromNewPending(m_postMine.logBloom(i), changeds); changeds.insert(PendingChangedFilter); m_postMine = m_preMine; } @@ -181,7 +181,7 @@ unsigned Client::installWatch(h256 _h) return ret; } -unsigned Client::installWatch(MessageFilter const& _f) +unsigned Client::installWatch(LogFilter const& _f) { lock_guard l(m_filterLock); @@ -222,7 +222,7 @@ void Client::noteChanged(h256Set const& _filters) } } -void Client::appendFromNewPending(h256 _bloom, h256Set& o_changed) const +void Client::appendFromNewPending(LogBloom _bloom, h256Set& o_changed) const { lock_guard l(m_filterLock); for (pair const& i: m_filters) @@ -232,12 +232,19 @@ void Client::appendFromNewPending(h256 _bloom, h256Set& o_changed) const void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const { - auto d = m_bc.details(_block); - +// auto d = m_bc.details(_block); + auto d = m_bc.logBlooms(_block); + lock_guard l(m_filterLock); for (pair const& i: m_filters) - if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.bloom)) - o_changed.insert(i.first); + for (auto b: d.blooms) + if (i.second.filter.matches(b)) + { + o_changed.insert(i.first); + break; + } +// if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.bloom)) +// o_changed.insert(i.first); } void Client::setForceMining(bool _enable) @@ -440,7 +447,7 @@ void Client::doWork() // returns h256s as blooms, once for each transaction. cwork << "postSTATE <== TQ"; - h256s newPendingBlooms = m_postMine.sync(m_tq); + h512s newPendingBlooms = m_postMine.sync(m_tq); if (newPendingBlooms.size()) { for (auto i: newPendingBlooms) @@ -564,9 +571,9 @@ BlockInfo Client::uncle(h256 _blockHash, unsigned _i) const return BlockInfo::fromHeader(b[2][_i].data()); } -PastMessages Client::messages(MessageFilter const& _f) const +LogEntries Client::logs(LogFilter const& _f) const { - PastMessages ret; + LogEntries ret; unsigned begin = min(m_bc.number(), (unsigned)_f.latest()); unsigned end = min(begin, (unsigned)_f.earliest()); unsigned m = _f.max(); @@ -578,23 +585,22 @@ PastMessages Client::messages(MessageFilter const& _f) const ReadGuard l(x_stateDB); for (unsigned i = 0; i < m_postMine.pending().size(); ++i) { - // Might have a transaction that contains a matching message. - Manifest const& ms = m_postMine.changesFromPending(i); - PastMessages pm = _f.matches(ms, i); - if (pm.size()) + // Might have a transaction that contains a matching log. + TransactionReceipt const& tr = m_postMine.receipt(i); + LogEntries le = _f.matches(tr); + if (le.size()) { - auto ts = time(0); - for (unsigned j = 0; j < pm.size() && ret.size() != m; ++j) + for (unsigned j = 0; j < le.size() && ret.size() != m; ++j) if (s) s--; else - // Have a transaction that contains a matching message. - ret.insert(ret.begin(), pm[j].polish(h256(), ts, m_bc.number() + 1, m_postMine.address())); + ret.insert(ret.begin(), le[j]); } } } #if ETH_DEBUG + // fill these params unsigned skipped = 0; unsigned falsePos = 0; #endif @@ -602,50 +608,28 @@ PastMessages Client::messages(MessageFilter const& _f) const unsigned n = begin; for (; ret.size() != m && n != end; n--, h = m_bc.details(h).parent) { - auto d = m_bc.details(h); #if ETH_DEBUG int total = 0; #endif - if (_f.matches(d.bloom)) - { - // Might have a block that contains a transaction that contains a matching message. - auto bs = m_bc.blooms(h).blooms; - Manifests ms; - BlockInfo bi; - for (unsigned i = 0; i < bs.size(); ++i) - if (_f.matches(bs[i])) + //? check block bloom + for (TransactionReceipt receipt: m_bc.receipts(h).receipts) + if (_f.matches(receipt.bloom())) + { + LogEntries le = _f.matches(receipt); + if (le.size()) { - // Might have a transaction that contains a matching message. - if (ms.empty()) - ms = m_bc.traces(h).traces; - Manifest const& changes = ms[i]; - PastMessages pm = _f.matches(changes, i); - if (pm.size()) - { #if ETH_DEBUG - total += pm.size(); + total += le.size(); #endif - if (!bi) - bi.populate(m_bc.block(h)); - auto ts = bi.timestamp; - auto cb = bi.coinbaseAddress; - for (unsigned j = 0; j < pm.size() && ret.size() != m; ++j) - if (s) - s--; - else - // Have a transaction that contains a matching message. - ret.push_back(pm[j].polish(h, ts, n, cb)); + for (unsigned j = 0; j < le.size() && ret.size() != m; ++j) + { + if (s) + s--; + else + ret.insert(ret.begin(), le[j]); } } -#if ETH_DEBUG - if (!total) - falsePos++; - } - else - skipped++; -#else - } -#endif + } if (n == end) break; } diff --git a/libethereum/Client.h b/libethereum/Client.h index 8ec65c199..283251e24 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -79,9 +79,11 @@ static const int GenesisBlock = INT_MIN; struct InstalledFilter { - InstalledFilter(MessageFilter const& _f): filter(_f) {} +// InstalledFilter(MessageFilter const& _f): filter(_f) {} +// MessageFilter filter; + InstalledFilter(LogFilter const& _f): filter(_f) {} - MessageFilter filter; + LogFilter filter; unsigned refCount = 1; }; @@ -152,14 +154,14 @@ public: virtual bytes codeAt(Address _a, int _block) const; virtual std::map storageAt(Address _a, int _block) const; - virtual unsigned installWatch(MessageFilter const& _filter); + virtual unsigned installWatch(LogFilter const& _filter); virtual unsigned installWatch(h256 _filterId); virtual void uninstallWatch(unsigned _watchId); virtual bool peekWatch(unsigned _watchId) const { std::lock_guard l(m_filterLock); try { return m_watches.at(_watchId).changes != 0; } catch (...) { return false; } } virtual bool checkWatch(unsigned _watchId) { std::lock_guard l(m_filterLock); bool ret = false; try { ret = m_watches.at(_watchId).changes != 0; m_watches.at(_watchId).changes = 0; } catch (...) {} return ret; } - virtual PastMessages messages(unsigned _watchId) const { try { std::lock_guard l(m_filterLock); return messages(m_filters.at(m_watches.at(_watchId).id).filter); } catch (...) { return PastMessages(); } } - virtual PastMessages messages(MessageFilter const& _filter) const; + virtual LogEntries logs(unsigned _watchId) const { try { std::lock_guard l(m_filterLock); return logs(m_filters.at(m_watches.at(_watchId).id).filter); } catch (...) { return LogEntries(); } } + virtual LogEntries logs(LogFilter const& _filter) const; // [EXTRA API]: @@ -259,7 +261,7 @@ private: /// Collate the changed filters for the bloom filter of the given pending transaction. /// Insert any filters that are activated into @a o_changed. - void appendFromNewPending(h256 _pendingTransactionBloom, h256Set& o_changed) const; + void appendFromNewPending(LogBloom _pendingTransactionBloom, h256Set& o_changed) const; /// Collate the changed filters for the hash of the given block. /// Insert any filters that are activated into @a o_changed. diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 7ae650590..add9a1bda 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -84,13 +84,18 @@ public: virtual bytes codeAt(Address _a, int _block) const = 0; virtual std::map storageAt(Address _a, int _block) const = 0; - // [MESSAGE API] - - virtual PastMessages messages(unsigned _watchId) const = 0; - virtual PastMessages messages(MessageFilter const& _filter) const = 0; +// // [MESSAGE API] +// +// virtual PastMessages messages(unsigned _watchId) const = 0; +// virtual PastMessages messages(MessageFilter const& _filter) const = 0; + + // [LOGS API] + + virtual LogEntries logs(unsigned _watchId) const = 0; + virtual LogEntries logs(LogFilter const& _filter) const = 0; /// Install, uninstall and query watches. - virtual unsigned installWatch(MessageFilter const& _filter) = 0; + virtual unsigned installWatch(LogFilter const& _filter) = 0; virtual unsigned installWatch(h256 _filterId) = 0; virtual void uninstallWatch(unsigned _watchId) = 0; virtual bool peekWatch(unsigned _watchId) const = 0; @@ -175,12 +180,13 @@ class Watch: public boost::noncopyable public: Watch() {} Watch(Interface& _c, h256 _f): m_c(&_c), m_id(_c.installWatch(_f)) {} - Watch(Interface& _c, MessageFilter const& _tf): m_c(&_c), m_id(_c.installWatch(_tf)) {} + Watch(Interface& _c, LogFilter const& _tf): m_c(&_c), m_id(_c.installWatch(_tf)) {} ~Watch() { if (m_c) m_c->uninstallWatch(m_id); } bool check() { return m_c ? m_c->checkWatch(m_id) : false; } bool peek() { return m_c ? m_c->peekWatch(m_id) : false; } - PastMessages messages() const { return m_c->messages(m_id); } +// PastMessages messages() const { return m_c->messages(m_id); } + LogEntries logs() const { return m_c->logs(m_id); } private: Interface* m_c = nullptr; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 69faf983c..a37c26645 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -534,10 +534,10 @@ bool State::cull(TransactionQueue& _tq) const return ret; } -h256s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) +h512s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) { // TRANSACTIONS - h256s ret; + h512s ret; auto ts = _tq.transactions(); for (int goodTxs = 1; goodTxs;) @@ -552,7 +552,7 @@ h256s State::sync(TransactionQueue& _tq, bool* o_transactionQueueChanged) uncommitToMine(); // boost::timer t; execute(i.second); - ret.push_back(m_receipts.back().changes().bloom()); + ret.push_back(m_receipts.back().bloom()); _tq.noteGood(i); ++goodTxs; // cnote << "TX took:" << t.elapsed() * 1000; diff --git a/libethereum/State.h b/libethereum/State.h index d3c7fa313..9c41843ff 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -147,7 +147,7 @@ public: /// @returns a list of bloom filters one for each transaction placed from the queue into the state. /// @a o_transactionQueueChanged boolean pointer, the value of which will be set to true if the transaction queue /// changed and the pointer is non-null - h256s sync(TransactionQueue& _tq, bool* o_transactionQueueChanged = nullptr); + h512s sync(TransactionQueue& _tq, bool* o_transactionQueueChanged = nullptr); /// Like sync but only operate on _tq, killing the invalid/old ones. bool cull(TransactionQueue& _tq) const; diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index c83d3f763..6bedfed3f 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -59,34 +59,6 @@ static Json::Value toJson(dev::eth::BlockInfo const& _bi) 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; @@ -111,15 +83,7 @@ static Json::Value toJson(dev::eth::LogEntry const& _e) return res; } -static Json::Value toJson(std::map const& _storage) -{ - Json::Value res(Json::objectValue); - for (auto i: _storage) - res[toJS(i.first)] = toJS(i.second); - return res; -} - -/*static*/ Json::Value toJson(dev::eth::LogEntries const& _es) // commented to avoid warning. Uncomment once in use @ poC-7. +static Json::Value toJson(dev::eth::LogEntries const& _es) // commented to avoid warning. Uncomment once in use @ poC-7. { Json::Value res; for (dev::eth::LogEntry const& e: _es) @@ -127,59 +91,15 @@ static Json::Value toJson(std::map const& _storage) return res; } -static dev::eth::MessageFilter toMessageFilter(Json::Value const& _json) +static Json::Value toJson(std::map const& _storage) { - dev::eth::MessageFilter filter; - if (!_json.isObject() || _json.empty()) - return filter; - - if (_json["earliest"].isInt()) - filter.withEarliest(_json["earliest"].asInt()); - if (_json["latest"].isInt()) - filter.withLatest(_json["lastest"].asInt()); - if (_json["max"].isInt()) - filter.withMax(_json["max"].asInt()); - if (_json["skip"].isInt()) - filter.withSkip(_json["skip"].asInt()); - if (!_json["from"].empty()) - { - if (_json["from"].isArray()) - { - for (auto i : _json["from"]) - if (i.isString()) - filter.from(jsToAddress(i.asString())); - } - else if (_json["from"].isString()) - filter.from(jsToAddress(_json["from"].asString())); - } - if (!_json["to"].empty()) - { - if (_json["to"].isArray()) - { - for (auto i : _json["to"]) - if (i.isString()) - filter.to(jsToAddress(i.asString())); - } - else if (_json["to"].isString()) - filter.to(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; + Json::Value res(Json::objectValue); + for (auto i: _storage) + res[toJS(i.first)] = toJS(i.second); + return res; } -/*static*/ dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to avoid warning. Uncomment once in use @ PoC-7. +static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to avoid warning. Uncomment once in use @ PoC-7. { dev::eth::LogFilter filter; if (!_json.isObject() || _json.empty()) @@ -478,7 +398,8 @@ Json::Value WebThreeStubServer::eth_getMessages(int const& _id) { if (!client()) return Json::Value(); - return toJson(client()->messages(_id)); +// return toJson(client()->messages(_id)); + return toJson(client()->logs(_id)); } std::string WebThreeStubServer::db_getString(std::string const& _name, std::string const& _key) @@ -509,7 +430,8 @@ int WebThreeStubServer::eth_newFilter(Json::Value const& _json) unsigned ret = -1; if (!client()) return ret; - ret = client()->installWatch(toMessageFilter(_json)); +// ret = client()->installWatch(toMessageFilter(_json)); + ret = client()->installWatch(toLogFilter(_json)); return ret; } From c04f252b29707f767329417a58168e1b0c6e2a96 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 18 Nov 2014 11:14:28 +0100 Subject: [PATCH 34/44] changes in az mainwin --- alethzero/MainWin.cpp | 21 +++++---------------- alethzero/MainWin.h | 1 - 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 6bad7ea75..460669cf9 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -248,15 +248,6 @@ unsigned Main::installWatch(dev::eth::LogFilter const& _tf, std::function const& _f) -{ -// auto ret = ethereum()->installWatch(_tf); -// m_handlers[ret] = _f; -// return ret; -} - - - unsigned Main::installWatch(dev::h256 _tf, std::function const& _f) { auto ret = ethereum()->installWatch(_tf); @@ -274,8 +265,6 @@ void Main::installWatches() { installWatch(dev::eth::LogFilter().address(c_config), [=]() { installNameRegWatch(); }); installWatch(dev::eth::LogFilter().address(c_config), [=]() { installCurrenciesWatch(); }); -// installWatch(dev::eth::MessageFilter().altered(c_config, 0), [=](){ installNameRegWatch(); }); -// installWatch(dev::eth::MessageFilter().altered(c_config, 1), [=](){ installCurrenciesWatch(); }); installWatch(dev::eth::PendingChangedFilter, [=](){ onNewPending(); }); installWatch(dev::eth::ChainChangedFilter, [=](){ onNewBlock(); }); } @@ -283,18 +272,18 @@ void Main::installWatches() void Main::installNameRegWatch() { uninstallWatch(m_nameRegFilter); - m_nameRegFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); + m_nameRegFilter = installWatch(dev::eth::LogFilter().address((u160)ethereum()->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); } void Main::installCurrenciesWatch() { uninstallWatch(m_currenciesFilter); - m_currenciesFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); + m_currenciesFilter = installWatch(dev::eth::LogFilter().address((u160)ethereum()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); } void Main::installBalancesWatch() { - dev::eth::MessageFilter tf; + dev::eth::LogFilter tf; vector
altCoins; Address coinsAddr = right160(ethereum()->stateAt(c_config, 1)); @@ -302,9 +291,9 @@ void Main::installBalancesWatch() altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1))); for (auto i: m_myKeys) { - tf.altered(i.address()); + tf.address(i.address()); for (auto c: altCoins) - tf.altered(c, (u160)i.address()); + tf.address(c); } uninstallWatch(m_balancesFilter); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index a401333a5..50b9df413 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -190,7 +190,6 @@ private: dev::u256 gasPrice() const; unsigned installWatch(dev::eth::LogFilter const& _tf, std::function const& _f); - unsigned installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f); unsigned installWatch(dev::h256 _tf, std::function const& _f); void uninstallWatch(unsigned _w); From b876f24ea94feb67033030bca5287c2753b3dbc5 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 18 Nov 2014 11:56:09 +0100 Subject: [PATCH 35/44] common changes --- libethereum/Client.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 71638ce8f..01aa75b9a 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -232,18 +232,11 @@ void Client::appendFromNewPending(LogBloom _bloom, h256Set& o_changed) const void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const { -// auto d = m_bc.details(_block); - auto d = m_bc.logBlooms(_block); - - lock_guard l(m_filterLock); - for (pair const& i: m_filters) - for (auto b: d.blooms) - if (i.second.filter.matches(b)) - { - o_changed.insert(i.first); - break; - } -// if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.bloom)) +// auto d = m_bc.info(_block); +// +// lock_guard l(m_filterLock); +// for (pair const& i: m_filters) +// if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom)) // o_changed.insert(i.first); } From 908e0c498a0e8c38d7ab72ea377ee736d9334b0c Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 18 Nov 2014 12:00:58 +0100 Subject: [PATCH 36/44] Remove overly verbose log. --- stdserv.js | 2 +- test/crypto.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stdserv.js b/stdserv.js index fe681414e..676aaa949 100644 --- a/stdserv.js +++ b/stdserv.js @@ -17,7 +17,7 @@ config.then(function() { web3.eth.accounts.then(function(accounts) { var funded = send(accounts[0], '100000000000000000000', accounts[1]); - funded.then(function(){ env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); regName(accounts[1], 'Gav Would'); env.note("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); approve(accounts[1], exchange); }); + funded.then(function(){ regName(accounts[1], 'Gav Would'); approve(accounts[1], exchange); }); regName(accounts[0], 'Gav'); approve(accounts[0], exchange).then(function(){ offer(accounts[0], coin, '5000', '0', '5000000000000000000'); }); diff --git a/test/crypto.cpp b/test/crypto.cpp index 08236135a..87047f0d4 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) KeyPair key(secret); bytes m(1, 0xff); - int tests = 2; + int tests = 2 while (m[0]++, tests--) { h256 hm(sha3(m)); From 5c17838ca13dc489fd9d4e699dffb81c582cb0a5 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 18 Nov 2014 12:01:25 +0100 Subject: [PATCH 37/44] Build fix. --- test/crypto.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/crypto.cpp b/test/crypto.cpp index 87047f0d4..08236135a 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) KeyPair key(secret); bytes m(1, 0xff); - int tests = 2 + int tests = 2; while (m[0]++, tests--) { h256 hm(sha3(m)); From 7a0cb2bf23e346d5458ad8aba4f2ef4764de3a53 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 18 Nov 2014 12:41:10 +0100 Subject: [PATCH 38/44] Renaming and fixes. --- alethzero/MainWin.cpp | 3 ++- libethereum/BlockChain.h | 4 ++++ libethereum/Client.cpp | 12 ++++++------ libjsqrc/ethereum.js | 6 ++++-- libweb3jsonrpc/WebThreeStubServer.cpp | 2 +- libweb3jsonrpc/WebThreeStubServer.h | 2 +- libweb3jsonrpc/abstractwebthreestubserver.h | 8 ++++---- libweb3jsonrpc/spec.json | 2 +- test/webthreestubclient.h | 4 ++-- third/MainWin.cpp | 17 +++++++---------- third/MainWin.h | 4 ++-- 11 files changed, 34 insertions(+), 30 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 460669cf9..6aaf6fc18 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1292,7 +1292,7 @@ void Main::on_blocks_currentItemChanged() Transaction tx(block[1][txi].data()); auto ss = tx.safeSender(); h256 th = sha3(rlpList(ss, tx.nonce())); - auto receipt = ethereum()->blockChain().receipts(h).receipts[txi]; + TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi]; s << "

" << th << "

"; s << "

" << h << "[" << txi << "]

"; s << "
From: " << pretty(ss).toHtmlEscaped().toStdString() << " " << ss; @@ -1308,6 +1308,7 @@ void Main::on_blocks_currentItemChanged() s << "
R: " << hex << nouppercase << tx.signature().r << ""; s << "
S: " << hex << nouppercase << tx.signature().s << ""; s << "
Msg: " << tx.sha3(eth::WithoutSignature) << ""; + s << "
Log Bloom: " << receipt.bloom() << "
"; s << "
Hex: " << toHex(block[1][txi].data()) << "
"; auto r = receipt.rlp(); s << "
Receipt: " << toString(RLP(r)) << "
"; diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 49f7b149e..74d94e164 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -93,6 +93,10 @@ public: /// Returns true if the given block is known (though not necessarily a part of the canon chain). bool isKnown(h256 _hash) const; + /// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe. + BlockInfo info(h256 _hash) const { return BlockInfo(block(_hash)); } + BlockInfo info() const { return BlockInfo(block()); } + /// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe. BlockDetails details(h256 _hash) const { return queryExtras(_hash, m_details, x_details, NullBlockDetails); } BlockDetails details() const { return details(currentHash()); } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 01aa75b9a..79001d2fb 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -232,12 +232,12 @@ void Client::appendFromNewPending(LogBloom _bloom, h256Set& o_changed) const void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const { -// auto d = m_bc.info(_block); -// -// lock_guard l(m_filterLock); -// for (pair const& i: m_filters) -// if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom)) -// o_changed.insert(i.first); + auto d = m_bc.info(_block); + + lock_guard l(m_filterLock); + for (pair const& i: m_filters) + if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom)) + o_changed.insert(i.first); } void Client::setForceMining(bool _enable) diff --git a/libjsqrc/ethereum.js b/libjsqrc/ethereum.js index bd5b4fb4e..43ac12fd8 100644 --- a/libjsqrc/ethereum.js +++ b/libjsqrc/ethereum.js @@ -599,7 +599,7 @@ var ethWatchMethods = function () { return [ { name: 'newFilter', call: newFilter }, { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, - { name: 'getMessages', call: 'eth_getMessages' } + { name: 'logs', call: 'eth_getMessages' } ]; }; @@ -904,6 +904,8 @@ Filter.prototype.messages = function() { }); }; +Filter.prototype.logs = Filter.prototype.messages; + function messageHandler(data) { if(data._event !== undefined) { web3.trigger(data._event, data._id, data.data); @@ -1060,4 +1062,4 @@ module.exports = web3; },{"./lib/autoprovider":2,"./lib/contract":3,"./lib/httprpc":4,"./lib/main":5,"./lib/qt":6,"./lib/websocket":7}]},{},[]) -//# sourceMappingURL=ethereum.js.map \ No newline at end of file +//# sourceMappingURL=ethereum.js.map diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 6bedfed3f..2676913e5 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -394,7 +394,7 @@ std::string WebThreeStubServer::db_get(std::string const& _name, std::string con return toJS(dev::asBytes(ret)); } -Json::Value WebThreeStubServer::eth_getMessages(int const& _id) +Json::Value WebThreeStubServer::eth_getLogs(int const& _id) { if (!client()) return Json::Value(); diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 7d25f5954..007c06cb8 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -76,7 +76,7 @@ public: virtual double eth_countAt(std::string const& _address); virtual int eth_defaultBlock(); virtual std::string eth_gasPrice(); - virtual Json::Value eth_getMessages(int const& _id); + virtual Json::Value eth_getLogs(int const& _id); virtual bool eth_listening(); virtual bool eth_mining(); virtual int eth_newFilter(Json::Value const& _json); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index b86576572..fd3f8b051 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -29,7 +29,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI); - this->bindAndAddMethod(new jsonrpc::Procedure("eth_getMessages", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_getMessagesI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_getLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_getLogsI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_listeningI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_lll", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_lllI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_miningI); @@ -142,9 +142,9 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_gasPrice(); } - inline virtual void eth_getMessagesI(const Json::Value& request, Json::Value& response) + inline virtual void eth_getLogsI(const Json::Value& request, Json::Value& response) { - response = this->eth_getMessages(request[0u].asInt()); + response = this->eth_getLogs(request[0u].asInt()); } inline virtual void eth_listeningI(const Json::Value& request, Json::Value& response) @@ -309,7 +309,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerclient->CallMethod("eth_getMessages",p); + Json::Value result = this->client->CallMethod("eth_getLogs",p); if (result.isArray()) return result; else diff --git a/third/MainWin.cpp b/third/MainWin.cpp index c2dcb7ce2..299aafaaa 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -182,7 +182,7 @@ void Main::onKeysChanged() installBalancesWatch(); } -unsigned Main::installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f) +unsigned Main::installWatch(dev::eth::LogFilter const& _tf, std::function const& _f) { auto ret = ethereum()->installWatch(_tf); m_handlers[ret] = _f; @@ -198,37 +198,34 @@ unsigned Main::installWatch(dev::h256 _tf, std::function const& _f) void Main::installWatches() { - installWatch(dev::eth::MessageFilter().altered(c_config, 0), [=](){ installNameRegWatch(); }); - installWatch(dev::eth::MessageFilter().altered(c_config, 1), [=](){ installCurrenciesWatch(); }); + installWatch(dev::eth::LogFilter().topic((u256)(u160)c_config).topic((u256)0), [=](){ installNameRegWatch(); }); + installWatch(dev::eth::LogFilter().topic((u256)(u160)c_config).topic((u256)1), [=](){ installCurrenciesWatch(); }); installWatch(dev::eth::ChainChangedFilter, [=](){ onNewBlock(); }); } void Main::installNameRegWatch() { ethereum()->uninstallWatch(m_nameRegFilter); - m_nameRegFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); + m_nameRegFilter = installWatch(dev::eth::LogFilter().topic(ethereum()->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); } void Main::installCurrenciesWatch() { ethereum()->uninstallWatch(m_currenciesFilter); - m_currenciesFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); + m_currenciesFilter = installWatch(dev::eth::LogFilter().topic(ethereum()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); } void Main::installBalancesWatch() { - dev::eth::MessageFilter tf; + dev::eth::LogFilter tf; vector
altCoins; Address coinsAddr = right160(ethereum()->stateAt(c_config, 1)); for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i) altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1))); for (auto i: m_myKeys) - { - tf.altered(i.address()); for (auto c: altCoins) - tf.altered(c, (u160)i.address()); - } + tf.address(c).topic((u256)(u160)i.address()); ethereum()->uninstallWatch(m_balancesFilter); m_balancesFilter = installWatch(tf, [=](){ onBalancesChange(); }); diff --git a/third/MainWin.h b/third/MainWin.h index 607d65fee..478fb6fb6 100644 --- a/third/MainWin.h +++ b/third/MainWin.h @@ -40,7 +40,7 @@ namespace dev { class WebThreeDirect; namespace eth { class Client; class State; -class MessageFilter; +class LogFilter; } namespace shh { class WhisperHost; @@ -95,7 +95,7 @@ private: void readSettings(bool _skipGeometry = false); void writeSettings(); - unsigned installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f); + unsigned installWatch(dev::eth::LogFilter const& _tf, std::function const& _f); unsigned installWatch(dev::h256 _tf, std::function const& _f); void onNewBlock(); From e2948c7040188bb047e48be0a7acbdeef97596a2 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 18 Nov 2014 12:41:53 +0100 Subject: [PATCH 39/44] logs in spec --- libweb3jsonrpc/abstractwebthreestubserver.h | 19 +++++++---- libweb3jsonrpc/spec.json | 3 +- test/webthreestubclient.h | 35 ++++++++++++++------- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index b86576572..c1208b5c4 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -28,10 +28,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_compilersI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_filterLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_filterLogsI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI); - this->bindAndAddMethod(new jsonrpc::Procedure("eth_getMessages", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_getMessagesI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_listeningI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_lll", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_lllI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_logs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_logsI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_miningI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_newFilterI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newFilterStringI); @@ -137,14 +138,14 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_defaultBlock(); } - inline virtual void eth_gasPriceI(const Json::Value& request, Json::Value& response) + inline virtual void eth_filterLogsI(const Json::Value& request, Json::Value& response) { - response = this->eth_gasPrice(); + response = this->eth_filterLogs(request[0u].asInt()); } - inline virtual void eth_getMessagesI(const Json::Value& request, Json::Value& response) + inline virtual void eth_gasPriceI(const Json::Value& request, Json::Value& response) { - response = this->eth_getMessages(request[0u].asInt()); + response = this->eth_gasPrice(); } inline virtual void eth_listeningI(const Json::Value& request, Json::Value& response) @@ -157,6 +158,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_lll(request[0u].asString()); } + inline virtual void eth_logsI(const Json::Value& request, Json::Value& response) + { + response = this->eth_logs(request[0u]); + } + inline virtual void eth_miningI(const Json::Value& request, Json::Value& response) { response = this->eth_mining(); @@ -308,10 +314,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerclient->CallMethod("eth_gasPrice",p); - if (result.isString()) - return result.asString(); + p.append(param1); + + Json::Value result = this->client->CallMethod("eth_filterLogs",p); + if (result.isArray()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - Json::Value eth_getMessages(const int& param1) throw (jsonrpc::JsonRpcException) + std::string eth_gasPrice() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); - - Json::Value result = this->client->CallMethod("eth_getMessages",p); - if (result.isArray()) - return result; + p = Json::nullValue; + Json::Value result = this->client->CallMethod("eth_gasPrice",p); + if (result.isString()) + return result.asString(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); @@ -266,6 +266,19 @@ p.append(param3); } + Json::Value eth_logs(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + + Json::Value result = this->client->CallMethod("eth_logs",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + bool eth_mining() throw (jsonrpc::JsonRpcException) { Json::Value p; From 89ee4a3d2bdc1c58b144e96d99e3ae3328082ffc Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 18 Nov 2014 13:08:33 +0100 Subject: [PATCH 40/44] More fixes for logging. --- alethzero/MainWin.cpp | 5 +--- libethereum/Client.cpp | 33 ++++++++++++++++----------- libethereum/MessageFilter.h | 1 - libethereum/State.cpp | 4 ++-- libweb3jsonrpc/WebThreeStubServer.cpp | 13 +---------- 5 files changed, 24 insertions(+), 32 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 6aaf6fc18..66fa00b36 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -290,11 +290,8 @@ void Main::installBalancesWatch() for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, 0); ++i) altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1))); for (auto i: m_myKeys) - { - tf.address(i.address()); for (auto c: altCoins) - tf.address(c); - } + tf.address(c).topic(h256(i.address(), h256::AlignRight)); uninstallWatch(m_balancesFilter); m_balancesFilter = installWatch(tf, [=](){ onBalancesChange(); }); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 79001d2fb..6405134c7 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -604,30 +604,37 @@ LogEntries Client::logs(LogFilter const& _f) const #if ETH_DEBUG int total = 0; #endif - //? check block bloom - for (TransactionReceipt receipt: m_bc.receipts(h).receipts) - if (_f.matches(receipt.bloom())) + // check block bloom + if (_f.matches(m_bc.info(h).logBloom)) + for (TransactionReceipt receipt: m_bc.receipts(h).receipts) { - LogEntries le = _f.matches(receipt); - if (le.size()) + if (_f.matches(receipt.bloom())) { + LogEntries le = _f.matches(receipt); + if (le.size()) + { #if ETH_DEBUG - total += le.size(); + total += le.size(); #endif - for (unsigned j = 0; j < le.size() && ret.size() != m; ++j) - { - if (s) - s--; - else - ret.insert(ret.begin(), le[j]); + for (unsigned j = 0; j < le.size() && ret.size() != m; ++j) + { + if (s) + s--; + else + ret.insert(ret.begin(), le[j]); + } } } + if (!total) + falsePos++; } + else + skipped++; if (n == end) break; } #if ETH_DEBUG -// cdebug << (begin - n) << "searched; " << skipped << "skipped; " << falsePos << "false +ves"; + cdebug << (begin - n) << "searched; " << skipped << "skipped; " << falsePos << "false +ves"; #endif return ret; } diff --git a/libethereum/MessageFilter.h b/libethereum/MessageFilter.h index 5602d7a17..482c68ef6 100644 --- a/libethereum/MessageFilter.h +++ b/libethereum/MessageFilter.h @@ -90,7 +90,6 @@ public: LogEntries matches(TransactionReceipt const& _r) const; LogFilter address(Address _a) { m_addresses.insert(_a); return *this; } - LogFilter from(Address _a) { return topic(u256((u160)_a) + 1); } LogFilter topic(h256 const& _t) { m_topics.insert(_t); return *this; } LogFilter withMax(unsigned _m) { m_max = _m; return *this; } LogFilter withSkip(unsigned _m) { m_skip = _m; return *this; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index a37c26645..34d9eae99 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -802,7 +802,7 @@ void State::commitToMine(BlockChain const& _bc) { uncommitToMine(); - cnote << "Committing to mine on block" << m_previousBlock.hash.abridged(); +// cnote << "Committing to mine on block" << m_previousBlock.hash.abridged(); #ifdef ETH_PARANOIA commit(); cnote << "Pre-reward stateRoot:" << m_state.root(); @@ -877,7 +877,7 @@ void State::commitToMine(BlockChain const& _bc) // Commit any and all changes to the trie that are in the cache, then update the state root accordingly. commit(); - cnote << "Post-reward stateRoot:" << m_state.root().abridged(); +// cnote << "Post-reward stateRoot:" << m_state.root().abridged(); // cnote << m_state; // cnote << *this; diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 2676913e5..6589c9068 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -113,17 +113,6 @@ static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to filter.withMax(_json["max"].asInt()); if (_json["skip"].isInt()) filter.withSkip(_json["skip"].asInt()); - if (!_json["from"].empty()) - { - if (_json["from"].isArray()) - { - for (auto i : _json["from"]) - if (i.isString()) - filter.from(jsToAddress(i.asString())); - } - else if (_json["from"].isString()) - filter.from(jsToAddress(_json["from"].asString())); - } if (!_json["address"].empty()) { if (_json["address"].isArray()) @@ -133,7 +122,7 @@ static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to filter.address(jsToAddress(i.asString())); } else if (_json["address"].isString()) - filter.from(jsToAddress(_json["address"].asString())); + filter.address(jsToAddress(_json["address"].asString())); } if (!_json["topics"].empty()) { From ee7c423868695f3b2c68b1fa6d07c7d588599ce7 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 18 Nov 2014 13:09:05 +0100 Subject: [PATCH 41/44] common changes --- libjsqrc/ethereum.js | 19 ++++++----- libweb3jsonrpc/WebThreeStubServer.cpp | 12 +++++-- libweb3jsonrpc/WebThreeStubServer.h | 3 +- libweb3jsonrpc/abstractwebthreestubserver.h | 19 +++++++---- libweb3jsonrpc/spec.json | 3 +- test/webthreestubclient.h | 35 ++++++++++++++------- 6 files changed, 59 insertions(+), 32 deletions(-) diff --git a/libjsqrc/ethereum.js b/libjsqrc/ethereum.js index 43ac12fd8..cbff8b341 100644 --- a/libjsqrc/ethereum.js +++ b/libjsqrc/ethereum.js @@ -217,7 +217,7 @@ module.exports = { You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** @file websocket.js +/** @file autoprovider.js * @authors: * Marek Kotewicz * Marian Oancea @@ -231,7 +231,7 @@ module.exports = { */ if ("build" !== 'build') {/* var WebSocket = require('ws'); // jshint ignore:line - var web3 = require('./web3'); // jshint ignore:line + var web3 = require('./main.js'); // jshint ignore:line */} var AutoProvider = function (userOptions) { @@ -247,13 +247,13 @@ var AutoProvider = function (userOptions) { this.provider = new web3.providers.QtProvider(); return; } - + userOptions = userOptions || {}; var options = { httprpc: userOptions.httprpc || 'http://localhost:8080', websockets: userOptions.websockets || 'ws://localhost:40404/eth' }; - + var self = this; var closeWithSuccess = function (success) { ws.close(); @@ -274,7 +274,7 @@ var AutoProvider = function (userOptions) { var ws = new WebSocket(options.websockets); ws.onopen = function() { - closeWithSuccess(true); + closeWithSuccess(true); }; ws.onerror = function() { @@ -553,7 +553,8 @@ var ethMethods = function () { { name: 'compilers', call: 'eth_compilers' }, { name: 'lll', call: 'eth_lll' }, { name: 'solidity', call: 'eth_solidity' }, - { name: 'serpent', call: 'eth_serpent' } + { name: 'serpent', call: 'eth_serpent' }, + { name: 'logs', call: 'eth_logs' } ]; return methods; }; @@ -599,7 +600,7 @@ var ethWatchMethods = function () { return [ { name: 'newFilter', call: newFilter }, { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, - { name: 'logs', call: 'eth_getMessages' } + { name: 'getMessages', call: 'eth_filterLogs' } ]; }; @@ -904,8 +905,6 @@ Filter.prototype.messages = function() { }); }; -Filter.prototype.logs = Filter.prototype.messages; - function messageHandler(data) { if(data._event !== undefined) { web3.trigger(data._event, data._id, data.data); @@ -1062,4 +1061,4 @@ module.exports = web3; },{"./lib/autoprovider":2,"./lib/contract":3,"./lib/httprpc":4,"./lib/main":5,"./lib/qt":6,"./lib/websocket":7}]},{},[]) -//# sourceMappingURL=ethereum.js.map +//# sourceMappingURL=ethereum.js.map \ No newline at end of file diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 2676913e5..410f2d3cd 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -394,14 +394,20 @@ std::string WebThreeStubServer::db_get(std::string const& _name, std::string con return toJS(dev::asBytes(ret)); } -Json::Value WebThreeStubServer::eth_getLogs(int const& _id) +Json::Value WebThreeStubServer::eth_filterLogs(int const& _id) { if (!client()) - return Json::Value(); -// return toJson(client()->messages(_id)); + return Json::Value(Json::arrayValue); return toJson(client()->logs(_id)); } +Json::Value WebThreeStubServer::eth_logs(Json::Value const& _json) +{ + if (!client()) + return Json::Value(Json::arrayValue); + return toJson(client()->logs(toLogFilter(_json))); +} + std::string WebThreeStubServer::db_getString(std::string const& _name, std::string const& _key) { bytes k = sha3(_name).asBytes() + sha3(_key).asBytes(); diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 007c06cb8..cf969186d 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -76,7 +76,8 @@ public: virtual double eth_countAt(std::string const& _address); virtual int eth_defaultBlock(); virtual std::string eth_gasPrice(); - virtual Json::Value eth_getLogs(int const& _id); + virtual Json::Value eth_filterLogs(int const& _id); + virtual Json::Value eth_logs(Json::Value const& _json); virtual bool eth_listening(); virtual bool eth_mining(); virtual int eth_newFilter(Json::Value const& _json); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index fd3f8b051..c1208b5c4 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -28,10 +28,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("eth_compilers", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, NULL), &AbstractWebThreeStubServer::eth_compilersI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_defaultBlock", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_defaultBlockI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_filterLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_filterLogsI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_gasPrice", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_gasPriceI); - this->bindAndAddMethod(new jsonrpc::Procedure("eth_getLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_getLogsI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_listening", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_listeningI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_lll", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_lllI); + this->bindAndAddMethod(new jsonrpc::Procedure("eth_logs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_logsI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_mining", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, NULL), &AbstractWebThreeStubServer::eth_miningI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_newFilterI); this->bindAndAddMethod(new jsonrpc::Procedure("eth_newFilterString", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newFilterStringI); @@ -137,14 +138,14 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_defaultBlock(); } - inline virtual void eth_gasPriceI(const Json::Value& request, Json::Value& response) + inline virtual void eth_filterLogsI(const Json::Value& request, Json::Value& response) { - response = this->eth_gasPrice(); + response = this->eth_filterLogs(request[0u].asInt()); } - inline virtual void eth_getLogsI(const Json::Value& request, Json::Value& response) + inline virtual void eth_gasPriceI(const Json::Value& request, Json::Value& response) { - response = this->eth_getLogs(request[0u].asInt()); + response = this->eth_gasPrice(); } inline virtual void eth_listeningI(const Json::Value& request, Json::Value& response) @@ -157,6 +158,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_lll(request[0u].asString()); } + inline virtual void eth_logsI(const Json::Value& request, Json::Value& response) + { + response = this->eth_logs(request[0u]); + } + inline virtual void eth_miningI(const Json::Value& request, Json::Value& response) { response = this->eth_mining(); @@ -308,10 +314,11 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerclient->CallMethod("eth_gasPrice",p); - if (result.isString()) - return result.asString(); + p.append(param1); + + Json::Value result = this->client->CallMethod("eth_filterLogs",p); + if (result.isArray()) + return result; else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } - Json::Value eth_getLogs(const int& param1) throw (jsonrpc::JsonRpcException) + std::string eth_gasPrice() throw (jsonrpc::JsonRpcException) { Json::Value p; - p.append(param1); - - Json::Value result = this->client->CallMethod("eth_getLogs",p); - if (result.isArray()) - return result; + p = Json::nullValue; + Json::Value result = this->client->CallMethod("eth_gasPrice",p); + if (result.isString()) + return result.asString(); else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); @@ -266,6 +266,19 @@ p.append(param3); } + Json::Value eth_logs(const Json::Value& param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + + Json::Value result = this->client->CallMethod("eth_logs",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + + } + bool eth_mining() throw (jsonrpc::JsonRpcException) { Json::Value p; From d59a5713500d35157e0a9c322e3c3ee743cfc612 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 18 Nov 2014 13:11:12 +0100 Subject: [PATCH 42/44] logs method in ethereum.js --- libjsqrc/ethereum.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libjsqrc/ethereum.js b/libjsqrc/ethereum.js index cbff8b341..cc8afc932 100644 --- a/libjsqrc/ethereum.js +++ b/libjsqrc/ethereum.js @@ -905,6 +905,10 @@ Filter.prototype.messages = function() { }); }; +Filter.prototype.logs = function () { + return this.messages(); +}; + function messageHandler(data) { if(data._event !== undefined) { web3.trigger(data._event, data._id, data.data); From e81197606ae29c4be3ac37ad4e8aaf699fbcd039 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 18 Nov 2014 13:21:36 +0100 Subject: [PATCH 43/44] Log & watches. --- libethereum/Client.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 6405134c7..183a072e3 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -224,6 +224,7 @@ void Client::noteChanged(h256Set const& _filters) void Client::appendFromNewPending(LogBloom _bloom, h256Set& o_changed) const { + // TODO: more precise check on whether the txs match. lock_guard l(m_filterLock); for (pair const& i: m_filters) if ((unsigned)i.second.filter.latest() > m_bc.number() && i.second.filter.matches(_bloom)) @@ -232,6 +233,7 @@ void Client::appendFromNewPending(LogBloom _bloom, h256Set& o_changed) const void Client::appendFromNewBlock(h256 _block, h256Set& o_changed) const { + // TODO: more precise check on whether the txs match. auto d = m_bc.info(_block); lock_guard l(m_filterLock); From 85e3bd49397bfbba564148796704f938f6af87c2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 18 Nov 2014 13:40:32 +0100 Subject: [PATCH 44/44] Allow data to be passed in old way. --- libweb3jsonrpc/WebThreeStubServer.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 6a91080e3..8ee9ee722 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -310,9 +310,16 @@ static TransactionSkeleton toTransaction(Json::Value const& _json) else if (_json["gasPrice"].isInt()) ret.gas = u256(_json["gas"].asInt()); } - if (_json["data"].isString()) - ret.data = jsToBytes(_json["data"].asString()); - else if (_json["code"].isString()) + if (!_json["data"].empty()) + { + if (_json["data"].isString()) // ethereum.js has preconstructed the data array + ret.data = jsToBytes(_json["data"].asString()); + else if (_json["data"].isArray()) // old style: array of 32-byte-padded values. TODO: remove PoC-8 + for (auto i: _json["data"]) + dev::operator +=(ret.data, padded(jsToBytes(i.asString()), 32)); + } + + if (_json["code"].isString()) ret.data = jsToBytes(_json["code"].asString()); return ret; }