Browse Source

Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into new_account_ui

cl-refactor
debris 10 years ago
parent
commit
0dc12f8a6d
  1. 27
      alethzero/CMakeLists.txt
  2. 233
      alethzero/Main.ui
  3. 1
      alethzero/MainFace.cpp
  4. 3
      alethzero/MainFace.h
  5. 175
      alethzero/MainWin.cpp
  6. 13
      alethzero/MainWin.h
  7. 2
      alethzero/OurWebThreeStubServer.cpp
  8. 2
      alethzero/Transact.h
  9. 0
      alethzero/plugins/blockchain/AllAccounts.cpp
  10. 0
      alethzero/plugins/blockchain/AllAccounts.h
  11. 0
      alethzero/plugins/blockchain/AllAccounts.ui
  12. 0
      alethzero/plugins/brainwallet/BrainWallet.cpp
  13. 0
      alethzero/plugins/brainwallet/BrainWallet.h
  14. 0
      alethzero/plugins/brainwallet/BrainWallet.ui
  15. 0
      alethzero/plugins/log/LogPanel.cpp
  16. 0
      alethzero/plugins/log/LogPanel.h
  17. 0
      alethzero/plugins/log/LogPanel.ui
  18. 108
      alethzero/plugins/namers/NameRegNamer.cpp
  19. 59
      alethzero/plugins/namers/NameRegNamer.h
  20. 0
      alethzero/plugins/namers/NewAccount.cpp
  21. 0
      alethzero/plugins/namers/NewAccount.h
  22. 0
      alethzero/plugins/namers/NewAccount.ui
  23. 0
      alethzero/plugins/namers/OtherAccounts.cpp
  24. 0
      alethzero/plugins/namers/OtherAccounts.h
  25. 0
      alethzero/plugins/namers/OtherAccounts.ui
  26. 0
      alethzero/plugins/namers/OurAccounts.cpp
  27. 0
      alethzero/plugins/namers/OurAccounts.h
  28. 178
      alethzero/plugins/whisper/Whisper.cpp
  29. 60
      alethzero/plugins/whisper/Whisper.h
  30. 176
      alethzero/plugins/whisper/Whisper.ui
  31. 78
      alethzero/plugins/whisper/WhisperPeers.cpp
  32. 55
      alethzero/plugins/whisper/WhisperPeers.h
  33. 32
      alethzero/plugins/whisper/WhisperPeers.ui
  34. 8
      eth/main.cpp
  35. 5
      evmjit/CMakeLists.txt
  36. 4
      evmjit/include/evmjit/JIT-c.h
  37. 4
      evmjit/include/evmjit/JIT.h
  38. 6
      evmjit/libevmjit-cpp/JitVM.cpp
  39. 12
      evmjit/libevmjit/Array.cpp
  40. 8
      evmjit/libevmjit/Array.h
  41. 360
      evmjit/libevmjit/BasicBlock.cpp
  42. 127
      evmjit/libevmjit/BasicBlock.h
  43. 277
      evmjit/libevmjit/Compiler.cpp
  44. 35
      evmjit/libevmjit/Compiler.h
  45. 1
      evmjit/libevmjit/Optimizer.cpp
  46. 19
      evmjit/libevmjit/RuntimeManager.cpp
  47. 2
      evmjit/libevmjit/RuntimeManager.h
  48. 44
      evmjit/libevmjit/Stack.cpp
  49. 13
      evmjit/libevmjit/Stack.h
  50. 25
      libethcore/ABI.h
  51. 2
      libethereum/ClientBase.h
  52. 6
      libethereum/GasPricer.h
  53. 8
      libethereum/Interface.h
  54. 6
      libethereumx/Ethereum.h
  55. 4
      libevm/SmartVM.cpp
  56. 10
      libp2p/Host.cpp
  57. 12
      mix/ClientModel.cpp
  58. 2
      mix/MixClient.cpp
  59. 47
      test/TestHelper.cpp
  60. 13
      test/TestHelper.h
  61. 66
      test/boostTest.cpp
  62. 5
      test/fuzzTesting/fuzzHelper.cpp
  63. 25
      test/libdevcore/rlp.cpp
  64. 14
      test/libdevcrypto/AES.cpp
  65. 2
      test/libdevcrypto/hexPrefix.cpp
  66. 100
      test/libdevcrypto/trie.cpp
  67. 2
      test/libethcore/dagger.cpp
  68. 72
      test/libethereum/blockchain.cpp
  69. 8
      test/libethereum/gaspricer.cpp
  70. 4
      test/libethereum/genesis.cpp
  71. 22
      test/libethereum/state.cpp
  72. 2
      test/libethereum/stateOriginal.cpp
  73. 40
      test/libethereum/transactionTests.cpp
  74. 124
      test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json
  75. 15
      test/libevm/vm.cpp
  76. 2
      test/libevm/vm.h
  77. 4
      test/libp2p/capability.cpp
  78. 10
      test/libp2p/peer.cpp
  79. 4
      test/libsolidity/solidityExecutionFramework.h
  80. 12
      test/libwhisper/bloomFilter.cpp
  81. 20
      test/libwhisper/whisperDB.cpp
  82. 7
      test/libwhisper/whisperMessage.cpp
  83. 8
      test/libwhisper/whisperTopic.cpp

27
alethzero/CMakeLists.txt

@ -14,6 +14,15 @@ endif ()
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(. SRC_LIST) 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 ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..) include_directories(BEFORE ..)
@ -39,10 +48,6 @@ qt5_wrap_ui(ui_GasPricing.h GasPricing.ui)
# Extensions # Extensions
qt5_wrap_ui(ui_AllAccounts.h AllAccounts.ui) 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") file(GLOB HEADERS "*.h")
@ -55,19 +60,7 @@ endif ()
# eth_add_executable is defined in cmake/EthExecutableHelper.cmake # eth_add_executable is defined in cmake/EthExecutableHelper.cmake
eth_add_executable(${EXECUTABLE} eth_add_executable(${EXECUTABLE}
ICON alethzero ICON alethzero
UI_RESOURCES alethzero.icns UI_RESOURCES ${PLUGIN_UI} alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui
Main.ui
Connect.ui
Debugger.ui
Transact.ui
ExportState.ui
GetPassword.ui
GasPricing.ui
AllAccounts.ui
LogPanel.ui
BrainWallet.ui
OtherAccounts.ui
NewAccount.ui
WIN_RESOURCES alethzero.rc WIN_RESOURCES alethzero.rc
) )

233
alethzero/Main.ui

@ -209,12 +209,6 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="preview"/> <addaction name="preview"/>
</widget> </widget>
<widget class="QMenu" name="menuWhispe">
<property name="title">
<string>&amp;Whisper</string>
</property>
<addaction name="newIdentity"/>
</widget>
<widget class="QMenu" name="menuDebug"> <widget class="QMenu" name="menuDebug">
<property name="title"> <property name="title">
<string>&amp;Debug</string> <string>&amp;Debug</string>
@ -235,7 +229,6 @@
<addaction name="menuView"/> <addaction name="menuView"/>
<addaction name="menuNetwork"/> <addaction name="menuNetwork"/>
<addaction name="menuTools"/> <addaction name="menuTools"/>
<addaction name="menuWhispe"/>
<addaction name="menuDebug"/> <addaction name="menuDebug"/>
<addaction name="menuConfig"/> <addaction name="menuConfig"/>
<addaction name="menuHelp"/> <addaction name="menuHelp"/>
@ -978,224 +971,6 @@ font-size: 14pt</string>
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QDockWidget" name="dockWidget_14">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Whisper</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_14">
<layout class="QGridLayout" name="gridLayout_4">
<item row="4" column="0" rowspan="2">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Data</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QLabel" name="label5_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Work to Prove</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhData">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhTopic">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
<widget class="QComboBox" name="shhFrom">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Topic</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label5_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="4">
<widget class="QComboBox" name="shhTo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="shhTtl">
<property name="suffix">
<string> seconds</string>
</property>
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>259200</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label5_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TTL</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label5_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>From</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QSpinBox" name="shhWork">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QPushButton" name="post">
<property name="text">
<string>Post</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_15">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Active Whispers</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_15">
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="whispers">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="quit"> <action name="quit">
<property name="text"> <property name="text">
<string>&amp;Quit</string> <string>&amp;Quit</string>
@ -1635,13 +1410,6 @@ font-size: 14pt</string>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>shhTo</tabstop>
<tabstop>shhFrom</tabstop>
<tabstop>shhTtl</tabstop>
<tabstop>shhTopic</tabstop>
<tabstop>shhWork</tabstop>
<tabstop>shhData</tabstop>
<tabstop>post</tabstop>
<tabstop>tabWidget</tabstop> <tabstop>tabWidget</tabstop>
<tabstop>urlEdit</tabstop> <tabstop>urlEdit</tabstop>
<tabstop>listenIP</tabstop> <tabstop>listenIP</tabstop>
@ -1651,7 +1419,6 @@ font-size: 14pt</string>
<tabstop>blockChainFilter</tabstop> <tabstop>blockChainFilter</tabstop>
<tabstop>nameReg</tabstop> <tabstop>nameReg</tabstop>
<tabstop>nodes</tabstop> <tabstop>nodes</tabstop>
<tabstop>whispers</tabstop>
<tabstop>jsInput</tabstop> <tabstop>jsInput</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>

1
alethzero/MainFace.cpp

@ -58,6 +58,7 @@ QDockWidget* Plugin::dock(Qt::DockWidgetArea _area, QString _title)
if (!m_dock) if (!m_dock)
{ {
m_dock = new QDockWidget(_title, m_main); m_dock = new QDockWidget(_title, m_main);
m_dock->setObjectName(_title);
m_main->addDockWidget(_area, m_dock); m_main->addDockWidget(_area, m_dock);
m_dock->setFeatures(QDockWidget::AllDockWidgetFeatures | QDockWidget::DockWidgetVerticalTitleBar); m_dock->setFeatures(QDockWidget::AllDockWidgetFeatures | QDockWidget::DockWidgetVerticalTitleBar);
} }

3
alethzero/MainFace.h

@ -49,6 +49,7 @@ namespace az
class Plugin; class Plugin;
class MainFace; class MainFace;
class Main; class Main;
class OurWebThreeStubServer;
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>; using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
@ -89,10 +90,12 @@ public:
// TODO: provide a set of available web3 modules. // TODO: provide a set of available web3 modules.
virtual dev::WebThreeDirect* web3() const = 0; virtual dev::WebThreeDirect* web3() const = 0;
virtual dev::eth::Client* ethereum() const = 0; virtual dev::eth::Client* ethereum() const = 0;
virtual OurWebThreeStubServer* web3Server() const = 0;
virtual std::shared_ptr<dev::shh::WhisperHost> whisper() const = 0; virtual std::shared_ptr<dev::shh::WhisperHost> whisper() const = 0;
virtual unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f) = 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 unsigned installWatch(dev::h256 const& _tf, WatchHandler const& _f) = 0;
virtual void uninstallWatch(unsigned _id) = 0;
// Account naming API // Account naming API
virtual void install(AccountNamer* _adopt) = 0; virtual void install(AccountNamer* _adopt) = 0;

175
alethzero/MainWin.cpp

@ -94,8 +94,8 @@ QString dev::az::contentsOfQResource(string const& res)
} }
//Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f");
Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b"); //Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b");
//Address c_nameReg = Address("ddd1cea741d548f90d86fb87a3ae6492e18c03a1"); Address c_nameReg = Address("96d76ae3397b52d9f61215270df65d72358709e3");
Main::Main(QWidget* _parent): Main::Main(QWidget* _parent):
MainFace(_parent), MainFace(_parent),
@ -197,8 +197,6 @@ Main::Main(QWidget* _parent):
auto w3ss = new OurWebThreeStubServer(*m_httpConnector, this); auto w3ss = new OurWebThreeStubServer(*m_httpConnector, this);
m_server.reset(w3ss); m_server.reset(w3ss);
auto sessionKey = w3ss->newSession(SessionPermissions{{Privilege::Admin}}); auto sessionKey = w3ss->newSession(SessionPermissions{{Privilege::Admin}});
connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString)));
m_server->setIdentities(keysAsVector(owned()));
m_server->StartListening(); m_server->StartListening();
WebPage* webPage = new WebPage(this); WebPage* webPage = new WebPage(this);
@ -387,29 +385,6 @@ void Main::on_sentinel_triggered()
ethereum()->setSentinel(sentinel.toStdString()); 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 NetworkPreferences Main::netPrefs() const
{ {
auto listenIP = ui->listenIP->text().toStdString(); auto listenIP = ui->listenIP->text().toStdString();
@ -486,8 +461,8 @@ void Main::installWatches()
cdebug << "newBlock watch ID: " << newBlockId; cdebug << "newBlock watch ID: " << newBlockId;
cdebug << "newPending watch ID: " << newPendingId; cdebug << "newPending watch ID: " << newPendingId;
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); // installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); });
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); // installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); });
} }
Address Main::getNameReg() const Address Main::getNameReg() const
@ -498,7 +473,8 @@ Address Main::getNameReg() const
Address Main::getCurrencies() const Address Main::getCurrencies() const
{ {
return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)).output); // return abiOut<Address>(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)).output);
return Address();
} }
bool Main::doConfirm() bool Main::doConfirm()
@ -665,17 +641,6 @@ void Main::addConsoleMessage(QString const& _js, QString const& _s)
ui->jsConsole->setHtml(r); 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 std::string Main::pretty(dev::Address const& _a) const
{ {
auto g_newNameReg = getNameReg(); auto g_newNameReg = getNameReg();
@ -806,17 +771,6 @@ void Main::writeSettings()
{ {
QSettings s("ethereum", "alethzero"); QSettings s("ethereum", "alethzero");
s.remove("address"); 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<Plugin> p) forEach([&](std::shared_ptr<Plugin> p)
{ {
@ -904,27 +858,12 @@ void Main::readSettings(bool _skipGeometry)
restoreGeometry(s.value("geometry").toByteArray()); restoreGeometry(s.value("geometry").toByteArray());
restoreState(s.value("windowState").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<Plugin> p) forEach([&](std::shared_ptr<Plugin> p)
{ {
p->readSettings(s); p->readSettings(s);
}); });
static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->setAsk(u256(s.value("askPrice", QString::fromStdString(toString(c_defaultGasPrice))).toString().toStdString())); static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->setAsk(u256(s.value("askPrice", QString::fromStdString(toString(DefaultGasPrice))).toString().toStdString()));
static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->setBid(u256(s.value("bidPrice", QString::fromStdString(toString(c_defaultGasPrice))).toString().toStdString())); static_cast<TrivialGasPricer*>(ethereum()->gasPricer().get())->setBid(u256(s.value("bidPrice", QString::fromStdString(toString(DefaultGasPrice))).toString().toStdString()));
ui->upnp->setChecked(s.value("upnp", true).toBool()); ui->upnp->setChecked(s.value("upnp", true).toBool());
ui->forcePublicIP->setText(s.value("forceAddress", "").toString()); ui->forcePublicIP->setText(s.value("forceAddress", "").toString());
@ -1522,7 +1461,6 @@ void Main::timerEvent(QTimerEvent*)
{ {
interval = 0; interval = 0;
refreshNetwork(); refreshNetwork();
refreshWhispers();
refreshCache(); refreshCache();
refreshBlockCount(); refreshBlockCount();
poll(); poll();
@ -1952,60 +1890,6 @@ void Main::on_ourAccounts_doubleClicked()
m_logHistory.clear(); 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() void Main::on_clearPending_triggered()
{ {
writeSettings(); writeSettings();
@ -2215,19 +2099,6 @@ std::string Main::prettyU256(dev::u256 const& _n) const
return s.str(); 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) int Main::authenticate(QString _title, QString _text)
{ {
QMessageBox userInput(this); QMessageBox userInput(this);
@ -2240,36 +2111,6 @@ int Main::authenticate(QString _title, QString _text)
return userInput.exec(); 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<Public, Secret> 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) void Main::dappLoaded(Dapp& _dapp)
{ {
QUrl url = m_dappHost->hostDapp(std::move(_dapp)); QUrl url = m_dappHost->hostDapp(std::move(_dapp));

13
alethzero/MainWin.h

@ -84,6 +84,7 @@ public:
~Main(); ~Main();
WebThreeDirect* web3() const override { return m_webThree.get(); } 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(); } eth::Client* ethereum() const override { return m_webThree->ethereum(); }
std::shared_ptr<shh::WhisperHost> whisper() const override { return m_webThree->whisper(); } std::shared_ptr<shh::WhisperHost> whisper() const override { return m_webThree->whisper(); }
@ -96,8 +97,6 @@ public:
std::pair<Address, bytes> fromString(std::string const& _a) const override; std::pair<Address, bytes> fromString(std::string const& _a) const override;
std::string renderDiff(eth::StateDiff const& _d) const override; std::string renderDiff(eth::StateDiff const& _d) const override;
QList<KeyPair> owned() const { return m_myIdentities; }
u256 gasPrice() const override; u256 gasPrice() const override;
eth::KeyManager& keyManager() override { return m_keyManager; } eth::KeyManager& keyManager() override { return m_keyManager; }
@ -198,17 +197,11 @@ private slots:
void on_debugDumpStatePre_triggered() { debugDumpState(0); } void on_debugDumpStatePre_triggered() { debugDumpState(0); }
void on_dumpBlockState_triggered(); void on_dumpBlockState_triggered();
// Whisper
void on_newIdentity_triggered();
void on_post_clicked();
// Config // Config
void on_gasPrices_triggered(); void on_gasPrices_triggered();
void on_sentinel_triggered(); void on_sentinel_triggered();
void refreshWhisper();
void refreshBlockChain(); void refreshBlockChain();
void addNewId(QString _ids);
// Dapps // Dapps
void dappLoaded(Dapp& _dapp); //qt does not support rvalue refs for signals 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(eth::LogFilter const& _tf, WatchHandler const& _f) override;
unsigned installWatch(h256 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(); void keysChanged();
@ -258,7 +251,6 @@ private:
void refreshNetwork(); void refreshNetwork();
void refreshMining(); void refreshMining();
void refreshWhispers();
void refreshCache(); void refreshCache();
void refreshAll(); void refreshAll();
@ -280,7 +272,6 @@ private:
QByteArray m_networkConfig; QByteArray m_networkConfig;
QStringList m_servers; QStringList m_servers;
QList<KeyPair> m_myIdentities;
eth::KeyManager m_keyManager; eth::KeyManager m_keyManager;
QString m_privateChain; QString m_privateChain;
dev::Address m_nameReg; dev::Address m_nameReg;

2
alethzero/OurWebThreeStubServer.cpp

@ -34,7 +34,7 @@ OurWebThreeStubServer::OurWebThreeStubServer(
jsonrpc::AbstractServerConnector& _conn, jsonrpc::AbstractServerConnector& _conn,
Main* _main Main* _main
): ):
WebThreeStubServer(_conn, *_main->web3(), make_shared<OurAccountHolder>(_main), _main->owned().toVector().toStdVector(), _main->keyManager(), *static_cast<TrivialGasPricer*>(_main->ethereum()->gasPricer().get())), WebThreeStubServer(_conn, *_main->web3(), make_shared<OurAccountHolder>(_main), vector<KeyPair>{}, _main->keyManager(), *static_cast<TrivialGasPricer*>(_main->ethereum()->gasPricer().get())),
m_main(_main) m_main(_main)
{ {
} }

2
alethzero/Transact.h

@ -105,6 +105,8 @@ private:
MainFace* m_main = nullptr; MainFace* m_main = nullptr;
NatSpecFace* m_natSpecDB = nullptr; NatSpecFace* m_natSpecDB = nullptr;
bool m_allGood = false; bool m_allGood = false;
bool m_determiningGas = false;
}; };
} }

0
alethzero/AllAccounts.cpp → alethzero/plugins/blockchain/AllAccounts.cpp

0
alethzero/AllAccounts.h → alethzero/plugins/blockchain/AllAccounts.h

0
alethzero/AllAccounts.ui → alethzero/plugins/blockchain/AllAccounts.ui

0
alethzero/BrainWallet.cpp → alethzero/plugins/brainwallet/BrainWallet.cpp

0
alethzero/BrainWallet.h → alethzero/plugins/brainwallet/BrainWallet.h

0
alethzero/BrainWallet.ui → alethzero/plugins/brainwallet/BrainWallet.ui

0
alethzero/LogPanel.cpp → alethzero/plugins/log/LogPanel.cpp

0
alethzero/LogPanel.h → alethzero/plugins/log/LogPanel.h

0
alethzero/LogPanel.ui → alethzero/plugins/log/LogPanel.ui

108
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 <http://www.gnu.org/licenses/>.
*/
/** @file NameRegNamer.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "NameRegNamer.h"
#include <QSettings>
#include <libdevcore/Log.h>
#include <libethereum/Client.h>
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<string>(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<Address>(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&)
{
}

59
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 <http://www.gnu.org/licenses/>.
*/
/** @file NameRegNamer.h
* @author Gav Wood <i@gavwood.com>
* @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<Address, unsigned> m_filters;
mutable Addresses m_knownCache;
// mutable std::unordered_map<Address, std::string> m_forwardCache;
// mutable std::unordered_map<std::string, Address> m_reverseCache;
};
}
}

0
alethzero/NewAccount.cpp → alethzero/plugins/namers/NewAccount.cpp

0
alethzero/NewAccount.h → alethzero/plugins/namers/NewAccount.h

0
alethzero/NewAccount.ui → alethzero/plugins/namers/NewAccount.ui

0
alethzero/OtherAccounts.cpp → alethzero/plugins/namers/OtherAccounts.cpp

0
alethzero/OtherAccounts.h → alethzero/plugins/namers/OtherAccounts.h

0
alethzero/OtherAccounts.ui → alethzero/plugins/namers/OtherAccounts.ui

0
alethzero/OurAccounts.cpp → alethzero/plugins/namers/OurAccounts.cpp

0
alethzero/OurAccounts.h → alethzero/plugins/namers/OurAccounts.h

178
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 <http://www.gnu.org/licenses/>.
*/
/** @file Whisper.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Whisper.h"
#include <QSettings>
#include <libethereum/Client.h>
#include <libethereum/Utility.h>
#include <libwhisper/WhisperHost.h>
#include <libweb3jsonrpc/WebThreeStubServerBase.h>
#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()));
}

60
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 <http://www.gnu.org/licenses/>.
*/
/** @file Whisper.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <QMutex>
#include <QString>
#include <QPair>
#include <QList>
#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<KeyPair> m_myIdentities;
};
}
}

176
alethzero/plugins/whisper/Whisper.ui

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Whisper</class>
<widget class="QWidget" name="WhisperWidget">
<layout class="QGridLayout" name="gridLayout_4">
<item row="4" column="0" rowspan="2">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Data</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QLabel" name="label5_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Work to Prove</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhData">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="1" colspan="4">
<widget class="QPlainTextEdit" name="shhTopic">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
<widget class="QComboBox" name="shhFrom">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Topic</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label5_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="4">
<widget class="QComboBox" name="shhTo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="shhTtl">
<property name="suffix">
<string> seconds</string>
</property>
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>259200</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label5_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TTL</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label5_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>From</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QSpinBox" name="shhWork">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QPushButton" name="post">
<property name="text">
<string>Post</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

78
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 <http://www.gnu.org/licenses/>.
*/
/** @file WhisperPeers.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "WhisperPeers.h"
#include <QSettings>
#include <libethereum/Client.h>
#include <libwhisper/WhisperHost.h>
#include <libweb3jsonrpc/WebThreeStubServerBase.h>
#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<Public, Secret> 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);
}
}

55
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 <http://www.gnu.org/licenses/>.
*/
/** @file WhisperPeers.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <QMutex>
#include <QString>
#include <QPair>
#include <QList>
#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;
};
}
}

32
alethzero/plugins/whisper/WhisperPeers.ui

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WhisperPeers</class>
<widget class="QWidget" name="whisperPeersWidget">
<layout class="QHBoxLayout" name="whisperPeersLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="whispers">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

8
eth/main.cpp

@ -109,8 +109,8 @@ void help()
/*<< " -B,--block-fees <n> Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl /*<< " -B,--block-fees <n> Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl
<< " -e,--ether-price <n> Set the ether price in the reference unit e.g. ¢ (default: 30.679)." << endl << " -e,--ether-price <n> 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*/ << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl*/
<< " --ask <wei> Set the minimum ask gas price under which no transactions will be mined (default " << toString(c_defaultGasPrice) << " )." << endl << " --ask <wei> Set the minimum ask gas price under which no transactions will be mined (default " << toString(DefaultGasPrice) << " )." << endl
<< " --bid <wei> Set the bid gas price for to pay for transactions (default " << toString(c_defaultGasPrice) << " )." << endl << " --bid <wei> Set the bid gas price for to pay for transactions (default " << toString(DefaultGasPrice) << " )." << endl
<< endl << endl
<< "Client mining:" << endl << "Client mining:" << endl
<< " -a,--address <addr> Set the coinbase (mining payout) address to addr (default: auto)." << endl << " -a,--address <addr> 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; // TransactionPriority priority = TransactionPriority::Medium;
// double etherPrice = 30.679; // double etherPrice = 30.679;
// double blockFees = 15.0; // double blockFees = 15.0;
u256 askPrice = c_defaultGasPrice; u256 askPrice = DefaultGasPrice;
u256 bidPrice = c_defaultGasPrice; u256 bidPrice = DefaultGasPrice;
// javascript console // javascript console
bool useConsole = false; bool useConsole = false;

5
evmjit/CMakeLists.txt

@ -3,13 +3,14 @@ cmake_minimum_required(VERSION 2.8.12)
if (${CMAKE_VERSION} VERSION_GREATER 3.0) if (${CMAKE_VERSION} VERSION_GREATER 3.0)
cmake_policy(SET CMP0042 OLD) # fix MACOSX_RPATH cmake_policy(SET CMP0042 OLD) # fix MACOSX_RPATH
cmake_policy(SET CMP0048 NEW) # allow VERSION argument in project() 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() else()
project(EVMJIT) project(EVMJIT)
set(EVMJIT_VERSION "0.9.0") set(EVMJIT_VERSION "0.9.0.1")
set(EVMJIT_VERSION_MAJOR 0) set(EVMJIT_VERSION_MAJOR 0)
set(EVMJIT_VERSION_MINOR 9) set(EVMJIT_VERSION_MINOR 9)
set(EVMJIT_VERSION_PATCH 0) set(EVMJIT_VERSION_PATCH 0)
set(EVMJIT_VERSION_TWEAK 1)
endif() endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)

4
evmjit/include/evmjit/JIT-c.h

@ -47,10 +47,6 @@ typedef enum evmjit_return_code
// Standard error codes // Standard error codes
OutOfGas = -1, 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 // Internal error codes
LLVMError = -101, LLVMError = -101,

4
evmjit/include/evmjit/JIT.h

@ -101,10 +101,6 @@ enum class ReturnCode
// Standard error codes // Standard error codes
OutOfGas = -1, 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 // Internal error codes
LLVMError = -101, LLVMError = -101,

6
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))); _ext.suicide(right160(jit2eth(m_data.address)));
break; break;
case evmjit::ReturnCode::BadJumpDestination:
BOOST_THROW_EXCEPTION(BadJumpDestination());
case evmjit::ReturnCode::OutOfGas: case evmjit::ReturnCode::OutOfGas:
BOOST_THROW_EXCEPTION(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 case evmjit::ReturnCode::LinkerWorkaround: // never happens
env_sload(); // but forces linker to include env_* JIT callback functions env_sload(); // but forces linker to include env_* JIT callback functions
break; break;

12
evmjit/libevmjit/Array.cpp

@ -217,11 +217,7 @@ llvm::Type* Array::getType()
} }
Array::Array(llvm::IRBuilder<>& _builder, char const* _name) : Array::Array(llvm::IRBuilder<>& _builder, char const* _name) :
CompilerHelper(_builder), CompilerHelper(_builder)
m_pushFunc([this](){ return createArrayPushFunc(); }),
m_setFunc([this](){ return createArraySetFunc(); }),
m_getFunc([this](){ return createArrayGetFunc(); }),
m_freeFunc([this](){ return createFreeFunc(); })
{ {
m_array = m_builder.CreateAlloca(getType(), nullptr, _name); m_array = m_builder.CreateAlloca(getType(), nullptr, _name);
m_builder.CreateStore(llvm::ConstantAggregateZero::get(getType()), m_array); 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) : Array::Array(llvm::IRBuilder<>& _builder, llvm::Value* _array) :
CompilerHelper(_builder), CompilerHelper(_builder),
m_array(_array), m_array(_array)
m_pushFunc([this](){ return createArrayPushFunc(); }),
m_setFunc([this](){ return createArraySetFunc(); }),
m_getFunc([this](){ return createArrayGetFunc(); }),
m_freeFunc([this](){ return createFreeFunc(); })
{ {
m_builder.CreateStore(llvm::ConstantAggregateZero::get(getType()), m_array); m_builder.CreateStore(llvm::ConstantAggregateZero::get(getType()), m_array);
} }

8
evmjit/libevmjit/Array.h

@ -59,10 +59,10 @@ private:
llvm::Function* getReallocFunc(); llvm::Function* getReallocFunc();
LazyFunction m_pushFunc = {[this](){ return createArrayPushFunc(); }}; // TODO: If works on MSVC, remove form initialization list 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_getPtrFunc = {[this](){ return createGetPtrFunc(); }};
LazyFunction m_getFunc; LazyFunction m_getFunc = {[this](){ return createArrayGetFunc(); }};
LazyFunction m_freeFunc; LazyFunction m_freeFunc = {[this](){ return createFreeFunc(); }};
LazyFunction m_extendFunc = {[this](){ return createExtendFunc(); }}; LazyFunction m_extendFunc = {[this](){ return createExtendFunc(); }};
LazyFunction m_reallocFunc = {[this](){ return getReallocFunc(); }}; LazyFunction m_reallocFunc = {[this](){ return getReallocFunc(); }};
}; };
@ -70,5 +70,3 @@ private:
} }
} }
} }

360
evmjit/libevmjit/BasicBlock.cpp

@ -20,53 +20,42 @@ namespace eth
namespace jit namespace jit
{ {
static const char* jumpDestName = "JmpDst."; BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc):
static const char* basicBlockName = "Instr.";
BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) :
m_firstInstrIdx{_firstInstrIdx}, m_firstInstrIdx{_firstInstrIdx},
m_begin(_begin), m_begin(_begin),
m_end(_end), m_end(_end),
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {isJumpDest ? jumpDestName : basicBlockName, std::to_string(_firstInstrIdx)}, _mainFunc)), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", 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)
{} {}
BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) : LocalStack::LocalStack(Stack& _globalStack):
m_bblock(_owner) m_global(_globalStack)
{} {}
void BasicBlock::LocalStack::push(llvm::Value* _value) void LocalStack::push(llvm::Value* _value)
{ {
assert(_value->getType() == Type::Word); assert(_value->getType() == Type::Word);
m_bblock.m_currentStack.push_back(_value); m_local.push_back(_value);
m_bblock.m_tosOffset += 1; m_maxSize = std::max(m_maxSize, size());
m_maxSize = std::max(m_maxSize, m_bblock.m_tosOffset);
} }
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) if (m_local.size() > 0)
m_bblock.m_currentStack.pop_back(); m_local.pop_back();
else
++m_globalPops;
m_bblock.m_tosOffset -= 1; m_minSize = std::min(m_minSize, size());
return result; return item;
} }
/** /**
* Pushes a copy of _index-th element (tos is 0-th elem). * 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); auto val = get(_index);
push(val); push(val);
@ -76,7 +65,7 @@ void BasicBlock::LocalStack::dup(size_t _index)
* Swaps tos with _index-th element (tos is 0-th elem). * Swaps tos with _index-th element (tos is 0-th elem).
* _index must be > 0. * _index must be > 0.
*/ */
void BasicBlock::LocalStack::swap(size_t _index) void LocalStack::swap(size_t _index)
{ {
assert(_index > 0); assert(_index > 0);
auto val = get(_index); auto val = get(_index);
@ -85,306 +74,73 @@ void BasicBlock::LocalStack::swap(size_t _index)
set(0, val); set(0, val);
} }
std::vector<llvm::Value*>::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) llvm::Value* LocalStack::get(size_t _index)
{ {
auto& currentStack = m_bblock.m_currentStack; if (_index < m_local.size())
if (_index < currentStack.size()) return *(m_local.rbegin() + _index); // count from back
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);
return currentStack.end() - _index - 1; auto idx = _index - m_local.size() + m_globalPops;
} if (idx >= m_input.size())
m_input.resize(idx + 1);
llvm::Value* BasicBlock::LocalStack::get(size_t _index) auto& item = m_input[idx];
{
auto& initialStack = m_bblock.m_initialStack;
auto itemIter = getItemIterator(_index);
if (*itemIter == nullptr) if (!item)
{ {
// Need to fetch a new item from the EVM stack item = m_global.get(idx); // Reach an item from global stack
assert(static_cast<int>(_index) >= m_bblock.m_tosOffset); m_minSize = std::min(m_minSize, -static_cast<ssize_t>(idx) - 1); // and remember required stack size
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];
} }
return *itemIter; return item;
} }
void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) void LocalStack::set(size_t _index, llvm::Value* _word)
{
auto itemIter = getItemIterator(_index);
*itemIter = _word;
}
void BasicBlock::synchronizeLocalStack(Stack& _evmStack)
{ {
auto blockTerminator = m_llvmBB->getTerminator(); if (_index < m_local.size())
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<size_t>(idx) < m_initialStack.size());
if (*currIter != m_initialStack[idx]) // value needs update
_evmStack.set(static_cast<size_t>(idx), *currIter);
}
// Pop values
if (m_tosOffset < 0)
_evmStack.pop(static_cast<size_t>(-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)
{ {
auto val = m_initialStack[idx]; *(m_local.rbegin() + _index) = _word;
if (val == nullptr) return;
continue;
llvm::PHINode* phi = llvm::cast<llvm::PHINode>(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();
} }
// Reset the stack auto idx = _index - m_local.size() + m_globalPops;
m_initialStack.erase(m_initialStack.begin(), m_initialStack.end()); assert(idx < m_input.size());
m_currentStack.erase(m_currentStack.begin(), m_currentStack.end()); m_input[idx] = _word;
m_tosOffset = 0;
} }
void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRBuilder<>& _builder)
{
struct BBInfo
{
BasicBlock& bblock;
std::vector<BBInfo*> predecessors;
size_t inputItems;
size_t outputItems;
std::vector<llvm::PHINode*> 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<llvm::BasicBlock*, BBInfo> 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. void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb)
bool valuesChanged = true; {
while (valuesChanged) auto blockTerminator = _bb.getTerminator();
assert(blockTerminator);
if (blockTerminator->getOpcode() != llvm::Instruction::Ret)
{ {
for (auto& pair : cfg) // Not needed in case of ret instruction. Ret invalidates the stack.
{ _builder.SetInsertPoint(blockTerminator);
DLOG(bb) << pair.second.bblock.llvm()->getName().str()
<< ": in " << pair.second.inputItems
<< ", out " << pair.second.outputItems
<< "\n";
}
valuesChanged = false; // Update items fetched from global stack ignoring the poped ones
for (auto& pair : cfg) 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 (m_input[i])
m_global.set(i, m_input[i]);
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;
}
}
} }
}
// Propagate values between blocks.
for (auto& entry : cfg)
{
auto& info = entry.second;
auto& bblock = info.bblock;
llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI()); // Add new items
auto phiIter = bblock.m_initialStack.begin(); auto pops = m_globalPops; // Copy pops counter to keep original value
for (size_t index = 0; index < info.inputItems; ++index, ++phiIter) for (auto& item: m_local)
{ {
assert(llvm::isa<llvm::PHINode>(*phiIter)); if (pops) // Override poped global items
auto phi = llvm::cast<llvm::PHINode>(*phiIter); m_global.set(--pops, item); // using pops counter as the index
else
for (auto predIt : info.predecessors) m_global.push(item);
{
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);
}
} }
// The items pulled directly from predecessors block must be removed // Pop not overriden items
// from the list of items that has to be popped from the initial stack. if (pops)
auto& initialStack = bblock.m_initialStack; m_global.pop(pops);
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<llvm::ExtractValueInst>(val))
out << " " << val->getName();
else if (llvm::isa<llvm::Instruction>(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<llvm::ExtractValueInst>(*val))
out << " " << (*val)->getName();
else if (llvm::isa<llvm::Instruction>(*val))
out << **val;
else
out << " " << **val;
out << (_dotOutput ? "\\l" : "\n");
} }
if (! _dotOutput)
out << " ...\n----------------------------------------\n";
} }
} }
} }
} }

127
evmjit/libevmjit/BasicBlock.h

@ -14,52 +14,58 @@ namespace jit
using namespace evmjit; using namespace evmjit;
using instr_idx = uint64_t; using instr_idx = uint64_t;
class BasicBlock class LocalStack
{ {
public: public:
class LocalStack explicit LocalStack(Stack& _globalStack);
{ LocalStack(LocalStack const&) = delete;
public: void operator=(LocalStack const&) = delete;
/// Pushes value on stack
void push(llvm::Value* _value); /// Pushes value on stack
void push(llvm::Value* _value);
/// Pops and returns top value /// Pops and returns top value
llvm::Value* pop(); llvm::Value* pop();
/// Duplicates _index'th value on stack /// Duplicates _index'th value on stack
void dup(size_t _index); void dup(size_t _index);
/// Swaps _index'th value on stack with a value on stack top. /// Swaps _index'th value on stack with a value on stack top.
/// @param _index Index of value to be swaped. Must be > 0. /// @param _index Index of value to be swaped. Must be > 0.
void swap(size_t _index); void swap(size_t _index);
size_t getMaxSize() const { return m_maxSize; } ssize_t size() const { return static_cast<ssize_t>(m_local.size()) - static_cast<ssize_t>(m_globalPops); }
int getDiff() const { return m_bblock.m_tosOffset; } ssize_t minSize() const { return m_minSize; }
ssize_t maxSize() const { return m_maxSize; }
private: /// Finalize local stack: check the requirements and update of the global stack.
LocalStack(BasicBlock& _owner); void finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb);
LocalStack(LocalStack const&) = delete;
void operator=(LocalStack const&) = delete;
friend BasicBlock;
/// Gets _index'th value from top (counting from 0) private:
llvm::Value* get(size_t _index); /// Gets _index'th value from top (counting from 0)
llvm::Value* get(size_t _index);
/// Sets _index'th value from top (counting from 0) /// Sets _index'th value from top (counting from 0)
void set(size_t _index, llvm::Value* _value); void set(size_t _index, llvm::Value* _value);
std::vector<llvm::Value*>::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<llvm::Value*> m_input;
private: /// Local stack items that has not been pushed to global stack. First item is just above global stack.
BasicBlock& m_bblock; std::vector<llvm::Value*> m_local;
int m_maxSize = 0; ///< Max size reached by the stack.
};
explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); Stack& m_global; ///< Reference to global stack.
explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest);
BasicBlock(const BasicBlock&) = delete; size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap.
BasicBlock& operator=(const BasicBlock&) = delete; 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; } llvm::BasicBlock* llvm() { return m_llvmBB; }
@ -67,61 +73,12 @@ public:
code_iterator begin() const { return m_begin; } code_iterator begin() const { return m_begin; }
code_iterator end() const { return m_end; } 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<BasicBlock*> _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: private:
instr_idx const m_firstInstrIdx = 0; ///< Code index of first instruction in the block 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_begin = {}; ///< Iterator pointing code beginning of the block
code_iterator const m_end = {}; ///< Iterator pointing code end 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<llvm::Value*> 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<llvm::Value*> 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;
/// If block finishes with dynamic jump target index is stored here llvm::BasicBlock* const m_llvmBB; ///< Reference to the LLVM BasicBlock
llvm::Value* m_jumpTarget = nullptr;
}; };
} }

277
evmjit/libevmjit/Compiler.cpp

@ -36,7 +36,7 @@ Compiler::Compiler(Options const& _options):
Type::init(m_builder.getContext()); Type::init(m_builder.getContext());
} }
void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEnd) std::vector<BasicBlock> 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) /// Helper function that skips push data and finds next iterator (can be the end)
auto skipPushDataAndGetNext = [](code_iterator _curr, code_iterator _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<byte>(Instruction::STOP)) if (*(_codeEnd - 1) != static_cast<byte>(Instruction::STOP))
break; break;
std::vector<BasicBlock> blocks;
auto begin = _codeBegin; // begin of current block auto begin = _codeBegin; // begin of current block
bool nextJumpDest = false;
for (auto curr = begin, next = begin; curr != _codeEnd; curr = next) for (auto curr = begin, next = begin; curr != _codeEnd; curr = next)
{ {
next = skipPushDataAndGetNext(curr, _codeEnd); next = skipPushDataAndGetNext(curr, _codeEnd);
@ -71,10 +72,6 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn
isEnd = true; isEnd = true;
break; break;
case Instruction::JUMPDEST:
nextJumpDest = true;
break;
default: default:
break; break;
} }
@ -86,42 +83,32 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn
if (isEnd) if (isEnd)
{ {
auto beginIdx = begin - _codeBegin; auto beginIdx = begin - _codeBegin;
m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), blocks.emplace_back(beginIdx, begin, next, m_mainFunc);
std::forward_as_tuple(beginIdx, begin, next, m_mainFunc, m_builder, nextJumpDest)); if (Instruction(*begin) == Instruction::JUMPDEST)
nextJumpDest = false; _jumpTable.addCase(Constant::get(beginIdx), blocks.back().llvm());
begin = next; 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)); m_jumpTableBB->eraseFromParent(); // remove if unused
InsertPointGuard g{m_builder}; return;
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());
}
} }
return m_jumpTableBlock->llvm();
}
llvm::BasicBlock* Compiler::getBadJumpBlock(RuntimeManager& _runtimeManager) // TODO: Extend this function as `resolveJumps()` and fill gaps in branch instructions.
{ auto target = llvm::cast<llvm::PHINode>(m_jumpTableBB->begin());
if (!m_badJumpBlock) for (auto pred: llvm::predecessors(m_jumpTableBB))
{ {
m_badJumpBlock.reset(new BasicBlock("BadJump", m_mainFunc, m_builder, true)); auto targetMd = llvm::cast<llvm::LocalAsMetadata>(pred->getTerminator()->getMetadata("target")->getOperand(0));
InsertPointGuard g{m_builder}; target->addIncoming(targetMd->getValue(), pred);
m_builder.SetInsertPoint(m_badJumpBlock->llvm());
_runtimeManager.exit(ReturnCode::BadJumpDestination);
} }
return m_badJumpBlock->llvm();
} }
std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_iterator _end, std::string const& _id) std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_iterator _end, std::string const& _id)
@ -135,16 +122,24 @@ std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_itera
// Create entry basic block // Create entry basic block
auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), {}, m_mainFunc); 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); m_builder.SetInsertPoint(entryBlock);
createBasicBlocks(_begin, _end); auto blocks = createBasicBlocks(_begin, _end, jumpTable);
// Init runtime structures. // Init runtime structures.
RuntimeManager runtimeManager(m_builder, _begin, _end); RuntimeManager runtimeManager(m_builder, _begin, _end);
GasMeter gasMeter(m_builder, runtimeManager); GasMeter gasMeter(m_builder, runtimeManager);
Memory memory(runtimeManager, gasMeter); Memory memory(runtimeManager, gasMeter);
Ext ext(runtimeManager, memory); Ext ext(runtimeManager, memory);
Stack stack(m_builder, runtimeManager); Stack stack(m_builder);
runtimeManager.setStack(stack); // Runtime Manager will free stack memory runtimeManager.setStack(stack); // Runtime Manager will free stack memory
Arith256 arith(m_builder); Arith256 arith(m_builder);
@ -162,87 +157,39 @@ std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_itera
auto normalFlow = m_builder.CreateICmpEQ(r, m_builder.getInt32(0)); auto normalFlow = m_builder.CreateICmpEQ(r, m_builder.getInt32(0));
runtimeManager.setJmpBuf(jmpBuf); runtimeManager.setJmpBuf(jmpBuf);
// TODO: Create Stop basic block on demand auto firstBB = blocks.empty() ? m_stopBB : blocks.front().llvm();
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();
m_builder.CreateCondBr(normalFlow, firstBB, m_abortBB, Type::expectTrue); 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; // TODO: Rewrite
auto iterCopy = basicBlockPairIt; auto nextIt = it + 1;
++iterCopy; auto nextBasicBlock = (nextIt != blocks.end()) ? nextIt->llvm() : nullptr; // TODO: What with Stop block?
auto nextBasicBlock = (iterCopy != m_basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; compileBasicBlock(*it, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack, jumpTable);
compileBasicBlock(basicBlock, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock);
} }
// Code for special blocks: // Code for special blocks:
// TODO: move to separate function.
m_builder.SetInsertPoint(m_stopBB); m_builder.SetInsertPoint(m_stopBB);
runtimeManager.exit(ReturnCode::Stop); runtimeManager.exit(ReturnCode::Stop);
m_builder.SetInsertPoint(m_abortBB); m_builder.SetInsertPoint(m_abortBB);
runtimeManager.exit(ReturnCode::OutOfGas); runtimeManager.exit(ReturnCode::OutOfGas);
removeDeadBlocks(); fillJumpTable();
// Link jump table target index
if (m_jumpTableBlock)
{
auto phi = llvm::cast<llvm::PHINode>(&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<BasicBlock*> 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");
return module; return module;
} }
void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runtimeManager, 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 if (!_nextBasicBlock) // this is the last block in the code
_nextBasicBlock = m_stopBB; _nextBasicBlock = m_stopBB;
m_builder.SetInsertPoint(_basicBlock.llvm()); m_builder.SetInsertPoint(_basicBlock.llvm());
auto& stack = _basicBlock.localStack(); LocalStack stack{_globalStack};
for (auto it = _basicBlock.begin(); it != _basicBlock.end(); ++it) 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::JUMP:
case Instruction::JUMPI: case Instruction::JUMPI:
{ {
llvm::BasicBlock* targetBlock = nullptr; auto jumpBlock = m_jumpTableBB;
auto target = stack.pop(); auto target = stack.pop();
if (auto constant = llvm::dyn_cast<llvm::ConstantInt>(target)) auto jumpInst = (inst == Instruction::JUMP) ?
{ m_builder.CreateBr(jumpBlock) :
auto&& c = constant->getValue(); m_builder.CreateCondBr(m_builder.CreateICmpNE(stack.pop(), Constant::get(0), "jump.check"), jumpBlock, _nextBasicBlock);
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);
}
// TODO: Improve; check for constants if (auto constant = llvm::dyn_cast<llvm::ConstantInt>(target))
if (inst == Instruction::JUMP)
{ {
if (targetBlock) // If target index is a constant do direct jump to the target block.
{ auto bb = jumpTable.findCaseValue(constant).getCaseSuccessor();
m_builder.CreateBr(targetBlock); jumpInst->setSuccessor(0, bb);
}
else
{
_basicBlock.setJumpTarget(target);
m_builder.CreateBr(getJumpTableBlock(_runtimeManager));
}
} }
else // JUMPI else
{ {
auto val = stack.pop(); // Attach medatada to branch instruction with information about target index.
auto zero = Constant::get(0); auto targetMd = llvm::MDNode::get(jumpInst->getContext(), llvm::LocalAsMetadata::get(target));
auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); jumpInst->setMetadata("target", targetMd);
if (targetBlock)
{
m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock);
}
else
{
_basicBlock.setJumpTarget(target);
m_builder.CreateCondBr(cond, getJumpTableBlock(_runtimeManager), _nextBasicBlock);
}
} }
break; break;
} }
@ -868,109 +794,12 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
if (!_basicBlock.llvm()->getTerminator()) if (!_basicBlock.llvm()->getTerminator())
m_builder.CreateBr(_nextBasicBlock); m_builder.CreateBr(_nextBasicBlock);
m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); stack.finalize(m_builder, *_basicBlock.llvm()); // TODO: Use references
_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();
}
}
void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); // TODO: Move to LocalStack::finalize
{ _runtimeManager.checkStackLimit(stack.minSize(), stack.maxSize(), stack.size());
if (! m_options.dumpCFG)
return;
// TODO: handle i/o failures
std::ofstream ofs(_dotfilePath);
dumpCFGtoStream(ofs);
ofs.close();
} }
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<BasicBlock*> 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<BasicBlock*,int> 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();
}
} }
} }

35
evmjit/libevmjit/Compiler.h

@ -15,9 +15,6 @@ public:
struct Options struct Options
{ {
/// Optimize stack operations between basic blocks
bool optimizeStack = true;
/// Rewrite switch instructions to sequences of branches /// Rewrite switch instructions to sequences of branches
bool rewriteSwitchToBranches = true; bool rewriteSwitchToBranches = true;
@ -25,32 +22,18 @@ public:
bool dumpCFG = false; bool dumpCFG = false;
}; };
using ProgramCounter = uint64_t;
Compiler(Options const& _options); Compiler(Options const& _options);
std::unique_ptr<llvm::Module> compile(code_iterator _begin, code_iterator _end, std::string const& _id); std::unique_ptr<llvm::Module> compile(code_iterator _begin, code_iterator _end, std::string const& _id);
private: private:
void createBasicBlocks(code_iterator _begin, code_iterator _end); std::vector<BasicBlock> createBasicBlocks(code_iterator _begin, code_iterator _end, llvm::SwitchInst& _switchInst);
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);
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 fillJumpTable();
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();
/// Compiler options /// Compiler options
Options const& m_options; Options const& m_options;
@ -58,9 +41,6 @@ private:
/// Helper class for generating IR /// Helper class for generating IR
llvm::IRBuilder<> m_builder; llvm::IRBuilder<> m_builder;
/// Maps a program counter pc to a basic block that starts at pc (if any).
std::map<ProgramCounter, BasicBlock> m_basicBlocks;
/// Stop basic block - terminates execution with STOP code (0) /// Stop basic block - terminates execution with STOP code (0)
llvm::BasicBlock* m_stopBB = nullptr; llvm::BasicBlock* m_stopBB = nullptr;
@ -68,13 +48,10 @@ private:
llvm::BasicBlock* m_abortBB = nullptr; llvm::BasicBlock* m_abortBB = nullptr;
/// Block with a jump table. /// Block with a jump table.
std::unique_ptr<BasicBlock> m_jumpTableBlock; llvm::BasicBlock* m_jumpTableBB = nullptr;
/// Destination for invalid jumps
std::unique_ptr<BasicBlock> m_badJumpBlock;
/// Main program function /// Main program function
llvm::Function* m_mainFunc = nullptr; llvm::Function* m_mainFunc = nullptr; // TODO: Remove
}; };
} }

1
evmjit/libevmjit/Optimizer.cpp

@ -114,6 +114,7 @@ bool LowerEVMPass::doFinalization(llvm::Module&)
bool prepare(llvm::Module& _module) bool prepare(llvm::Module& _module)
{ {
auto pm = llvm::legacy::PassManager{}; auto pm = llvm::legacy::PassManager{};
pm.add(llvm::createCFGSimplificationPass());
pm.add(llvm::createDeadCodeEliminationPass()); pm.add(llvm::createDeadCodeEliminationPass());
pm.add(new LowerEVMPass{}); pm.add(new LowerEVMPass{});
return pm.run(_module); return pm.run(_module);

19
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_gasPtr = m_builder.CreateAlloca(Type::Gas, nullptr, "gas.ptr");
m_builder.CreateStore(m_dataElts[RuntimeData::Index::Gas], m_gasPtr); m_builder.CreateStore(m_dataElts[RuntimeData::Index::Gas], m_gasPtr);
llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::BytePtr}; 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, "stack.checkSize", getModule()); m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "evm.stack.require", getModule());
m_checkStackLimit->setDoesNotThrow(); m_checkStackLimit->setDoesNotThrow();
m_checkStackLimit->setDoesNotCapture(1); m_checkStackLimit->setDoesNotCapture(1);
@ -121,7 +121,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB
auto currSizePtr = &m_checkStackLimit->getArgumentList().front(); auto currSizePtr = &m_checkStackLimit->getArgumentList().front();
currSizePtr->setName("currSize"); currSizePtr->setName("currSize");
auto max = currSizePtr->getNextNode(); auto min = currSizePtr->getNextNode();
min->setName("min");
auto max = min->getNextNode();
max->setName("max"); max->setName("max");
auto diff = max->getNextNode(); auto diff = max->getNextNode();
diff->setName("diff"); diff->setName("diff");
@ -131,8 +133,11 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB
InsertPointGuard guard{m_builder}; InsertPointGuard guard{m_builder};
m_builder.SetInsertPoint(checkBB); m_builder.SetInsertPoint(checkBB);
auto currSize = m_builder.CreateLoad(currSizePtr, "cur"); auto currSize = m_builder.CreateLoad(currSizePtr, "cur");
auto maxSize = m_builder.CreateNUWAdd(currSize, max, "maxSize"); auto minSize = m_builder.CreateAdd(currSize, min, "minSize", false, true);
auto ok = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(1024), "ok"); 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.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue);
m_builder.SetInsertPoint(updateBB); m_builder.SetInsertPoint(updateBB);
@ -145,9 +150,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB
m_builder.CreateUnreachable(); 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() llvm::Value* RuntimeManager::getRuntimePtr()

2
evmjit/libevmjit/RuntimeManager.h

@ -50,7 +50,7 @@ public:
static llvm::StructType* getRuntimeType(); static llvm::StructType* getRuntimeType();
static llvm::StructType* getRuntimeDataType(); static llvm::StructType* getRuntimeDataType();
void checkStackLimit(size_t _max, int _diff); void checkStackLimit(ssize_t _min, ssize_t _max, ssize_t _diff);
private: private:
llvm::Value* getPtr(RuntimeData::Index _index); llvm::Value* getPtr(RuntimeData::Index _index);

44
evmjit/libevmjit/Stack.cpp

@ -16,52 +16,14 @@ namespace eth
namespace jit namespace jit
{ {
Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager): Stack::Stack(llvm::IRBuilder<>& _builder):
CompilerHelper(_builder), CompilerHelper(_builder),
m_runtimeManager(_runtimeManager),
m_stack(_builder, "stack") 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) llvm::Value* Stack::get(size_t _index)
{ {
createCall(getGetFunc(), {m_builder.getInt64(_index), m_stack.size(), m_runtimeManager.getJmpBuf()}); return m_stack.get(m_builder.CreateSub(m_stack.size(), m_builder.getInt64(_index + 1)));
auto value = m_stack.get(m_builder.CreateSub(m_stack.size(), m_builder.getInt64(_index + 1)));
//return m_builder.CreateLoad(valuePtr);
return value;
} }
void Stack::set(size_t _index, llvm::Value* _value) 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) 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)); m_stack.pop(m_builder.getInt64(_count));
} }

13
evmjit/libevmjit/Stack.h

@ -1,7 +1,5 @@
#pragma once #pragma once
#include <functional>
#include "Array.h" #include "Array.h"
namespace dev namespace dev
@ -10,12 +8,11 @@ namespace eth
{ {
namespace jit namespace jit
{ {
class RuntimeManager;
class Stack : public CompilerHelper class Stack: public CompilerHelper
{ {
public: public:
Stack(llvm::IRBuilder<>& builder, RuntimeManager& runtimeManager); Stack(llvm::IRBuilder<>& builder);
llvm::Value* get(size_t _index); llvm::Value* get(size_t _index);
void set(size_t _index, llvm::Value* _value); void set(size_t _index, llvm::Value* _value);
@ -24,10 +21,6 @@ public:
void free() { m_stack.free(); } void free() { m_stack.free(); }
private: private:
llvm::Function* getGetFunc();
RuntimeManager& m_runtimeManager;
llvm::Function* m_get = nullptr;
Array m_stack; Array m_stack;
}; };
@ -35,5 +28,3 @@ private:
} }
} }
} }

25
libethcore/ABI.h

@ -43,7 +43,17 @@ template <class T> struct ABISerialiser {};
template <unsigned N> struct ABISerialiser<FixedHash<N>> { static bytes serialise(FixedHash<N> 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 <unsigned N> struct ABISerialiser<FixedHash<N>> { static bytes serialise(FixedHash<N> 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<u256> { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } }; template <> struct ABISerialiser<u256> { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } };
template <> struct ABISerialiser<u160> { static bytes serialise(u160 const& _t) { return bytes(12, 0) + h160(_t).asBytes(); } }; template <> struct ABISerialiser<u160> { static bytes serialise(u160 const& _t) { return bytes(12, 0) + h160(_t).asBytes(); } };
template <> struct ABISerialiser<string32> { static bytes serialise(string32 const& _t) { return bytesConstRef((byte const*)_t.data(), 32).toBytes(); } }; template <> struct ABISerialiser<string32> { static bytes serialise(string32 const& _t) { bytes ret; bytesConstRef((byte const*)_t.data(), 32).populate(bytesRef(&ret)); return ret; } };
template <> struct ABISerialiser<std::string>
{
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 {}; } inline bytes abiInAux() { return {}; }
template <class T, class ... U> bytes abiInAux(T const& _t, U const& ... _u) template <class T, class ... U> bytes abiInAux(T const& _t, U const& ... _u)
@ -61,6 +71,19 @@ template <unsigned N> struct ABIDeserialiser<FixedHash<N>> { static FixedHash<N>
template <> struct ABIDeserialiser<u256> { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian<u256>(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } }; template <> struct ABIDeserialiser<u256> { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian<u256>(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } };
template <> struct ABIDeserialiser<u160> { static u160 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian<u160>(io_t.cropped(12, 20)); io_t = io_t.cropped(32); return ret; } }; template <> struct ABIDeserialiser<u160> { static u160 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian<u160>(io_t.cropped(12, 20)); io_t = io_t.cropped(32); return ret; } };
template <> struct ABIDeserialiser<string32> { 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<string32> { 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<std::string>
{
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 <class T> T abiOut(bytes const& _data) template <class T> T abiOut(bytes const& _data)
{ {

2
libethereum/ClientBase.h

@ -148,7 +148,7 @@ public:
using Interface::addresses; using Interface::addresses;
virtual Addresses addresses(BlockNumber _block) const override; virtual Addresses addresses(BlockNumber _block) const override;
virtual u256 gasLimitRemaining() 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 /// Get the coinbase address
virtual Address address() const override; virtual Address address() const override;

6
libethereum/GasPricer.h

@ -40,7 +40,7 @@ enum class TransactionPriority
Highest = 8 Highest = 8
}; };
static const u256 c_defaultGasPrice = 50 * shannon; static const u256 DefaultGasPrice = 50 * shannon;
class GasPricer class GasPricer
{ {
@ -68,8 +68,8 @@ public:
u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return m_bid; } u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return m_bid; }
private: private:
u256 m_ask = c_defaultGasPrice; u256 m_ask = DefaultGasPrice;
u256 m_bid = c_defaultGasPrice; u256 m_bid = DefaultGasPrice;
}; };
} }

8
libethereum/Interface.h

@ -71,25 +71,25 @@ public:
virtual std::pair<h256, Address> submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; virtual std::pair<h256, Address> submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0;
/// Submits the given message-call transaction. /// 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. /// Submits a new contract-creation transaction.
/// @returns the new contract's address (assuming it all goes through). /// @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. /// Blocks until all pending transactions have been processed.
virtual void flushTransactions() = 0; virtual void flushTransactions() = 0;
/// Makes the given call. Nothing is recorded into the state. /// 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; 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, 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); } 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. /// Does the given creation. Nothing is recorded into the state.
/// @returns the pair of the Address of the created contract together with its code. /// @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; 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, 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); } 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); }

6
libethereumx/Ethereum.h

@ -62,11 +62,11 @@ public:
~Ethereum(); ~Ethereum();
/// Submits the given message-call transaction. /// 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. /// Submits a new contract-creation transaction.
/// @returns the new contract's address (assuming it all goes through). /// @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. /// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
void inject(bytesConstRef _rlp); void inject(bytesConstRef _rlp);
@ -75,7 +75,7 @@ public:
void flushTransactions(); void flushTransactions();
/// Makes the given call. Nothing is recorded into the state. /// 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 // Informational stuff

4
libevm/SmartVM.cpp

@ -54,7 +54,7 @@ namespace
bool isStopSentinel() 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(); return code.empty();
} }
}; };
@ -102,7 +102,7 @@ bytesConstRef SmartVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _
clog(JitInfo) << "JIT: " << codeHash; clog(JitInfo) << "JIT: " << codeHash;
vmKind = VMKind::JIT; vmKind = VMKind::JIT;
} }
else else if (!_ext.code.empty()) // This check is needed for VM tests
{ {
static JitWorker s_worker; static JitWorker s_worker;

10
libp2p/Host.cpp

@ -530,14 +530,8 @@ void Host::connect(std::shared_ptr<Peer> const& _p)
return; return;
} }
if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id)) if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id) && !_p->required)
{ return;
// 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;
}
// prevent concurrently connecting to a node // prevent concurrently connecting to a node
Peer *nptr = _p.get(); Peer *nptr = _p.get();

12
mix/ClientModel.cpp

@ -446,9 +446,13 @@ void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence)
if (contractAddressIter == m_contractAddresses.end()) if (contractAddressIter == m_contractAddresses.end())
{ {
emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId);
break; Address fakeAddress = Address::random();
std::pair<QString, int> 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); m_gasCosts.append(m_client->lastExecution().gasUsed);
onNewTransaction(); onNewTransaction();
@ -833,9 +837,9 @@ void ClientModel::onNewTransaction()
else else
{ {
//transaction/call //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)); function = QString::fromStdString(toJS(functionHash));
abi = true; abi = true;
} }

2
mix/MixClient.cpp

@ -269,7 +269,7 @@ void MixClient::mine()
RLPStream header; RLPStream header;
h.streamRLP(header); h.streamRLP(header);
m_postMine.sealBlock(header.out()); 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_postMine.sync(bc());
m_preMine = m_postMine; m_preMine = m_postMine;
} }

47
test/TestHelper.cpp

@ -253,12 +253,16 @@ void ImportTest::importTransaction(json_spirit::mObject const& o_tr)
importTransaction(o_tr, m_transaction); 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) \ #define CHECK(a,b) \
{ \ { \
if (_throw == WhenError::Throw) \ if (_throw == WhenError::Throw) \
{TBOOST_CHECK_MESSAGE(a,b);}\ { \
TBOOST_CHECK_MESSAGE(a, b); \
if (!a) \
return 1; \
} \
else \ else \
{TBOOST_WARN_MESSAGE(a,b);} \ {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)) << "'"); "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 // export output
m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add); m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add);
// compare expected output with post output // 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(); std::string warning = "Check State: Error! Unexpected output: " + m_testObject["out"].get_str() + " Expected: " + m_testObject["expectOut"].get_str();
if (Options::get().checkState) 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 else
TBOOST_WARN_MESSAGE((m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()), warning); 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["pre"] = fillJsonWithState(m_statePre);
m_testObject["env"] = makeAllFieldsHex(m_testObject["env"].get_obj()); m_testObject["env"] = makeAllFieldsHex(m_testObject["env"].get_obj());
m_testObject["transaction"] = makeAllFieldsHex(m_testObject["transaction"].get_obj()); m_testObject["transaction"] = makeAllFieldsHex(m_testObject["transaction"].get_obj());
return err;
} }
json_spirit::mObject fillJsonWithTransaction(Transaction _txn) json_spirit::mObject fillJsonWithTransaction(Transaction _txn)
@ -566,7 +577,10 @@ void userDefinedTest(std::function<void(json_spirit::mValue&, bool)> doTests)
auto& filename = Options::get().singleTestFile; auto& filename = Options::get().singleTestFile;
auto& testname = Options::get().singleTestName; auto& testname = Options::get().singleTestName;
VerbosityHolder sentinel(12);
if (g_logVerbosity != -1)
VerbosityHolder sentinel(12);
try try
{ {
cnote << "Testing user defined test: " << filename; cnote << "Testing user defined test: " << filename;
@ -631,7 +645,7 @@ void executeTests(const string& _name, const string& _testPathAppendix, const bo
try try
{ {
std::cout << "TEST " << _name << ":\n"; cnote << "TEST " << _name << ":";
json_spirit::mValue v; json_spirit::mValue v;
string s = asString(dev::contents(testPath + "/" + _name + ".json")); 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?"); 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") else if (arg == "--fulloutput")
fulloutput = true; 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() Options const& Options::get()

13
test/TestHelper.h

@ -22,7 +22,6 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -143,8 +142,8 @@ public:
static json_spirit::mObject& makeAllFieldsHex(json_spirit::mObject& _o); static json_spirit::mObject& makeAllFieldsHex(json_spirit::mObject& _o);
bytes executeTest(); bytes executeTest();
void exportTest(bytes const& _output); int 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); 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_statePre;
eth::State m_statePost; eth::State m_statePost;
@ -218,6 +217,13 @@ void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs)
TBOOST_CHECK((_expectedAddrs == _resultAddrs)); TBOOST_CHECK((_expectedAddrs == _resultAddrs));
}*/ }*/
enum class Verbosity
{
Full,
NiceReport,
None
};
class Options class Options
{ {
public: public:
@ -227,6 +233,7 @@ public:
std::string statsOutFile; ///< Stats output file. "out" for standard output std::string statsOutFile; ///< Stats output file. "out" for standard output
bool checkState = false;///< Throw error when checking test states bool checkState = false;///< Throw error when checking test states
bool fulloutput = false;///< Replace large output to just it's length bool fulloutput = false;///< Replace large output to just it's length
Verbosity logVerbosity = Verbosity::NiceReport;
/// Test selection /// Test selection
/// @{ /// @{

66
test/boostTest.cpp

@ -18,11 +18,75 @@
* @author Marko Simovic <markobarko@gmail.com> * @author Marko Simovic <markobarko@gmail.com>
* @date 2014 * @date 2014
* Stub for generating main boost.test module. * Stub for generating main boost.test module.
* Original code taken from boost sources.
*/ */
#define BOOST_TEST_MODULE EthereumTests #define BOOST_TEST_MODULE EthereumTests
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter" #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 <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#include <test/TestHelper.h>
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;
}

5
test/fuzzTesting/fuzzHelper.cpp

@ -402,13 +402,12 @@ void RandomCodeOptions::setWeights()
opCodeProbability = boostDescreteDistrib(weights); opCodeProbability = boostDescreteDistrib(weights);
} }
BOOST_AUTO_TEST_SUITE(RandomCodeTests) BOOST_AUTO_TEST_SUITE(RandomCodeTests)
BOOST_AUTO_TEST_CASE(rndCode) BOOST_AUTO_TEST_CASE(rndCode)
{ {
std::string code; std::string code;
std::cerr << "Testing Random Code: "; cnote << "Testing Random Code: ";
try try
{ {
code = dev::test::RandomCode::generate(10); code = dev::test::RandomCode::generate(10);
@ -417,7 +416,7 @@ BOOST_AUTO_TEST_CASE(rndCode)
{ {
BOOST_ERROR("Exception thrown when generating random code!"); BOOST_ERROR("Exception thrown when generating random code!");
} }
std::cerr << code; cnote << code;
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

25
test/libdevcore/rlp.cpp

@ -52,6 +52,7 @@ namespace dev
void doRlpTests(json_spirit::mValue& v, bool _fillin) void doRlpTests(json_spirit::mValue& v, bool _fillin)
{ {
string testname;
for (auto& i: v.get_obj()) for (auto& i: v.get_obj())
{ {
js::mObject& o = i.second.get_obj(); js::mObject& o = i.second.get_obj();
@ -61,9 +62,11 @@ namespace dev
continue; continue;
} }
cout << " " << i.first << endl; cnote << " " << i.first;
TBOOST_REQUIRE((o.count("out") > 0)); testname = "(" + i.first + ") ";
TBOOST_REQUIRE((!o["out"].is_null()));
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) if (_fillin)
{ {
@ -88,7 +91,7 @@ namespace dev
else else
{ {
//Check Encode //Check Encode
TBOOST_REQUIRE((o.count("in") > 0)); TBOOST_REQUIRE_MESSAGE((o.count("in") > 0), testname + "in not set!");
RlpType rlpType = RlpType::Test; RlpType rlpType = RlpType::Test;
if (o["in"].type() == js::str_type) if (o["in"].type() == js::str_type)
{ {
@ -112,7 +115,7 @@ namespace dev
msg << " But Computed: " << computedText; msg << " But Computed: " << computedText;
TBOOST_CHECK_MESSAGE( TBOOST_CHECK_MESSAGE(
(expectedText == computedText), (expectedText == computedText),
msg.str() testname + msg.str()
); );
} }
@ -155,11 +158,11 @@ namespace dev
//Check that there was an exception as input is INVALID //Check that there was an exception as input is INVALID
if (rlpType == RlpType::Invalid && !was_exception) 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 //input is VALID check that there was no exceptions
if (was_exception) 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) 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) 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) 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) catch (std::exception const& _e)
{ {
TBOOST_ERROR("Failed test with Exception: " << _e.what()); TBOOST_ERROR(path.filename().string() + "Failed test with Exception: " << _e.what());
} }
} }
} }

14
test/libdevcrypto/AES.cpp

@ -25,6 +25,7 @@
#include <libdevcore/SHA3.h> #include <libdevcore/SHA3.h>
#include <libdevcrypto/AES.h> #include <libdevcrypto/AES.h>
#include <libdevcore/FixedHash.h> #include <libdevcore/FixedHash.h>
#include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
@ -33,7 +34,7 @@ BOOST_AUTO_TEST_SUITE(AES)
BOOST_AUTO_TEST_CASE(AesDecrypt) BOOST_AUTO_TEST_CASE(AesDecrypt)
{ {
cout << "AesDecrypt" << endl; cnote << "AesDecrypt";
bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621");
KeyPair kp(sha3Secure(aesDecrypt(&seed, "test"))); KeyPair kp(sha3Secure(aesDecrypt(&seed, "test")));
BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") == kp.address()); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") == kp.address());
@ -41,7 +42,7 @@ BOOST_AUTO_TEST_CASE(AesDecrypt)
BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed) BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed)
{ {
cout << "AesDecryptWrongSeed" << endl; cnote << "AesDecryptWrongSeed";
bytes seed = fromHex("badaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); bytes seed = fromHex("badaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621");
KeyPair kp(sha3Secure(aesDecrypt(&seed, "test"))); KeyPair kp(sha3Secure(aesDecrypt(&seed, "test")));
BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address()); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address());
@ -49,7 +50,7 @@ BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed)
BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword) BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword)
{ {
cout << "AesDecryptWrongPassword" << endl; cnote << "AesDecryptWrongPassword";
bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621");
KeyPair kp(sha3Secure(aesDecrypt(&seed, "badtest"))); KeyPair kp(sha3Secure(aesDecrypt(&seed, "badtest")));
BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address()); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address());
@ -57,24 +58,23 @@ BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword)
BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed) BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed)
{ {
cout << "AesDecryptFailInvalidSeed" << endl; cnote << "AesDecryptFailInvalidSeed";
bytes seed = fromHex("xdbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); bytes seed = fromHex("xdbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621");
BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test"));
} }
BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeedSize) BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeedSize)
{ {
cout << "AesDecryptFailInvalidSeedSize" << endl; cnote << "AesDecryptFailInvalidSeedSize";
bytes seed = fromHex("000102030405060708090a0b0c0d0e0f"); bytes seed = fromHex("000102030405060708090a0b0c0d0e0f");
BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test"));
} }
BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed2) BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed2)
{ {
cout << "AesDecryptFailInvalidSeed2" << endl; cnote << "AesDecryptFailInvalidSeed2";
bytes seed = fromHex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); bytes seed = fromHex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f");
BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test"));
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

2
test/libdevcrypto/hexPrefix.cpp

@ -29,7 +29,7 @@
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/Base64.h> #include <libdevcore/Base64.h>
#include <libdevcore/TrieCommon.h> #include <libdevcore/TrieCommon.h>
#include "../TestHelper.h" #include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

100
test/libdevcrypto/trie.cpp

@ -27,7 +27,7 @@
#include <libdevcore/TrieDB.h> #include <libdevcore/TrieDB.h>
#include <libdevcore/TrieHash.h> #include <libdevcore/TrieHash.h>
#include "MemTrie.h" #include "MemTrie.h"
#include "../TestHelper.h" #include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
@ -315,35 +315,35 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
MemoryDB m; MemoryDB m;
GenericTrieDB<MemoryDB> t(&m); GenericTrieDB<MemoryDB> t(&m);
t.init(); // initialise as empty tree. t.init(); // initialise as empty tree.
cout << t; cnote << t;
cout << m; cnote << m;
cout << t.root() << endl; cnote << t.root();
cout << stringMapHash256(StringMap()) << endl; cnote << stringMapHash256(StringMap());
t.insert(string("tesz"), string("test")); t.insert(string("tesz"), string("test"));
cout << t; cnote << t;
cout << m; cnote << m;
cout << t.root() << endl; cnote << t.root();
cout << stringMapHash256({{"test", "test"}}) << endl; cnote << stringMapHash256({{"test", "test"}});
t.insert(string("tesa"), string("testy")); t.insert(string("tesa"), string("testy"));
cout << t; cnote << t;
cout << m; cnote << m;
cout << t.root() << endl; cnote << t.root();
cout << stringMapHash256({{"test", "test"}, {"te", "testy"}}) << endl; cnote << stringMapHash256({{"test", "test"}, {"te", "testy"}});
cout << t.at(string("test")) << endl; cnote << t.at(string("test"));
cout << t.at(string("te")) << endl; cnote << t.at(string("te"));
cout << t.at(string("t")) << endl; cnote << t.at(string("t"));
t.remove(string("te")); t.remove(string("te"));
cout << m; cnote << m;
cout << t.root() << endl; cnote << t.root();
cout << stringMapHash256({{"test", "test"}}) << endl; cnote << stringMapHash256({{"test", "test"}});
t.remove(string("test")); t.remove(string("test"));
cout << m; cnote << m;
cout << t.root() << endl; cnote << t.root();
cout << stringMapHash256(StringMap()) << endl; cnote << stringMapHash256(StringMap());
} }
{ {
MemoryDB m; MemoryDB m;
@ -351,37 +351,37 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
t.init(); // initialise as empty tree. t.init(); // initialise as empty tree.
t.insert(string("a"), string("A")); t.insert(string("a"), string("A"));
t.insert(string("b"), string("B")); t.insert(string("b"), string("B"));
cout << t; cnote << t;
cout << m; cnote << m;
cout << t.root() << endl; cnote << t.root();
cout << stringMapHash256({{"b", "B"}, {"a", "A"}}) << endl; cnote << stringMapHash256({{"b", "B"}, {"a", "A"}});
bytes r(stringMapRlp256({{"b", "B"}, {"a", "A"}})); bytes r(stringMapRlp256({{"b", "B"}, {"a", "A"}}));
cout << RLP(r) << endl; cnote << RLP(r);
} }
{ {
MemTrie t; MemTrie t;
t.insert("dog", "puppy"); t.insert("dog", "puppy");
cout << hex << t.hash256() << endl; cnote << hex << t.hash256();
bytes r(t.rlp()); bytes r(t.rlp());
cout << RLP(r) << endl; cnote << RLP(r);
} }
{ {
MemTrie t; MemTrie t;
t.insert("bed", "d"); t.insert("bed", "d");
t.insert("be", "e"); t.insert("be", "e");
cout << hex << t.hash256() << endl; cnote << hex << t.hash256();
bytes r(t.rlp()); 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; MemTrie t;
t.insert("dog", "puppy"); t.insert("dog", "puppy");
t.insert("doe", "reindeer"); t.insert("doe", "reindeer");
cout << hex << t.hash256() << endl; cnote << hex << t.hash256();
bytes r(t.rlp()); bytes r(t.rlp());
cout << RLP(r) << endl; cnote << RLP(r);
cout << toHex(t.rlp()) << endl; cnote << toHex(t.rlp());
} }
{ {
MemoryDB m; MemoryDB m;
@ -397,12 +397,12 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
t.insert(a, b); t.insert(a, b);
s[a] = b; s[a] = b;
cout << endl << "-------------------------------" << endl; cnote << "/n-------------------------------";
cout << a << " -> " << b << endl; cnote << a << " -> " << b;
cout << d; cnote << d;
cout << m; cnote << m;
cout << d.root() << endl; cnote << d.root();
cout << stringMapHash256(s) << endl; cnote << stringMapHash256(s);
BOOST_REQUIRE(d.check(true)); BOOST_REQUIRE(d.check(true));
BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s)); BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s));
@ -421,12 +421,12 @@ BOOST_AUTO_TEST_CASE(moreTrieTests)
t.remove(a); t.remove(a);
d.remove(string(a)); d.remove(string(a));
/*cout << endl << "-------------------------------" << endl; /*cnote << endl << "-------------------------------";
cout << "X " << a << endl; cnote << "X " << a;
cout << d; cnote << d;
cout << m; cnote << m;
cout << d.root() << endl; cnote << d.root();
cout << hash256(s) << endl;*/ cnote << hash256(s);*/
BOOST_REQUIRE(d.check(true)); BOOST_REQUIRE(d.check(true));
BOOST_REQUIRE(t.at(a).empty()); BOOST_REQUIRE(t.at(a).empty());
@ -559,9 +559,11 @@ BOOST_AUTO_TEST_CASE(trieStess)
// for (auto i: dm2.get()) // for (auto i: dm2.get())
// cwarn << i.first << ": " << RLP(i.second); // cwarn << i.first << ": " << RLP(i.second);
d2.debugStructure(cerr); d2.debugStructure(cerr);
g_logVerbosity = 99; if (g_logVerbosity != -1)
g_logVerbosity = 99;
d2.remove(k); d2.remove(k);
g_logVerbosity = 4; if (g_logVerbosity != -1)
g_logVerbosity = 4;
cwarn << "Good?" << d2.root(); cwarn << "Good?" << d2.root();
} }

2
test/libethcore/dagger.cpp

@ -25,7 +25,7 @@
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethcore/EthashAux.h> #include <libethcore/EthashAux.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "../TestHelper.h" #include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

72
test/libethereum/blockchain.cpp

@ -53,6 +53,7 @@ mArray importUncles(mObject const& _blObj, vector<BlockHeader>& _vBiUncles, vect
void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
{ {
string testname;
for (auto& i: _v.get_obj()) for (auto& i: _v.get_obj())
{ {
mObject& o = i.second.get_obj(); mObject& o = i.second.get_obj();
@ -62,7 +63,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
continue; continue;
} }
cerr << i.first << endl; cnote << i.first;
testname = "(" + i.first + ") ";
TBOOST_REQUIRE(o.count("genesisBlockHeader")); TBOOST_REQUIRE(o.count("genesisBlockHeader"));
TBOOST_REQUIRE(o.count("pre")); TBOOST_REQUIRE(o.count("pre"));
@ -81,7 +83,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
if (_fillin) if (_fillin)
biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj(), trueState.rootHash()); biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj(), trueState.rootHash());
else 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) if (_fillin)
{ {
@ -381,24 +383,24 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
if (importedAndBest) if (importedAndBest)
{ {
//Check the fields restored from RLP to original fields //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.headerHash(WithProof) == blockFromRlp.headerHash(WithProof)), testname + "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.parentHash() == blockFromRlp.parentHash()), testname + "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.sha3Uncles() == blockFromRlp.sha3Uncles()), testname + "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.beneficiary() == blockFromRlp.beneficiary()), testname + "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.stateRoot() == blockFromRlp.stateRoot()), testname + "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.transactionsRoot() == blockFromRlp.transactionsRoot()), testname + "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.receiptsRoot() == blockFromRlp.receiptsRoot()), testname + "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.logBloom() == blockFromRlp.logBloom()), testname + "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.difficulty() == blockFromRlp.difficulty()), testname + "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.number() == blockFromRlp.number()), testname + "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.gasLimit() == blockFromRlp.gasLimit()),"testname + 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.gasUsed() == blockFromRlp.gasUsed()), testname + "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.timestamp() == blockFromRlp.timestamp()), testname + "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.extraData() == blockFromRlp.extraData()), testname + "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.mixHash() == blockFromRlp.mixHash()), testname + "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.nonce() == blockFromRlp.nonce()), testname + "nonce in given RLP not matching the block nonce!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields == blockFromRlp), "However, blockHeaderFromFields != blockFromRlp!"); TBOOST_CHECK_MESSAGE((blockHeaderFromFields == blockFromRlp), testname + "However, blockHeaderFromFields != blockFromRlp!");
//Check transaction list //Check transaction list
@ -445,18 +447,18 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
for (size_t i = 0; i < txsFromField.size(); ++i) 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].data() == txsFromRlp[i].data()), testname + "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].gas() == txsFromRlp[i].gas()), testname + "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].gasPrice() == txsFromRlp[i].gasPrice()), testname + "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].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), "transaction r 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), "transaction s 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), "transaction v 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()), "transaction receiveAddress 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()), "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]), "transactions from rlp and transaction from 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()), "transactions rlp do not match"); TBOOST_CHECK_MESSAGE((txsFromField[i].rlp() == txsFromRlp[i].rlp()), testname + "transactions rlp do not match");
} }
// check uncle list // check uncle list
@ -477,7 +479,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
} }
catch(...) catch(...)
{ {
TBOOST_ERROR("invalid uncle header"); TBOOST_ERROR(testname + "invalid uncle header");
} }
uBlHsFromField.push_back(uncleBlockHeader); uBlHsFromField.push_back(uncleBlockHeader);
} }
@ -494,13 +496,13 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
TBOOST_REQUIRE_EQUAL(uBlHsFromField.size(), uBlHsFromRlp.size()); TBOOST_REQUIRE_EQUAL(uBlHsFromField.size(), uBlHsFromRlp.size());
for (size_t i = 0; i < uBlHsFromField.size(); ++i) 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 }//importedAndBest
}//all blocks }//all blocks
TBOOST_REQUIRE((o.count("lastblockhash") > 0)); TBOOST_REQUIRE((o.count("lastblockhash") > 0));
TBOOST_CHECK_MESSAGE((toString(trueBc.info().hash()) == o["lastblockhash"].get_str()), 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());
} }
} }
} }

8
test/libethereum/gaspricer.cpp

@ -55,13 +55,13 @@ BOOST_AUTO_TEST_CASE(trivialGasPricer)
{ {
cnote << "trivialGasPricer"; cnote << "trivialGasPricer";
std::shared_ptr<dev::eth::GasPricer> gp(new TrivialGasPricer); std::shared_ptr<dev::eth::GasPricer> gp(new TrivialGasPricer);
BOOST_CHECK_EQUAL(gp->ask(Block()), c_defaultGasPrice); BOOST_CHECK_EQUAL(gp->ask(Block()), DefaultGasPrice);
BOOST_CHECK_EQUAL(gp->bid(), c_defaultGasPrice); BOOST_CHECK_EQUAL(gp->bid(), DefaultGasPrice);
bytes bl = CanonBlockChain<Ethash>::createGenesisBlock(); bytes bl = CanonBlockChain<Ethash>::createGenesisBlock();
gp->update(FullBlockChain<Ethash>(bl, AccountMap(), TransientDirectory().path(), WithExisting::Kill)); gp->update(FullBlockChain<Ethash>(bl, AccountMap(), TransientDirectory().path(), WithExisting::Kill));
BOOST_CHECK_EQUAL(gp->ask(Block()), c_defaultGasPrice); BOOST_CHECK_EQUAL(gp->ask(Block()), DefaultGasPrice);
BOOST_CHECK_EQUAL(gp->bid(), c_defaultGasPrice); BOOST_CHECK_EQUAL(gp->bid(), DefaultGasPrice);
} }
BOOST_AUTO_TEST_CASE(basicGasPricerNoUpdate) BOOST_AUTO_TEST_CASE(basicGasPricerNoUpdate)

4
test/libethereum/genesis.cpp

@ -21,11 +21,13 @@
*/ */
#include <fstream> #include <fstream>
#include <random>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include "../JsonSpiritHeaders.h" #include "../JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
#include "../TestHelper.h" #include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

22
test/libethereum/state.cpp

@ -41,6 +41,7 @@ namespace dev { namespace test {
void doStateTests(json_spirit::mValue& v, bool _fillin) void doStateTests(json_spirit::mValue& v, bool _fillin)
{ {
string testname;
for (auto& i: v.get_obj()) for (auto& i: v.get_obj())
{ {
mObject& o = i.second.get_obj(); mObject& o = i.second.get_obj();
@ -50,10 +51,12 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
continue; continue;
} }
std::cout << " " << i.first << std::endl; cnote << i.first;
TBOOST_REQUIRE((o.count("env") > 0)); testname = "(" + i.first + ") ";
TBOOST_REQUIRE((o.count("pre") > 0));
TBOOST_REQUIRE((o.count("transaction") > 0)); 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); ImportTest importer(o, _fillin);
const State importedStatePost = importer.m_statePost; const State importedStatePost = importer.m_statePost;
@ -66,9 +69,10 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
if (_fillin) if (_fillin)
{ {
#if ETH_FATDB #if ETH_FATDB
importer.exportTest(output); if (importer.exportTest(output))
cerr << testname << endl;
#else #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 #endif
} }
else else
@ -86,7 +90,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
#if ETH_FATDB #if ETH_FATDB
ImportTest::compareStates(importer.m_statePost, importedStatePost); ImportTest::compareStates(importer.m_statePost, importedStatePost);
#endif #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) 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) catch (std::exception const& _e)
{ {
BOOST_ERROR("Failed test with Exception: " << _e.what()); BOOST_ERROR(path.filename().string() + "Failed test with Exception: " << _e.what());
} }
} }
} }

2
test/libethereum/stateOriginal.cpp

@ -20,6 +20,7 @@
* State test functions. * State test functions.
*/ */
#include <test/TestHelper.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
@ -27,7 +28,6 @@
#include <libethcore/Farm.h> #include <libethcore/Farm.h>
#include <libethcore/BasicAuthority.h> #include <libethcore/BasicAuthority.h>
#include <libethereum/Defaults.h> #include <libethereum/Defaults.h>
#include <test/TestHelper.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

40
test/libethereum/transactionTests.cpp

@ -32,6 +32,7 @@ namespace dev { namespace test {
void doTransactionTests(json_spirit::mValue& _v, bool _fillin) void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{ {
string testname;
for (auto& i: _v.get_obj()) for (auto& i: _v.get_obj())
{ {
mObject& o = i.second.get_obj(); mObject& o = i.second.get_obj();
@ -41,7 +42,8 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
continue; continue;
} }
cerr << i.first << endl; testname = "(" + i.first + ") ";
cnote << testname;
if (_fillin) if (_fillin)
{ {
TBOOST_REQUIRE((o.count("transaction") > 0)); TBOOST_REQUIRE((o.count("transaction") > 0));
@ -55,7 +57,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{ {
Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything); Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything);
if (!txFromFields.signature().isValid()) 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["sender"] = toString(txFromFields.sender());
o["transaction"] = ImportTest::makeAllFieldsHex(tObj); o["transaction"] = ImportTest::makeAllFieldsHex(tObj);
@ -69,9 +71,9 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{ {
bool expectInValid = (o["expect"].get_str() == "invalid"); bool expectInValid = (o["expect"].get_str() == "invalid");
if (Options::get().checkState) 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 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")); o.erase(o.find("expect"));
} }
@ -82,9 +84,9 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{ {
bool expectValid = (o["expect"].get_str() == "valid"); bool expectValid = (o["expect"].get_str() == "valid");
if (Options::get().checkState) 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 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")); o.erase(o.find("expect"));
} }
@ -99,39 +101,39 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
RLP rlp(stream); RLP rlp(stream);
txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything); txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything);
if (!txFromRlp.signature().isValid()) 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) catch(Exception const& _e)
{ {
cnote << i.first; cnote << i.first;
cnote << "Transaction Exception: " << diagnostic_information(_e); 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; continue;
} }
catch(...) 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; 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(); mObject tObj = o["transaction"].get_obj();
Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckTransaction::Everything); Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckTransaction::Everything);
//Check the fields restored from RLP to original fields //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.data() == txFromRlp.data()), testname + "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.value() == txFromRlp.value()), testname + "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.gasPrice() == txFromRlp.gasPrice()), testname + "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.gas() == txFromRlp.gas()), testname + "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.nonce() == txFromRlp.nonce()), testname + "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.receiveAddress() == txFromRlp.receiveAddress()), testname + "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.sender() == txFromRlp.sender()), testname + "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
TBOOST_CHECK_MESSAGE((txFromFields == txFromRlp), "However, txFromFields != txFromRlp!"); TBOOST_CHECK_MESSAGE((txFromFields == txFromRlp), testname + "However, txFromFields != txFromRlp!");
TBOOST_REQUIRE ((o.count("sender") > 0)); TBOOST_REQUIRE ((o.count("sender") > 0));
Address addressReaded = Address(o["sender"].get_str()); 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 }//for
}//doTransactionTests }//doTransactionTests

124
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": { "BlockNumberDynamicJumpiAfterStop": {
"env" : { "env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

15
test/libevm/vm.cpp

@ -296,6 +296,7 @@ namespace dev { namespace test {
void doVMTests(json_spirit::mValue& v, bool _fillin) void doVMTests(json_spirit::mValue& v, bool _fillin)
{ {
string testname;
for (auto& i: v.get_obj()) for (auto& i: v.get_obj())
{ {
mObject& o = i.second.get_obj(); mObject& o = i.second.get_obj();
@ -305,10 +306,12 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
continue; continue;
} }
std::cout << " " << i.first << "\n"; cnote << i.first;
TBOOST_REQUIRE((o.count("env") > 0)); testname = "(" + i.first + ") ";
TBOOST_REQUIRE((o.count("pre") > 0));
TBOOST_REQUIRE((o.count("exec") > 0)); 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{}); FakeExtVM fev(eth::EnvInfo{});
fev.importEnv(o["env"].get_obj()); fev.importEnv(o["env"].get_obj());
@ -338,7 +341,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
} }
catch (VMException const&) catch (VMException const&)
{ {
std::cout << " Safe VM Exception\n"; cnote << " Safe VM Exception\n";
vmExceptionOccured = true; vmExceptionOccured = true;
} }
catch (Exception const& _e) catch (Exception const& _e)
@ -535,7 +538,7 @@ BOOST_AUTO_TEST_CASE(vmRandom)
{ {
try try
{ {
std::cout << "TEST " << path.filename() << "\n"; cnote << "TEST " << path.filename();
json_spirit::mValue v; json_spirit::mValue v;
string s = asString(dev::contents(path.string())); 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?"); 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?");

2
test/libevm/vm.h

@ -26,6 +26,7 @@ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
#include <fstream> #include <fstream>
#include <cstdint> #include <cstdint>
#include <test/TestHelper.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <json_spirit/json_spirit.h> #include <json_spirit/json_spirit.h>
@ -38,7 +39,6 @@ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
#include <libethereum/Transaction.h> #include <libethereum/Transaction.h>
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include <libethereum/State.h> #include <libethereum/State.h>
#include <test/TestHelper.h>
namespace dev { namespace test { namespace dev { namespace test {

4
test/libp2p/capability.cpp

@ -102,7 +102,9 @@ BOOST_AUTO_TEST_CASE(capability)
if (test::Options::get().nonetwork) if (test::Options::get().nonetwork)
return; return;
VerbosityHolder verbosityHolder(10); if (g_logVerbosity != -1)
VerbosityHolder verbosityHolder(10);
cnote << "Testing Capability..."; cnote << "Testing Capability...";
const char* const localhost = "127.0.0.1"; const char* const localhost = "127.0.0.1";

10
test/libp2p/peer.cpp

@ -43,7 +43,9 @@ BOOST_AUTO_TEST_CASE(host)
if (test::Options::get().nonetwork) if (test::Options::get().nonetwork)
return; return;
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
NetworkPreferences host1prefs("127.0.0.1", 30321, false); NetworkPreferences host1prefs("127.0.0.1", 30321, false);
NetworkPreferences host2prefs("127.0.0.1", 30322, false); NetworkPreferences host2prefs("127.0.0.1", 30322, false);
Host host1("Test", host1prefs); Host host1("Test", host1prefs);
@ -88,7 +90,8 @@ BOOST_AUTO_TEST_CASE(saveNodes)
if (test::Options::get().nonetwork) if (test::Options::get().nonetwork)
return; return;
VerbosityHolder reduceVerbosity(2); if (g_logVerbosity != -1)
VerbosityHolder reduceVerbosity(2);
std::list<Host*> hosts; std::list<Host*> hosts;
unsigned const c_step = 10; unsigned const c_step = 10;
@ -152,7 +155,8 @@ BOOST_AUTO_TEST_CASE(requirePeer)
if (test::Options::get().nonetwork) if (test::Options::get().nonetwork)
return; return;
VerbosityHolder temporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder reduceVerbosity(10);
unsigned const step = 10; unsigned const step = 10;
const char* const localhost = "127.0.0.1"; const char* const localhost = "127.0.0.1";

4
test/libsolidity/solidityExecutionFramework.h

@ -44,7 +44,9 @@ class ExecutionFramework
public: public:
ExecutionFramework() ExecutionFramework()
{ {
g_logVerbosity = 0; if (g_logVerbosity != -1)
g_logVerbosity = 0;
//m_state.resetCurrent();
} }
bytes const& compileAndRunWithoutCheck( bytes const& compileAndRunWithoutCheck(

12
test/libwhisper/bloomFilter.cpp

@ -106,7 +106,9 @@ BOOST_AUTO_TEST_SUITE(bloomFilter)
BOOST_AUTO_TEST_CASE(falsePositiveRate) BOOST_AUTO_TEST_CASE(falsePositiveRate)
{ {
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing Bloom Filter False Positive Rate..."; cnote << "Testing Bloom Filter False Positive Rate...";
TopicBloomFilterTest f; TopicBloomFilterTest f;
@ -124,7 +126,9 @@ BOOST_AUTO_TEST_CASE(falsePositiveRate)
BOOST_AUTO_TEST_CASE(bloomFilterRandom) BOOST_AUTO_TEST_CASE(bloomFilterRandom)
{ {
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing Bloom Filter matching..."; cnote << "Testing Bloom Filter matching...";
TopicBloomFilterShort f; TopicBloomFilterShort f;
@ -150,7 +154,9 @@ BOOST_AUTO_TEST_CASE(bloomFilterRandom)
BOOST_AUTO_TEST_CASE(bloomFilterRaw) BOOST_AUTO_TEST_CASE(bloomFilterRaw)
{ {
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing Raw Bloom matching..."; cnote << "Testing Raw Bloom matching...";
TopicBloomFilterShort f; TopicBloomFilterShort f;

20
test/libwhisper/whisperDB.cpp

@ -41,7 +41,9 @@ BOOST_FIXTURE_TEST_SUITE(whisperDB, P2PFixture)
BOOST_AUTO_TEST_CASE(basic) BOOST_AUTO_TEST_CASE(basic)
{ {
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing Whisper DB..."; cnote << "Testing Whisper DB...";
string s; string s;
@ -86,7 +88,9 @@ BOOST_AUTO_TEST_CASE(basic)
BOOST_AUTO_TEST_CASE(persistence) BOOST_AUTO_TEST_CASE(persistence)
{ {
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing persistence of Whisper DB..."; cnote << "Testing persistence of Whisper DB...";
string s; string s;
@ -135,7 +139,9 @@ BOOST_AUTO_TEST_CASE(messages)
return; return;
cnote << "Testing load/save Whisper messages..."; cnote << "Testing load/save Whisper messages...";
VerbosityHolder setTemporaryLevel(2); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(2);
unsigned const TestSize = 3; unsigned const TestSize = 3;
map<h256, Envelope> m1; map<h256, Envelope> m1;
map<h256, Envelope> preexisting; map<h256, Envelope> preexisting;
@ -193,7 +199,9 @@ BOOST_AUTO_TEST_CASE(corruptedData)
return; return;
cnote << "Testing corrupted data..."; cnote << "Testing corrupted data...";
VerbosityHolder setTemporaryLevel(2); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(2);
map<h256, Envelope> m; map<h256, Envelope> m;
h256 x = h256::random(); h256 x = h256::random();
@ -222,7 +230,9 @@ BOOST_AUTO_TEST_CASE(filters)
return; return;
cnote << "Testing filters saving..."; cnote << "Testing filters saving...";
VerbosityHolder setTemporaryLevel(2); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(2);
h256 persistID(0xC0FFEE); h256 persistID(0xC0FFEE);
{ {

7
test/libwhisper/whisperMessage.cpp

@ -82,7 +82,9 @@ BOOST_AUTO_TEST_SUITE(whisperMessage)
BOOST_AUTO_TEST_CASE(seal) BOOST_AUTO_TEST_CASE(seal)
{ {
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing Envelope encryption..."; cnote << "Testing Envelope encryption...";
for (unsigned int i = 1; i < 10; ++i) for (unsigned int i = 1; i < 10; ++i)
@ -91,7 +93,8 @@ BOOST_AUTO_TEST_CASE(seal)
BOOST_AUTO_TEST_CASE(work) BOOST_AUTO_TEST_CASE(work)
{ {
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing proof of work..."; cnote << "Testing proof of work...";
Secret zero; Secret zero;

8
test/libwhisper/whisperTopic.cpp

@ -47,7 +47,8 @@ BOOST_AUTO_TEST_CASE(topic)
return; return;
cnote << "Testing Whisper..."; cnote << "Testing Whisper...";
VerbosityHolder setTemporaryLevel(0); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(0);
uint16_t port1 = 30311; uint16_t port1 = 30311;
Host host1("Test", NetworkPreferences("127.0.0.1", port1, false)); 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. // Host must be configured not to share peers.
uint16_t port2 = 30313; uint16_t port2 = 30313;
Host host2("Forwarder", NetworkPreferences("127.0.0.1", port2, false)); Host host2("Forwarder", NetworkPreferences("127.0.0.1", port2, false));
@ -392,7 +394,9 @@ BOOST_AUTO_TEST_CASE(selfAddressed)
if (test::Options::get().nonetwork) if (test::Options::get().nonetwork)
return; return;
VerbosityHolder setTemporaryLevel(10); if (g_logVerbosity != -1)
VerbosityHolder setTemporaryLevel(10);
cnote << "Testing self-addressed messaging with bloom filter matching..."; cnote << "Testing self-addressed messaging with bloom filter matching...";
char const* text = "deterministic pseudorandom test"; char const* text = "deterministic pseudorandom test";

Loading…
Cancel
Save