From 2a5977d14f4c2eed20849b451108749df8855d9f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 20 May 2014 10:46:21 +0200 Subject: [PATCH] Fixed #185. --- eth/EthStubServer.cpp | 8 +++ eth/EthStubServer.h | 1 + eth/abstractethstubserver.h | 7 +++ eth/eth.js | 31 ++++----- eth/spec.json | 3 +- libethereum/Instruction.cpp | 121 ++++++++++++++++++++++++++++++++---- libqethereum/QEthereum.cpp | 7 +++ libqethereum/QEthereum.h | 1 + 8 files changed, 150 insertions(+), 29 deletions(-) diff --git a/eth/EthStubServer.cpp b/eth/EthStubServer.cpp index 2153cce06..8a54efbad 100644 --- a/eth/EthStubServer.cpp +++ b/eth/EthStubServer.cpp @@ -23,6 +23,7 @@ #if ETH_JSONRPC #include "EthStubServer.h" #include +#include #include "CommonJS.h" using namespace std; using namespace eth; @@ -87,6 +88,13 @@ Json::Value EthStubServer::create(const std::string& _bCode, const std::string& return Json::Value(); } +std::string EthStubServer::lll(const std::string& _s) +{ + bytes ret; + eth::compileLisp(_s, true, ret); + return "0x" + toHex(ret); +} + std::string EthStubServer::gasPrice() { return "100000000000000"; diff --git a/eth/EthStubServer.h b/eth/EthStubServer.h index 52b33fc38..01da9086a 100644 --- a/eth/EthStubServer.h +++ b/eth/EthStubServer.h @@ -53,6 +53,7 @@ public: virtual std::string txCountAt(const std::string& a); virtual std::string secretToAddress(const std::string& a); virtual Json::Value lastBlock(); + virtual std::string lll(const std::string& s); virtual Json::Value block(const std::string&); void setKeys(std::vector _keys) { m_keys = _keys; } private: diff --git a/eth/abstractethstubserver.h b/eth/abstractethstubserver.h index 3355b5557..5531b362c 100644 --- a/eth/abstractethstubserver.h +++ b/eth/abstractethstubserver.h @@ -25,6 +25,7 @@ class AbstractEthStubServer : public jsonrpc::AbstractServerbindAndAddMethod(new jsonrpc::Procedure("key", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::keyI); this->bindAndAddMethod(new jsonrpc::Procedure("keys", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_ARRAY, NULL), &AbstractEthStubServer::keysI); this->bindAndAddMethod(new jsonrpc::Procedure("lastBlock", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, NULL), &AbstractEthStubServer::lastBlockI); + this->bindAndAddMethod(new jsonrpc::Procedure("lll", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "s",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::lllI); this->bindAndAddMethod(new jsonrpc::Procedure("peerCount", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_INTEGER, NULL), &AbstractEthStubServer::peerCountI); this->bindAndAddMethod(new jsonrpc::Procedure("procedures", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_ARRAY, NULL), &AbstractEthStubServer::proceduresI); this->bindAndAddMethod(new jsonrpc::Procedure("secretToAddress", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_STRING, "a",jsonrpc::JSON_STRING, NULL), &AbstractEthStubServer::secretToAddressI); @@ -94,6 +95,11 @@ class AbstractEthStubServer : public jsonrpc::AbstractServerlastBlock(); } + inline virtual void lllI(const Json::Value& request, Json::Value& response) + { + response = this->lll(request["s"].asString()); + } + inline virtual void peerCountI(const Json::Value& request, Json::Value& response) { response = this->peerCount(); @@ -137,6 +143,7 @@ class AbstractEthStubServer : public jsonrpc::AbstractServer= 0x69 ether))"); - static string readQuoted(char const*& o_d, char const* _e) { string ret; @@ -1144,6 +1131,114 @@ bytes eth::compileLisp(std::string const& _code, bool _quiet, bytes& _init) compileLispFragment(d, e, _quiet, body, locs, vars); return body; } +/* +bytes eth::compileLLL(string const& _s, vector* _errors) +{ + sp::utree o; + parseLLL(_s, o); + bytes ret; + compileLLLFragment(o, ret, _errors); +// debugOut(cout, o); +// cout << endl; + killBigints(o); + return ret; +} + +struct CompileState +{ + map vars; +}; + +class CodeLocation +{ +public: + void increase(); + +private: + CodeFragment* m_f; + unsigned m_pos; +}; + +class CodeFragment +{ +public: + CodeFragment(sp::utree _t, CompileState _s = CompileState()); + + unsigned appendPush(u256 _l); + CodeLocation appendPushLocation(u256 _l); + void appendFragment(CodeFragment const& _f); + void appendInstruction(Instruction _i); + +private: + int m_deposit; + bytes m_code; + vector m_locs; +}; + +void CodeLocation::increase(unsigned _inc) +{ + assert(m_f->m_code[m_pos] == (byte)Instruction::PUSH4); + bytesRef r(&m_f->m_code[1 + m_pos], 4); + toBigEndian(fromBigEndian(bytesConstRef(&m_f->m_code[1 + m_pos], 4)) + _inc, r); +} + +void CodeFragment::appendFragment(CodeFragment const& _f) +{ + m_locs.reserve(m_locs.size() + _f.m_locs.size()); + for (auto i: _f.m_locs) + { + increaseLocation(_f.m_code, i, (unsigned)m_code.size()); + m_locs.push_back(i + (unsigned)m_code.size()); + } + m_code.reserve(m_code.size() + _f.m_code.size()); + for (auto i: _f.m_code) + m_code.push_back(i); +} + +void CodeFragment::appendPushLocation(uint32_t _locationValue) +{ + o_code.push_back((byte)Instruction::PUSH4); + o_code.resize(o_code.size() + 4); + bytesRef r(&o_code[o_code.size() - 4], 4); + toBigEndian(_locationValue, r); + m_deposit++; +} + +unsigned CodeFragment::appendPush(u256 _literalValue) +{ + unsigned br = max(1, bytesRequired(_literalValue)); + m_code.push_back((byte)Instruction::PUSH1 + br - 1); + m_code.resize(m_code.size() + br); + for (unsigned i = 0; i < br; ++i) + { + m_code[m_code.size() - 1 - i] = (byte)(_literalValue & 0xff); + _literalValue >>= 8; + } + m_deposit++; + return br + 1; +} + + +void debugOut(ostream& _out, sp::utree const& _this) +{ + switch (_this.which()) + { + case sp::utree_type::list_type: _out << "( "; for (auto const& i: _this) { debugOut(_out, i); _out << " "; } _out << ")"; break; + case sp::utree_type::int_type: _out << _this.get(); break; + case sp::utree_type::string_type: _out << "\"" << _this.get, sp::utree_type::string_type>>() << "\""; break; + case sp::utree_type::symbol_type: _out << _this.get, sp::utree_type::symbol_type>>(); break; + case sp::utree_type::any_type: _out << *_this.get(); break; + default: _out << "nil"; + } +} + +CodeFragment::CodeFragment(sp::utree _t, CompileState _s) +{ + if (_t.) + +} +*/ +//try compileLLL("(((69wei) 'hello) (xyz \"abc\") (>= 0x69 ether))"); string eth::disassemble(bytes const& _mem) { diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index 6ed366b23..82c8fbabb 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -267,6 +267,13 @@ Client* QEthereum::client() const return m_client; } +QString QEthereum::lll(QString _s) const +{ + bytes ret; + eth::compileLisp(_s.toStdString(), true, ret); + return asQString(ret); +} + QString QEthereum::coinbase() const { return toQJS(client()->address()); diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index a637e3d2a..1387731c1 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -373,6 +373,7 @@ public: Q_INVOKABLE QEthereum* self() { return this; } Q_INVOKABLE QString secretToAddress(QString _s) const; + Q_INVOKABLE QString lll(QString _s) const; Q_INVOKABLE QString pad(QString _s, unsigned _l) const { return padded(_s, _l); } Q_INVOKABLE QString pad(QString _s, unsigned _l, unsigned _r) const { return padded(_s, _l, _r); }