From 250ed6ab893d0f0f54ab27934d9eeda8bede5306 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 30 Apr 2014 16:04:17 +0100 Subject: [PATCH] Basics of new string-based JS-API data passing. --- libethcore/FixedHash.h | 2 +- libqethereum/QEthereum.cpp | 42 +++++++++++++++++++--- libqethereum/QEthereum.h | 72 ++++++++++++++++++++++++++++++-------- 3 files changed, 95 insertions(+), 21 deletions(-) diff --git a/libethcore/FixedHash.h b/libethcore/FixedHash.h index 762f39090..207e9a0eb 100644 --- a/libethcore/FixedHash.h +++ b/libethcore/FixedHash.h @@ -36,10 +36,10 @@ namespace eth template class FixedHash { +public: /// The corresponding arithmetic type. using Arith = boost::multiprecision::number>; -public: /// The size of the container. enum { size = N }; diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index 47138cdbc..fab626593 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -183,6 +183,33 @@ void QmlEthereum::transact(Secret _secret, Address _dest, u256 _amount, u256 _ga //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +eth::bytes toBytes(QString const& _s) +{ + if (_s.startsWith("0x")) + // Hex + return eth::fromHex(_s.mid(2).toStdString()); + else if (!_s.contains(QRegExp("[^0-9]"))) + { + // Decimal + eth::bytes ret; + eth::toBigEndian(eth::bigint(_s.toStdString()), ret); + return ret; + } + else + // Binary + return eth::asBytes(_s.toStdString()); +} + +QString padded(QString const& _s, unsigned _l, unsigned _r) +{ + eth::bytes b = toBytes(_s); + while (b.size() < _l) + b.insert(b.begin(), 0); + while (b.size() < _r) + b.push_back(0); + b.resize(_r); + return QString::fromStdString(eth::asString(b)); +} QEthereum::QEthereum(QObject* _p, Client* _c, QList _accounts): QObject(_p), m_client(_c), m_accounts(_accounts) { @@ -201,11 +228,16 @@ void QEthereum::setup(QWebFrame* _e) _e->addToJavaScriptWindowObject("u256", new U256Helper, QWebFrame::ScriptOwnership); _e->addToJavaScriptWindowObject("key", new KeyHelper, QWebFrame::ScriptOwnership); _e->addToJavaScriptWindowObject("bytes", new BytesHelper, QWebFrame::ScriptOwnership); -// _e->evaluateJavaScript("xeth = new Object({\"callback\": function(f) { eth.testcallback.connect(f) }})"); - _e->evaluateJavaScript("eth.onChanged = function(f) { eth.changed.connect(f) }"); + _e->evaluateJavaScript("eth.newBlock = function(f) { eth.changed.connect(f) }"); + _e->evaluateJavaScript("eth.watch = function(a, s, f) { eth.changed.connect(f ? f : s) }"); + _e->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { eth.doCreate(s, v, c, g, p); if (f) f() }"); + _e->evaluateJavaScript("eth.transact = function(s, v, t, d, g, p, f) { eth.doTransact(s, v, t, d, g, p); if (f) f() }"); + _e->evaluateJavaScript("String.prototype.pad = function(l, r) { return eth.pad(this, l, r) }"); + _e->evaluateJavaScript("String.prototype.bin = function(l) { return eth.toBinary(this) }"); + _e->evaluateJavaScript("String.prototype.unbin = function(l) { return eth.fromBinary(this) }"); } -void QEthereum::teardown(QWebFrame* _e) +void QEthereum::teardown(QWebFrame*) { } @@ -324,12 +356,12 @@ unsigned QEthereum::peerCount() const return (unsigned)client()->peerCount(); } -QVariant QEthereum::create(QVariant _secret, QVariant _amount, QByteArray _init, QVariant _gas, QVariant _gasPrice) +QVariant QEthereum::doCreate(QVariant _secret, QVariant _amount, QByteArray _init, QVariant _gas, QVariant _gasPrice) { return toQJS(client()->transact(to(_secret), to(_amount), bytes(_init.data(), _init.data() + _init.size()), to(_gas), to(_gasPrice))); } -void QEthereum::transact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice) +void QEthereum::doTransact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice) { client()->transact(to(_secret), to(_amount), to
(_dest), bytes(_data.data(), _data.data() + _data.size()), to(_gas), to(_gasPrice)); } diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index ce51592b0..260f8807c 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -283,6 +283,42 @@ public: } }; +eth::bytes toBytes(QString const& _s); +QString padded(QString const& _s, unsigned _l, unsigned _r); + +template H toFixed(QString const& _s) +{ + if (_s.startsWith("0x")) + // Hex + return H(_s.mid(2)); + else if (!_s.contains(QRegExp("[^0-9]"))) + // Decimal + return (typename H::Arith)(_s); + else + // Binary + return H(toBytes(_s)); +} + +template I toInt(QString const& _s) +{ + if (_s.startsWith("0x") || !_s.contains(QRegExp("[^0-9]"))) + // Hex or Decimal + return (I)eth::bigint(_s); + else + // Binary + return eth::fromBigEndian(toBytes(_s)); +} + +inline QString toBinary(QString const& _s) +{ + return QString::fromStdString(eth::asString(toBytes(_s))); +} + +inline QString fromBinary(QString const& _s) +{ + return QString::fromStdString("0x" + eth::toHex(eth::asBytes(_s.toStdString()))); +} + class QEthereum: public QObject { Q_OBJECT @@ -296,32 +332,35 @@ public: void setup(QWebFrame* _e); void teardown(QWebFrame* _e); + Q_INVOKABLE QString pad(QString _s, unsigned _l, unsigned _r) const { return padded(_s, _l, _r); } + Q_INVOKABLE QString toBinary(QString _s) const { return ::toBinary(_s); } + Q_INVOKABLE QString fromBinary(QString _s) const { return ::fromBinary(_s); } + Q_INVOKABLE QVariant/*eth::Address*/ coinbase() const; - Q_INVOKABLE bool isListening() const; - Q_INVOKABLE bool isMining() const; + bool isListening() const; + bool isMining() const; Q_INVOKABLE QVariant/*eth::u256*/ balanceAt(QVariant/*eth::Address*/ _a) const; Q_INVOKABLE QVariant/*eth::u256*/ storageAt(QVariant/*eth::Address*/ _a, QVariant/*eth::u256*/ _p) const; Q_INVOKABLE double txCountAt(QVariant/*eth::Address*/ _a) const; Q_INVOKABLE bool isContractAt(QVariant/*eth::Address*/ _a) const; - Q_INVOKABLE QVariant gasPrice() const { return toQJS(10 * eth::szabo); } + QVariant gasPrice() const { return toQJS(10 * eth::szabo); } Q_INVOKABLE QString ethTest() const { return "Hello world!"; } - Q_INVOKABLE void ethTest2() { changed(); } - Q_INVOKABLE QVariant/*eth::KeyPair*/ key() const; - Q_INVOKABLE QList keys() const; - Q_INVOKABLE QVariant/*eth::Address*/ account() const; - Q_INVOKABLE QList accounts() const; + QVariant/*eth::KeyPair*/ key() const; + QList keys() const; + QVariant/*eth::Address*/ account() const; + QList accounts() const; - Q_INVOKABLE unsigned peerCount() const; + unsigned peerCount() const; Q_INVOKABLE QEthereum* self() { return this; } - Q_INVOKABLE QVariant create(QVariant _secret, QVariant _amount, QByteArray _init, QVariant _gas, QVariant _gasPrice); - Q_INVOKABLE void transact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice); + Q_INVOKABLE QVariant doCreate(QVariant _secret, QVariant _amount, QByteArray _init, QVariant _gas, QVariant _gasPrice); + Q_INVOKABLE void doTransact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice); eth::u256 balanceAt(eth::Address _a) const; double txCountAt(eth::Address _a) const; @@ -335,14 +374,17 @@ public slots: signals: void changed(); - void testcallback(); // void netChanged(); // void miningChanged(); private: -// Q_PROPERTY(QVariant coinbase READ coinbase WRITE setCoinbase NOTIFY changed) -// Q_PROPERTY(bool listening READ isListening WRITE setListening) -// Q_PROPERTY(bool mining READ isMining WRITE setMining) + Q_PROPERTY(QVariant coinbase READ coinbase WRITE setCoinbase NOTIFY changed) + Q_PROPERTY(bool listening READ isListening WRITE setListening) + Q_PROPERTY(bool mining READ isMining WRITE setMining) + Q_PROPERTY(QVariant gasPrice READ gasPrice NOTIFY changed) + Q_PROPERTY(QVariant key READ key NOTIFY changed) + Q_PROPERTY(QVariant keys READ keys NOTIFY changed) + Q_PROPERTY(unsigned peerCount READ peerCount) eth::Client* m_client; QList m_accounts;