diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 73061b38a..e4dfabc5f 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -14,6 +14,15 @@ endif () set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) +file(GLOB_RECURSE SRC_LIST "./plugins/*.cpp") +file(GLOB_RECURSE HEADERS "./plugins/*.h") +aux_source_directory(. SRC_LIST) + +file(GLOB_RECURSE PLUGIN_UI RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/plugins/*.ui") +foreach(ITEM ${PLUGIN_UI}) + get_filename_component(UI_NAME ${ITEM} NAME_WE) + qt5_wrap_ui(ui_${UI_NAME}.h ./${ITEM}) +endforeach() include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ..) @@ -39,10 +48,6 @@ qt5_wrap_ui(ui_GasPricing.h GasPricing.ui) # Extensions qt5_wrap_ui(ui_AllAccounts.h AllAccounts.ui) -qt5_wrap_ui(ui_LogPanel.h LogPanel.ui) -qt5_wrap_ui(ui_BrainWallet.h BrainWallet.ui) -qt5_wrap_ui(ui_OtherAccounts.h OtherAccounts.ui) -qt5_wrap_ui(ui_NewAccount.h NewAccount.ui) file(GLOB HEADERS "*.h") @@ -55,19 +60,7 @@ endif () # eth_add_executable is defined in cmake/EthExecutableHelper.cmake eth_add_executable(${EXECUTABLE} ICON alethzero - UI_RESOURCES alethzero.icns - Main.ui - Connect.ui - Debugger.ui - Transact.ui - ExportState.ui - GetPassword.ui - GasPricing.ui - AllAccounts.ui - LogPanel.ui - BrainWallet.ui - OtherAccounts.ui - NewAccount.ui + UI_RESOURCES ${PLUGIN_UI} alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui WIN_RESOURCES alethzero.rc ) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 69846f34c..52e973fe8 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -209,12 +209,6 @@ - - - &Whisper - - - &Debug @@ -235,7 +229,6 @@ - @@ -978,224 +971,6 @@ font-size: 14pt - - - QDockWidget::DockWidgetFeatureMask - - - Whisper - - - 1 - - - - - - - - 0 - 0 - - - - Data - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Work to Prove - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - 0 - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - 0 - - - - - - - false - - - - - - - - 0 - 0 - - - - Topic - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - To - - - - - - - true - - - - - - - seconds - - - 5 - - - 259200 - - - - - - - - 0 - 0 - - - - TTL - - - - - - - - 0 - 0 - - - - From - - - - - - - ms - - - 1 - - - 1000 - - - 50 - - - - - - - Post - - - - - - - - - QDockWidget::DockWidgetFeatureMask - - - Active Whispers - - - 2 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - - - - &Quit @@ -1635,13 +1410,6 @@ font-size: 14pt - shhTo - shhFrom - shhTtl - shhTopic - shhWork - shhData - post tabWidget urlEdit listenIP @@ -1651,7 +1419,6 @@ font-size: 14pt blockChainFilter nameReg nodes - whispers jsInput diff --git a/alethzero/MainFace.cpp b/alethzero/MainFace.cpp index 5c9651f73..9382fdf26 100644 --- a/alethzero/MainFace.cpp +++ b/alethzero/MainFace.cpp @@ -58,6 +58,7 @@ QDockWidget* Plugin::dock(Qt::DockWidgetArea _area, QString _title) if (!m_dock) { m_dock = new QDockWidget(_title, m_main); + m_dock->setObjectName(_title); m_main->addDockWidget(_area, m_dock); m_dock->setFeatures(QDockWidget::AllDockWidgetFeatures | QDockWidget::DockWidgetVerticalTitleBar); } diff --git a/alethzero/MainFace.h b/alethzero/MainFace.h index 525cc312d..2c25b0584 100644 --- a/alethzero/MainFace.h +++ b/alethzero/MainFace.h @@ -49,6 +49,7 @@ namespace az class Plugin; class MainFace; class Main; +class OurWebThreeStubServer; using WatchHandler = std::function; @@ -89,10 +90,12 @@ public: // TODO: provide a set of available web3 modules. virtual dev::WebThreeDirect* web3() const = 0; virtual dev::eth::Client* ethereum() const = 0; + virtual OurWebThreeStubServer* web3Server() const = 0; virtual std::shared_ptr whisper() const = 0; virtual unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f) = 0; virtual unsigned installWatch(dev::h256 const& _tf, WatchHandler const& _f) = 0; + virtual void uninstallWatch(unsigned _id) = 0; // Account naming API virtual void install(AccountNamer* _adopt) = 0; diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 60455969a..1fb84dddc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -94,8 +94,8 @@ QString dev::az::contentsOfQResource(string const& res) } //Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); -Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b"); -//Address c_nameReg = Address("ddd1cea741d548f90d86fb87a3ae6492e18c03a1"); +//Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b"); +Address c_nameReg = Address("96d76ae3397b52d9f61215270df65d72358709e3"); Main::Main(QWidget* _parent): MainFace(_parent), @@ -197,8 +197,6 @@ Main::Main(QWidget* _parent): auto w3ss = new OurWebThreeStubServer(*m_httpConnector, this); m_server.reset(w3ss); auto sessionKey = w3ss->newSession(SessionPermissions{{Privilege::Admin}}); - connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString))); - m_server->setIdentities(keysAsVector(owned())); m_server->StartListening(); WebPage* webPage = new WebPage(this); @@ -387,29 +385,6 @@ void Main::on_sentinel_triggered() ethereum()->setSentinel(sentinel.toStdString()); } -void Main::on_newIdentity_triggered() -{ - KeyPair kp = KeyPair::create(); - m_myIdentities.append(kp); - m_server->setIdentities(keysAsVector(owned())); - refreshWhisper(); -} - -void Main::refreshWhisper() -{ - ui->shhFrom->clear(); - for (auto i: m_server->ids()) - ui->shhFrom->addItem(QString::fromStdString(toHex(i.first.ref()))); -} - -void Main::addNewId(QString _ids) -{ - KeyPair kp(jsToSecret(_ids.toStdString())); - m_myIdentities.push_back(kp); - m_server->setIdentities(keysAsVector(owned())); - refreshWhisper(); -} - NetworkPreferences Main::netPrefs() const { auto listenIP = ui->listenIP->text().toStdString(); @@ -486,8 +461,8 @@ void Main::installWatches() cdebug << "newBlock watch ID: " << newBlockId; cdebug << "newPending watch ID: " << newPendingId; - installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); - installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); +// installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); +// installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); } Address Main::getNameReg() const @@ -498,7 +473,8 @@ Address Main::getNameReg() const Address Main::getCurrencies() const { - return abiOut
(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)).output); +// return abiOut
(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)).output); + return Address(); } bool Main::doConfirm() @@ -665,17 +641,6 @@ void Main::addConsoleMessage(QString const& _js, QString const& _s) ui->jsConsole->setHtml(r); } -static Public stringToPublic(QString const& _a) -{ - string sn = _a.toStdString(); - if (_a.size() == sizeof(Public) * 2) - return Public(fromHex(_a.toStdString())); - else if (_a.size() == sizeof(Public) * 2 + 2 && _a.startsWith("0x")) - return Public(fromHex(_a.mid(2).toStdString())); - else - return Public(); -} - std::string Main::pretty(dev::Address const& _a) const { auto g_newNameReg = getNameReg(); @@ -806,17 +771,6 @@ void Main::writeSettings() { QSettings s("ethereum", "alethzero"); s.remove("address"); - { - QByteArray b; - b.resize(sizeof(Secret) * m_myIdentities.size()); - auto p = b.data(); - for (auto i: m_myIdentities) - { - memcpy(p, &(i.secret()), sizeof(Secret)); - p += sizeof(Secret); - } - s.setValue("identities", b); - } forEach([&](std::shared_ptr p) { @@ -904,27 +858,12 @@ void Main::readSettings(bool _skipGeometry) restoreGeometry(s.value("geometry").toByteArray()); restoreState(s.value("windowState").toByteArray()); - { - m_myIdentities.clear(); - QByteArray b = s.value("identities").toByteArray(); - if (!b.isEmpty()) - { - Secret k; - for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i) - { - memcpy(k.writable().data(), b.data() + i * sizeof(Secret), sizeof(Secret)); - if (!count(m_myIdentities.begin(), m_myIdentities.end(), KeyPair(k))) - m_myIdentities.append(KeyPair(k)); - } - } - } - forEach([&](std::shared_ptr p) { p->readSettings(s); }); - static_cast(ethereum()->gasPricer().get())->setAsk(u256(s.value("askPrice", QString::fromStdString(toString(c_defaultGasPrice))).toString().toStdString())); - static_cast(ethereum()->gasPricer().get())->setBid(u256(s.value("bidPrice", QString::fromStdString(toString(c_defaultGasPrice))).toString().toStdString())); + static_cast(ethereum()->gasPricer().get())->setAsk(u256(s.value("askPrice", QString::fromStdString(toString(DefaultGasPrice))).toString().toStdString())); + static_cast(ethereum()->gasPricer().get())->setBid(u256(s.value("bidPrice", QString::fromStdString(toString(DefaultGasPrice))).toString().toStdString())); ui->upnp->setChecked(s.value("upnp", true).toBool()); ui->forcePublicIP->setText(s.value("forceAddress", "").toString()); @@ -1522,7 +1461,6 @@ void Main::timerEvent(QTimerEvent*) { interval = 0; refreshNetwork(); - refreshWhispers(); refreshCache(); refreshBlockCount(); poll(); @@ -1952,60 +1890,6 @@ void Main::on_ourAccounts_doubleClicked() m_logHistory.clear(); }*/ -static shh::Topics topicFromText(QString _s) -{ - shh::BuildTopic ret; - while (_s.size()) - { - QRegExp r("(@|\\$)?\"([^\"]*)\"(\\s.*)?"); - QRegExp d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?"); - QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?"); - bytes part; - if (r.exactMatch(_s)) - { - for (auto i: r.cap(2)) - part.push_back((byte)i.toLatin1()); - if (r.cap(1) != "$") - for (int i = r.cap(2).size(); i < 32; ++i) - part.push_back(0); - else - part.push_back(0); - _s = r.cap(3); - } - else if (d.exactMatch(_s)) - { - u256 v(d.cap(2).toStdString()); - if (d.cap(6) == "szabo") - v *= szabo; - else if (d.cap(5) == "finney") - v *= finney; - else if (d.cap(4) == "ether") - v *= ether; - bytes bs = dev::toCompactBigEndian(v); - if (d.cap(1) != "$") - for (auto i = bs.size(); i < 32; ++i) - part.push_back(0); - for (auto b: bs) - part.push_back(b); - _s = d.cap(7); - } - else if (h.exactMatch(_s)) - { - bytes bs = fromHex((((h.cap(3).size() & 1) ? "0" : "") + h.cap(3)).toStdString()); - if (h.cap(1) != "$") - for (auto i = bs.size(); i < 32; ++i) - part.push_back(0); - for (auto b: bs) - part.push_back(b); - _s = h.cap(5); - } - else - _s = _s.mid(1); - ret.shift(part); - } - return ret; -} - void Main::on_clearPending_triggered() { writeSettings(); @@ -2215,19 +2099,6 @@ std::string Main::prettyU256(dev::u256 const& _n) const return s.str(); } -void Main::on_post_clicked() -{ - return; - shh::Message m; - m.setTo(stringToPublic(ui->shhTo->currentText())); - m.setPayload(parseData(ui->shhData->toPlainText().toStdString())); - Public f = stringToPublic(ui->shhFrom->currentText()); - Secret from; - if (m_server->ids().count(f)) - from = m_server->ids().at(f); - whisper()->inject(m.seal(from, topicFromText(ui->shhTopic->toPlainText()), ui->shhTtl->value(), ui->shhWork->value())); -} - int Main::authenticate(QString _title, QString _text) { QMessageBox userInput(this); @@ -2240,36 +2111,6 @@ int Main::authenticate(QString _title, QString _text) return userInput.exec(); } -void Main::refreshWhispers() -{ - return; - ui->whispers->clear(); - for (auto const& w: whisper()->all()) - { - shh::Envelope const& e = w.second; - shh::Message m; - for (pair const& i: m_server->ids()) - if (!!(m = e.open(shh::Topics(), i.second))) - break; - if (!m) - m = e.open(shh::Topics()); - - QString msg; - if (m.from()) - // Good message. - msg = QString("{%1 -> %2} %3").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str()); - else if (m) - // Maybe message. - msg = QString("{%1 -> %2} %3 (?)").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str()); - - time_t ex = e.expiry(); - QString t(ctime(&ex)); - t.chop(1); - QString item = QString("[%1 - %2s] *%3 %5 %4").arg(t).arg(e.ttl()).arg(e.workProved()).arg(toString(e.topic()).c_str()).arg(msg); - ui->whispers->addItem(item); - } -} - void Main::dappLoaded(Dapp& _dapp) { QUrl url = m_dappHost->hostDapp(std::move(_dapp)); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index c110f54e8..db9298704 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -84,6 +84,7 @@ public: ~Main(); WebThreeDirect* web3() const override { return m_webThree.get(); } + OurWebThreeStubServer* web3Server() const override { return m_server.get(); } eth::Client* ethereum() const override { return m_webThree->ethereum(); } std::shared_ptr whisper() const override { return m_webThree->whisper(); } @@ -96,8 +97,6 @@ public: std::pair fromString(std::string const& _a) const override; std::string renderDiff(eth::StateDiff const& _d) const override; - QList owned() const { return m_myIdentities; } - u256 gasPrice() const override; eth::KeyManager& keyManager() override { return m_keyManager; } @@ -198,17 +197,11 @@ private slots: void on_debugDumpStatePre_triggered() { debugDumpState(0); } void on_dumpBlockState_triggered(); - // Whisper - void on_newIdentity_triggered(); - void on_post_clicked(); - // Config void on_gasPrices_triggered(); void on_sentinel_triggered(); - void refreshWhisper(); void refreshBlockChain(); - void addNewId(QString _ids); // Dapps void dappLoaded(Dapp& _dapp); //qt does not support rvalue refs for signals @@ -239,7 +232,7 @@ private: unsigned installWatch(eth::LogFilter const& _tf, WatchHandler const& _f) override; unsigned installWatch(h256 const& _tf, WatchHandler const& _f) override; - void uninstallWatch(unsigned _w); + void uninstallWatch(unsigned _w) override; void keysChanged(); @@ -258,7 +251,6 @@ private: void refreshNetwork(); void refreshMining(); - void refreshWhispers(); void refreshCache(); void refreshAll(); @@ -280,7 +272,6 @@ private: QByteArray m_networkConfig; QStringList m_servers; - QList m_myIdentities; eth::KeyManager m_keyManager; QString m_privateChain; dev::Address m_nameReg; diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index 0eea40c2c..1015e565c 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -34,7 +34,7 @@ OurWebThreeStubServer::OurWebThreeStubServer( jsonrpc::AbstractServerConnector& _conn, Main* _main ): - WebThreeStubServer(_conn, *_main->web3(), make_shared(_main), _main->owned().toVector().toStdVector(), _main->keyManager(), *static_cast(_main->ethereum()->gasPricer().get())), + WebThreeStubServer(_conn, *_main->web3(), make_shared(_main), vector{}, _main->keyManager(), *static_cast(_main->ethereum()->gasPricer().get())), m_main(_main) { } diff --git a/alethzero/Transact.h b/alethzero/Transact.h index 60d4a3c2e..015e9d3cc 100644 --- a/alethzero/Transact.h +++ b/alethzero/Transact.h @@ -105,6 +105,8 @@ private: MainFace* m_main = nullptr; NatSpecFace* m_natSpecDB = nullptr; bool m_allGood = false; + + bool m_determiningGas = false; }; } diff --git a/alethzero/AllAccounts.cpp b/alethzero/plugins/blockchain/AllAccounts.cpp similarity index 100% rename from alethzero/AllAccounts.cpp rename to alethzero/plugins/blockchain/AllAccounts.cpp diff --git a/alethzero/AllAccounts.h b/alethzero/plugins/blockchain/AllAccounts.h similarity index 100% rename from alethzero/AllAccounts.h rename to alethzero/plugins/blockchain/AllAccounts.h diff --git a/alethzero/AllAccounts.ui b/alethzero/plugins/blockchain/AllAccounts.ui similarity index 100% rename from alethzero/AllAccounts.ui rename to alethzero/plugins/blockchain/AllAccounts.ui diff --git a/alethzero/BrainWallet.cpp b/alethzero/plugins/brainwallet/BrainWallet.cpp similarity index 100% rename from alethzero/BrainWallet.cpp rename to alethzero/plugins/brainwallet/BrainWallet.cpp diff --git a/alethzero/BrainWallet.h b/alethzero/plugins/brainwallet/BrainWallet.h similarity index 100% rename from alethzero/BrainWallet.h rename to alethzero/plugins/brainwallet/BrainWallet.h diff --git a/alethzero/BrainWallet.ui b/alethzero/plugins/brainwallet/BrainWallet.ui similarity index 100% rename from alethzero/BrainWallet.ui rename to alethzero/plugins/brainwallet/BrainWallet.ui diff --git a/alethzero/LogPanel.cpp b/alethzero/plugins/log/LogPanel.cpp similarity index 100% rename from alethzero/LogPanel.cpp rename to alethzero/plugins/log/LogPanel.cpp diff --git a/alethzero/LogPanel.h b/alethzero/plugins/log/LogPanel.h similarity index 100% rename from alethzero/LogPanel.h rename to alethzero/plugins/log/LogPanel.h diff --git a/alethzero/LogPanel.ui b/alethzero/plugins/log/LogPanel.ui similarity index 100% rename from alethzero/LogPanel.ui rename to alethzero/plugins/log/LogPanel.ui diff --git a/alethzero/plugins/namers/NameRegNamer.cpp b/alethzero/plugins/namers/NameRegNamer.cpp new file mode 100644 index 000000000..312fcbc18 --- /dev/null +++ b/alethzero/plugins/namers/NameRegNamer.cpp @@ -0,0 +1,108 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file NameRegNamer.h + * @author Gav Wood + * @date 2015 + */ + +#include "NameRegNamer.h" +#include +#include +#include +using namespace std; +using namespace dev; +using namespace az; +using namespace eth; + +DEV_AZ_NOTE_PLUGIN(NameRegNamer); + +NameRegNamer::NameRegNamer(MainFace* _m): + AccountNamerPlugin(_m, "NameRegNamer") +{ +} + +NameRegNamer::~NameRegNamer() +{ +} + +string NameRegNamer::toName(Address const& _a) const +{ + for (auto const& r: m_registrars) + { + string n = abiOut(main()->ethereum()->call(Address(1), 0, r, abiIn("name(address)", _a), 1000000, DefaultGasPrice, PendingBlock, FudgeFactor::Lenient).output); + if (!n.empty()) + return n; + } + return string(); +} + +Address NameRegNamer::toAddress(std::string const& _n) const +{ + for (auto const& r: m_registrars) + if (Address a = abiOut
(main()->ethereum()->call(r, abiIn("addr(string)", _n)).output)) + return a; + return Address(); +} + +Addresses NameRegNamer::knownAddresses() const +{ + return m_knownCache; +} + +void NameRegNamer::killRegistrar(Address const& _r) +{ + if (m_filters.count(_r)) + { + main()->uninstallWatch(m_filters.at(_r)); + m_filters.erase(_r); + } + for (auto i = m_registrars.begin(); i != m_registrars.end();) + if (*i == _r) + i = m_registrars.erase(i); + else + ++i; +} + +void NameRegNamer::updateCache() +{ +// m_forwardCache.clear(); +// m_reverseCache.clear(); + m_knownCache.clear(); +#if ETH_FATDB || !ETH_TRUE + for (auto const& r: m_registrars) + for (u256 const& a: keysOf(ethereum()->storageAt(r))) + if (a < u256(1) << 160) + m_knownCache.push_back(Address((u160)a - 1)); +#endif +} + +void NameRegNamer::readSettings(QSettings const& _s) +{ + (void)_s; + while (!m_registrars.empty()) + killRegistrar(m_registrars.back()); + + Address a("047cdba9627a8686bb24b3a65d87dab7efa53d31"); + m_registrars.push_back(a); + m_filters[a] = main()->installWatch(LogFilter().address(a), [=](LocalisedLogEntries const&){ updateCache(); }); + + noteKnownChanged(); +} + +void NameRegNamer::writeSettings(QSettings&) +{ +} diff --git a/alethzero/plugins/namers/NameRegNamer.h b/alethzero/plugins/namers/NameRegNamer.h new file mode 100644 index 000000000..d56e9d41b --- /dev/null +++ b/alethzero/plugins/namers/NameRegNamer.h @@ -0,0 +1,59 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file NameRegNamer.h + * @author Gav Wood + * @date 2015 + */ + +#pragma once + +#include "MainFace.h" + +namespace dev +{ +namespace az +{ + +class NameRegNamer: public QObject, public AccountNamerPlugin +{ + Q_OBJECT + +public: + NameRegNamer(MainFace* _m); + ~NameRegNamer(); + +private: + void readSettings(QSettings const&) override; + void writeSettings(QSettings&) override; + + std::string toName(Address const&) const override; + Address toAddress(std::string const&) const override; + Addresses knownAddresses() const override; + + void updateCache(); + void killRegistrar(Address const& _r); + + Addresses m_registrars; + std::unordered_map m_filters; + + mutable Addresses m_knownCache; +// mutable std::unordered_map m_forwardCache; +// mutable std::unordered_map m_reverseCache; +}; + +} +} diff --git a/alethzero/NewAccount.cpp b/alethzero/plugins/namers/NewAccount.cpp similarity index 100% rename from alethzero/NewAccount.cpp rename to alethzero/plugins/namers/NewAccount.cpp diff --git a/alethzero/NewAccount.h b/alethzero/plugins/namers/NewAccount.h similarity index 100% rename from alethzero/NewAccount.h rename to alethzero/plugins/namers/NewAccount.h diff --git a/alethzero/NewAccount.ui b/alethzero/plugins/namers/NewAccount.ui similarity index 100% rename from alethzero/NewAccount.ui rename to alethzero/plugins/namers/NewAccount.ui diff --git a/alethzero/OtherAccounts.cpp b/alethzero/plugins/namers/OtherAccounts.cpp similarity index 100% rename from alethzero/OtherAccounts.cpp rename to alethzero/plugins/namers/OtherAccounts.cpp diff --git a/alethzero/OtherAccounts.h b/alethzero/plugins/namers/OtherAccounts.h similarity index 100% rename from alethzero/OtherAccounts.h rename to alethzero/plugins/namers/OtherAccounts.h diff --git a/alethzero/OtherAccounts.ui b/alethzero/plugins/namers/OtherAccounts.ui similarity index 100% rename from alethzero/OtherAccounts.ui rename to alethzero/plugins/namers/OtherAccounts.ui diff --git a/alethzero/OurAccounts.cpp b/alethzero/plugins/namers/OurAccounts.cpp similarity index 100% rename from alethzero/OurAccounts.cpp rename to alethzero/plugins/namers/OurAccounts.cpp diff --git a/alethzero/OurAccounts.h b/alethzero/plugins/namers/OurAccounts.h similarity index 100% rename from alethzero/OurAccounts.h rename to alethzero/plugins/namers/OurAccounts.h diff --git a/alethzero/plugins/whisper/Whisper.cpp b/alethzero/plugins/whisper/Whisper.cpp new file mode 100644 index 000000000..cb5d9908f --- /dev/null +++ b/alethzero/plugins/whisper/Whisper.cpp @@ -0,0 +1,178 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Whisper.cpp + * @author Gav Wood + * @date 2015 + */ + +#include "Whisper.h" +#include +#include +#include +#include +#include +#include "OurWebThreeStubServer.h" +#include "ui_Whisper.h" +using namespace std; +using namespace dev; +using namespace az; +using namespace eth; + +DEV_AZ_NOTE_PLUGIN(Whisper); + +static Public stringToPublic(QString const& _a) +{ + string sn = _a.toStdString(); + if (_a.size() == sizeof(Public) * 2) + return Public(fromHex(_a.toStdString())); + else if (_a.size() == sizeof(Public) * 2 + 2 && _a.startsWith("0x")) + return Public(fromHex(_a.mid(2).toStdString())); + else + return Public(); +} + +static shh::Topics topicFromText(QString _s) +{ + shh::BuildTopic ret; + while (_s.size()) + { + QRegExp r("(@|\\$)?\"([^\"]*)\"(\\s.*)?"); + QRegExp d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?"); + QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?"); + bytes part; + if (r.exactMatch(_s)) + { + for (auto i: r.cap(2)) + part.push_back((byte)i.toLatin1()); + if (r.cap(1) != "$") + for (int i = r.cap(2).size(); i < 32; ++i) + part.push_back(0); + else + part.push_back(0); + _s = r.cap(3); + } + else if (d.exactMatch(_s)) + { + u256 v(d.cap(2).toStdString()); + if (d.cap(6) == "szabo") + v *= szabo; + else if (d.cap(5) == "finney") + v *= finney; + else if (d.cap(4) == "ether") + v *= ether; + bytes bs = dev::toCompactBigEndian(v); + if (d.cap(1) != "$") + for (auto i = bs.size(); i < 32; ++i) + part.push_back(0); + for (auto b: bs) + part.push_back(b); + _s = d.cap(7); + } + else if (h.exactMatch(_s)) + { + bytes bs = fromHex((((h.cap(3).size() & 1) ? "0" : "") + h.cap(3)).toStdString()); + if (h.cap(1) != "$") + for (auto i = bs.size(); i < 32; ++i) + part.push_back(0); + for (auto b: bs) + part.push_back(b); + _s = h.cap(5); + } + else + _s = _s.mid(1); + ret.shift(part); + } + return ret; +} + + +Whisper::Whisper(MainFace* _m): + Plugin(_m, "Whisper"), + m_ui(new Ui::Whisper) +{ + dock(Qt::RightDockWidgetArea, "Whisper")->setWidget(new QWidget); + m_ui->setupUi(dock()->widget()); + connect(addMenuItem("New Whisper identity.", "menuNetwork", true), &QAction::triggered, this, &Whisper::on_newIdentity_triggered); + connect(_m->web3Server(), &OurWebThreeStubServer::onNewId, this, &Whisper::addNewId); +} + +void Whisper::readSettings(QSettings const& _s) +{ + m_myIdentities.clear(); + QByteArray b = _s.value("identities").toByteArray(); + if (!b.isEmpty()) + { + Secret k; + for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i) + { + memcpy(k.writable().data(), b.data() + i * sizeof(Secret), sizeof(Secret)); + if (!count(m_myIdentities.begin(), m_myIdentities.end(), KeyPair(k))) + m_myIdentities.append(KeyPair(k)); + } + } + main()->web3Server()->setIdentities(keysAsVector(m_myIdentities)); + refreshWhisper(); +} + +void Whisper::writeSettings(QSettings& _s) +{ + QByteArray b; + b.resize(sizeof(Secret) * m_myIdentities.size()); + auto p = b.data(); + for (auto i: m_myIdentities) + { + memcpy(p, &(i.secret()), sizeof(Secret)); + p += sizeof(Secret); + } + _s.setValue("identities", b); +} + +void Whisper::addNewId(QString _ids) +{ + KeyPair kp(jsToSecret(_ids.toStdString())); + m_myIdentities.push_back(kp); + main()->web3Server()->setIdentities(keysAsVector(m_myIdentities)); + refreshWhisper(); +} + +void Whisper::refreshWhisper() +{ + m_ui->shhFrom->clear(); + for (auto i: main()->web3Server()->ids()) + m_ui->shhFrom->addItem(QString::fromStdString(toHex(i.first.ref()))); +} + +void Whisper::on_newIdentity_triggered() +{ + KeyPair kp = KeyPair::create(); + m_myIdentities.append(kp); + main()->web3Server()->setIdentities(keysAsVector(m_myIdentities)); + refreshWhisper(); +} + +void Whisper::on_post_clicked() +{ + return; + shh::Message m; + m.setTo(stringToPublic(m_ui->shhTo->currentText())); + m.setPayload(parseData(m_ui->shhData->toPlainText().toStdString())); + Public f = stringToPublic(m_ui->shhFrom->currentText()); + Secret from; + if (main()->web3Server()->ids().count(f)) + from = main()->web3Server()->ids().at(f); + whisper()->inject(m.seal(from, topicFromText(m_ui->shhTopic->toPlainText()), m_ui->shhTtl->value(), m_ui->shhWork->value())); +} diff --git a/alethzero/plugins/whisper/Whisper.h b/alethzero/plugins/whisper/Whisper.h new file mode 100644 index 000000000..bcc1d16df --- /dev/null +++ b/alethzero/plugins/whisper/Whisper.h @@ -0,0 +1,60 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Whisper.h + * @author Gav Wood + * @date 2015 + */ + +#pragma once + +#include +#include +#include +#include +#include "MainFace.h" + +namespace Ui +{ +class Whisper; +} + +namespace dev +{ +namespace az +{ + +class Whisper: public QObject, public Plugin +{ + Q_OBJECT + +public: + Whisper(MainFace* _m); + +private: + void readSettings(QSettings const&) override; + void writeSettings(QSettings&) override; + void refreshWhisper(); + void addNewId(QString _ids); + void on_newIdentity_triggered(); + void on_post_clicked(); + + Ui::Whisper* m_ui; + QList m_myIdentities; +}; + +} +} diff --git a/alethzero/plugins/whisper/Whisper.ui b/alethzero/plugins/whisper/Whisper.ui new file mode 100644 index 000000000..e143c2f93 --- /dev/null +++ b/alethzero/plugins/whisper/Whisper.ui @@ -0,0 +1,176 @@ + + + Whisper + + + + + + + 0 + 0 + + + + Data + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Work to Prove + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + 0 + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + 0 + + + + + + + false + + + + + + + + 0 + 0 + + + + Topic + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + To + + + + + + + true + + + + + + + seconds + + + 5 + + + 259200 + + + + + + + + 0 + 0 + + + + TTL + + + + + + + + 0 + 0 + + + + From + + + + + + + ms + + + 1 + + + 1000 + + + 50 + + + + + + + Post + + + + + + + + diff --git a/alethzero/plugins/whisper/WhisperPeers.cpp b/alethzero/plugins/whisper/WhisperPeers.cpp new file mode 100644 index 000000000..07198f93d --- /dev/null +++ b/alethzero/plugins/whisper/WhisperPeers.cpp @@ -0,0 +1,78 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file WhisperPeers.cpp + * @author Gav Wood + * @date 2015 + */ + +#include "WhisperPeers.h" +#include +#include +#include +#include +#include "OurWebThreeStubServer.h" +#include "ui_WhisperPeers.h" +using namespace std; +using namespace dev; +using namespace az; +using namespace eth; + +DEV_AZ_NOTE_PLUGIN(WhisperPeers); + +WhisperPeers::WhisperPeers(MainFace* _m): + Plugin(_m, "WhisperPeers"), + m_ui(new Ui::WhisperPeers) +{ + dock(Qt::RightDockWidgetArea, "Active Whispers")->setWidget(new QWidget); + m_ui->setupUi(dock()->widget()); + startTimer(1000); +} + +void WhisperPeers::timerEvent(QTimerEvent*) +{ + refreshWhispers(); +} + +void WhisperPeers::refreshWhispers() +{ + return; + m_ui->whispers->clear(); + for (auto const& w: whisper()->all()) + { + shh::Envelope const& e = w.second; + shh::Message m; + for (pair const& i: main()->web3Server()->ids()) + if (!!(m = e.open(shh::Topics(), i.second))) + break; + if (!m) + m = e.open(shh::Topics()); + + QString msg; + if (m.from()) + // Good message. + msg = QString("{%1 -> %2} %3").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str()); + else if (m) + // Maybe message. + msg = QString("{%1 -> %2} %3 (?)").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str()); + + time_t ex = e.expiry(); + QString t(ctime(&ex)); + t.chop(1); + QString item = QString("[%1 - %2s] *%3 %5 %4").arg(t).arg(e.ttl()).arg(e.workProved()).arg(toString(e.topic()).c_str()).arg(msg); + m_ui->whispers->addItem(item); + } +} diff --git a/alethzero/plugins/whisper/WhisperPeers.h b/alethzero/plugins/whisper/WhisperPeers.h new file mode 100644 index 000000000..2e9ade3a2 --- /dev/null +++ b/alethzero/plugins/whisper/WhisperPeers.h @@ -0,0 +1,55 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file WhisperPeers.h + * @author Gav Wood + * @date 2015 + */ + +#pragma once + +#include +#include +#include +#include +#include "MainFace.h" + +namespace Ui +{ +class WhisperPeers; +} + +namespace dev +{ +namespace az +{ + +class WhisperPeers: public QObject, public Plugin +{ + Q_OBJECT + +public: + WhisperPeers(MainFace* _m); + +private: + void timerEvent(QTimerEvent*) override; + void refreshWhispers(); + + Ui::WhisperPeers* m_ui; +}; + +} +} diff --git a/alethzero/plugins/whisper/WhisperPeers.ui b/alethzero/plugins/whisper/WhisperPeers.ui new file mode 100644 index 000000000..d73c215e8 --- /dev/null +++ b/alethzero/plugins/whisper/WhisperPeers.ui @@ -0,0 +1,32 @@ + + + WhisperPeers + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + + + + + + diff --git a/eth/main.cpp b/eth/main.cpp index 68f1da726..7be21eb3d 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -109,8 +109,8 @@ void help() /*<< " -B,--block-fees Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl << " -e,--ether-price Set the ether price in the reference unit e.g. ¢ (default: 30.679)." << endl << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl*/ - << " --ask Set the minimum ask gas price under which no transactions will be mined (default " << toString(c_defaultGasPrice) << " )." << endl - << " --bid Set the bid gas price for to pay for transactions (default " << toString(c_defaultGasPrice) << " )." << endl + << " --ask Set the minimum ask gas price under which no transactions will be mined (default " << toString(DefaultGasPrice) << " )." << endl + << " --bid Set the bid gas price for to pay for transactions (default " << toString(DefaultGasPrice) << " )." << endl << endl << "Client mining:" << endl << " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl @@ -338,8 +338,8 @@ int main(int argc, char** argv) // TransactionPriority priority = TransactionPriority::Medium; // double etherPrice = 30.679; // double blockFees = 15.0; - u256 askPrice = c_defaultGasPrice; - u256 bidPrice = c_defaultGasPrice; + u256 askPrice = DefaultGasPrice; + u256 bidPrice = DefaultGasPrice; // javascript console bool useConsole = false; diff --git a/evmjit/CMakeLists.txt b/evmjit/CMakeLists.txt index 619477119..49bf7f73d 100644 --- a/evmjit/CMakeLists.txt +++ b/evmjit/CMakeLists.txt @@ -3,13 +3,14 @@ cmake_minimum_required(VERSION 2.8.12) if (${CMAKE_VERSION} VERSION_GREATER 3.0) cmake_policy(SET CMP0042 OLD) # fix MACOSX_RPATH cmake_policy(SET CMP0048 NEW) # allow VERSION argument in project() - project(EVMJIT VERSION 0.9.0 LANGUAGES CXX) + project(EVMJIT VERSION 0.9.0.1 LANGUAGES CXX) else() project(EVMJIT) - set(EVMJIT_VERSION "0.9.0") + set(EVMJIT_VERSION "0.9.0.1") set(EVMJIT_VERSION_MAJOR 0) set(EVMJIT_VERSION_MINOR 9) set(EVMJIT_VERSION_PATCH 0) + set(EVMJIT_VERSION_TWEAK 1) endif() set_property(GLOBAL PROPERTY USE_FOLDERS ON) diff --git a/evmjit/include/evmjit/JIT-c.h b/evmjit/include/evmjit/JIT-c.h index d7c792451..4e0993ab7 100644 --- a/evmjit/include/evmjit/JIT-c.h +++ b/evmjit/include/evmjit/JIT-c.h @@ -47,10 +47,6 @@ typedef enum evmjit_return_code // Standard error codes OutOfGas = -1, - StackUnderflow = -2, - BadJumpDestination = -3, - BadInstruction = -4, - Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected // Internal error codes LLVMError = -101, diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index e74534243..285a33218 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -101,10 +101,6 @@ enum class ReturnCode // Standard error codes OutOfGas = -1, - StackUnderflow = -2, - BadJumpDestination = -3, - BadInstruction = -4, - Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected // Internal error codes LLVMError = -101, diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index 2bc9043db..6db58b594 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -60,14 +60,8 @@ bytesConstRef JitVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _on _ext.suicide(right160(jit2eth(m_data.address))); break; - case evmjit::ReturnCode::BadJumpDestination: - BOOST_THROW_EXCEPTION(BadJumpDestination()); case evmjit::ReturnCode::OutOfGas: BOOST_THROW_EXCEPTION(OutOfGas()); - case evmjit::ReturnCode::StackUnderflow: // FIXME: Remove support for detail errors - BOOST_THROW_EXCEPTION(StackUnderflow()); - case evmjit::ReturnCode::BadInstruction: - BOOST_THROW_EXCEPTION(BadInstruction()); case evmjit::ReturnCode::LinkerWorkaround: // never happens env_sload(); // but forces linker to include env_* JIT callback functions break; diff --git a/evmjit/libevmjit/Array.cpp b/evmjit/libevmjit/Array.cpp index 96329afd5..4f1f47d6e 100644 --- a/evmjit/libevmjit/Array.cpp +++ b/evmjit/libevmjit/Array.cpp @@ -217,11 +217,7 @@ llvm::Type* Array::getType() } Array::Array(llvm::IRBuilder<>& _builder, char const* _name) : - CompilerHelper(_builder), - m_pushFunc([this](){ return createArrayPushFunc(); }), - m_setFunc([this](){ return createArraySetFunc(); }), - m_getFunc([this](){ return createArrayGetFunc(); }), - m_freeFunc([this](){ return createFreeFunc(); }) + CompilerHelper(_builder) { m_array = m_builder.CreateAlloca(getType(), nullptr, _name); m_builder.CreateStore(llvm::ConstantAggregateZero::get(getType()), m_array); @@ -229,11 +225,7 @@ Array::Array(llvm::IRBuilder<>& _builder, char const* _name) : Array::Array(llvm::IRBuilder<>& _builder, llvm::Value* _array) : CompilerHelper(_builder), - m_array(_array), - m_pushFunc([this](){ return createArrayPushFunc(); }), - m_setFunc([this](){ return createArraySetFunc(); }), - m_getFunc([this](){ return createArrayGetFunc(); }), - m_freeFunc([this](){ return createFreeFunc(); }) + m_array(_array) { m_builder.CreateStore(llvm::ConstantAggregateZero::get(getType()), m_array); } diff --git a/evmjit/libevmjit/Array.h b/evmjit/libevmjit/Array.h index 41842f0c9..a2db976b3 100644 --- a/evmjit/libevmjit/Array.h +++ b/evmjit/libevmjit/Array.h @@ -59,10 +59,10 @@ private: llvm::Function* getReallocFunc(); LazyFunction m_pushFunc = {[this](){ return createArrayPushFunc(); }}; // TODO: If works on MSVC, remove form initialization list - LazyFunction m_setFunc; + LazyFunction m_setFunc = {[this](){ return createArraySetFunc(); }}; LazyFunction m_getPtrFunc = {[this](){ return createGetPtrFunc(); }}; - LazyFunction m_getFunc; - LazyFunction m_freeFunc; + LazyFunction m_getFunc = {[this](){ return createArrayGetFunc(); }}; + LazyFunction m_freeFunc = {[this](){ return createFreeFunc(); }}; LazyFunction m_extendFunc = {[this](){ return createExtendFunc(); }}; LazyFunction m_reallocFunc = {[this](){ return getReallocFunc(); }}; }; @@ -70,5 +70,3 @@ private: } } } - - diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index be57a28b8..47b590103 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -20,53 +20,42 @@ namespace eth namespace jit { -static const char* jumpDestName = "JmpDst."; -static const char* basicBlockName = "Instr."; - -BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : +BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc): m_firstInstrIdx{_firstInstrIdx}, m_begin(_begin), m_end(_end), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {isJumpDest ? jumpDestName : basicBlockName, std::to_string(_firstInstrIdx)}, _mainFunc)), - m_stack(*this), - m_builder(_builder), - m_isJumpDest(isJumpDest) -{} - -BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_stack(*this), - m_builder(_builder), - m_isJumpDest(isJumpDest) + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_firstInstrIdx)}, _mainFunc)) {} -BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) : - m_bblock(_owner) +LocalStack::LocalStack(Stack& _globalStack): + m_global(_globalStack) {} -void BasicBlock::LocalStack::push(llvm::Value* _value) +void LocalStack::push(llvm::Value* _value) { assert(_value->getType() == Type::Word); - m_bblock.m_currentStack.push_back(_value); - m_bblock.m_tosOffset += 1; - m_maxSize = std::max(m_maxSize, m_bblock.m_tosOffset); + m_local.push_back(_value); + m_maxSize = std::max(m_maxSize, size()); } -llvm::Value* BasicBlock::LocalStack::pop() +llvm::Value* LocalStack::pop() { - auto result = get(0); + auto item = get(0); + assert(!m_local.empty() || !m_input.empty()); - if (m_bblock.m_currentStack.size() > 0) - m_bblock.m_currentStack.pop_back(); + if (m_local.size() > 0) + m_local.pop_back(); + else + ++m_globalPops; - m_bblock.m_tosOffset -= 1; - return result; + m_minSize = std::min(m_minSize, size()); + return item; } /** * Pushes a copy of _index-th element (tos is 0-th elem). */ -void BasicBlock::LocalStack::dup(size_t _index) +void LocalStack::dup(size_t _index) { auto val = get(_index); push(val); @@ -76,7 +65,7 @@ void BasicBlock::LocalStack::dup(size_t _index) * Swaps tos with _index-th element (tos is 0-th elem). * _index must be > 0. */ -void BasicBlock::LocalStack::swap(size_t _index) +void LocalStack::swap(size_t _index) { assert(_index > 0); auto val = get(_index); @@ -85,306 +74,73 @@ void BasicBlock::LocalStack::swap(size_t _index) set(0, val); } -std::vector::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) +llvm::Value* LocalStack::get(size_t _index) { - auto& currentStack = m_bblock.m_currentStack; - if (_index < currentStack.size()) - return currentStack.end() - _index - 1; - - // Need to map more elements from the EVM stack - auto nNewItems = 1 + _index - currentStack.size(); - currentStack.insert(currentStack.begin(), nNewItems, nullptr); + if (_index < m_local.size()) + return *(m_local.rbegin() + _index); // count from back - return currentStack.end() - _index - 1; -} - -llvm::Value* BasicBlock::LocalStack::get(size_t _index) -{ - auto& initialStack = m_bblock.m_initialStack; - auto itemIter = getItemIterator(_index); + auto idx = _index - m_local.size() + m_globalPops; + if (idx >= m_input.size()) + m_input.resize(idx + 1); + auto& item = m_input[idx]; - if (*itemIter == nullptr) + if (!item) { - // Need to fetch a new item from the EVM stack - assert(static_cast(_index) >= m_bblock.m_tosOffset); - size_t initialIdx = _index - m_bblock.m_tosOffset; - if (initialIdx >= initialStack.size()) - { - auto nNewItems = 1 + initialIdx - initialStack.size(); - initialStack.insert(initialStack.end(), nNewItems, nullptr); - } - - assert(initialStack[initialIdx] == nullptr); - // Create a dummy value. - std::string name = "get_" + std::to_string(_index); - initialStack[initialIdx] = m_bblock.m_builder.CreatePHI(Type::Word, 0, std::move(name)); - *itemIter = initialStack[initialIdx]; + item = m_global.get(idx); // Reach an item from global stack + m_minSize = std::min(m_minSize, -static_cast(idx) - 1); // and remember required stack size } - return *itemIter; + return item; } -void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) -{ - auto itemIter = getItemIterator(_index); - *itemIter = _word; -} - - - - - -void BasicBlock::synchronizeLocalStack(Stack& _evmStack) +void LocalStack::set(size_t _index, llvm::Value* _word) { - auto blockTerminator = m_llvmBB->getTerminator(); - assert(blockTerminator != nullptr); - if (blockTerminator->getOpcode() != llvm::Instruction::Ret) - { - // Not needed in case of ret instruction. Ret also invalidates the stack. - m_builder.SetInsertPoint(blockTerminator); - - auto currIter = m_currentStack.begin(); - auto endIter = m_currentStack.end(); - - // Update (emit set()) changed values - for (int idx = (int)m_currentStack.size() - 1 - m_tosOffset; - currIter < endIter && idx >= 0; - ++currIter, --idx) - { - assert(static_cast(idx) < m_initialStack.size()); - if (*currIter != m_initialStack[idx]) // value needs update - _evmStack.set(static_cast(idx), *currIter); - } - - // Pop values - if (m_tosOffset < 0) - _evmStack.pop(static_cast(-m_tosOffset)); - - // Push new values - for (; currIter < endIter; ++currIter) - { - assert(*currIter != nullptr); - _evmStack.push(*currIter); - } - } - - // Emit get() for all (used) values from the initial stack - for (size_t idx = 0; idx < m_initialStack.size(); ++idx) + if (_index < m_local.size()) { - auto val = m_initialStack[idx]; - if (val == nullptr) - continue; - - llvm::PHINode* phi = llvm::cast(val); - // Insert call to get() just before the PHI node and replace - // the uses of PHI with the uses of this new instruction. - m_builder.SetInsertPoint(phi); - auto newVal = _evmStack.get(idx); // OPT: Value may be never user but we need to check stack heigth - // It is probably a good idea to keep heigth as a local variable accesible by LLVM directly - phi->replaceAllUsesWith(newVal); - phi->eraseFromParent(); + *(m_local.rbegin() + _index) = _word; + return; } - // Reset the stack - m_initialStack.erase(m_initialStack.begin(), m_initialStack.end()); - m_currentStack.erase(m_currentStack.begin(), m_currentStack.end()); - m_tosOffset = 0; + auto idx = _index - m_local.size() + m_globalPops; + assert(idx < m_input.size()); + m_input[idx] = _word; } -void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRBuilder<>& _builder) -{ - struct BBInfo - { - BasicBlock& bblock; - std::vector predecessors; - size_t inputItems; - size_t outputItems; - std::vector phisToRewrite; - - BBInfo(BasicBlock& _bblock) : - bblock(_bblock), - predecessors(), - inputItems(0), - outputItems(0) - { - auto& initialStack = bblock.m_initialStack; - for (auto it = initialStack.begin(); - it != initialStack.end() && *it != nullptr; - ++it, ++inputItems); - - //if (bblock.localStack().m_tosOffset > 0) - // outputItems = bblock.localStack().m_tosOffset; - auto& exitStack = bblock.m_currentStack; - for (auto it = exitStack.rbegin(); - it != exitStack.rend() && *it != nullptr; - ++it, ++outputItems); - } - }; - - std::map cfg; - - // Create nodes in cfg - for (auto bb : basicBlocks) - cfg.emplace(bb->llvm(), *bb); - - // Create edges in cfg: for each bb info fill the list - // of predecessor infos. - for (auto& pair : cfg) - { - auto bb = pair.first; - auto& info = pair.second; - - for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt) - { - auto predInfoEntry = cfg.find(*predIt); - if (predInfoEntry != cfg.end()) // FIXME: It is wrong - will skip entry block - info.predecessors.push_back(&predInfoEntry->second); - } - } - // Iteratively compute inputs and outputs of each block, until reaching fixpoint. - bool valuesChanged = true; - while (valuesChanged) +void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb) +{ + auto blockTerminator = _bb.getTerminator(); + assert(blockTerminator); + if (blockTerminator->getOpcode() != llvm::Instruction::Ret) { - for (auto& pair : cfg) - { - DLOG(bb) << pair.second.bblock.llvm()->getName().str() - << ": in " << pair.second.inputItems - << ", out " << pair.second.outputItems - << "\n"; - } + // Not needed in case of ret instruction. Ret invalidates the stack. + _builder.SetInsertPoint(blockTerminator); - valuesChanged = false; - for (auto& pair : cfg) + // Update items fetched from global stack ignoring the poped ones + assert(m_globalPops <= m_input.size()); // pop() always does get() + for (auto i = m_globalPops; i < m_input.size(); ++i) { - auto& info = pair.second; - - if (&info.bblock == basicBlocks.front()) - info.inputItems = 0; // we cannot use phi nodes for first block as it is a successor of entry block - - if (info.predecessors.empty()) - info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false - - for (auto predInfo : info.predecessors) - { - if (predInfo->outputItems < info.inputItems) - { - info.inputItems = predInfo->outputItems; - valuesChanged = true; - } - else if (predInfo->outputItems > info.inputItems) - { - predInfo->outputItems = info.inputItems; - valuesChanged = true; - } - } + if (m_input[i]) + m_global.set(i, m_input[i]); } - } - - // Propagate values between blocks. - for (auto& entry : cfg) - { - auto& info = entry.second; - auto& bblock = info.bblock; - llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI()); - auto phiIter = bblock.m_initialStack.begin(); - for (size_t index = 0; index < info.inputItems; ++index, ++phiIter) + // Add new items + auto pops = m_globalPops; // Copy pops counter to keep original value + for (auto& item: m_local) { - assert(llvm::isa(*phiIter)); - auto phi = llvm::cast(*phiIter); - - for (auto predIt : info.predecessors) - { - auto& predExitStack = predIt->bblock.m_currentStack; - auto value = *(predExitStack.end() - 1 - index); - phi->addIncoming(value, predIt->bblock.llvm()); - } - - // Move phi to the front - if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin()) - { - phi->removeFromParent(); - _builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin()); - _builder.Insert(phi); - } + if (pops) // Override poped global items + m_global.set(--pops, item); // using pops counter as the index + else + m_global.push(item); } - // The items pulled directly from predecessors block must be removed - // from the list of items that has to be popped from the initial stack. - auto& initialStack = bblock.m_initialStack; - initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems); - // Initial stack shrinks, so the size difference grows: - bblock.m_tosOffset += (int)info.inputItems; - } - - // We must account for the items that were pushed directly to successor - // blocks and thus should not be on the list of items to be pushed onto - // to EVM stack - for (auto& entry : cfg) - { - auto& info = entry.second; - auto& bblock = info.bblock; - - auto& exitStack = bblock.m_currentStack; - exitStack.erase(exitStack.end() - info.outputItems, exitStack.end()); - bblock.m_tosOffset -= (int)info.outputItems; // FIXME: Fix types - } -} - -void BasicBlock::dump() -{ - dump(std::cerr, false); -} - -void BasicBlock::dump(std::ostream& _out, bool _dotOutput) -{ - llvm::raw_os_ostream out(_out); - - out << (_dotOutput ? "" : "Initial stack:\n"); - for (auto val : m_initialStack) - { - if (val == nullptr) - out << " ?"; - else if (llvm::isa(val)) - out << " " << val->getName(); - else if (llvm::isa(val)) - out << *val; - else - out << " " << *val; - - out << (_dotOutput ? "\\l" : "\n"); - } - - out << (_dotOutput ? "| " : "Instructions:\n"); - for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins) - out << *ins << (_dotOutput ? "\\l" : "\n"); - - if (! _dotOutput) - out << "Current stack (offset = " << m_tosOffset << "):\n"; - else - out << "|"; - - for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val) - { - if (*val == nullptr) - out << " ?"; - else if (llvm::isa(*val)) - out << " " << (*val)->getName(); - else if (llvm::isa(*val)) - out << **val; - else - out << " " << **val; - out << (_dotOutput ? "\\l" : "\n"); + // Pop not overriden items + if (pops) + m_global.pop(pops); } - - if (! _dotOutput) - out << " ...\n----------------------------------------\n"; } - - } } } diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index ddf73a04c..a6e420efc 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -14,52 +14,58 @@ namespace jit using namespace evmjit; using instr_idx = uint64_t; -class BasicBlock +class LocalStack { public: - class LocalStack - { - public: - /// Pushes value on stack - void push(llvm::Value* _value); + explicit LocalStack(Stack& _globalStack); + LocalStack(LocalStack const&) = delete; + void operator=(LocalStack const&) = delete; + + /// Pushes value on stack + void push(llvm::Value* _value); - /// Pops and returns top value - llvm::Value* pop(); + /// Pops and returns top value + llvm::Value* pop(); - /// Duplicates _index'th value on stack - void dup(size_t _index); + /// Duplicates _index'th value on stack + void dup(size_t _index); - /// Swaps _index'th value on stack with a value on stack top. - /// @param _index Index of value to be swaped. Must be > 0. - void swap(size_t _index); + /// Swaps _index'th value on stack with a value on stack top. + /// @param _index Index of value to be swaped. Must be > 0. + void swap(size_t _index); - size_t getMaxSize() const { return m_maxSize; } - int getDiff() const { return m_bblock.m_tosOffset; } + ssize_t size() const { return static_cast(m_local.size()) - static_cast(m_globalPops); } + ssize_t minSize() const { return m_minSize; } + ssize_t maxSize() const { return m_maxSize; } - private: - LocalStack(BasicBlock& _owner); - LocalStack(LocalStack const&) = delete; - void operator=(LocalStack const&) = delete; - friend BasicBlock; + /// Finalize local stack: check the requirements and update of the global stack. + void finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb); - /// Gets _index'th value from top (counting from 0) - llvm::Value* get(size_t _index); +private: + /// Gets _index'th value from top (counting from 0) + llvm::Value* get(size_t _index); - /// Sets _index'th value from top (counting from 0) - void set(size_t _index, llvm::Value* _value); + /// Sets _index'th value from top (counting from 0) + void set(size_t _index, llvm::Value* _value); - std::vector::iterator getItemIterator(size_t _index); + /// Items fetched from global stack. First element matches the top of the global stack. + /// Can contain nulls if some items has been skipped. + std::vector m_input; - private: - BasicBlock& m_bblock; - int m_maxSize = 0; ///< Max size reached by the stack. - }; + /// Local stack items that has not been pushed to global stack. First item is just above global stack. + std::vector m_local; - explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); - explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); + Stack& m_global; ///< Reference to global stack. - BasicBlock(const BasicBlock&) = delete; - BasicBlock& operator=(const BasicBlock&) = delete; + size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap. + ssize_t m_minSize = 0; ///< Minimum reached local stack size. Can be negative. + ssize_t m_maxSize = 0; ///< Maximum reached local stack size. +}; + +class BasicBlock +{ +public: + explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc); llvm::BasicBlock* llvm() { return m_llvmBB; } @@ -67,61 +73,12 @@ public: code_iterator begin() const { return m_begin; } code_iterator end() const { return m_end; } - bool isJumpDest() const { return m_isJumpDest; } - - llvm::Value* getJumpTarget() const { return m_jumpTarget; } - void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; } - - LocalStack& localStack() { return m_stack; } - - /// Optimization: propagates values between local stacks in basic blocks - /// to avoid excessive pushing/popping on the EVM stack. - static void linkLocalStacks(std::vector _basicBlocks, llvm::IRBuilder<>& _builder); - - /// Synchronize current local stack with the EVM stack. - void synchronizeLocalStack(Stack& _evmStack); - - /// Prints local stack and block instructions to stderr. - /// Useful for calling in a debugger session. - void dump(); - void dump(std::ostream& os, bool _dotOutput = false); - private: instr_idx const m_firstInstrIdx = 0; ///< Code index of first instruction in the block - code_iterator const m_begin = {}; ///< Iterator pointing code beginning of the block - code_iterator const m_end = {}; ///< Iterator pointing code end of the block - - llvm::BasicBlock* const m_llvmBB; - - /// Basic black state vector (stack) - current/end values and their positions on stack - /// @internal Must be AFTER m_llvmBB - LocalStack m_stack; - - llvm::IRBuilder<>& m_builder; - - /// This stack contains LLVM values that correspond to items found at - /// the EVM stack when the current basic block starts executing. - /// Location 0 corresponds to the top of the EVM stack, location 1 is - /// the item below the top and so on. The stack grows as the code - /// accesses more items on the EVM stack but once a value is put on - /// the stack, it will never be replaced. - std::vector m_initialStack; - - /// This stack tracks the contents of the EVM stack as the basic block - /// executes. It may grow on both sides, as the code pushes items on - /// top of the stack or changes existing items. - std::vector m_currentStack; - - /// How many items higher is the current stack than the initial one. - /// May be negative. - int m_tosOffset = 0; - - /// Is the basic block a valid jump destination. - /// JUMPDEST is the first instruction of the basic block. - bool const m_isJumpDest = false; + code_iterator const m_begin = {}; ///< Iterator pointing code beginning of the block + code_iterator const m_end = {}; ///< Iterator pointing code end of the block - /// If block finishes with dynamic jump target index is stored here - llvm::Value* m_jumpTarget = nullptr; + llvm::BasicBlock* const m_llvmBB; ///< Reference to the LLVM BasicBlock }; } diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 61aa464a6..182b5fef8 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -36,7 +36,7 @@ Compiler::Compiler(Options const& _options): Type::init(m_builder.getContext()); } -void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEnd) +std::vector Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEnd, llvm::SwitchInst& _jumpTable) { /// Helper function that skips push data and finds next iterator (can be the end) auto skipPushDataAndGetNext = [](code_iterator _curr, code_iterator _end) @@ -54,8 +54,9 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn if (*(_codeEnd - 1) != static_cast(Instruction::STOP)) break; + std::vector blocks; + auto begin = _codeBegin; // begin of current block - bool nextJumpDest = false; for (auto curr = begin, next = begin; curr != _codeEnd; curr = next) { next = skipPushDataAndGetNext(curr, _codeEnd); @@ -71,10 +72,6 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn isEnd = true; break; - case Instruction::JUMPDEST: - nextJumpDest = true; - break; - default: break; } @@ -86,42 +83,32 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn if (isEnd) { auto beginIdx = begin - _codeBegin; - m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), - std::forward_as_tuple(beginIdx, begin, next, m_mainFunc, m_builder, nextJumpDest)); - nextJumpDest = false; + blocks.emplace_back(beginIdx, begin, next, m_mainFunc); + if (Instruction(*begin) == Instruction::JUMPDEST) + _jumpTable.addCase(Constant::get(beginIdx), blocks.back().llvm()); begin = next; } } + + return blocks; } -llvm::BasicBlock* Compiler::getJumpTableBlock(RuntimeManager& _runtimeManager) +void Compiler::fillJumpTable() { - if (!m_jumpTableBlock) + assert(m_jumpTableBB); + if (llvm::pred_empty(m_jumpTableBB)) { - m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder, true)); - InsertPointGuard g{m_builder}; - m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); - auto dest = m_builder.CreatePHI(Type::Word, 8, "target"); - auto switchInstr = m_builder.CreateSwitch(dest, getBadJumpBlock(_runtimeManager)); - for (auto&& p : m_basicBlocks) - { - if (p.second.isJumpDest()) - switchInstr->addCase(Constant::get(p.first), p.second.llvm()); - } + m_jumpTableBB->eraseFromParent(); // remove if unused + return; } - return m_jumpTableBlock->llvm(); -} -llvm::BasicBlock* Compiler::getBadJumpBlock(RuntimeManager& _runtimeManager) -{ - if (!m_badJumpBlock) + // TODO: Extend this function as `resolveJumps()` and fill gaps in branch instructions. + auto target = llvm::cast(m_jumpTableBB->begin()); + for (auto pred: llvm::predecessors(m_jumpTableBB)) { - m_badJumpBlock.reset(new BasicBlock("BadJump", m_mainFunc, m_builder, true)); - InsertPointGuard g{m_builder}; - m_builder.SetInsertPoint(m_badJumpBlock->llvm()); - _runtimeManager.exit(ReturnCode::BadJumpDestination); + auto targetMd = llvm::cast(pred->getTerminator()->getMetadata("target")->getOperand(0)); + target->addIncoming(targetMd->getValue(), pred); } - return m_badJumpBlock->llvm(); } std::unique_ptr Compiler::compile(code_iterator _begin, code_iterator _end, std::string const& _id) @@ -135,16 +122,24 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera // Create entry basic block auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), {}, m_mainFunc); + + m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); + m_abortBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Abort", m_mainFunc); + m_jumpTableBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "JumpTable", m_mainFunc); + m_builder.SetInsertPoint(m_jumpTableBB); + auto target = m_builder.CreatePHI(Type::Word, 16, "target"); + auto& jumpTable = *m_builder.CreateSwitch(target, m_abortBB); + m_builder.SetInsertPoint(entryBlock); - createBasicBlocks(_begin, _end); + auto blocks = createBasicBlocks(_begin, _end, jumpTable); // Init runtime structures. RuntimeManager runtimeManager(m_builder, _begin, _end); GasMeter gasMeter(m_builder, runtimeManager); Memory memory(runtimeManager, gasMeter); Ext ext(runtimeManager, memory); - Stack stack(m_builder, runtimeManager); + Stack stack(m_builder); runtimeManager.setStack(stack); // Runtime Manager will free stack memory Arith256 arith(m_builder); @@ -162,87 +157,39 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto normalFlow = m_builder.CreateICmpEQ(r, m_builder.getInt32(0)); runtimeManager.setJmpBuf(jmpBuf); - // TODO: Create Stop basic block on demand - m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - m_abortBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Abort", m_mainFunc); - - auto firstBB = m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.begin()->second.llvm(); + auto firstBB = blocks.empty() ? m_stopBB : blocks.front().llvm(); m_builder.CreateCondBr(normalFlow, firstBB, m_abortBB, Type::expectTrue); - for (auto basicBlockPairIt = m_basicBlocks.begin(); basicBlockPairIt != m_basicBlocks.end(); ++basicBlockPairIt) + for (auto it = blocks.begin(); it != blocks.end(); ++it) { - auto& basicBlock = basicBlockPairIt->second; - auto iterCopy = basicBlockPairIt; - ++iterCopy; - auto nextBasicBlock = (iterCopy != m_basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); + // TODO: Rewrite + auto nextIt = it + 1; + auto nextBasicBlock = (nextIt != blocks.end()) ? nextIt->llvm() : nullptr; // TODO: What with Stop block? + compileBasicBlock(*it, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack, jumpTable); } // Code for special blocks: - // TODO: move to separate function. m_builder.SetInsertPoint(m_stopBB); runtimeManager.exit(ReturnCode::Stop); m_builder.SetInsertPoint(m_abortBB); runtimeManager.exit(ReturnCode::OutOfGas); - removeDeadBlocks(); - - // Link jump table target index - if (m_jumpTableBlock) - { - auto phi = llvm::cast(&m_jumpTableBlock->llvm()->getInstList().front()); - for (auto predIt = llvm::pred_begin(m_jumpTableBlock->llvm()); predIt != llvm::pred_end(m_jumpTableBlock->llvm()); ++predIt) - { - BasicBlock* pred = nullptr; - for (auto&& p : m_basicBlocks) - { - if (p.second.llvm() == *predIt) - { - pred = &p.second; - break; - } - } - - phi->addIncoming(pred->getJumpTarget(), pred->llvm()); - } - } - - dumpCFGifRequired("blocks-init.dot"); - - if (m_options.optimizeStack) - { - std::vector blockList; - for (auto& entry : m_basicBlocks) - blockList.push_back(&entry.second); - - if (m_jumpTableBlock) - blockList.push_back(m_jumpTableBlock.get()); - - BasicBlock::linkLocalStacks(blockList, m_builder); - - dumpCFGifRequired("blocks-opt.dot"); - } - - for (auto& entry : m_basicBlocks) - entry.second.synchronizeLocalStack(stack); - if (m_jumpTableBlock) - m_jumpTableBlock->synchronizeLocalStack(stack); - - dumpCFGifRequired("blocks-sync.dot"); + fillJumpTable(); return module; } void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runtimeManager, - Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock) + Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, Stack& _globalStack, + llvm::SwitchInst& jumpTable) { if (!_nextBasicBlock) // this is the last block in the code _nextBasicBlock = m_stopBB; m_builder.SetInsertPoint(_basicBlock.llvm()); - auto& stack = _basicBlock.localStack(); + LocalStack stack{_globalStack}; for (auto it = _basicBlock.begin(); it != _basicBlock.end(); ++it) { @@ -609,44 +556,23 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti case Instruction::JUMP: case Instruction::JUMPI: { - llvm::BasicBlock* targetBlock = nullptr; + auto jumpBlock = m_jumpTableBB; auto target = stack.pop(); - if (auto constant = llvm::dyn_cast(target)) - { - auto&& c = constant->getValue(); - auto targetIdx = c.getActiveBits() <= 64 ? c.getZExtValue() : -1; - auto it = m_basicBlocks.find(targetIdx); - targetBlock = (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : getBadJumpBlock(_runtimeManager); - } + auto jumpInst = (inst == Instruction::JUMP) ? + m_builder.CreateBr(jumpBlock) : + m_builder.CreateCondBr(m_builder.CreateICmpNE(stack.pop(), Constant::get(0), "jump.check"), jumpBlock, _nextBasicBlock); - // TODO: Improve; check for constants - if (inst == Instruction::JUMP) + if (auto constant = llvm::dyn_cast(target)) { - if (targetBlock) - { - m_builder.CreateBr(targetBlock); - } - else - { - _basicBlock.setJumpTarget(target); - m_builder.CreateBr(getJumpTableBlock(_runtimeManager)); - } + // If target index is a constant do direct jump to the target block. + auto bb = jumpTable.findCaseValue(constant).getCaseSuccessor(); + jumpInst->setSuccessor(0, bb); } - else // JUMPI + else { - auto val = stack.pop(); - auto zero = Constant::get(0); - auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - - if (targetBlock) - { - m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock); - } - else - { - _basicBlock.setJumpTarget(target); - m_builder.CreateCondBr(cond, getJumpTableBlock(_runtimeManager), _nextBasicBlock); - } + // Attach medatada to branch instruction with information about target index. + auto targetMd = llvm::MDNode::get(jumpInst->getContext(), llvm::LocalAsMetadata::get(target)); + jumpInst->setMetadata("target", targetMd); } break; } @@ -868,109 +794,12 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti if (!_basicBlock.llvm()->getTerminator()) m_builder.CreateBr(_nextBasicBlock); - m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); - _runtimeManager.checkStackLimit(_basicBlock.localStack().getMaxSize(), _basicBlock.localStack().getDiff()); -} - - - -void Compiler::removeDeadBlocks() -{ - // Remove dead basic blocks - auto sthErased = false; - do - { - sthErased = false; - for (auto it = m_basicBlocks.begin(); it != m_basicBlocks.end();) - { - auto llvmBB = it->second.llvm(); - if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) - { - llvmBB->eraseFromParent(); - m_basicBlocks.erase(it++); - sthErased = true; - } - else - ++it; - } - } - while (sthErased); - - if (m_jumpTableBlock && llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) - { - m_jumpTableBlock->llvm()->eraseFromParent(); - m_jumpTableBlock.reset(); - } - - if (m_badJumpBlock && llvm::pred_begin(m_badJumpBlock->llvm()) == llvm::pred_end(m_badJumpBlock->llvm())) - { - m_badJumpBlock->llvm()->eraseFromParent(); - m_badJumpBlock.reset(); - } -} + stack.finalize(m_builder, *_basicBlock.llvm()); // TODO: Use references -void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) -{ - if (! m_options.dumpCFG) - return; - - // TODO: handle i/o failures - std::ofstream ofs(_dotfilePath); - dumpCFGtoStream(ofs); - ofs.close(); + m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); // TODO: Move to LocalStack::finalize + _runtimeManager.checkStackLimit(stack.minSize(), stack.maxSize(), stack.size()); } -void Compiler::dumpCFGtoStream(std::ostream& _out) -{ - _out << "digraph BB {\n" - << " node [shape=record, fontname=Courier, fontsize=10];\n" - << " entry [share=record, label=\"entry block\"];\n"; - - std::vector blocks; - for (auto& pair : m_basicBlocks) - blocks.push_back(&pair.second); - if (m_jumpTableBlock) - blocks.push_back(m_jumpTableBlock.get()); - if (m_badJumpBlock) - blocks.push_back(m_badJumpBlock.get()); - - // std::map phiNodesPerBlock; - - // Output nodes - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - std::ostringstream oss; - bb->dump(oss, true); - - _out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; - } - - // Output edges - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - auto end = llvm::pred_end(bb->llvm()); - for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) - { - _out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" - << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") - << "];\n"; - } - } - - _out << "}\n"; -} - -void Compiler::dump() -{ - for (auto& entry : m_basicBlocks) - entry.second.dump(); - if (m_jumpTableBlock != nullptr) - m_jumpTableBlock->dump(); -} } } diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index 0b31ae0f2..af45acedb 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -15,9 +15,6 @@ public: struct Options { - /// Optimize stack operations between basic blocks - bool optimizeStack = true; - /// Rewrite switch instructions to sequences of branches bool rewriteSwitchToBranches = true; @@ -25,32 +22,18 @@ public: bool dumpCFG = false; }; - using ProgramCounter = uint64_t; - Compiler(Options const& _options); std::unique_ptr compile(code_iterator _begin, code_iterator _end, std::string const& _id); private: - void createBasicBlocks(code_iterator _begin, code_iterator _end); - - void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); - - llvm::BasicBlock* getJumpTableBlock(RuntimeManager& _runtimeManager); - - llvm::BasicBlock* getBadJumpBlock(RuntimeManager& _runtimeManager); + std::vector createBasicBlocks(code_iterator _begin, code_iterator _end, llvm::SwitchInst& _switchInst); - void removeDeadBlocks(); + void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, + llvm::BasicBlock* _nextBasicBlock, class Stack& _globalStack, llvm::SwitchInst& _jumpTable); - /// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled. - void dumpCFGifRequired(std::string const& _dotfilePath); - - /// Dumps basic block graph in graphviz format to a stream. - void dumpCFGtoStream(std::ostream& _out); - - /// Dumps all basic blocks to stderr. Useful in a debugging session. - void dump(); + void fillJumpTable(); /// Compiler options Options const& m_options; @@ -58,9 +41,6 @@ private: /// Helper class for generating IR llvm::IRBuilder<> m_builder; - /// Maps a program counter pc to a basic block that starts at pc (if any). - std::map m_basicBlocks; - /// Stop basic block - terminates execution with STOP code (0) llvm::BasicBlock* m_stopBB = nullptr; @@ -68,13 +48,10 @@ private: llvm::BasicBlock* m_abortBB = nullptr; /// Block with a jump table. - std::unique_ptr m_jumpTableBlock; - - /// Destination for invalid jumps - std::unique_ptr m_badJumpBlock; + llvm::BasicBlock* m_jumpTableBB = nullptr; /// Main program function - llvm::Function* m_mainFunc = nullptr; + llvm::Function* m_mainFunc = nullptr; // TODO: Remove }; } diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index dea3ea2a0..9cc6aa54a 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -114,6 +114,7 @@ bool LowerEVMPass::doFinalization(llvm::Module&) bool prepare(llvm::Module& _module) { auto pm = llvm::legacy::PassManager{}; + pm.add(llvm::createCFGSimplificationPass()); pm.add(llvm::createDeadCodeEliminationPass()); pm.add(new LowerEVMPass{}); return pm.run(_module); diff --git a/evmjit/libevmjit/RuntimeManager.cpp b/evmjit/libevmjit/RuntimeManager.cpp index 971f14abd..bce378b64 100644 --- a/evmjit/libevmjit/RuntimeManager.cpp +++ b/evmjit/libevmjit/RuntimeManager.cpp @@ -110,8 +110,8 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB m_gasPtr = m_builder.CreateAlloca(Type::Gas, nullptr, "gas.ptr"); m_builder.CreateStore(m_dataElts[RuntimeData::Index::Gas], m_gasPtr); - llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::BytePtr}; - m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "stack.checkSize", getModule()); + llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::Size, Type::BytePtr}; + m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "evm.stack.require", getModule()); m_checkStackLimit->setDoesNotThrow(); m_checkStackLimit->setDoesNotCapture(1); @@ -121,7 +121,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB auto currSizePtr = &m_checkStackLimit->getArgumentList().front(); currSizePtr->setName("currSize"); - auto max = currSizePtr->getNextNode(); + auto min = currSizePtr->getNextNode(); + min->setName("min"); + auto max = min->getNextNode(); max->setName("max"); auto diff = max->getNextNode(); diff->setName("diff"); @@ -131,8 +133,11 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB InsertPointGuard guard{m_builder}; m_builder.SetInsertPoint(checkBB); auto currSize = m_builder.CreateLoad(currSizePtr, "cur"); - auto maxSize = m_builder.CreateNUWAdd(currSize, max, "maxSize"); - auto ok = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(1024), "ok"); + auto minSize = m_builder.CreateAdd(currSize, min, "minSize", false, true); + auto maxSize = m_builder.CreateAdd(currSize, max, "maxSize", true, true); + auto minOk = m_builder.CreateICmpSGE(minSize, m_builder.getInt64(0), "min.ok"); + auto maxOk = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(1024), "max.ok"); + auto ok = m_builder.CreateAnd(minOk, maxOk, "ok"); m_builder.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue); m_builder.SetInsertPoint(updateBB); @@ -145,9 +150,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB m_builder.CreateUnreachable(); } -void RuntimeManager::checkStackLimit(size_t _max, int _diff) +void RuntimeManager::checkStackLimit(ssize_t _min, ssize_t _max, ssize_t _diff) { - createCall(m_checkStackLimit, {m_stackSize, m_builder.getInt64(_max), m_builder.getInt64(_diff), getJmpBuf()}); + createCall(m_checkStackLimit, {m_stackSize, m_builder.getInt64(_min), m_builder.getInt64(_max), m_builder.getInt64(_diff), getJmpBuf()}); } llvm::Value* RuntimeManager::getRuntimePtr() diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index 8c0728aaf..8511c8898 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -50,7 +50,7 @@ public: static llvm::StructType* getRuntimeType(); static llvm::StructType* getRuntimeDataType(); - void checkStackLimit(size_t _max, int _diff); + void checkStackLimit(ssize_t _min, ssize_t _max, ssize_t _diff); private: llvm::Value* getPtr(RuntimeData::Index _index); diff --git a/evmjit/libevmjit/Stack.cpp b/evmjit/libevmjit/Stack.cpp index b7b8f25b1..273aa3855 100644 --- a/evmjit/libevmjit/Stack.cpp +++ b/evmjit/libevmjit/Stack.cpp @@ -16,52 +16,14 @@ namespace eth namespace jit { -Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager): +Stack::Stack(llvm::IRBuilder<>& _builder): CompilerHelper(_builder), - m_runtimeManager(_runtimeManager), m_stack(_builder, "stack") {} -llvm::Function* Stack::getGetFunc() -{ - auto& func = m_get; - if (!func) - { - llvm::Type* argTypes[] = {Type::Size, Type::Size, Type::BytePtr}; - func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::ExternalLinkage, "stack.require", getModule()); - - auto index = &func->getArgumentList().front(); - index->setName("index"); - auto size = index->getNextNode(); - size->setName("size"); - auto jmpBuf = size->getNextNode(); - jmpBuf->setName("jmpBuf"); - - InsertPointGuard guard{m_builder}; - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), {}, func); - auto underflowBB = llvm::BasicBlock::Create(m_builder.getContext(), "Underflow", func); - auto returnBB = llvm::BasicBlock::Create(m_builder.getContext(), "Return", func); - - m_builder.SetInsertPoint(entryBB); - auto underflow = m_builder.CreateICmpUGE(index, size, "underflow"); - m_builder.CreateCondBr(underflow, underflowBB, returnBB); - - m_builder.SetInsertPoint(underflowBB); - m_runtimeManager.abort(jmpBuf); - m_builder.CreateUnreachable(); - - m_builder.SetInsertPoint(returnBB); - m_builder.CreateRetVoid(); - } - return func; -} - llvm::Value* Stack::get(size_t _index) { - createCall(getGetFunc(), {m_builder.getInt64(_index), m_stack.size(), m_runtimeManager.getJmpBuf()}); - auto value = m_stack.get(m_builder.CreateSub(m_stack.size(), m_builder.getInt64(_index + 1))); - //return m_builder.CreateLoad(valuePtr); - return value; + return m_stack.get(m_builder.CreateSub(m_stack.size(), m_builder.getInt64(_index + 1))); } void Stack::set(size_t _index, llvm::Value* _value) @@ -71,8 +33,6 @@ void Stack::set(size_t _index, llvm::Value* _value) void Stack::pop(size_t _count) { - // FIXME: Pop does not check for stack underflow but looks like not needed - // We should place stack.require() check and begining of every BB m_stack.pop(m_builder.getInt64(_count)); } diff --git a/evmjit/libevmjit/Stack.h b/evmjit/libevmjit/Stack.h index ad10dae12..72e3d88d2 100644 --- a/evmjit/libevmjit/Stack.h +++ b/evmjit/libevmjit/Stack.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "Array.h" namespace dev @@ -10,12 +8,11 @@ namespace eth { namespace jit { -class RuntimeManager; -class Stack : public CompilerHelper +class Stack: public CompilerHelper { public: - Stack(llvm::IRBuilder<>& builder, RuntimeManager& runtimeManager); + Stack(llvm::IRBuilder<>& builder); llvm::Value* get(size_t _index); void set(size_t _index, llvm::Value* _value); @@ -24,10 +21,6 @@ public: void free() { m_stack.free(); } private: - llvm::Function* getGetFunc(); - - RuntimeManager& m_runtimeManager; - llvm::Function* m_get = nullptr; Array m_stack; }; @@ -35,5 +28,3 @@ private: } } } - - diff --git a/libethcore/ABI.h b/libethcore/ABI.h index 7d7be90dd..5b7d160d0 100644 --- a/libethcore/ABI.h +++ b/libethcore/ABI.h @@ -43,7 +43,17 @@ template struct ABISerialiser {}; template struct ABISerialiser> { static bytes serialise(FixedHash const& _t) { static_assert(N <= 32, "Cannot serialise hash > 32 bytes."); static_assert(N > 0, "Cannot serialise zero-length hash."); return bytes(32 - N, 0) + _t.asBytes(); } }; template <> struct ABISerialiser { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } }; template <> struct ABISerialiser { static bytes serialise(u160 const& _t) { return bytes(12, 0) + h160(_t).asBytes(); } }; -template <> struct ABISerialiser { static bytes serialise(string32 const& _t) { return bytesConstRef((byte const*)_t.data(), 32).toBytes(); } }; +template <> struct ABISerialiser { static bytes serialise(string32 const& _t) { bytes ret; bytesConstRef((byte const*)_t.data(), 32).populate(bytesRef(&ret)); return ret; } }; +template <> struct ABISerialiser +{ + static bytes serialise(std::string const& _t) + { + bytes ret = h256(u256(32)).asBytes() + h256(u256(_t.size())).asBytes(); + ret.resize(ret.size() + (_t.size() + 31) / 32 * 32); + bytesConstRef(&_t).populate(bytesRef(&ret).cropped(64)); + return ret; + } +}; inline bytes abiInAux() { return {}; } template bytes abiInAux(T const& _t, U const& ... _u) @@ -61,6 +71,19 @@ template struct ABIDeserialiser> { static FixedHash template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } }; template <> struct ABIDeserialiser { static u160 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian(io_t.cropped(12, 20)); io_t = io_t.cropped(32); return ret; } }; template <> struct ABIDeserialiser { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).populate(bytesRef((byte*)ret.data(), 32)); io_t = io_t.cropped(32); return ret; } }; +template <> struct ABIDeserialiser +{ + static std::string deserialise(bytesConstRef& io_t) + { + unsigned o = (uint16_t)u256(h256(io_t.cropped(0, 32))); + unsigned s = (uint16_t)u256(h256(io_t.cropped(o, 32))); + std::string ret; + ret.resize(s); + io_t.cropped(o + 32, s).populate(bytesRef((byte*)ret.data(), s)); + io_t = io_t.cropped(32); + return ret; + } +}; template T abiOut(bytes const& _data) { diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index e5e93e5d1..504fb2dbd 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -148,7 +148,7 @@ public: using Interface::addresses; virtual Addresses addresses(BlockNumber _block) const override; virtual u256 gasLimitRemaining() const override; - virtual u256 gasBidPrice() const override { return c_defaultGasPrice; } + virtual u256 gasBidPrice() const override { return DefaultGasPrice; } /// Get the coinbase address virtual Address address() const override; diff --git a/libethereum/GasPricer.h b/libethereum/GasPricer.h index 9a89fe94d..47867fee7 100644 --- a/libethereum/GasPricer.h +++ b/libethereum/GasPricer.h @@ -40,7 +40,7 @@ enum class TransactionPriority Highest = 8 }; -static const u256 c_defaultGasPrice = 50 * shannon; +static const u256 DefaultGasPrice = 50 * shannon; class GasPricer { @@ -68,8 +68,8 @@ public: u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return m_bid; } private: - u256 m_ask = c_defaultGasPrice; - u256 m_bid = c_defaultGasPrice; + u256 m_ask = DefaultGasPrice; + u256 m_bid = DefaultGasPrice; }; } diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 9c109000f..ed9659f3b 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -71,25 +71,25 @@ public: virtual std::pair submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; /// Submits the given message-call transaction. - void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 10000, u256 const& _gasPrice = c_defaultGasPrice, u256 const& _nonce = UndefinedU256); + void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 1000000, u256 const& _gasPrice = DefaultGasPrice, u256 const& _nonce = UndefinedU256); /// Submits a new contract-creation transaction. /// @returns the new contract's address (assuming it all goes through). - Address submitTransaction(Secret const& _secret, u256 const& _endowment, bytes const& _init, u256 const& _gas = 10000, u256 const& _gasPrice = c_defaultGasPrice, u256 const& _nonce = UndefinedU256); + Address submitTransaction(Secret const& _secret, u256 const& _endowment, bytes const& _init, u256 const& _gas = 1000000, u256 const& _gasPrice = DefaultGasPrice, u256 const& _nonce = UndefinedU256); /// Blocks until all pending transactions have been processed. virtual void flushTransactions() = 0; /// Makes the given call. Nothing is recorded into the state. virtual ExecutionResult call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; - ExecutionResult call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return call(_from, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); } + ExecutionResult call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 1000000, u256 _gasPrice = DefaultGasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return call(_from, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); } ExecutionResult call(Secret const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) { return call(toAddress(_secret), _value, _dest, _data, _gas, _gasPrice, _blockNumber, _ff); } ExecutionResult call(Secret const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return call(toAddress(_secret), _value, _dest, _data, _gas, _gasPrice, _ff); } /// Does the given creation. Nothing is recorded into the state. /// @returns the pair of the Address of the created contract together with its code. virtual ExecutionResult create(Address const& _from, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; - ExecutionResult create(Address const& _from, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return create(_from, _value, _data, _gas, _gasPrice, m_default, _ff); } + ExecutionResult create(Address const& _from, u256 _value, bytes const& _data = bytes(), u256 _gas = 1000000, u256 _gasPrice = DefaultGasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return create(_from, _value, _data, _gas, _gasPrice, m_default, _ff); } ExecutionResult create(Secret const& _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) { return create(toAddress(_secret), _value, _data, _gas, _gasPrice, _blockNumber, _ff); } ExecutionResult create(Secret const& _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return create(toAddress(_secret), _value, _data, _gas, _gasPrice, _ff); } diff --git a/libethereumx/Ethereum.h b/libethereumx/Ethereum.h index 73392ea88..50eab0de3 100644 --- a/libethereumx/Ethereum.h +++ b/libethereumx/Ethereum.h @@ -62,11 +62,11 @@ public: ~Ethereum(); /// Submits the given message-call transaction. - void submitTransaction(Secret const& _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice); + void submitTransaction(Secret const& _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = DefaultGasPrice); /// Submits a new contract-creation transaction. /// @returns the new contract's address (assuming it all goes through). - Address submitTransaction(Secret const& _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice); + Address submitTransaction(Secret const& _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = DefaultGasPrice); /// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly. void inject(bytesConstRef _rlp); @@ -75,7 +75,7 @@ public: void flushTransactions(); /// Makes the given call. Nothing is recorded into the state. - bytes call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice); + bytes call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = DefaultGasPrice); // Informational stuff diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index 565e88213..965adf13e 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -54,7 +54,7 @@ namespace bool isStopSentinel() { - assert((!code.empty() || !codeHash) && "'empty code => empty hash' invariand failed"); + assert((!code.empty() || !codeHash) && "'empty code => empty hash' invariant failed"); return code.empty(); } }; @@ -102,7 +102,7 @@ bytesConstRef SmartVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _ clog(JitInfo) << "JIT: " << codeHash; vmKind = VMKind::JIT; } - else + else if (!_ext.code.empty()) // This check is needed for VM tests { static JitWorker s_worker; diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 9086664a4..2356e10be 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -530,14 +530,8 @@ void Host::connect(std::shared_ptr const& _p) return; } - if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id)) - { - // connect was attempted, so try again by adding to node table - m_nodeTable->addNode(*_p.get()); - // abort unless peer is required - if (!_p->required) - return; - } + if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id) && !_p->required) + return; // prevent concurrently connecting to a node Peer *nptr = _p.get(); diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index f5e978971..d5973ce5e 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -446,9 +446,13 @@ void ClientModel::executeSequence(vector const& _sequence) if (contractAddressIter == m_contractAddresses.end()) { emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); - break; + Address fakeAddress = Address::random(); + std::pair contractToken = resolvePair(transaction.contractId); + m_contractNames[fakeAddress] = contractToken.first; + callAddress(fakeAddress, encoder.encodedData(), transaction); //Transact to a random fake address to that transaction is added to the list anyway } - callAddress(contractAddressIter->second, encoder.encodedData(), transaction); + else + callAddress(contractAddressIter->second, encoder.encodedData(), transaction); } m_gasCosts.append(m_client->lastExecution().gasUsed); onNewTransaction(); @@ -833,9 +837,9 @@ void ClientModel::onNewTransaction() else { //transaction/call - if (tr.transactionData.size() > 0 && tr.transactionData.front().size() >= 4) + if (tr.inputParameters.size() >= 4) { - functionHash = FixedHash<4>(tr.transactionData.front().data(), FixedHash<4>::ConstructFromPointer); + functionHash = FixedHash<4>(tr.inputParameters.data(), FixedHash<4>::ConstructFromPointer); function = QString::fromStdString(toJS(functionHash)); abi = true; } diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 2d43ddc96..7d2125436 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -269,7 +269,7 @@ void MixClient::mine() RLPStream header; h.streamRLP(header); m_postMine.sealBlock(header.out()); - bc().import(m_postMine.blockData(), m_stateDB, (ImportRequirements::Everything & ~ImportRequirements::ValidSeal) != 0); + bc().import(m_postMine.blockData(), m_postMine.state().db(), (ImportRequirements::Everything & ~ImportRequirements::ValidSeal) != 0); m_postMine.sync(bc()); m_preMine = m_postMine; } diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 4a3de4dc6..15a5d5633 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -253,12 +253,16 @@ void ImportTest::importTransaction(json_spirit::mObject const& o_tr) importTransaction(o_tr, m_transaction); } -void ImportTest::compareStates(State const& _stateExpect, State const& _statePost, AccountMaskMap const _expectedStateOptions, WhenError _throw) +int ImportTest::compareStates(State const& _stateExpect, State const& _statePost, AccountMaskMap const _expectedStateOptions, WhenError _throw) { #define CHECK(a,b) \ { \ if (_throw == WhenError::Throw) \ - {TBOOST_CHECK_MESSAGE(a,b);}\ + { \ + TBOOST_CHECK_MESSAGE(a, b); \ + if (!a) \ + return 1; \ + } \ else \ {TBOOST_WARN_MESSAGE(a,b);} \ } @@ -309,12 +313,13 @@ void ImportTest::compareStates(State const& _stateExpect, State const& _statePos "Check State: " << a.first << ": incorrect code '" << toHex(_statePost.code(a.first)) << "', expected '" << toHex(_stateExpect.code(a.first)) << "'"); } } + return 0; } -void ImportTest::exportTest(bytes const& _output) +int ImportTest::exportTest(bytes const& _output) { + int err = 0; // export output - m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add); // compare expected output with post output @@ -322,7 +327,12 @@ void ImportTest::exportTest(bytes const& _output) { std::string warning = "Check State: Error! Unexpected output: " + m_testObject["out"].get_str() + " Expected: " + m_testObject["expectOut"].get_str(); if (Options::get().checkState) - {TBOOST_CHECK_MESSAGE((m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()), warning);} + { + bool statement = (m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()); + TBOOST_CHECK_MESSAGE(statement, warning); + if (!statement) + err = 1; + } else TBOOST_WARN_MESSAGE((m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()), warning); @@ -350,6 +360,7 @@ void ImportTest::exportTest(bytes const& _output) m_testObject["pre"] = fillJsonWithState(m_statePre); m_testObject["env"] = makeAllFieldsHex(m_testObject["env"].get_obj()); m_testObject["transaction"] = makeAllFieldsHex(m_testObject["transaction"].get_obj()); + return err; } json_spirit::mObject fillJsonWithTransaction(Transaction _txn) @@ -566,7 +577,10 @@ void userDefinedTest(std::function doTests) auto& filename = Options::get().singleTestFile; auto& testname = Options::get().singleTestName; - VerbosityHolder sentinel(12); + + if (g_logVerbosity != -1) + VerbosityHolder sentinel(12); + try { cnote << "Testing user defined test: " << filename; @@ -631,7 +645,7 @@ void executeTests(const string& _name, const string& _testPathAppendix, const bo try { - std::cout << "TEST " << _name << ":\n"; + cnote << "TEST " << _name << ":"; json_spirit::mValue v; string s = asString(dev::contents(testPath + "/" + _name + ".json")); TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); @@ -773,7 +787,26 @@ Options::Options() } else if (arg == "--fulloutput") fulloutput = true; + else if (arg == "--verbosity" && i + 1 < argc) + { + static std::ostringstream strCout; //static string to redirect logs to + std::string indentLevel = std::string{argv[i + 1]}; + if (indentLevel == "0") + { + logVerbosity = Verbosity::None; + std::cout.rdbuf(strCout.rdbuf()); + std::cerr.rdbuf(strCout.rdbuf()); + } + else if (indentLevel == "1") + logVerbosity = Verbosity::NiceReport; + else + logVerbosity = Verbosity::Full; + } } + + //Default option + if (logVerbosity == Verbosity::NiceReport) + g_logVerbosity = -1; //disable cnote but leave cerr and cout } Options const& Options::get() diff --git a/test/TestHelper.h b/test/TestHelper.h index 5f2f8d6d5..e5cf13233 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -22,7 +22,6 @@ #pragma once #include - #include #include @@ -143,8 +142,8 @@ public: static json_spirit::mObject& makeAllFieldsHex(json_spirit::mObject& _o); bytes executeTest(); - void exportTest(bytes const& _output); - static void compareStates(eth::State const& _stateExpect, eth::State const& _statePost, eth::AccountMaskMap const _expectedStateOptions = eth::AccountMaskMap(), WhenError _throw = WhenError::Throw); + int exportTest(bytes const& _output); + static int compareStates(eth::State const& _stateExpect, eth::State const& _statePost, eth::AccountMaskMap const _expectedStateOptions = eth::AccountMaskMap(), WhenError _throw = WhenError::Throw); eth::State m_statePre; eth::State m_statePost; @@ -218,6 +217,13 @@ void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) TBOOST_CHECK((_expectedAddrs == _resultAddrs)); }*/ +enum class Verbosity +{ + Full, + NiceReport, + None +}; + class Options { public: @@ -227,6 +233,7 @@ public: std::string statsOutFile; ///< Stats output file. "out" for standard output bool checkState = false;///< Throw error when checking test states bool fulloutput = false;///< Replace large output to just it's length + Verbosity logVerbosity = Verbosity::NiceReport; /// Test selection /// @{ diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 1523a7a11..f448c48e3 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -18,11 +18,75 @@ * @author Marko Simovic * @date 2014 * Stub for generating main boost.test module. + * Original code taken from boost sources. */ #define BOOST_TEST_MODULE EthereumTests #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" -#define BOOST_DISABLE_WIN32 //disables SEH warning +//#define BOOST_DISABLE_WIN32 //disables SEH warning +#define BOOST_TEST_NO_MAIN #include #pragma GCC diagnostic pop + +#include +using namespace boost::unit_test; + +//Custom Boost Initialization +test_suite* init_func( int argc, char* argv[] ) +{ + if (argc == 0) + argv[1]=(char*)"a"; + + dev::test::Options::get(); + + return 0; +} + +//Custom Boost Unit Test Main +int main( int argc, char* argv[] ) +{ + try + { + framework::init( init_func, argc, argv ); + + if( !runtime_config::test_to_run().is_empty() ) + { + test_case_filter filter( runtime_config::test_to_run() ); + + traverse_test_tree( framework::master_test_suite().p_id, filter ); + } + + framework::run(); + + results_reporter::make_report(); + + return runtime_config::no_result_code() + ? boost::exit_success + : results_collector.results( framework::master_test_suite().p_id ).result_code(); + } + catch (framework::nothing_to_test const&) + { + return boost::exit_success; + } + catch (framework::internal_error const& ex) + { + results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl; + + return boost::exit_exception_failure; + } + catch (framework::setup_error const& ex) + { + results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl; + + return boost::exit_exception_failure; + } + catch (...) + { + results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl; + + return boost::exit_exception_failure; + } + + return 0; +} diff --git a/test/fuzzTesting/fuzzHelper.cpp b/test/fuzzTesting/fuzzHelper.cpp index 863c2477c..63fad5a46 100644 --- a/test/fuzzTesting/fuzzHelper.cpp +++ b/test/fuzzTesting/fuzzHelper.cpp @@ -402,13 +402,12 @@ void RandomCodeOptions::setWeights() opCodeProbability = boostDescreteDistrib(weights); } - BOOST_AUTO_TEST_SUITE(RandomCodeTests) BOOST_AUTO_TEST_CASE(rndCode) { std::string code; - std::cerr << "Testing Random Code: "; + cnote << "Testing Random Code: "; try { code = dev::test::RandomCode::generate(10); @@ -417,7 +416,7 @@ BOOST_AUTO_TEST_CASE(rndCode) { BOOST_ERROR("Exception thrown when generating random code!"); } - std::cerr << code; + cnote << code; } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libdevcore/rlp.cpp b/test/libdevcore/rlp.cpp index e64621053..d351bb41a 100644 --- a/test/libdevcore/rlp.cpp +++ b/test/libdevcore/rlp.cpp @@ -52,6 +52,7 @@ namespace dev void doRlpTests(json_spirit::mValue& v, bool _fillin) { + string testname; for (auto& i: v.get_obj()) { js::mObject& o = i.second.get_obj(); @@ -61,9 +62,11 @@ namespace dev continue; } - cout << " " << i.first << endl; - TBOOST_REQUIRE((o.count("out") > 0)); - TBOOST_REQUIRE((!o["out"].is_null())); + cnote << " " << i.first; + testname = "(" + i.first + ") "; + + TBOOST_REQUIRE_MESSAGE((o.count("out") > 0), testname + "out not set!"); + TBOOST_REQUIRE_MESSAGE((!o["out"].is_null()), testname + "out is set to null!"); if (_fillin) { @@ -88,7 +91,7 @@ namespace dev else { //Check Encode - TBOOST_REQUIRE((o.count("in") > 0)); + TBOOST_REQUIRE_MESSAGE((o.count("in") > 0), testname + "in not set!"); RlpType rlpType = RlpType::Test; if (o["in"].type() == js::str_type) { @@ -112,7 +115,7 @@ namespace dev msg << " But Computed: " << computedText; TBOOST_CHECK_MESSAGE( (expectedText == computedText), - msg.str() + testname + msg.str() ); } @@ -155,11 +158,11 @@ namespace dev //Check that there was an exception as input is INVALID if (rlpType == RlpType::Invalid && !was_exception) - TBOOST_ERROR("Expected RLP Exception as rlp should be invalid!"); + TBOOST_ERROR(testname + "Expected RLP Exception as rlp should be invalid!"); //input is VALID check that there was no exceptions if (was_exception) - TBOOST_ERROR("Unexpected RLP Exception!"); + TBOOST_ERROR(testname + "Unexpected RLP Exception!"); } } } @@ -256,11 +259,11 @@ BOOST_AUTO_TEST_CASE(EmptyArrayList) } catch (Exception const& _e) { - TBOOST_ERROR("Failed test with Exception: " << _e.what()); + TBOOST_ERROR("(EmptyArrayList) Failed test with Exception: " << _e.what()); } catch (exception const& _e) { - TBOOST_ERROR("Failed test with Exception: " << _e.what()); + TBOOST_ERROR("(EmptyArrayList) Failed test with Exception: " << _e.what()); } } @@ -302,11 +305,11 @@ BOOST_AUTO_TEST_CASE(rlpRandom) catch (Exception const& _e) { - TBOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); + TBOOST_ERROR(path.filename().string() + "Failed test with Exception: " << diagnostic_information(_e)); } catch (std::exception const& _e) { - TBOOST_ERROR("Failed test with Exception: " << _e.what()); + TBOOST_ERROR(path.filename().string() + "Failed test with Exception: " << _e.what()); } } } diff --git a/test/libdevcrypto/AES.cpp b/test/libdevcrypto/AES.cpp index 0617033aa..3991a7471 100644 --- a/test/libdevcrypto/AES.cpp +++ b/test/libdevcrypto/AES.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; using namespace dev; @@ -33,7 +34,7 @@ BOOST_AUTO_TEST_SUITE(AES) BOOST_AUTO_TEST_CASE(AesDecrypt) { - cout << "AesDecrypt" << endl; + cnote << "AesDecrypt"; bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "test"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") == kp.address()); @@ -41,7 +42,7 @@ BOOST_AUTO_TEST_CASE(AesDecrypt) BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed) { - cout << "AesDecryptWrongSeed" << endl; + cnote << "AesDecryptWrongSeed"; bytes seed = fromHex("badaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "test"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address()); @@ -49,7 +50,7 @@ BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed) BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword) { - cout << "AesDecryptWrongPassword" << endl; + cnote << "AesDecryptWrongPassword"; bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "badtest"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address()); @@ -57,24 +58,23 @@ BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword) BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed) { - cout << "AesDecryptFailInvalidSeed" << endl; + cnote << "AesDecryptFailInvalidSeed"; bytes seed = fromHex("xdbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeedSize) { - cout << "AesDecryptFailInvalidSeedSize" << endl; + cnote << "AesDecryptFailInvalidSeedSize"; bytes seed = fromHex("000102030405060708090a0b0c0d0e0f"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed2) { - cout << "AesDecryptFailInvalidSeed2" << endl; + cnote << "AesDecryptFailInvalidSeed2"; bytes seed = fromHex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } BOOST_AUTO_TEST_SUITE_END() - diff --git a/test/libdevcrypto/hexPrefix.cpp b/test/libdevcrypto/hexPrefix.cpp index 4d89ec594..6c87387cf 100644 --- a/test/libdevcrypto/hexPrefix.cpp +++ b/test/libdevcrypto/hexPrefix.cpp @@ -29,7 +29,7 @@ #include #include #include -#include "../TestHelper.h" +#include using namespace std; using namespace dev; diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index be88c7cee..23fec311b 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -27,7 +27,7 @@ #include #include #include "MemTrie.h" -#include "../TestHelper.h" +#include using namespace std; using namespace dev; @@ -315,35 +315,35 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) MemoryDB m; GenericTrieDB t(&m); t.init(); // initialise as empty tree. - cout << t; - cout << m; - cout << t.root() << endl; - cout << stringMapHash256(StringMap()) << endl; + cnote << t; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256(StringMap()); t.insert(string("tesz"), string("test")); - cout << t; - cout << m; - cout << t.root() << endl; - cout << stringMapHash256({{"test", "test"}}) << endl; + cnote << t; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256({{"test", "test"}}); t.insert(string("tesa"), string("testy")); - cout << t; - cout << m; - cout << t.root() << endl; - cout << stringMapHash256({{"test", "test"}, {"te", "testy"}}) << endl; - cout << t.at(string("test")) << endl; - cout << t.at(string("te")) << endl; - cout << t.at(string("t")) << endl; + cnote << t; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256({{"test", "test"}, {"te", "testy"}}); + cnote << t.at(string("test")); + cnote << t.at(string("te")); + cnote << t.at(string("t")); t.remove(string("te")); - cout << m; - cout << t.root() << endl; - cout << stringMapHash256({{"test", "test"}}) << endl; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256({{"test", "test"}}); t.remove(string("test")); - cout << m; - cout << t.root() << endl; - cout << stringMapHash256(StringMap()) << endl; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256(StringMap()); } { MemoryDB m; @@ -351,37 +351,37 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.init(); // initialise as empty tree. t.insert(string("a"), string("A")); t.insert(string("b"), string("B")); - cout << t; - cout << m; - cout << t.root() << endl; - cout << stringMapHash256({{"b", "B"}, {"a", "A"}}) << endl; + cnote << t; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256({{"b", "B"}, {"a", "A"}}); bytes r(stringMapRlp256({{"b", "B"}, {"a", "A"}})); - cout << RLP(r) << endl; + cnote << RLP(r); } { MemTrie t; t.insert("dog", "puppy"); - cout << hex << t.hash256() << endl; + cnote << hex << t.hash256(); bytes r(t.rlp()); - cout << RLP(r) << endl; + cnote << RLP(r); } { MemTrie t; t.insert("bed", "d"); t.insert("be", "e"); - cout << hex << t.hash256() << endl; + cnote << hex << t.hash256(); bytes r(t.rlp()); - cout << RLP(r) << endl; + cnote << RLP(r); } { - cout << hex << stringMapHash256({{"dog", "puppy"}, {"doe", "reindeer"}}) << endl; + cnote << hex << stringMapHash256({{"dog", "puppy"}, {"doe", "reindeer"}}); MemTrie t; t.insert("dog", "puppy"); t.insert("doe", "reindeer"); - cout << hex << t.hash256() << endl; + cnote << hex << t.hash256(); bytes r(t.rlp()); - cout << RLP(r) << endl; - cout << toHex(t.rlp()) << endl; + cnote << RLP(r); + cnote << toHex(t.rlp()); } { MemoryDB m; @@ -397,12 +397,12 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.insert(a, b); s[a] = b; - cout << endl << "-------------------------------" << endl; - cout << a << " -> " << b << endl; - cout << d; - cout << m; - cout << d.root() << endl; - cout << stringMapHash256(s) << endl; + cnote << "/n-------------------------------"; + cnote << a << " -> " << b; + cnote << d; + cnote << m; + cnote << d.root(); + cnote << stringMapHash256(s); BOOST_REQUIRE(d.check(true)); BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s)); @@ -421,12 +421,12 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.remove(a); d.remove(string(a)); - /*cout << endl << "-------------------------------" << endl; - cout << "X " << a << endl; - cout << d; - cout << m; - cout << d.root() << endl; - cout << hash256(s) << endl;*/ + /*cnote << endl << "-------------------------------"; + cnote << "X " << a; + cnote << d; + cnote << m; + cnote << d.root(); + cnote << hash256(s);*/ BOOST_REQUIRE(d.check(true)); BOOST_REQUIRE(t.at(a).empty()); @@ -559,9 +559,11 @@ BOOST_AUTO_TEST_CASE(trieStess) // for (auto i: dm2.get()) // cwarn << i.first << ": " << RLP(i.second); d2.debugStructure(cerr); - g_logVerbosity = 99; + if (g_logVerbosity != -1) + g_logVerbosity = 99; d2.remove(k); - g_logVerbosity = 4; + if (g_logVerbosity != -1) + g_logVerbosity = 4; cwarn << "Good?" << d2.root(); } diff --git a/test/libethcore/dagger.cpp b/test/libethcore/dagger.cpp index 0473a0136..9841b1b4b 100644 --- a/test/libethcore/dagger.cpp +++ b/test/libethcore/dagger.cpp @@ -25,7 +25,7 @@ #include #include #include -#include "../TestHelper.h" +#include using namespace std; using namespace dev; diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 0be4d6622..3ec623685 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -53,6 +53,7 @@ mArray importUncles(mObject const& _blObj, vector& _vBiUncles, vect void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) { + string testname; for (auto& i: _v.get_obj()) { mObject& o = i.second.get_obj(); @@ -62,7 +63,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) continue; } - cerr << i.first << endl; + cnote << i.first; + testname = "(" + i.first + ") "; TBOOST_REQUIRE(o.count("genesisBlockHeader")); TBOOST_REQUIRE(o.count("pre")); @@ -81,7 +83,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) if (_fillin) biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj(), trueState.rootHash()); else - TBOOST_CHECK_MESSAGE((biGenesisBlock.stateRoot() == trueState.rootHash()), "root hash does not match"); + TBOOST_CHECK_MESSAGE((biGenesisBlock.stateRoot() == trueState.rootHash()), testname + "root hash does not match"); if (_fillin) { @@ -381,24 +383,24 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) if (importedAndBest) { //Check the fields restored from RLP to original fields - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.headerHash(WithProof) == blockFromRlp.headerHash(WithProof)), "hash in given RLP not matching the block hash!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.parentHash() == blockFromRlp.parentHash()), "parentHash in given RLP not matching the block parentHash!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.sha3Uncles() == blockFromRlp.sha3Uncles()), "sha3Uncles in given RLP not matching the block sha3Uncles!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.beneficiary() == blockFromRlp.beneficiary()),"beneficiary in given RLP not matching the block beneficiary!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.stateRoot() == blockFromRlp.stateRoot()), "stateRoot in given RLP not matching the block stateRoot!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.transactionsRoot() == blockFromRlp.transactionsRoot()), "transactionsRoot in given RLP not matching the block transactionsRoot!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.receiptsRoot() == blockFromRlp.receiptsRoot()), "receiptsRoot in given RLP not matching the block receiptsRoot!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.logBloom() == blockFromRlp.logBloom()), "logBloom in given RLP not matching the block logBloom!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.difficulty() == blockFromRlp.difficulty()), "difficulty in given RLP not matching the block difficulty!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.number() == blockFromRlp.number()), "number in given RLP not matching the block number!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasLimit() == blockFromRlp.gasLimit()),"gasLimit in given RLP not matching the block gasLimit!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasUsed() == blockFromRlp.gasUsed()), "gasUsed in given RLP not matching the block gasUsed!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.timestamp() == blockFromRlp.timestamp()), "timestamp in given RLP not matching the block timestamp!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.extraData() == blockFromRlp.extraData()), "extraData in given RLP not matching the block extraData!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.mixHash() == blockFromRlp.mixHash()), "mixHash in given RLP not matching the block mixHash!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.nonce() == blockFromRlp.nonce()), "nonce in given RLP not matching the block nonce!"); - - TBOOST_CHECK_MESSAGE((blockHeaderFromFields == blockFromRlp), "However, blockHeaderFromFields != blockFromRlp!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.headerHash(WithProof) == blockFromRlp.headerHash(WithProof)), testname + "hash in given RLP not matching the block hash!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.parentHash() == blockFromRlp.parentHash()), testname + "parentHash in given RLP not matching the block parentHash!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.sha3Uncles() == blockFromRlp.sha3Uncles()), testname + "sha3Uncles in given RLP not matching the block sha3Uncles!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.beneficiary() == blockFromRlp.beneficiary()), testname + "beneficiary in given RLP not matching the block beneficiary!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.stateRoot() == blockFromRlp.stateRoot()), testname + "stateRoot in given RLP not matching the block stateRoot!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.transactionsRoot() == blockFromRlp.transactionsRoot()), testname + "transactionsRoot in given RLP not matching the block transactionsRoot!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.receiptsRoot() == blockFromRlp.receiptsRoot()), testname + "receiptsRoot in given RLP not matching the block receiptsRoot!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.logBloom() == blockFromRlp.logBloom()), testname + "logBloom in given RLP not matching the block logBloom!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.difficulty() == blockFromRlp.difficulty()), testname + "difficulty in given RLP not matching the block difficulty!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.number() == blockFromRlp.number()), testname + "number in given RLP not matching the block number!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasLimit() == blockFromRlp.gasLimit()),"testname + gasLimit in given RLP not matching the block gasLimit!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasUsed() == blockFromRlp.gasUsed()), testname + "gasUsed in given RLP not matching the block gasUsed!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.timestamp() == blockFromRlp.timestamp()), testname + "timestamp in given RLP not matching the block timestamp!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.extraData() == blockFromRlp.extraData()), testname + "extraData in given RLP not matching the block extraData!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.mixHash() == blockFromRlp.mixHash()), testname + "mixHash in given RLP not matching the block mixHash!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.nonce() == blockFromRlp.nonce()), testname + "nonce in given RLP not matching the block nonce!"); + + TBOOST_CHECK_MESSAGE((blockHeaderFromFields == blockFromRlp), testname + "However, blockHeaderFromFields != blockFromRlp!"); //Check transaction list @@ -445,18 +447,18 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) for (size_t i = 0; i < txsFromField.size(); ++i) { - TBOOST_CHECK_MESSAGE((txsFromField[i].data() == txsFromRlp[i].data()), "transaction data in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].gas() == txsFromRlp[i].gas()), "transaction gasLimit in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice()), "transaction gasPrice in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].nonce() == txsFromRlp[i].nonce()), "transaction nonce in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].signature().r == txsFromRlp[i].signature().r), "transaction r in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].signature().s == txsFromRlp[i].signature().s), "transaction s in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].signature().v == txsFromRlp[i].signature().v), "transaction v in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress()), "transaction receiveAddress in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].value() == txsFromRlp[i].value()), "transaction receiveAddress in rlp and in field do not match"); - - TBOOST_CHECK_MESSAGE((txsFromField[i] == txsFromRlp[i]), "transactions from rlp and transaction from field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].rlp() == txsFromRlp[i].rlp()), "transactions rlp do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].data() == txsFromRlp[i].data()), testname + "transaction data in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].gas() == txsFromRlp[i].gas()), testname + "transaction gasLimit in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice()), testname + "transaction gasPrice in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].nonce() == txsFromRlp[i].nonce()), testname + "transaction nonce in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].signature().r == txsFromRlp[i].signature().r), testname + "transaction r in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].signature().s == txsFromRlp[i].signature().s), testname + "transaction s in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].signature().v == txsFromRlp[i].signature().v), testname + "transaction v in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress()), testname + "transaction receiveAddress in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].value() == txsFromRlp[i].value()), testname + "transaction receiveAddress in rlp and in field do not match"); + + TBOOST_CHECK_MESSAGE((txsFromField[i] == txsFromRlp[i]), testname + "transactions from rlp and transaction from field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].rlp() == txsFromRlp[i].rlp()), testname + "transactions rlp do not match"); } // check uncle list @@ -477,7 +479,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) } catch(...) { - TBOOST_ERROR("invalid uncle header"); + TBOOST_ERROR(testname + "invalid uncle header"); } uBlHsFromField.push_back(uncleBlockHeader); } @@ -494,13 +496,13 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) TBOOST_REQUIRE_EQUAL(uBlHsFromField.size(), uBlHsFromRlp.size()); for (size_t i = 0; i < uBlHsFromField.size(); ++i) - TBOOST_CHECK_MESSAGE((uBlHsFromField[i] == uBlHsFromRlp[i]), "block header in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((uBlHsFromField[i] == uBlHsFromRlp[i]), testname + "block header in rlp and in field do not match"); }//importedAndBest }//all blocks TBOOST_REQUIRE((o.count("lastblockhash") > 0)); TBOOST_CHECK_MESSAGE((toString(trueBc.info().hash()) == o["lastblockhash"].get_str()), - "Boost check: " + i.first + " lastblockhash does not match " + toString(trueBc.info().hash()) + " expected: " + o["lastblockhash"].get_str()); + testname + "Boost check: " + i.first + " lastblockhash does not match " + toString(trueBc.info().hash()) + " expected: " + o["lastblockhash"].get_str()); } } } diff --git a/test/libethereum/gaspricer.cpp b/test/libethereum/gaspricer.cpp index f5a6b50be..8f54b05ea 100644 --- a/test/libethereum/gaspricer.cpp +++ b/test/libethereum/gaspricer.cpp @@ -55,13 +55,13 @@ BOOST_AUTO_TEST_CASE(trivialGasPricer) { cnote << "trivialGasPricer"; std::shared_ptr gp(new TrivialGasPricer); - BOOST_CHECK_EQUAL(gp->ask(Block()), c_defaultGasPrice); - BOOST_CHECK_EQUAL(gp->bid(), c_defaultGasPrice); + BOOST_CHECK_EQUAL(gp->ask(Block()), DefaultGasPrice); + BOOST_CHECK_EQUAL(gp->bid(), DefaultGasPrice); bytes bl = CanonBlockChain::createGenesisBlock(); gp->update(FullBlockChain(bl, AccountMap(), TransientDirectory().path(), WithExisting::Kill)); - BOOST_CHECK_EQUAL(gp->ask(Block()), c_defaultGasPrice); - BOOST_CHECK_EQUAL(gp->bid(), c_defaultGasPrice); + BOOST_CHECK_EQUAL(gp->ask(Block()), DefaultGasPrice); + BOOST_CHECK_EQUAL(gp->bid(), DefaultGasPrice); } BOOST_AUTO_TEST_CASE(basicGasPricerNoUpdate) diff --git a/test/libethereum/genesis.cpp b/test/libethereum/genesis.cpp index 8d4b2878f..aa0825c42 100644 --- a/test/libethereum/genesis.cpp +++ b/test/libethereum/genesis.cpp @@ -21,11 +21,13 @@ */ #include +#include + #include #include "../JsonSpiritHeaders.h" #include #include -#include "../TestHelper.h" +#include using namespace std; using namespace dev; diff --git a/test/libethereum/state.cpp b/test/libethereum/state.cpp index 4c9d998b2..30c0ccff0 100644 --- a/test/libethereum/state.cpp +++ b/test/libethereum/state.cpp @@ -41,6 +41,7 @@ namespace dev { namespace test { void doStateTests(json_spirit::mValue& v, bool _fillin) { + string testname; for (auto& i: v.get_obj()) { mObject& o = i.second.get_obj(); @@ -50,10 +51,12 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) continue; } - std::cout << " " << i.first << std::endl; - TBOOST_REQUIRE((o.count("env") > 0)); - TBOOST_REQUIRE((o.count("pre") > 0)); - TBOOST_REQUIRE((o.count("transaction") > 0)); + cnote << i.first; + testname = "(" + i.first + ") "; + + TBOOST_REQUIRE_MESSAGE((o.count("env") > 0), testname + "env not set!"); + TBOOST_REQUIRE_MESSAGE((o.count("pre") > 0), testname + "pre not set!"); + TBOOST_REQUIRE_MESSAGE((o.count("transaction") > 0), testname + "transaction not set!"); ImportTest importer(o, _fillin); const State importedStatePost = importer.m_statePost; @@ -66,9 +69,10 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) if (_fillin) { #if ETH_FATDB - importer.exportTest(output); + if (importer.exportTest(output)) + cerr << testname << endl; #else - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off")); + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(testname + "You can not fill tests when FATDB is switched off")); #endif } else @@ -86,7 +90,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) #if ETH_FATDB ImportTest::compareStates(importer.m_statePost, importedStatePost); #endif - TBOOST_CHECK_MESSAGE((importer.m_statePost.rootHash() == h256(o["postStateRoot"].get_str())), "wrong post state root"); + TBOOST_CHECK_MESSAGE((importer.m_statePost.rootHash() == h256(o["postStateRoot"].get_str())), testname + "wrong post state root"); } } } @@ -237,11 +241,11 @@ BOOST_AUTO_TEST_CASE(stRandom) } catch (Exception const& _e) { - BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); + BOOST_ERROR(path.filename().string() + "Failed test with Exception: " << diagnostic_information(_e)); } catch (std::exception const& _e) { - BOOST_ERROR("Failed test with Exception: " << _e.what()); + BOOST_ERROR(path.filename().string() + "Failed test with Exception: " << _e.what()); } } } diff --git a/test/libethereum/stateOriginal.cpp b/test/libethereum/stateOriginal.cpp index 21b332762..8ed3b228d 100644 --- a/test/libethereum/stateOriginal.cpp +++ b/test/libethereum/stateOriginal.cpp @@ -20,6 +20,7 @@ * State test functions. */ +#include #include #include #include @@ -27,7 +28,6 @@ #include #include #include -#include using namespace std; using namespace dev; diff --git a/test/libethereum/transactionTests.cpp b/test/libethereum/transactionTests.cpp index f6bde061a..d2f7523b0 100644 --- a/test/libethereum/transactionTests.cpp +++ b/test/libethereum/transactionTests.cpp @@ -32,6 +32,7 @@ namespace dev { namespace test { void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { + string testname; for (auto& i: _v.get_obj()) { mObject& o = i.second.get_obj(); @@ -41,7 +42,8 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) continue; } - cerr << i.first << endl; + testname = "(" + i.first + ") "; + cnote << testname; if (_fillin) { TBOOST_REQUIRE((o.count("transaction") > 0)); @@ -55,7 +57,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything); if (!txFromFields.signature().isValid()) - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") ); + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(testname + "transaction from RLP signature is invalid") ); o["sender"] = toString(txFromFields.sender()); o["transaction"] = ImportTest::makeAllFieldsHex(tObj); @@ -69,9 +71,9 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { bool expectInValid = (o["expect"].get_str() == "invalid"); if (Options::get().checkState) - {TBOOST_CHECK_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");} + {TBOOST_CHECK_MESSAGE(expectInValid, testname + "Check state: Transaction '" << i.first << "' is expected to be valid!");} else - {TBOOST_WARN_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");} + {TBOOST_WARN_MESSAGE(expectInValid, testname + "Check state: Transaction '" << i.first << "' is expected to be valid!");} o.erase(o.find("expect")); } @@ -82,9 +84,9 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { bool expectValid = (o["expect"].get_str() == "valid"); if (Options::get().checkState) - {TBOOST_CHECK_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");} + {TBOOST_CHECK_MESSAGE(expectValid, testname + "Check state: Transaction '" << i.first << "' is expected to be invalid!");} else - {TBOOST_WARN_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");} + {TBOOST_WARN_MESSAGE(expectValid, testname + "Check state: Transaction '" << i.first << "' is expected to be invalid!");} o.erase(o.find("expect")); } @@ -99,39 +101,39 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) RLP rlp(stream); txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything); if (!txFromRlp.signature().isValid()) - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") ); + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(testname + "transaction from RLP signature is invalid") ); } catch(Exception const& _e) { cnote << i.first; cnote << "Transaction Exception: " << diagnostic_information(_e); - TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), "A transaction object should not be defined because the RLP is invalid!"); + TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), testname + "A transaction object should not be defined because the RLP is invalid!"); continue; } catch(...) { - TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), "A transaction object should not be defined because the RLP is invalid!"); + TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), testname + "A transaction object should not be defined because the RLP is invalid!"); continue; } - TBOOST_REQUIRE((o.count("transaction") > 0)); + TBOOST_REQUIRE_MESSAGE((o.count("transaction") > 0), testname + "Expected a valid transaction!"); mObject tObj = o["transaction"].get_obj(); Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckTransaction::Everything); //Check the fields restored from RLP to original fields - TBOOST_CHECK_MESSAGE((txFromFields.data() == txFromRlp.data()), "Data in given RLP not matching the Transaction data!"); - TBOOST_CHECK_MESSAGE((txFromFields.value() == txFromRlp.value()), "Value in given RLP not matching the Transaction value!"); - TBOOST_CHECK_MESSAGE((txFromFields.gasPrice() == txFromRlp.gasPrice()), "GasPrice in given RLP not matching the Transaction gasPrice!"); - TBOOST_CHECK_MESSAGE((txFromFields.gas() == txFromRlp.gas()),"Gas in given RLP not matching the Transaction gas!"); - TBOOST_CHECK_MESSAGE((txFromFields.nonce() == txFromRlp.nonce()),"Nonce in given RLP not matching the Transaction nonce!"); - TBOOST_CHECK_MESSAGE((txFromFields.receiveAddress() == txFromRlp.receiveAddress()), "Receive address in given RLP not matching the Transaction 'to' address!"); - TBOOST_CHECK_MESSAGE((txFromFields.sender() == txFromRlp.sender()), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!"); - TBOOST_CHECK_MESSAGE((txFromFields == txFromRlp), "However, txFromFields != txFromRlp!"); + TBOOST_CHECK_MESSAGE((txFromFields.data() == txFromRlp.data()), testname + "Data in given RLP not matching the Transaction data!"); + TBOOST_CHECK_MESSAGE((txFromFields.value() == txFromRlp.value()), testname + "Value in given RLP not matching the Transaction value!"); + TBOOST_CHECK_MESSAGE((txFromFields.gasPrice() == txFromRlp.gasPrice()), testname + "GasPrice in given RLP not matching the Transaction gasPrice!"); + TBOOST_CHECK_MESSAGE((txFromFields.gas() == txFromRlp.gas()), testname + "Gas in given RLP not matching the Transaction gas!"); + TBOOST_CHECK_MESSAGE((txFromFields.nonce() == txFromRlp.nonce()), testname + "Nonce in given RLP not matching the Transaction nonce!"); + TBOOST_CHECK_MESSAGE((txFromFields.receiveAddress() == txFromRlp.receiveAddress()), testname + "Receive address in given RLP not matching the Transaction 'to' address!"); + TBOOST_CHECK_MESSAGE((txFromFields.sender() == txFromRlp.sender()), testname + "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!"); + TBOOST_CHECK_MESSAGE((txFromFields == txFromRlp), testname + "However, txFromFields != txFromRlp!"); TBOOST_REQUIRE ((o.count("sender") > 0)); Address addressReaded = Address(o["sender"].get_str()); - TBOOST_CHECK_MESSAGE((txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded), "Signature address of sender does not match given sender address!"); + TBOOST_CHECK_MESSAGE((txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded), testname + "Signature address of sender does not match given sender address!"); } }//for }//doTransactionTests diff --git a/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json b/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json index ece519112..4dfa41f6a 100644 --- a/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json +++ b/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json @@ -2281,6 +2281,130 @@ } }, + "DynamicJump_value1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "100000000000000000000000", + "nonce" : "0", + "code" : "(asm 1 2 3 CALLVALUE JUMP + JUMPDEST POP POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "8", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + + "DynamicJump_value2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "100000000000000000000000", + "nonce" : "0", + "code" : "(asm 1 2 3 CALLVALUE JUMP + JUMPDEST POP POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "18", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + + "DynamicJump_value3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "100000000000000000000000", + "nonce" : "0", + "code" : "(asm 1 2 3 CALLVALUE JUMP + JUMPDEST POP POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "27", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + + "DynamicJump_valueUnderflow": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "100000000000000000000000", + "nonce" : "0", + "code" : "(asm 1 2 3 CALLVALUE JUMP + JUMPDEST POP POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP POP POP 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "27", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "BlockNumberDynamicJumpiAfterStop": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 44e0ebe84..ec28f0005 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -296,6 +296,7 @@ namespace dev { namespace test { void doVMTests(json_spirit::mValue& v, bool _fillin) { + string testname; for (auto& i: v.get_obj()) { mObject& o = i.second.get_obj(); @@ -305,10 +306,12 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) continue; } - std::cout << " " << i.first << "\n"; - TBOOST_REQUIRE((o.count("env") > 0)); - TBOOST_REQUIRE((o.count("pre") > 0)); - TBOOST_REQUIRE((o.count("exec") > 0)); + cnote << i.first; + testname = "(" + i.first + ") "; + + TBOOST_REQUIRE_MESSAGE((o.count("env") > 0), testname + "env not set!"); + TBOOST_REQUIRE_MESSAGE((o.count("pre") > 0), testname + "pre not set!"); + TBOOST_REQUIRE_MESSAGE((o.count("exec") > 0), testname + "exec not set!"); FakeExtVM fev(eth::EnvInfo{}); fev.importEnv(o["env"].get_obj()); @@ -338,7 +341,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) } catch (VMException const&) { - std::cout << " Safe VM Exception\n"; + cnote << " Safe VM Exception\n"; vmExceptionOccured = true; } catch (Exception const& _e) @@ -535,7 +538,7 @@ BOOST_AUTO_TEST_CASE(vmRandom) { try { - std::cout << "TEST " << path.filename() << "\n"; + cnote << "TEST " << path.filename(); json_spirit::mValue v; 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?"); diff --git a/test/libevm/vm.h b/test/libevm/vm.h index c41ebf5dc..c51afbd02 100644 --- a/test/libevm/vm.h +++ b/test/libevm/vm.h @@ -26,6 +26,7 @@ along with cpp-ethereum. If not, see . #include #include +#include #include #include @@ -38,7 +39,6 @@ along with cpp-ethereum. If not, see . #include #include #include -#include namespace dev { namespace test { diff --git a/test/libp2p/capability.cpp b/test/libp2p/capability.cpp index e60f7f131..fffc43c40 100644 --- a/test/libp2p/capability.cpp +++ b/test/libp2p/capability.cpp @@ -102,7 +102,9 @@ BOOST_AUTO_TEST_CASE(capability) if (test::Options::get().nonetwork) return; - VerbosityHolder verbosityHolder(10); + if (g_logVerbosity != -1) + VerbosityHolder verbosityHolder(10); + cnote << "Testing Capability..."; const char* const localhost = "127.0.0.1"; diff --git a/test/libp2p/peer.cpp b/test/libp2p/peer.cpp index 43308b450..570c443ec 100644 --- a/test/libp2p/peer.cpp +++ b/test/libp2p/peer.cpp @@ -43,7 +43,9 @@ BOOST_AUTO_TEST_CASE(host) if (test::Options::get().nonetwork) return; - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + NetworkPreferences host1prefs("127.0.0.1", 30321, false); NetworkPreferences host2prefs("127.0.0.1", 30322, false); Host host1("Test", host1prefs); @@ -88,7 +90,8 @@ BOOST_AUTO_TEST_CASE(saveNodes) if (test::Options::get().nonetwork) return; - VerbosityHolder reduceVerbosity(2); + if (g_logVerbosity != -1) + VerbosityHolder reduceVerbosity(2); std::list hosts; unsigned const c_step = 10; @@ -152,7 +155,8 @@ BOOST_AUTO_TEST_CASE(requirePeer) if (test::Options::get().nonetwork) return; - VerbosityHolder temporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder reduceVerbosity(10); unsigned const step = 10; const char* const localhost = "127.0.0.1"; diff --git a/test/libsolidity/solidityExecutionFramework.h b/test/libsolidity/solidityExecutionFramework.h index 98241b2ff..05f93bb60 100644 --- a/test/libsolidity/solidityExecutionFramework.h +++ b/test/libsolidity/solidityExecutionFramework.h @@ -44,7 +44,9 @@ class ExecutionFramework public: ExecutionFramework() { - g_logVerbosity = 0; + if (g_logVerbosity != -1) + g_logVerbosity = 0; + //m_state.resetCurrent(); } bytes const& compileAndRunWithoutCheck( diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index d7d4bd849..6516f81b1 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -106,7 +106,9 @@ BOOST_AUTO_TEST_SUITE(bloomFilter) BOOST_AUTO_TEST_CASE(falsePositiveRate) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Bloom Filter False Positive Rate..."; TopicBloomFilterTest f; @@ -124,7 +126,9 @@ BOOST_AUTO_TEST_CASE(falsePositiveRate) BOOST_AUTO_TEST_CASE(bloomFilterRandom) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Bloom Filter matching..."; TopicBloomFilterShort f; @@ -150,7 +154,9 @@ BOOST_AUTO_TEST_CASE(bloomFilterRandom) BOOST_AUTO_TEST_CASE(bloomFilterRaw) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Raw Bloom matching..."; TopicBloomFilterShort f; diff --git a/test/libwhisper/whisperDB.cpp b/test/libwhisper/whisperDB.cpp index 3d7b09915..bc56c4b4c 100644 --- a/test/libwhisper/whisperDB.cpp +++ b/test/libwhisper/whisperDB.cpp @@ -41,7 +41,9 @@ BOOST_FIXTURE_TEST_SUITE(whisperDB, P2PFixture) BOOST_AUTO_TEST_CASE(basic) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Whisper DB..."; string s; @@ -86,7 +88,9 @@ BOOST_AUTO_TEST_CASE(basic) BOOST_AUTO_TEST_CASE(persistence) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing persistence of Whisper DB..."; string s; @@ -135,7 +139,9 @@ BOOST_AUTO_TEST_CASE(messages) return; cnote << "Testing load/save Whisper messages..."; - VerbosityHolder setTemporaryLevel(2); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(2); + unsigned const TestSize = 3; map m1; map preexisting; @@ -193,7 +199,9 @@ BOOST_AUTO_TEST_CASE(corruptedData) return; cnote << "Testing corrupted data..."; - VerbosityHolder setTemporaryLevel(2); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(2); + map m; h256 x = h256::random(); @@ -222,7 +230,9 @@ BOOST_AUTO_TEST_CASE(filters) return; cnote << "Testing filters saving..."; - VerbosityHolder setTemporaryLevel(2); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(2); + h256 persistID(0xC0FFEE); { diff --git a/test/libwhisper/whisperMessage.cpp b/test/libwhisper/whisperMessage.cpp index f0c0aedc9..662653540 100644 --- a/test/libwhisper/whisperMessage.cpp +++ b/test/libwhisper/whisperMessage.cpp @@ -82,7 +82,9 @@ BOOST_AUTO_TEST_SUITE(whisperMessage) BOOST_AUTO_TEST_CASE(seal) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Envelope encryption..."; for (unsigned int i = 1; i < 10; ++i) @@ -91,7 +93,8 @@ BOOST_AUTO_TEST_CASE(seal) BOOST_AUTO_TEST_CASE(work) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); cnote << "Testing proof of work..."; Secret zero; diff --git a/test/libwhisper/whisperTopic.cpp b/test/libwhisper/whisperTopic.cpp index 39d953e31..0ea7b2dd5 100644 --- a/test/libwhisper/whisperTopic.cpp +++ b/test/libwhisper/whisperTopic.cpp @@ -47,7 +47,8 @@ BOOST_AUTO_TEST_CASE(topic) return; cnote << "Testing Whisper..."; - VerbosityHolder setTemporaryLevel(0); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(0); uint16_t port1 = 30311; Host host1("Test", NetworkPreferences("127.0.0.1", port1, false)); @@ -161,6 +162,7 @@ BOOST_AUTO_TEST_CASE(forwarding) } }); + // Host must be configured not to share peers. uint16_t port2 = 30313; Host host2("Forwarder", NetworkPreferences("127.0.0.1", port2, false)); @@ -392,7 +394,9 @@ BOOST_AUTO_TEST_CASE(selfAddressed) if (test::Options::get().nonetwork) return; - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing self-addressed messaging with bloom filter matching..."; char const* text = "deterministic pseudorandom test";