diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a3dd89b75..f8670314d 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -232,7 +232,7 @@ void Main::onKeysChanged() installBalancesWatch(); } -unsigned Main::installWatch(eth::TransactionFilter const& _tf, std::function const& _f) +unsigned Main::installWatch(eth::MessageFilter const& _tf, std::function const& _f) { auto ret = m_client->installWatch(_tf); m_handlers[ret] = _f; @@ -248,27 +248,27 @@ unsigned Main::installWatch(eth::h256 _tf, std::function const& _f) void Main::installWatches() { - installWatch(eth::TransactionFilter().altered(c_config, 0), [=](){ installNameRegWatch(); }); - installWatch(eth::TransactionFilter().altered(c_config, 1), [=](){ installCurrenciesWatch(); }); - installWatch(eth::NewPendingFilter, [=](){ onNewPending(); }); - installWatch(eth::NewBlockFilter, [=](){ onNewBlock(); }); + installWatch(eth::MessageFilter().altered(c_config, 0), [=](){ installNameRegWatch(); }); + installWatch(eth::MessageFilter().altered(c_config, 1), [=](){ installCurrenciesWatch(); }); + installWatch(eth::PendingChangedFilter, [=](){ onNewPending(); }); + installWatch(eth::ChainChangedFilter, [=](){ onNewBlock(); }); } void Main::installNameRegWatch() { m_client->uninstallWatch(m_nameRegFilter); - m_nameRegFilter = installWatch(eth::TransactionFilter().altered((u160)m_client->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); + m_nameRegFilter = installWatch(eth::MessageFilter().altered((u160)m_client->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); } void Main::installCurrenciesWatch() { m_client->uninstallWatch(m_currenciesFilter); - m_currenciesFilter = installWatch(eth::TransactionFilter().altered((u160)m_client->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); + m_currenciesFilter = installWatch(eth::MessageFilter().altered((u160)m_client->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); } void Main::installBalancesWatch() { - eth::TransactionFilter tf; + eth::MessageFilter tf; vector
altCoins; Address coinsAddr = right160(m_client->stateAt(c_config, 1)); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 24e9c5ae1..f3af3dcba 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -39,7 +39,7 @@ class Main; namespace eth { class Client; class State; -class TransactionFilter; +class MessageFilter; } class QQuickView; @@ -166,7 +166,7 @@ private: eth::u256 value() const; eth::u256 gasPrice() const; - unsigned installWatch(eth::TransactionFilter const& _tf, std::function const& _f); + unsigned installWatch(eth::MessageFilter const& _tf, std::function const& _f); unsigned installWatch(eth::h256 _tf, std::function const& _f); void onNewPending(); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 1f1248e76..723c5adef 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -30,12 +30,12 @@ using namespace std; using namespace eth; -void TransactionFilter::fillStream(RLPStream& _s) const +void MessageFilter::fillStream(RLPStream& _s) const { _s.appendList(8) << m_from << m_to << m_stateAltered << m_altered << m_earliest << m_latest << m_max << m_skip; } -h256 TransactionFilter::sha3() const +h256 MessageFilter::sha3() const { RLPStream s; fillStream(s); @@ -125,7 +125,7 @@ void Client::clearPending() h256Set changeds; for (unsigned i = 0; i < m_postMine.pending().size(); ++i) appendFromNewPending(m_postMine.bloom(i), changeds); - changeds.insert(NewPendingFilter); + changeds.insert(PendingChangedFilter); m_postMine = m_preMine; noteChanged(changeds); } @@ -133,12 +133,12 @@ void Client::clearPending() unsigned Client::installWatch(h256 _h) { auto ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0; - m_watches[ret] = Watch(_h); + m_watches[ret] = ClientWatch(_h); cwatch << "+++" << ret << _h; return ret; } -unsigned Client::installWatch(TransactionFilter const& _f) +unsigned Client::installWatch(MessageFilter const& _f) { lock_guard l(m_filterLock); @@ -444,8 +444,8 @@ void Client::work(bool _justQueue) { for (auto h: hs) appendFromNewBlock(h, changeds); - changeds.insert(NewBlockFilter); - //changeds.insert(NewPendingFilter); // if we mined the new block, then we've probably reset the pending transactions. + changeds.insert(ChainChangedFilter); + //changeds.insert(PendingChangedFilter); // if we mined the new block, then we've probably reset the pending transactions. } } } @@ -474,7 +474,7 @@ void Client::work(bool _justQueue) { for (auto i: newBlocks) appendFromNewBlock(i, changeds); - changeds.insert(NewBlockFilter); + changeds.insert(ChainChangedFilter); } x_stateDB.lock(); if (newBlocks.size()) @@ -487,7 +487,7 @@ void Client::work(bool _justQueue) cnote << "New block on chain: Restarting mining operation."; m_restartMining = true; // need to re-commit to mine. m_postMine = m_preMine; - changeds.insert(NewPendingFilter); + changeds.insert(PendingChangedFilter); } // returns h256s as blooms, once for each transaction. @@ -497,7 +497,7 @@ void Client::work(bool _justQueue) { for (auto i: newPendingBlooms) appendFromNewPending(i, changeds); - changeds.insert(NewPendingFilter); + changeds.insert(PendingChangedFilter); if (m_doMine) cnote << "Additional transaction ready: Restarting mining operation."; @@ -594,7 +594,7 @@ bytes Client::codeAt(Address _a, int _block) const return asOf(_block).code(_a); } -bool TransactionFilter::matches(h256 _bloom) const +bool MessageFilter::matches(h256 _bloom) const { auto have = [=](Address const& a) { return _bloom.contains(a.bloom()); }; if (m_from.size()) @@ -627,7 +627,7 @@ bool TransactionFilter::matches(h256 _bloom) const return true; } -bool TransactionFilter::matches(State const& _s, unsigned _i) const +bool MessageFilter::matches(State const& _s, unsigned _i) const { h256 b = _s.changesFromPending(_i).bloom(); if (!matches(b)) @@ -658,14 +658,14 @@ bool TransactionFilter::matches(State const& _s, unsigned _i) const return true; } -PastMessages TransactionFilter::matches(Manifest const& _m, unsigned _i) const +PastMessages MessageFilter::matches(Manifest const& _m, unsigned _i) const { PastMessages ret; matches(_m, vector(1, _i), _m.from, PastMessages(), ret); return ret; } -bool TransactionFilter::matches(Manifest const& _m, vector _p, Address _o, PastMessages _limbo, PastMessages& o_ret) const +bool MessageFilter::matches(Manifest const& _m, vector _p, Address _o, PastMessages _limbo, PastMessages& o_ret) const { bool ret; @@ -705,7 +705,7 @@ bool TransactionFilter::matches(Manifest const& _m, vector _p, Address return ret; } -PastMessages Client::transactions(TransactionFilter const& _f) const +PastMessages Client::messages(MessageFilter const& _f) const { PastMessages ret; unsigned begin = min(m_bc.number(), (unsigned)_f.latest()); diff --git a/libethereum/Client.h b/libethereum/Client.h index 420fe7ad3..a969284d5 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -93,10 +94,10 @@ struct PastMessage typedef std::vector PastMessages; -class TransactionFilter +class MessageFilter { public: - TransactionFilter(int _earliest = 0, int _latest = -1, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {} + MessageFilter(int _earliest = 0, int _latest = -1, unsigned _max = 10, unsigned _skip = 0): m_earliest(_earliest), m_latest(_latest), m_max(_max), m_skip(_skip) {} void fillStream(RLPStream& _s) const; h256 sha3() const; @@ -109,14 +110,14 @@ public: bool matches(State const& _s, unsigned _i) const; PastMessages matches(Manifest const& _m, unsigned _i) const; - TransactionFilter from(Address _a) { m_from.insert(_a); return *this; } - TransactionFilter to(Address _a) { m_to.insert(_a); return *this; } - TransactionFilter altered(Address _a, u256 _l) { m_stateAltered.insert(std::make_pair(_a, _l)); return *this; } - TransactionFilter altered(Address _a) { m_altered.insert(_a); return *this; } - TransactionFilter withMax(unsigned _m) { m_max = _m; return *this; } - TransactionFilter withSkip(unsigned _m) { m_skip = _m; return *this; } - TransactionFilter withEarliest(int _e) { m_earliest = _e; return *this; } - TransactionFilter withLatest(int _e) { m_latest = _e; return *this; } + MessageFilter from(Address _a) { m_from.insert(_a); return *this; } + MessageFilter to(Address _a) { m_to.insert(_a); return *this; } + MessageFilter altered(Address _a, u256 _l) { m_stateAltered.insert(std::make_pair(_a, _l)); return *this; } + MessageFilter altered(Address _a) { m_altered.insert(_a); return *this; } + MessageFilter withMax(unsigned _m) { m_max = _m; return *this; } + MessageFilter withSkip(unsigned _m) { m_skip = _m; return *this; } + MessageFilter withEarliest(int _e) { m_earliest = _e; return *this; } + MessageFilter withLatest(int _e) { m_latest = _e; return *this; } private: bool matches(Manifest const& _m, std::vector _p, Address _o, PastMessages _limbo, PastMessages& o_ret) const; @@ -133,19 +134,19 @@ private: struct InstalledFilter { - InstalledFilter(TransactionFilter const& _f): filter(_f) {} + InstalledFilter(MessageFilter const& _f): filter(_f) {} - TransactionFilter filter; + MessageFilter filter; unsigned refCount = 1; }; -static const h256 NewPendingFilter = u256(0); -static const h256 NewBlockFilter = u256(1); +static const h256 PendingChangedFilter = u256(0); +static const h256 ChainChangedFilter = u256(1); -struct Watch +struct ClientWatch { - Watch() {} - explicit Watch(h256 _id): id(_id) {} + ClientWatch() {} + explicit ClientWatch(h256 _id): id(_id) {} h256 id; unsigned changes = 1; @@ -192,6 +193,7 @@ public: // [NEW API] + int getDefault() const { return m_default; } void setDefault(int _block) { m_default = _block; } u256 balanceAt(Address _a) const { return balanceAt(_a, m_default); } @@ -206,14 +208,14 @@ public: bytes codeAt(Address _a, int _block) const; std::map storageAt(Address _a, int _block) const; - unsigned installWatch(TransactionFilter const& _filter); + unsigned installWatch(MessageFilter const& _filter); unsigned installWatch(h256 _filterId); void uninstallWatch(unsigned _watchId); bool peekWatch(unsigned _watchId) const { std::lock_guard l(m_filterLock); try { return m_watches.at(_watchId).changes != 0; } catch (...) { return false; } } 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; } - PastMessages transactions(unsigned _watchId) const { try { std::lock_guard l(m_filterLock); return transactions(m_filters.at(m_watches.at(_watchId).id).filter); } catch (...) { return PastMessages(); } } - PastMessages transactions(TransactionFilter const& _filter) const; + 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(); } } + PastMessages messages(MessageFilter const& _filter) const; // [EXTRA API]: @@ -351,9 +353,48 @@ private: mutable std::mutex m_filterLock; std::map m_filters; - std::map m_watches; + std::map m_watches; int m_default = -1; }; +class Watch; + +} + +namespace std { void swap(eth::Watch& _a, eth::Watch& _b); } + +namespace eth +{ + +class Watch: public boost::noncopyable +{ + friend void std::swap(Watch& _a, Watch& _b); + +public: + Watch() {} + Watch(Client& _c, h256 _f): m_c(&_c), m_id(_c.installWatch(_f)) {} + Watch(Client& _c, MessageFilter 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); } + +private: + Client* m_c; + unsigned m_id; +}; + +} + +namespace std +{ + +inline void swap(eth::Watch& _a, eth::Watch& _b) +{ + swap(_a.m_c, _b.m_c); + swap(_a.m_id, _b.m_id); +} + } diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index 7300b558a..f6b114b6f 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -180,54 +180,50 @@ void QEthereum::setCoinbase(QString _a) } } -QString QEthereum::balanceAt(QString _a) const +void QEthereum::setDefault(int _block) { - return m_client ? toQJS(client()->postState().balance(toAddress(_a))) : ""; -} - -QString QEthereum::storageAt(QString _a, QString _p) const -{ - return m_client ? toQJS(client()->stateAt(toAddress(_a), toU256(_p))) : ""; + if (m_client) + m_client->setDefault(_block); } -double QEthereum::txCountAt(QString _a) const +int QEthereum::getDefault() const { - return m_client ? (double)client()->countAt(toAddress(_a)) : 0.0; + return m_client ? m_client->getDefault() : 0; } -bool QEthereum::isContractAt(QString _a) const +QString QEthereum::balanceAt(QString _a) const { - return m_client ? client()->codeAt(toAddress(_a)).size() : false; + return m_client ? toQJS(client()->balanceAt(toAddress(_a))) : ""; } -u256 QEthereum::balanceAt(Address _a) const +QString QEthereum::balanceAt(QString _a, int _block) const { - return m_client ? client()->balanceAt(_a) : 0; + return m_client ? toQJS(client()->balanceAt(toAddress(_a), _block)) : ""; } -double QEthereum::txCountAt(Address _a) const +QString QEthereum::stateAt(QString _a, QString _p) const { - return m_client ? (double)client()->countAt(_a) : 0.0; + return m_client ? toQJS(client()->stateAt(toAddress(_a), toU256(_p))) : ""; } -bool QEthereum::isContractAt(Address _a) const +QString QEthereum::stateAt(QString _a, QString _p, int _block) const { - return m_client ? client()->codeAt(_a).size() : false; + return m_client ? toQJS(client()->stateAt(toAddress(_a), toU256(_p), _block)) : ""; } -QString QEthereum::balanceAt(QString _a, int _block) const +QString QEthereum::codeAt(QString _a) const { - return m_client ? toQJS(client()->balanceAt(toAddress(_a), _block)) : ""; + return m_client ? ::fromBinary(client()->codeAt(toAddress(_a))) : ""; } -QString QEthereum::stateAt(QString _a, QString _p, int _block) const +QString QEthereum::codeAt(QString _a, int _block) const { - return m_client ? toQJS(client()->stateAt(toAddress(_a), toU256(_p), _block)) : ""; + return m_client ? ::fromBinary(client()->codeAt(toAddress(_a), _block)) : ""; } -QString QEthereum::codeAt(QString _a, int _block) const +double QEthereum::countAt(QString _a) const { - return m_client ? ::fromBinary(client()->codeAt(toAddress(_a), _block)) : ""; + return m_client ? (double)(uint64_t)client()->countAt(toAddress(_a)) : 0; } double QEthereum::countAt(QString _a, int _block) const @@ -235,9 +231,9 @@ double QEthereum::countAt(QString _a, int _block) const return m_client ? (double)(uint64_t)client()->countAt(toAddress(_a), _block) : 0; } -static eth::TransactionFilter toTransactionFilter(QString _json) +static eth::MessageFilter toMessageFilter(QString _json) { - eth::TransactionFilter filter; + eth::MessageFilter filter; QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object(); if (f.contains("earliest")) @@ -305,9 +301,9 @@ static QString toJson(eth::PastMessages const& _pms) return QString::fromUtf8(QJsonDocument(jsonArray).toJson()); } -QString QEthereum::getTransactions(QString _json) const +QString QEthereum::getMessages(QString _json) const { - return m_client ? toJson(m_client->transactions(toTransactionFilter(_json))) : ""; + return m_client ? toJson(m_client->messages(toMessageFilter(_json))) : ""; } bool QEthereum::isMining() const @@ -369,20 +365,20 @@ unsigned QEthereum::newWatch(QString _json) return (unsigned)-1; unsigned ret; if (_json == "chainChanged") - ret = m_client->installWatch(eth::NewBlockFilter); + ret = m_client->installWatch(eth::ChainChangedFilter); else if (_json == "pendingChanged") - ret = m_client->installWatch(eth::NewPendingFilter); + ret = m_client->installWatch(eth::PendingChangedFilter); else - ret = m_client->installWatch(toTransactionFilter(_json)); + ret = m_client->installWatch(toMessageFilter(_json)); m_watches.push_back(ret); return ret; } -QString QEthereum::watchTransactions(unsigned _w) +QString QEthereum::watchMessages(unsigned _w) { if (!m_client) return ""; - return toJson(m_client->transactions(_w)); + return toJson(m_client->messages(_w)); } void QEthereum::killWatch(unsigned _w) diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h index 70a41c32d..68bc76cdb 100644 --- a/libqethereum/QEthereum.h +++ b/libqethereum/QEthereum.h @@ -112,24 +112,24 @@ public: Q_INVOKABLE QString fromBinary(QString _s) const { return ::fromBinary(_s); } Q_INVOKABLE QString toDecimal(QString _s) const { return ::toDecimal(_s); } - // [OLD API] - Don't use this. - Q_INVOKABLE QString/*eth::u256*/ balanceAt(QString/*eth::Address*/ _a) const; - Q_INVOKABLE QString/*eth::u256*/ storageAt(QString/*eth::Address*/ _a, QString/*eth::u256*/ _p) const; - Q_INVOKABLE double txCountAt(QString/*eth::Address*/ _a) const; - Q_INVOKABLE bool isContractAt(QString/*eth::Address*/ _a) const; - // [NEW API] - Use this instead. Q_INVOKABLE QString/*eth::u256*/ balanceAt(QString/*eth::Address*/ _a, int _block) const; Q_INVOKABLE double countAt(QString/*eth::Address*/ _a, int _block) const; Q_INVOKABLE QString/*eth::u256*/ stateAt(QString/*eth::Address*/ _a, QString/*eth::u256*/ _p, int _block) const; Q_INVOKABLE QString/*eth::u256*/ codeAt(QString/*eth::Address*/ _a, int _block) const; - Q_INVOKABLE QString/*json*/ getTransactions(QString _attribs/*json*/) const; + + Q_INVOKABLE QString/*eth::u256*/ balanceAt(QString/*eth::Address*/ _a) const; + Q_INVOKABLE double countAt(QString/*eth::Address*/ _a) const; + Q_INVOKABLE QString/*eth::u256*/ stateAt(QString/*eth::Address*/ _a, QString/*eth::u256*/ _p) const; + Q_INVOKABLE QString/*eth::u256*/ codeAt(QString/*eth::Address*/ _a) const; + + Q_INVOKABLE QString/*json*/ getMessages(QString _attribs/*json*/) const; Q_INVOKABLE QString doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice); Q_INVOKABLE void doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice); Q_INVOKABLE unsigned newWatch(QString _json); - Q_INVOKABLE QString watchTransactions(unsigned _w); + Q_INVOKABLE QString watchMessages(unsigned _w); Q_INVOKABLE void killWatch(unsigned _w); void clearWatches(); @@ -138,11 +138,7 @@ public: QString/*eth::Address*/ coinbase() const; QString/*eth::u256*/ gasPrice() const { return toQJS(10 * eth::szabo); } - - QString number() const; - eth::u256 balanceAt(eth::Address _a) const; - double txCountAt(eth::Address _a) const; - bool isContractAt(eth::Address _a) const; + int getDefault() const; QString/*eth::KeyPair*/ key() const; QStringList/*list of eth::KeyPair*/ keys() const; @@ -155,6 +151,7 @@ public slots: void setCoinbase(QString/*eth::Address*/); void setMining(bool _l); void setListening(bool _l); + void setDefault(int _block); /// Check to see if anything has changed, fire off signals if so. /// @note Must be called in the QObject's thread. @@ -176,6 +173,7 @@ private: Q_PROPERTY(bool mining READ isMining WRITE setMining NOTIFY netChanged) Q_PROPERTY(bool listening READ isListening WRITE setListening NOTIFY netChanged) Q_PROPERTY(unsigned peerCount READ peerCount NOTIFY miningChanged) + Q_PROPERTY(int defaultBlock READ getDefault NOTIFY setDefault) eth::Client* m_client; std::vector m_watches; @@ -187,13 +185,14 @@ private: frame->disconnect(); \ frame->addToJavaScriptWindowObject("env", env, QWebFrame::QtOwnership); \ frame->addToJavaScriptWindowObject("eth", eth, QWebFrame::ScriptOwnership); \ - frame->evaluateJavaScript("eth.makeWatch = function(a) { var ww = eth.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { eth.killWatch(w); }; ret.changed = function(f) { eth.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.transactions = function() { return JSON.parse(eth.watchTransactions(this.w)) }; return ret; }"); \ + frame->evaluateJavaScript("eth.makeWatch = function(a) { var ww = eth.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { eth.killWatch(w); }; ret.changed = function(f) { eth.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(eth.watchMessages(this.w)) }; return ret; }"); \ frame->evaluateJavaScript("eth.watch = function(a) { return eth.makeWatch(JSON.stringify(a)) }"); \ frame->evaluateJavaScript("eth.watchChain = function() { return eth.makeWatch('chainChanged') }"); \ frame->evaluateJavaScript("eth.watchPending = function() { return eth.makeWatch('pendingChanged') }"); \ frame->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { var v = eth.doCreate(s, v, c, g, p); if (f) f(v) }"); \ frame->evaluateJavaScript("eth.transact = function(s, v, t, d, g, p, f) { eth.doTransact(s, v, t, d, g, p); if (f) f() }"); \ - frame->evaluateJavaScript("eth.transactions = function(a) { return JSON.parse(eth.getTransactions(JSON.stringify(a))); }"); \ + frame->evaluateJavaScript("eth.messages = function(a) { return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \ + frame->evaluateJavaScript("eth.transactions = function(a) { env.warn('THIS CALL IS DEPRECATED. USE eth.messages INSTEAD.'); return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \ frame->evaluateJavaScript("String.prototype.pad = function(l, r) { return eth.pad(this, l, r) }"); \ frame->evaluateJavaScript("String.prototype.bin = function() { return eth.toBinary(this) }"); \ frame->evaluateJavaScript("String.prototype.unbin = function(l) { return eth.fromBinary(this) }"); \