Browse Source

Merge branch 'develop' into discovery

cl-refactor
subtly 10 years ago
parent
commit
c27ff03eaf
  1. 1
      CMakeLists.txt
  2. 3
      alethzero/CMakeLists.txt
  3. 8
      alethzero/Context.h
  4. 4
      alethzero/Debugger.cpp
  5. 4
      alethzero/DownloadView.cpp
  6. 4
      alethzero/ExportState.cpp
  7. 121
      alethzero/Main.ui
  8. 249
      alethzero/MainWin.cpp
  9. 20
      alethzero/MainWin.h
  10. 6
      alethzero/OurWebThreeStubServer.cpp
  11. 14
      alethzero/Transact.cpp
  12. 16
      cmake/EthCompilerSettings.cmake
  13. 12
      eth/main.cpp
  14. 2
      evmjit/libevmjit-cpp/Env.cpp
  15. 14
      libdevcore/Common.cpp
  16. 57
      libdevcore/Common.h
  17. 1
      libdevcore/Exceptions.h
  18. 5
      libdevcore/FixedHash.h
  19. 13
      libdevcore/Guards.h
  20. 4
      libdevcore/Log.cpp
  21. 2
      libethcore/BlockInfo.cpp
  22. 2
      libethcore/CMakeLists.txt
  23. 12
      libethcore/EthashAux.cpp
  24. 2
      libethcore/ICAP.h
  25. 36
      libethcore/Params.cpp
  26. 37
      libethcore/Params.h
  27. 7
      libethereum/BlockChain.cpp
  28. 20
      libethereum/BlockChain.h
  29. 13
      libethereum/BlockDetails.h
  30. 26
      libethereum/BlockQueue.cpp
  31. 8
      libethereum/BlockQueue.h
  32. 1
      libethereum/CanonBlockChain.cpp
  33. 24
      libethereum/Client.cpp
  34. 7
      libethereum/Client.h
  35. 5
      libethereum/ClientBase.cpp
  36. 2
      libethereum/ClientBase.h
  37. 2
      libethereum/DownloadMan.cpp
  38. 3
      libethereum/DownloadMan.h
  39. 2
      libethereum/EthereumHost.cpp
  40. 19
      libethereum/EthereumPeer.cpp
  41. 3
      libethereum/Interface.h
  42. 2
      libethereum/Precompiled.cpp
  43. 1
      libethereum/State.h
  44. 2
      libethereum/Transaction.h
  45. 1
      libethereum/TransactionQueue.cpp
  46. 2
      libevm/VM.h
  47. 4
      libevmasm/Assembly.cpp
  48. 4
      libevmasm/Assembly.h
  49. 0
      libevmasm/AssemblyItem.cpp
  50. 2
      libevmasm/AssemblyItem.h
  51. 33
      libevmasm/CMakeLists.txt
  52. 4
      libevmasm/CommonSubexpressionEliminator.cpp
  53. 4
      libevmasm/CommonSubexpressionEliminator.h
  54. 8
      libevmasm/ControlFlowGraph.cpp
  55. 0
      libevmasm/ControlFlowGraph.h
  56. 36
      libevmasm/Exceptions.h
  57. 6
      libevmasm/ExpressionClasses.cpp
  58. 2
      libevmasm/ExpressionClasses.h
  59. 4
      libevmasm/SemanticInformation.cpp
  60. 0
      libevmasm/SemanticInformation.h
  61. 0
      libevmasm/SourceLocation.h
  62. 4
      libevmcore/CMakeLists.txt
  63. 7
      libevmcore/Exceptions.h
  64. 69
      libevmcore/Params.cpp
  65. 69
      libevmcore/Params.h
  66. 2
      libjsqrc/setup.js
  67. 3
      liblll/CMakeLists.txt
  68. 2
      liblll/CodeFragment.h
  69. 6
      libp2p/Host.cpp
  70. 28
      libsolidity/AST.cpp
  71. 2
      libsolidity/AST.h
  72. 2
      libsolidity/ASTUtils.h
  73. 2
      libsolidity/CMakeLists.txt
  74. 7
      libsolidity/Compiler.cpp
  75. 2
      libsolidity/Compiler.h
  76. 2
      libsolidity/CompilerContext.h
  77. 42
      libsolidity/DeclarationContainer.cpp
  78. 4
      libsolidity/DeclarationContainer.h
  79. 18
      libsolidity/Exceptions.h
  80. 2
      libsolidity/ExpressionCompiler.h
  81. 2
      libsolidity/LValue.h
  82. 37
      libsolidity/NameAndTypeResolver.cpp
  83. 2
      libsolidity/Parser.cpp
  84. 2
      libsolidity/Scanner.h
  85. 74
      libsolidity/SourceReferenceFormatter.cpp
  86. 12
      libsolidity/SourceReferenceFormatter.h
  87. 2
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  88. 14
      mix/ClientModel.cpp
  89. 96
      mix/CodeModel.cpp
  90. 22
      mix/CodeModel.h
  91. 1
      mix/MixClient.cpp
  92. 2
      mix/QBasicNodeDefinition.h
  93. 2
      mix/qml/StateDialog.qml
  94. 5
      mix/qml/html/codeeditor.js
  95. 3
      mix/qml/js/Debugger.js
  96. 2
      mix/test/qml/js/TestTutorial.js
  97. 48
      solc/CommandLineInterface.cpp
  98. 1
      solc/CommandLineInterface.h
  99. 55
      test/libp2p/peer.cpp
  100. 6
      test/libsolidity/Assembly.cpp

1
CMakeLists.txt

@ -305,6 +305,7 @@ endif()
add_subdirectory(libdevcore) add_subdirectory(libdevcore)
add_subdirectory(libevmcore) add_subdirectory(libevmcore)
add_subdirectory(libevmasm)
add_subdirectory(liblll) add_subdirectory(liblll)
if (SERPENT) if (SERPENT)

3
alethzero/CMakeLists.txt

@ -55,8 +55,7 @@ target_link_libraries(${EXECUTABLE} lll)
if (SOLIDITY) if (SOLIDITY)
target_link_libraries(${EXECUTABLE} solidity) target_link_libraries(${EXECUTABLE} solidity)
endif () endif ()
target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmasm)
target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} web3jsonrpc)
target_link_libraries(${EXECUTABLE} jsqrc) target_link_libraries(${EXECUTABLE} jsqrc)
target_link_libraries(${EXECUTABLE} natspec) target_link_libraries(${EXECUTABLE} natspec)

8
alethzero/Context.h

@ -59,10 +59,10 @@ class Context
public: public:
virtual ~Context(); virtual ~Context();
virtual QString pretty(dev::Address _a) const = 0; virtual std::string pretty(dev::Address const& _a) const = 0;
virtual QString prettyU256(dev::u256 _n) const = 0; virtual std::string prettyU256(dev::u256 const& _n) const = 0;
virtual QString render(dev::Address _a) const = 0; virtual std::pair<dev::Address, dev::bytes> fromString(std::string const& _a) const = 0;
virtual std::pair<dev::Address, dev::bytes> fromString(QString const& _a) const = 0;
virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0; virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0;
virtual std::string render(dev::Address const& _a) const = 0;
}; };

4
alethzero/Debugger.cpp

@ -226,7 +226,7 @@ void Debugger::update()
QString stack; QString stack;
for (auto i: ws.stack) for (auto i: ws.stack)
stack.prepend("<div>" + m_context->prettyU256(i) + "</div>"); stack.prepend("<div>" + QString::fromStdString(m_context->prettyU256(i)) + "</div>");
ui->debugStack->setHtml(stack); ui->debugStack->setHtml(stack);
ui->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true))); ui->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true)));
assert(m_session.codes.count(ws.code)); assert(m_session.codes.count(ws.code));
@ -246,7 +246,7 @@ void Debugger::update()
ui->debugStateInfo->setText(QString::fromStdString(ss.str())); ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
stringstream s; stringstream s;
for (auto const& i: ws.storage) for (auto const& i: ws.storage)
s << "@" << m_context->prettyU256(i.first).toStdString() << "&nbsp;&nbsp;&nbsp;&nbsp;" << m_context->prettyU256(i.second).toStdString() << "<br/>"; s << "@" << m_context->prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << m_context->prettyU256(i.second) << "<br/>";
ui->debugStorage->setHtml(QString::fromStdString(s.str())); ui->debugStorage->setHtml(QString::fromStdString(s.str()));
} }
} }

4
alethzero/DownloadView.cpp

@ -39,13 +39,13 @@ void DownloadView::paintEvent(QPaintEvent*)
QPainter p(this); QPainter p(this);
p.fillRect(rect(), Qt::white); p.fillRect(rect(), Qt::white);
if (!m_man || m_man->chain().empty() || !m_man->subCount()) if (!m_man || m_man->chainEmpty() || !m_man->subCount())
return; return;
double ratio = (double)rect().width() / rect().height(); double ratio = (double)rect().width() / rect().height();
if (ratio < 1) if (ratio < 1)
ratio = 1 / ratio; ratio = 1 / ratio;
double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chain().size() / ratio))); double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chainSize() / ratio)));
// QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n)); // QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n));
QSizeF area(n, n); QSizeF area(n, n);

4
alethzero/ExportState.cpp

@ -129,8 +129,8 @@ void ExportStateDialog::fillContracts()
ui->contracts->setEnabled(true); ui->contracts->setEnabled(true);
for (auto i: ethereum()->addresses(m_block)) for (auto i: ethereum()->addresses(m_block))
{ {
QString r = m_main->render(i); string r = m_main->render(i);
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? ui->accounts : ui->contracts)) (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ethereum()->codeAt(i).empty() ? ui->accounts : ui->contracts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
} }
} }

121
alethzero/Main.ui

@ -53,23 +53,23 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="balance"> <widget class="QLabel" name="blockCount">
<property name="text"> <property name="text">
<string>0 wei</string> <string>1 block</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="peerCount"> <widget class="QLabel" name="balance">
<property name="text"> <property name="text">
<string>0 peers</string> <string>0 wei</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="blockCount"> <widget class="QLabel" name="peerCount">
<property name="text"> <property name="text">
<string>1 block</string> <string>0 peers</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -160,8 +160,8 @@
<addaction name="killAccount"/> <addaction name="killAccount"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="loadJS"/> <addaction name="loadJS"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="exportState"/> <addaction name="exportState"/>
</widget> </widget>
<widget class="QMenu" name="menu_Help"> <widget class="QMenu" name="menu_Help">
<property name="title"> <property name="title">
@ -190,7 +190,6 @@
<string>&amp;View</string> <string>&amp;View</string>
</property> </property>
<addaction name="showAll"/> <addaction name="showAll"/>
<addaction name="showAllAccounts"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="preview"/> <addaction name="preview"/>
</widget> </widget>
@ -218,43 +217,6 @@
<addaction name="menu_Debug"/> <addaction name="menu_Debug"/>
</widget> </widget>
<widget class="QStatusBar" name="statusbar"/> <widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="dockWidget_accounts">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Accounts</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<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="accounts">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_3"> <widget class="QDockWidget" name="dockWidget_3">
<property name="features"> <property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set> <set>QDockWidget::DockWidgetFeatureMask</set>
@ -590,18 +552,21 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QDockWidget" name="dockWidget_contracts"> <widget class="QDockWidget" name="dockWidget_accounts">
<property name="features"> <property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set> <set>QDockWidget::DockWidgetFeatureMask</set>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Contracts</string> <string>Accounts</string>
</property> </property>
<attribute name="dockWidgetArea"> <attribute name="dockWidgetArea">
<number>2</number> <number>2</number>
</attribute> </attribute>
<widget class="QWidget" name="dockWidgetContents_6"> <widget class="QWidget" name="dockWidgetContents_6">
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -614,12 +579,66 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="accountsFilter">
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showBasic">
<property name="text">
<string>Basic</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showContracts">
<property name="text">
<string>Contracts</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<property name="text">
<string>Only Named</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshAccounts">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QSplitter" name="splitter_3"> <widget class="QSplitter" name="splitter_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QListWidget" name="contracts"> <widget class="QListWidget" name="accounts">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -633,7 +652,7 @@
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
</widget> </widget>
<widget class="QPlainTextEdit" name="contractInfo"> <widget class="QPlainTextEdit" name="accountInfo">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch> <horstretch>2</horstretch>
@ -1482,7 +1501,7 @@ font-size: 14pt</string>
</action> </action>
<action name="exportState"> <action name="exportState">
<property name="text"> <property name="text">
<string>&amp;Export State...</string> <string>&amp;Export State...</string>
</property> </property>
</action> </action>
<action name="debugStepBack"> <action name="debugStepBack">

249
alethzero/MainWin.cpp

@ -80,29 +80,29 @@ using namespace dev::p2p;
using namespace dev::eth; using namespace dev::eth;
namespace js = json_spirit; namespace js = json_spirit;
QString Main::fromRaw(h256 _n, unsigned* _inc) string Main::fromRaw(h256 _n, unsigned* _inc)
{ {
if (_n) if (_n)
{ {
string s((char const*)_n.data(), 32); string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0'); auto l = s.find_first_of('\0');
if (!l) if (!l)
return QString(); return string();
if (l != string::npos) if (l != string::npos)
{ {
auto p = s.find_first_not_of('\0', l); auto p = s.find_first_not_of('\0', l);
if (!(p == string::npos || (_inc && p == 31))) if (!(p == string::npos || (_inc && p == 31)))
return QString(); return string();
if (_inc) if (_inc)
*_inc = (byte)s[31]; *_inc = (byte)s[31];
s.resize(l); s.resize(l);
} }
for (auto i: s) for (auto i: s)
if (i < 32) if (i < 32)
return QString(); return string();
return QString::fromStdString(s); return s;
} }
return QString(); return string();
} }
QString contentsOfQResource(string const& res) QString contentsOfQResource(string const& res)
@ -143,11 +143,6 @@ Main::Main(QWidget *parent) :
// ui->log->addItem(QString::fromStdString(s)); // ui->log->addItem(QString::fromStdString(s));
}; };
#if !ETH_FATDB
delete ui->dockWidget_accounts;
delete ui->dockWidget_contracts;
#endif
#if ETH_DEBUG #if ETH_DEBUG
m_servers.append("127.0.0.1:30300"); m_servers.append("127.0.0.1:30300");
#endif #endif
@ -204,6 +199,9 @@ Main::Main(QWidget *parent) :
// QWebEngineInspector* inspector = new QWebEngineInspector(); // QWebEngineInspector* inspector = new QWebEngineInspector();
// inspector->setPage(page); // inspector->setPage(page);
readSettings(); readSettings();
#if !ETH_FATDB
removeDockWidget(ui->dockWidget_accounts);
#endif
installWatches(); installWatches();
startTimer(100); startTimer(100);
@ -398,7 +396,7 @@ void Main::onNewBlock()
// update blockchain dependent views. // update blockchain dependent views.
refreshBlockCount(); refreshBlockCount();
refreshBlockChain(); refreshBlockChain();
refreshAccounts(); ui->refreshAccounts->setEnabled(true);
// We must update balances since we can't filter updates to basic accounts. // We must update balances since we can't filter updates to basic accounts.
refreshBalances(); refreshBalances();
@ -410,7 +408,7 @@ void Main::onNewPending()
// update any pending-transaction dependent views. // update any pending-transaction dependent views.
refreshPending(); refreshPending();
refreshAccounts(); ui->refreshAccounts->setEnabled(true);
} }
void Main::on_forceMining_triggered() void Main::on_forceMining_triggered()
@ -510,33 +508,33 @@ static Public stringToPublic(QString const& _a)
return Public(); return Public();
} }
QString Main::pretty(dev::Address _a) const std::string Main::pretty(dev::Address const& _a) const
{ {
auto g_newNameReg = getNameReg(); auto g_newNameReg = getNameReg();
if (g_newNameReg) if (g_newNameReg)
{ {
QString s = QString::fromStdString(toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("getName(address)", _a)).output))); string n = toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("name(address)", _a)).output));
if (s.size()) if (!n.empty())
return s; return n;
} }
return QString(); return string();
} }
QString Main::render(dev::Address _a) const std::string Main::render(dev::Address const& _a) const
{ {
QString p = pretty(_a); string p = pretty(_a);
QString n; string n;
try { if (p.size() == 9 && p.find_first_not_of("QWERYUOPASDFGHJKLZXCVBNM1234567890") == string::npos)
n = QString::fromStdString(ICAP(_a).encoded()); p = ICAP(p, "XREG").encoded();
} else
catch (...) { DEV_IGNORE_EXCEPTIONS(n = ICAP(_a).encoded());
n = QString::fromStdString(_a.abridged()); if (n.empty())
} n = _a.abridged();
return p.isEmpty() ? n : (p + " " + n); return p.empty() ? n : (p + " " + n);
} }
pair<Address, bytes> Main::fromString(QString const& _n) const pair<Address, bytes> Main::fromString(std::string const& _n) const
{ {
if (_n == "(Create Contract)") if (_n == "(Create Contract)")
return make_pair(Address(), bytes()); return make_pair(Address(), bytes());
@ -544,7 +542,7 @@ pair<Address, bytes> Main::fromString(QString const& _n) const
auto g_newNameReg = getNameReg(); auto g_newNameReg = getNameReg();
if (g_newNameReg) if (g_newNameReg)
{ {
Address a = abiOut<Address>(ethereum()->call(g_newNameReg, abiIn("addr(bytes32)", ::toString32(_n.toStdString()))).output); Address a = abiOut<Address>(ethereum()->call(g_newNameReg, abiIn("addr(bytes32)", ::toString32(_n))).output);
if (a) if (a)
return make_pair(a, bytes()); return make_pair(a, bytes());
} }
@ -552,7 +550,7 @@ pair<Address, bytes> Main::fromString(QString const& _n) const
{ {
try try
{ {
return make_pair(Address(fromHex(_n.toStdString(), WhenError::Throw)), bytes()); return make_pair(Address(fromHex(_n, WhenError::Throw)), bytes());
} }
catch (BadHexCharacter& _e) catch (BadHexCharacter& _e)
{ {
@ -568,7 +566,7 @@ pair<Address, bytes> Main::fromString(QString const& _n) const
} }
else else
try { try {
return ICAP::decoded(_n.toStdString()).address([&](Address const& a, bytes const& b) -> bytes return ICAP::decoded(_n).address([&](Address const& a, bytes const& b) -> bytes
{ {
return ethereum()->call(a, b).output; return ethereum()->call(a, b).output;
}, g_newNameReg); }, g_newNameReg);
@ -600,7 +598,7 @@ QString Main::lookup(QString const& _a) const
return QString("%1.%2.%3.%4").arg((int)ret[28]).arg((int)ret[29]).arg((int)ret[30]).arg((int)ret[31]); return QString("%1.%2.%3.%4").arg((int)ret[28]).arg((int)ret[29]).arg((int)ret[30]).arg((int)ret[31]);
// TODO: support IPv6. // TODO: support IPv6.
else if (ret) else if (ret)
return fromRaw(ret); return QString::fromStdString(fromRaw(ret));
else else
return _a; return _a;
} }
@ -817,7 +815,7 @@ void Main::on_exportKey_triggered()
if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size()) if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size())
{ {
auto k = m_myKeys[ui->ourAccounts->currentRow()]; auto k = m_myKeys[ui->ourAccounts->currentRow()];
QMessageBox::information(this, "Export Account Key", "Secret key to account " + render(k.address()) + " is:\n" + QString::fromStdString(toHex(k.sec().ref()))); QMessageBox::information(this, "Export Account Key", "Secret key to account " + QString::fromStdString(render(k.address()) + " is:\n" + toHex(k.sec().ref())));
} }
} }
@ -936,7 +934,7 @@ void Main::refreshBalances()
for (auto i: m_myKeys) for (auto i: m_myKeys)
{ {
u256 b = ethereum()->balanceAt(i.address()); u256 b = ethereum()->balanceAt(i.address());
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(render(i.address())).arg((unsigned)ethereum()->countAt(i.address())), ui->ourAccounts)) (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(QString::fromStdString(render(i.address()))).arg((unsigned)ethereum()->countAt(i.address())), ui->ourAccounts))
->setData(Qt::UserRole, QByteArray((char const*)i.address().data(), Address::size)); ->setData(Qt::UserRole, QByteArray((char const*)i.address().data(), Address::size));
totalBalance += b; totalBalance += b;
@ -968,24 +966,24 @@ void Main::refreshNetwork()
map<h512, QString> sessions; map<h512, QString> sessions;
for (PeerSessionInfo const& i: ps) for (PeerSessionInfo const& i: ps)
ui->peers->addItem(QString("[%8 %7] %3 ms - %1:%2 - %4 %5 %6") ui->peers->addItem(QString("[%8 %7] %3 ms - %1:%2 - %4 %5 %6")
.arg(QString::fromStdString(i.host)) .arg(QString::fromStdString(i.host))
.arg(i.port) .arg(i.port)
.arg(chrono::duration_cast<chrono::milliseconds>(i.lastPing).count()) .arg(chrono::duration_cast<chrono::milliseconds>(i.lastPing).count())
.arg(sessions[i.id] = QString::fromStdString(i.clientVersion)) .arg(sessions[i.id] = QString::fromStdString(i.clientVersion))
.arg(QString::fromStdString(toString(i.caps))) .arg(QString::fromStdString(toString(i.caps)))
.arg(QString::fromStdString(toString(i.notes))) .arg(QString::fromStdString(toString(i.notes)))
.arg(i.socketId) .arg(i.socketId)
.arg(QString::fromStdString(i.id.abridged()))); .arg(QString::fromStdString(i.id.abridged())));
auto ns = web3()->nodes(); auto ns = web3()->nodes();
for (p2p::Peer const& i: ns) for (p2p::Peer const& i: ns)
ui->nodes->insertItem(sessions.count(i.id) ? 0 : ui->nodes->count(), QString("[%1 %3] %2 - ( =%5s | /%4s%6 ) - *%7 $%8") ui->nodes->insertItem(sessions.count(i.id) ? 0 : ui->nodes->count(), QString("[%1 %3] %2 - ( =%5s | /%4s%6 ) - *%7 $%8")
.arg(QString::fromStdString(i.id.abridged())) .arg(QString::fromStdString(i.id.abridged()))
.arg(QString::fromStdString(i.endpoint.address.to_string())) .arg(QString::fromStdString(i.endpoint.address.to_string()))
.arg(i.id == web3()->id() ? "self" : sessions.count(i.id) ? sessions[i.id] : "disconnected") .arg(i.id == web3()->id() ? "self" : sessions.count(i.id) ? sessions[i.id] : "disconnected")
.arg(i.isOffline() ? " | " + QString::fromStdString(reasonOf(i.lastDisconnect())) + " | " + QString::number(i.failedAttempts()) + "x" : "") .arg(i.isOffline() ? " | " + QString::fromStdString(reasonOf(i.lastDisconnect())) + " | " + QString::number(i.failedAttempts()) + "x" : "")
.arg(i.rating()) .arg(i.rating())
); );
} }
} }
@ -994,7 +992,7 @@ void Main::refreshAll()
refreshBlockChain(); refreshBlockChain();
refreshBlockCount(); refreshBlockCount();
refreshPending(); refreshPending();
refreshAccounts(); ui->refreshAccounts->setEnabled(true);
refreshBalances(); refreshBalances();
} }
@ -1007,40 +1005,66 @@ void Main::refreshPending()
QString s = t.receiveAddress() ? QString s = t.receiveAddress() ?
QString("%2 %5> %3: %1 [%4]") QString("%2 %5> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str()) .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender())) .arg(QString::fromStdString(render(t.safeSender())))
.arg(render(t.receiveAddress())) .arg(QString::fromStdString(render(t.receiveAddress())))
.arg((unsigned)t.nonce()) .arg((unsigned)t.nonce())
.arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') : .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') :
QString("%2 +> %3: %1 [%4]") QString("%2 +> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str()) .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender())) .arg(QString::fromStdString(render(t.safeSender())))
.arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))) .arg(QString::fromStdString(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))))
.arg((unsigned)t.nonce()); .arg((unsigned)t.nonce());
ui->transactionQueue->addItem(s); ui->transactionQueue->addItem(s);
} }
} }
void Main::on_accountsFilter_textChanged()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_showBasic_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_showContracts_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_onlyNamed_toggled()
{
ui->refreshAccounts->setEnabled(true);
}
void Main::on_refreshAccounts_clicked()
{
refreshAccounts();
}
void Main::refreshAccounts() void Main::refreshAccounts()
{ {
#if ETH_FATDB DEV_TIMED_FUNCTION;
#if ETH_FATDB || !ETH_TRUE
cwatch << "refreshAccounts()"; cwatch << "refreshAccounts()";
ui->accounts->clear(); ui->accounts->clear();
ui->contracts->clear(); bool showContract = ui->showContracts->isChecked();
for (auto n = 0; n < 2; ++n) bool showBasic = ui->showBasic->isChecked();
for (auto i: ethereum()->addresses()) bool onlyNamed = ui->onlyNamed->isChecked();
{ for (auto const& i: ethereum()->addresses())
auto r = render(i); {
if (r.contains('(') == !n) bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3);
{ if (!((showContract && isContract) || (showBasic && !isContract)))
if (n == 0 || ui->showAllAccounts->isChecked()) continue;
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ui->accounts)) string r = render(i);
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE"))
if (ethereum()->codeAt(i).size()) continue;
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ui->contracts)) (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size)); ->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
} }
}
#endif #endif
ui->refreshAccounts->setEnabled(false);
} }
void Main::refreshBlockCount() void Main::refreshBlockCount()
@ -1057,6 +1081,7 @@ void Main::on_turboMining_triggered()
void Main::refreshBlockChain() void Main::refreshBlockChain()
{ {
DEV_TIMED_FUNCTION;
cwatch << "refreshBlockChain()"; cwatch << "refreshBlockChain()";
// TODO: keep the same thing highlighted. // TODO: keep the same thing highlighted.
@ -1105,14 +1130,14 @@ void Main::refreshBlockChain()
QString s = t.receiveAddress() ? QString s = t.receiveAddress() ?
QString(" %2 %5> %3: %1 [%4]") QString(" %2 %5> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str()) .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender())) .arg(QString::fromStdString(render(t.safeSender())))
.arg(render(t.receiveAddress())) .arg(QString::fromStdString(render(t.receiveAddress())))
.arg((unsigned)t.nonce()) .arg((unsigned)t.nonce())
.arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') : .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') :
QString(" %2 +> %3: %1 [%4]") QString(" %2 +> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str()) .arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender())) .arg(QString::fromStdString(render(t.safeSender())))
.arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))) .arg(QString::fromStdString(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))))
.arg((unsigned)t.nonce()); .arg((unsigned)t.nonce());
QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks); QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks);
auto hba = QByteArray((char const*)h.data(), h.size); auto hba = QByteArray((char const*)h.data(), h.size);
@ -1256,7 +1281,7 @@ string Main::renderDiff(StateDiff const& _d) const
s << "<hr/>"; s << "<hr/>";
AccountDiff ad = i.second; AccountDiff ad = i.second;
s << "<code style=\"white-space: pre; font-weight: bold\">" << lead(ad.changeType()) << " </code>" << " <b>" << render(i.first).toStdString() << "</b>"; s << "<code style=\"white-space: pre; font-weight: bold\">" << lead(ad.changeType()) << " </code>" << " <b>" << render(i.first) << "</b>";
if (!ad.exist.to()) if (!ad.exist.to())
continue; continue;
@ -1289,7 +1314,7 @@ string Main::renderDiff(StateDiff const& _d) const
s << " * "; s << " * ";
s << " </code>"; s << " </code>";
s << prettyU256(i.first).toStdString(); s << prettyU256(i.first);
/* if (i.first > u256(1) << 246) /* if (i.first > u256(1) << 246)
s << (h256)i.first; s << (h256)i.first;
else if (i.first > u160(1) << 150) else if (i.first > u160(1) << 150)
@ -1298,11 +1323,11 @@ string Main::renderDiff(StateDiff const& _d) const
s << hex << i.first; s << hex << i.first;
*/ */
if (!i.second.from()) if (!i.second.from())
s << ": " << prettyU256(i.second.to()).toStdString(); s << ": " << prettyU256(i.second.to());
else if (!i.second.to()) else if (!i.second.to())
s << " (" << prettyU256(i.second.from()).toStdString() << ")"; s << " (" << prettyU256(i.second.from()) << ")";
else else
s << ": " << prettyU256(i.second.to()).toStdString() << " (" << prettyU256(i.second.from()).toStdString() << ")"; s << ": " << prettyU256(i.second.to()) << " (" << prettyU256(i.second.from()) << ")";
} }
} }
return s.str(); return s.str();
@ -1321,11 +1346,11 @@ void Main::on_transactionQueue_currentItemChanged()
auto ss = tx.safeSender(); auto ss = tx.safeSender();
h256 th = sha3(rlpList(ss, tx.nonce())); h256 th = sha3(rlpList(ss, tx.nonce()));
s << "<h3>" << th << "</h3>"; s << "<h3>" << th << "</h3>";
s << "From: <b>" << pretty(ss).toStdString() << "</b> " << ss; s << "From: <b>" << pretty(ss) << "</b> " << ss;
if (tx.isCreation()) if (tx.isCreation())
s << "<br/>Creates: <b>" << pretty(right160(th)).toStdString() << "</b> " << right160(th); s << "<br/>Creates: <b>" << pretty(right160(th)) << "</b> " << right160(th);
else else
s << "<br/>To: <b>" << pretty(tx.receiveAddress()).toStdString() << "</b> " << tx.receiveAddress(); s << "<br/>To: <b>" << pretty(tx.receiveAddress()) << "</b> " << tx.receiveAddress();
s << "<br/>Value: <b>" << formatBalance(tx.value()) << "</b>"; s << "<br/>Value: <b>" << formatBalance(tx.value()) << "</b>";
s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</b>"; s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</b>";
s << "<br/>Gas price: <b>" << formatBalance(tx.gasPrice()) << "</b>"; s << "<br/>Gas price: <b>" << formatBalance(tx.gasPrice()) << "</b>";
@ -1413,6 +1438,11 @@ void Main::on_injectBlock_triggered()
} }
} }
static string htmlEscaped(string const& _s)
{
return QString::fromStdString(_s).toHtmlEscaped().toStdString();
}
void Main::on_blocks_currentItemChanged() void Main::on_blocks_currentItemChanged()
{ {
ui->info->clear(); ui->info->clear();
@ -1442,7 +1472,7 @@ void Main::on_blocks_currentItemChanged()
s << "<div>D/TD: <b>" << info.difficulty << "</b>/<b>" << details.totalDifficulty << "</b> = 2^" << log2((double)info.difficulty) << "/2^" << log2((double)details.totalDifficulty) << "</div>"; s << "<div>D/TD: <b>" << info.difficulty << "</b>/<b>" << details.totalDifficulty << "</b> = 2^" << log2((double)info.difficulty) << "/2^" << log2((double)details.totalDifficulty) << "</div>";
s << "&nbsp;&emsp;&nbsp;Children: <b>" << details.children.size() << "</b></div>"; s << "&nbsp;&emsp;&nbsp;Children: <b>" << details.children.size() << "</b></div>";
s << "<div>Gas used/limit: <b>" << info.gasUsed << "</b>/<b>" << info.gasLimit << "</b>" << "</div>"; s << "<div>Gas used/limit: <b>" << info.gasUsed << "</b>/<b>" << info.gasLimit << "</b>" << "</div>";
s << "<div>Beneficiary: <b>" << pretty(info.coinbaseAddress).toHtmlEscaped().toStdString() << " " << info.coinbaseAddress << "</b>" << "</div>"; s << "<div>Beneficiary: <b>" << htmlEscaped(pretty(info.coinbaseAddress)) << " " << info.coinbaseAddress << "</b>" << "</div>";
s << "<div>Seed hash: <b>" << info.seedHash() << "</b>" << "</div>"; s << "<div>Seed hash: <b>" << info.seedHash() << "</b>" << "</div>";
s << "<div>Mix hash: <b>" << info.mixHash << "</b>" << "</div>"; s << "<div>Mix hash: <b>" << info.mixHash << "</b>" << "</div>";
s << "<div>Nonce: <b>" << info.nonce << "</b>" << "</div>"; s << "<div>Nonce: <b>" << info.nonce << "</b>" << "</div>";
@ -1473,7 +1503,7 @@ void Main::on_blocks_currentItemChanged()
s << line << "Hash: <b>" << uncle.hash() << "</b>" << "</div>"; s << line << "Hash: <b>" << uncle.hash() << "</b>" << "</div>";
s << line << "Parent: <b>" << uncle.parentHash << "</b>" << "</div>"; s << line << "Parent: <b>" << uncle.parentHash << "</b>" << "</div>";
s << line << "Number: <b>" << uncle.number << "</b>" << "</div>"; s << line << "Number: <b>" << uncle.number << "</b>" << "</div>";
s << line << "Coinbase: <b>" << pretty(uncle.coinbaseAddress).toHtmlEscaped().toStdString() << " " << uncle.coinbaseAddress << "</b>" << "</div>"; s << line << "Coinbase: <b>" << htmlEscaped(pretty(uncle.coinbaseAddress)) << " " << uncle.coinbaseAddress << "</b>" << "</div>";
s << line << "Seed hash: <b>" << uncle.seedHash() << "</b>" << "</div>"; s << line << "Seed hash: <b>" << uncle.seedHash() << "</b>" << "</div>";
s << line << "Mix hash: <b>" << uncle.mixHash << "</b>" << "</div>"; s << line << "Mix hash: <b>" << uncle.mixHash << "</b>" << "</div>";
s << line << "Nonce: <b>" << uncle.nonce << "</b>" << "</div>"; s << line << "Nonce: <b>" << uncle.nonce << "</b>" << "</div>";
@ -1508,11 +1538,11 @@ void Main::on_blocks_currentItemChanged()
TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi]; TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi];
s << "<h3>" << th << "</h3>"; s << "<h3>" << th << "</h3>";
s << "<h4>" << h << "[<b>" << txi << "</b>]</h4>"; s << "<h4>" << h << "[<b>" << txi << "</b>]</h4>";
s << "<div>From: <b>" << pretty(ss).toHtmlEscaped().toStdString() << " " << ss << "</b>" << "</div>"; s << "<div>From: <b>" << htmlEscaped(pretty(ss)) << " " << ss << "</b>" << "</div>";
if (tx.isCreation()) if (tx.isCreation())
s << "<div>Creates: <b>" << pretty(right160(th)).toHtmlEscaped().toStdString() << "</b> " << right160(th) << "</div>"; s << "<div>Creates: <b>" << htmlEscaped(pretty(right160(th))) << "</b> " << right160(th) << "</div>";
else else
s << "<div>To: <b>" << pretty(tx.receiveAddress()).toHtmlEscaped().toStdString() << "</b> " << tx.receiveAddress() << "</div>"; s << "<div>To: <b>" << htmlEscaped(pretty(tx.receiveAddress())) << "</b> " << tx.receiveAddress() << "</div>";
s << "<div>Value: <b>" << formatBalance(tx.value()) << "</b>" << "</div>"; s << "<div>Value: <b>" << formatBalance(tx.value()) << "</b>" << "</div>";
s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</b>" << "</div>"; s << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</b>" << "</div>";
s << "<div>Gas price: <b>" << formatBalance(tx.gasPrice()) << "</b>" << "</div>"; s << "<div>Gas price: <b>" << formatBalance(tx.gasPrice()) << "</b>" << "</div>";
@ -1590,10 +1620,10 @@ void Main::debugDumpState(int _add)
} }
} }
void Main::on_contracts_currentItemChanged() void Main::on_accounts_currentItemChanged()
{ {
ui->contractInfo->clear(); ui->accountInfo->clear();
if (auto item = ui->contracts->currentItem()) if (auto item = ui->accounts->currentItem())
{ {
auto hba = item->data(Qt::UserRole).toByteArray(); auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20); assert(hba.size() == 20);
@ -1604,16 +1634,16 @@ void Main::on_contracts_currentItemChanged()
{ {
auto storage = ethereum()->storageAt(address); auto storage = ethereum()->storageAt(address);
for (auto const& i: storage) for (auto const& i: storage)
s << "@" << showbase << hex << prettyU256(i.first).toStdString() << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << prettyU256(i.second).toStdString() << "<br/>"; s << "@" << showbase << hex << prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << prettyU256(i.second) << "<br/>";
s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address)); s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address));
s << Div(Mono) << toHex(ethereum()->codeAt(address)) << "</div>"; s << Div(Mono) << toHex(ethereum()->codeAt(address)) << "</div>";
ui->contractInfo->appendHtml(QString::fromStdString(s.str())); ui->accountInfo->appendHtml(QString::fromStdString(s.str()));
} }
catch (dev::InvalidTrie) catch (dev::InvalidTrie)
{ {
ui->contractInfo->appendHtml("Corrupted trie."); ui->accountInfo->appendHtml("Corrupted trie.");
} }
ui->contractInfo->moveCursor(QTextCursor::Start); ui->accountInfo->moveCursor(QTextCursor::Start);
} }
} }
@ -1645,16 +1675,6 @@ void Main::on_accounts_doubleClicked()
} }
} }
void Main::on_contracts_doubleClicked()
{
if (ui->contracts->count())
{
auto hba = ui->contracts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
}
}
static shh::FullTopic topicFromText(QString _s) static shh::FullTopic topicFromText(QString _s)
{ {
shh::BuildTopic ret; shh::BuildTopic ret;
@ -1885,7 +1905,12 @@ void Main::on_killAccount_triggered()
if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size()) if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size())
{ {
auto k = m_myKeys[ui->ourAccounts->currentRow()]; auto k = m_myKeys[ui->ourAccounts->currentRow()];
if (ethereum()->balanceAt(k.address()) != 0 && QMessageBox::critical(this, "Kill Account?!", "Account " + render(k.address()) + " has " + QString::fromStdString(formatBalance(ethereum()->balanceAt(k.address()))) + " in it. It, and any contract that this account can access, will be lost forever if you continue. Do NOT continue unless you know what you are doing.\nAre you sure you want to continue?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) if (
ethereum()->balanceAt(k.address()) != 0 &&
QMessageBox::critical(this, "Kill Account?!",
QString::fromStdString("Account " + render(k.address()) + " has " + formatBalance(ethereum()->balanceAt(k.address())) + " in it. It, and any contract that this account can access, will be lost forever if you continue. Do NOT continue unless you know what you are doing.\n"
"Are you sure you want to continue?"),
QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
return; return;
m_myKeys.erase(m_myKeys.begin() + ui->ourAccounts->currentRow()); m_myKeys.erase(m_myKeys.begin() + ui->ourAccounts->currentRow());
keysChanged(); keysChanged();
@ -1902,10 +1927,10 @@ void Main::on_go_triggered()
web3()->addNode(p2p::NodeId(), Host::pocHost()); web3()->addNode(p2p::NodeId(), Host::pocHost());
} }
QString Main::prettyU256(dev::u256 _n) const std::string Main::prettyU256(dev::u256 const& _n) const
{ {
unsigned inc = 0; unsigned inc = 0;
QString raw; string raw;
ostringstream s; ostringstream s;
if (_n > szabo && _n < 1000000 * ether) if (_n > szabo && _n < 1000000 * ether)
s << "<span style=\"color: #215\">" << formatBalance(_n) << "</span> <span style=\"color: #448\">(0x" << hex << (uint64_t)_n << ")</span>"; s << "<span style=\"color: #215\">" << formatBalance(_n) << "</span> <span style=\"color: #448\">(0x" << hex << (uint64_t)_n << ")</span>";
@ -1916,17 +1941,17 @@ QString Main::prettyU256(dev::u256 _n) const
else if ((_n >> 160) == 0) else if ((_n >> 160) == 0)
{ {
Address a = right160(_n); Address a = right160(_n);
QString n = pretty(a); string n = pretty(a);
if (n.isNull()) if (n.empty())
s << "<span style=\"color: #844\">0x</span><span style=\"color: #800\">" << a << "</span>"; s << "<span style=\"color: #844\">0x</span><span style=\"color: #800\">" << a << "</span>";
else else
s << "<span style=\"font-weight: bold; color: #800\">" << n.toHtmlEscaped().toStdString() << "</span> (<span style=\"color: #844\">0x</span><span style=\"color: #800\">" << a.abridged() << "</span>)"; s << "<span style=\"font-weight: bold; color: #800\">" << htmlEscaped(n) << "</span> (<span style=\"color: #844\">0x</span><span style=\"color: #800\">" << a.abridged() << "</span>)";
} }
else if ((raw = fromRaw((h256)_n, &inc)).size()) else if ((raw = fromRaw((h256)_n, &inc)).size())
return "<span style=\"color: #484\">\"</span><span style=\"color: #080\">" + raw.toHtmlEscaped() + "</span><span style=\"color: #484\">\"" + (inc ? " + " + QString::number(inc) : "") + "</span>"; return "<span style=\"color: #484\">\"</span><span style=\"color: #080\">" + htmlEscaped(raw) + "</span><span style=\"color: #484\">\"" + (inc ? " + " + toString(inc) : "") + "</span>";
else else
s << "<span style=\"color: #466\">0x</span><span style=\"color: #044\">" << (h256)_n << "</span>"; s << "<span style=\"color: #466\">0x</span><span style=\"color: #044\">" << (h256)_n << "</span>";
return QString::fromStdString(s.str()); return s.str();
} }
void Main::on_post_clicked() void Main::on_post_clicked()

20
alethzero/MainWin.h

@ -80,10 +80,10 @@ public:
bool confirm() const; bool confirm() const;
NatSpecFace* natSpec() { return &m_natSpecDB; } NatSpecFace* natSpec() { return &m_natSpecDB; }
QString pretty(dev::Address _a) const override; std::string pretty(dev::Address const& _a) const override;
QString prettyU256(dev::u256 _n) const override; std::string prettyU256(dev::u256 const& _n) const override;
QString render(dev::Address _a) const override; std::string render(dev::Address const& _a) const override;
std::pair<dev::Address, dev::bytes> fromString(QString const& _a) const override; std::pair<dev::Address, dev::bytes> fromString(std::string const& _a) const override;
std::string renderDiff(dev::eth::StateDiff const& _d) const override; std::string renderDiff(dev::eth::StateDiff const& _d) const override;
QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; } QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; }
@ -131,6 +131,13 @@ private slots:
void on_importKeyFile_triggered(); void on_importKeyFile_triggered();
void on_exportKey_triggered(); void on_exportKey_triggered();
// Account pane
void on_accountsFilter_textChanged();
void on_showBasic_toggled();
void on_showContracts_toggled();
void on_onlyNamed_toggled();
void on_refreshAccounts_clicked();
// Tools // Tools
void on_newTransaction_triggered(); void on_newTransaction_triggered();
void on_loadJS_triggered(); void on_loadJS_triggered();
@ -140,8 +147,7 @@ private slots:
void ourAccountsRowsMoved(); void ourAccountsRowsMoved();
void on_ourAccounts_doubleClicked(); void on_ourAccounts_doubleClicked();
void on_accounts_doubleClicked(); void on_accounts_doubleClicked();
void on_contracts_doubleClicked(); void on_accounts_currentItemChanged();
void on_contracts_currentItemChanged();
void on_transactionQueue_currentItemChanged(); void on_transactionQueue_currentItemChanged();
void on_blockChainFilter_textChanged(); void on_blockChainFilter_textChanged();
void on_blocks_currentItemChanged(); void on_blocks_currentItemChanged();
@ -254,7 +260,7 @@ private:
std::unique_ptr<jsonrpc::HttpServer> m_httpConnector; std::unique_ptr<jsonrpc::HttpServer> m_httpConnector;
std::unique_ptr<OurWebThreeStubServer> m_server; std::unique_ptr<OurWebThreeStubServer> m_server;
static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr); static std::string fromRaw(dev::h256 _n, unsigned* _inc = nullptr);
NatspecHandler m_natSpecDB; NatspecHandler m_natSpecDB;
Transact m_transact; Transact m_transact;

6
alethzero/OurWebThreeStubServer.cpp

@ -73,7 +73,7 @@ bool OurWebThreeStubServer::showCreationNotice(TransactionSkeleton const& _t, bo
bool OurWebThreeStubServer::showSendNotice(TransactionSkeleton const& _t, bool _toProxy) bool OurWebThreeStubServer::showSendNotice(TransactionSkeleton const& _t, bool _toProxy)
{ {
return showAuthenticationPopup("Fund Transfer Transaction", "ÐApp is attempting to send " + formatBalance(_t.value) + " to a recipient " + m_main->pretty(_t.to).toStdString() + (_toProxy ? " (this transaction is not executed directly, but forwarded to another ÐApp)" : "") + return showAuthenticationPopup("Fund Transfer Transaction", "ÐApp is attempting to send " + formatBalance(_t.value) + " to a recipient " + m_main->pretty(_t.to) + (_toProxy ? " (this transaction is not executed directly, but forwarded to another ÐApp)" : "") +
", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + "."); ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + ".");
} }
@ -81,7 +81,7 @@ bool OurWebThreeStubServer::showUnknownCallNotice(TransactionSkeleton const& _t,
{ {
return showAuthenticationPopup("DANGEROUS! Unknown Contract Transaction!", return showAuthenticationPopup("DANGEROUS! Unknown Contract Transaction!",
"ÐApp is attempting to call into an unknown contract at address " + "ÐApp is attempting to call into an unknown contract at address " +
m_main->pretty(_t.to).toStdString() + ".\n\n" + m_main->pretty(_t.to) + ".\n\n" +
(_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") + (_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") +
"Call involves sending " + "Call involves sending " +
formatBalance(_t.value) + " to the recipient, with additional network fees of up to " + formatBalance(_t.value) + " to the recipient, with additional network fees of up to " +
@ -137,7 +137,7 @@ bool OurWebThreeStubServer::validateTransaction(TransactionSkeleton const& _t, b
// otherwise it's a transaction to a contract for which we have the natspec // otherwise it's a transaction to a contract for which we have the natspec
return showAuthenticationPopup("Contract Transaction", return showAuthenticationPopup("Contract Transaction",
"ÐApp attempting to conduct contract interaction with " + "ÐApp attempting to conduct contract interaction with " +
m_main->pretty(_t.to).toStdString() + m_main->pretty(_t.to) +
": <b>" + userNotice + "</b>.\n\n" + ": <b>" + userNotice + "</b>.\n\n" +
(_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") + (_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") +
(_t.value > 0 ? (_t.value > 0 ?

14
alethzero/Transact.cpp

@ -110,12 +110,12 @@ void Transact::updateDestination()
cwatch << "updateDestination()"; cwatch << "updateDestination()";
QString s; QString s;
for (auto i: ethereum()->addresses()) for (auto i: ethereum()->addresses())
if ((s = m_context->pretty(i)).size()) if ((s = QString::fromStdString(m_context->pretty(i))).size())
// A namereg address // A namereg address
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1) if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1)
ui->destination->addItem(s); ui->destination->addItem(s);
for (int i = 0; i < ui->destination->count(); ++i) for (int i = 0; i < ui->destination->count(); ++i)
if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i)).first) if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i).toStdString()).first)
ui->destination->removeItem(i--); ui->destination->removeItem(i--);
} }
@ -142,9 +142,9 @@ void Transact::on_destination_currentTextChanged(QString)
{ {
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)") if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)")
{ {
auto p = m_context->fromString(ui->destination->currentText()); auto p = m_context->fromString(ui->destination->currentText().toStdString());
if (p.first) if (p.first)
ui->calculatedName->setText(m_context->render(p.first)); ui->calculatedName->setText(QString::fromStdString(m_context->render(p.first)));
else else
ui->calculatedName->setText("Unknown Address"); ui->calculatedName->setText("Unknown Address");
if (!p.second.empty()) if (!p.second.empty())
@ -347,7 +347,7 @@ void Transact::rejigData()
else else
{ {
// TODO: cache like m_data. // TODO: cache like m_data.
to = m_context->fromString(ui->destination->currentText()).first; to = m_context->fromString(ui->destination->currentText().toStdString()).first;
er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice()); er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice());
} }
gasNeeded = (qint64)(er.gasUsed + er.gasRefunded); gasNeeded = (qint64)(er.gasUsed + er.gasRefunded);
@ -434,7 +434,7 @@ void Transact::on_send_clicked()
} }
else else
// TODO: cache like m_data. // TODO: cache like m_data.
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()).first, m_data, ui->gas->value(), gasPrice()); ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, ui->gas->value(), gasPrice());
close(); close();
} }
@ -453,7 +453,7 @@ void Transact::on_debug_clicked()
State st(ethereum()->postState()); State st(ethereum()->postState());
Transaction t = isCreation() ? Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) : Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) :
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()).first, m_data, st.transactionsFrom(dev::toAddress(s)), s); Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, st.transactionsFrom(dev::toAddress(s)), s);
Debugger dw(m_context, this); Debugger dw(m_context, this);
Executive e(st, ethereum()->blockChain(), 0); Executive e(st, ethereum()->blockChain(), 0);
dw.populate(e, t); dw.populate(e, t);

16
cmake/EthCompilerSettings.cmake

@ -9,14 +9,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE")
if (PROFILING)
set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}")
add_definitions(-DETH_PROFILING_GPERF)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofiler")
# set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -lprofiler")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lprofiler")
endif ()
execute_process( execute_process(
COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7))
@ -61,6 +53,14 @@ else ()
message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.")
endif () endif ()
if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")))
set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}")
add_definitions(-DETH_PROFILING_GPERF)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofiler")
# set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -lprofiler")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lprofiler")
endif ()
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
option(USE_LD_GOLD "Use GNU gold linker" ON) option(USE_LD_GOLD "Use GNU gold linker" ON)
if (USE_LD_GOLD) if (USE_LD_GOLD)

12
eth/main.cpp

@ -146,6 +146,7 @@ void help()
<< " --listen <port> Listen on the given port for incoming connections (default: 30303)." << endl << " --listen <port> Listen on the given port for incoming connections (default: 30303)." << endl
<< " -r,--remote <host>(:<port>) Connect to remote host (default: none)." << endl << " -r,--remote <host>(:<port>) Connect to remote host (default: none)." << endl
<< " --port <port> Connect to remote port (default: 30303)." << endl << " --port <port> Connect to remote port (default: 30303)." << endl
<< " --network-id <n> Only connect to other hosts with this network id (default:0)." << endl
<< " --upnp <on/off> Use UPnP for NAT (default: on)." << endl << " --upnp <on/off> Use UPnP for NAT (default: on)." << endl
#if ETH_JSONRPC || !ETH_TRUE #if ETH_JSONRPC || !ETH_TRUE
<< "Work farming mode:" << endl << "Work farming mode:" << endl
@ -515,6 +516,7 @@ int main(int argc, char** argv)
unsigned short remotePort = 30303; unsigned short remotePort = 30303;
unsigned peers = 5; unsigned peers = 5;
bool bootstrap = false; bool bootstrap = false;
unsigned networkId = 0;
/// Mining params /// Mining params
unsigned mining = 0; unsigned mining = 0;
@ -668,6 +670,15 @@ int main(int argc, char** argv)
return -1; return -1;
} }
} }
else if (arg == "--network-id" && i + 1 < argc)
try {
networkId = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--benchmark-warmup" && i + 1 < argc) else if (arg == "--benchmark-warmup" && i + 1 < argc)
try { try {
benchmarkWarmup = stol(argv[++i]); benchmarkWarmup = stol(argv[++i]);
@ -1034,6 +1045,7 @@ int main(int argc, char** argv)
c->setForceMining(forceMining); c->setForceMining(forceMining);
c->setTurboMining(minerType == MinerType::GPU); c->setTurboMining(minerType == MinerType::GPU);
c->setAddress(coinbase); c->setAddress(coinbase);
c->setNetworkId(networkId);
} }
cout << "Transaction Signer: " << sigKey.address() << endl; cout << "Transaction Signer: " << sigKey.address() << endl;

2
evmjit/libevmjit-cpp/Env.cpp

@ -1,7 +1,7 @@
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libethcore/Params.h> #include <libevmcore/Params.h>
#include <libevm/ExtVMFace.h> #include <libevm/ExtVMFace.h>
#include "Utils.h" #include "Utils.h"

14
libdevcore/Common.cpp

@ -20,7 +20,8 @@
*/ */
#include "Common.h" #include "Common.h"
#include "Exceptions.h"
#include "Log.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
@ -29,5 +30,16 @@ namespace dev
char const* Version = "0.9.14"; char const* Version = "0.9.14";
void HasInvariants::checkInvariants() const
{
if (!invariants())
BOOST_THROW_EXCEPTION(FailedInvariant());
}
TimerHelper::~TimerHelper()
{
cdebug << "Timer" << id << t.elapsed() << "s";
}
} }

57
libdevcore/Common.h

@ -37,6 +37,7 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include <functional> #include <functional>
#include <boost/timer.hpp>
#pragma warning(push) #pragma warning(push)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
@ -128,14 +129,65 @@ inline N diff(N const& _a, N const& _b)
} }
/// RAII utility class whose destructor calls a given function. /// RAII utility class whose destructor calls a given function.
class ScopeGuard { class ScopeGuard
{
public: public:
ScopeGuard(std::function<void(void)> _f): m_f(_f) {} ScopeGuard(std::function<void(void)> _f): m_f(_f) {}
~ScopeGuard() { m_f(); } ~ScopeGuard() { m_f(); }
private: private:
std::function<void(void)> m_f; std::function<void(void)> m_f;
}; };
/// Inheritable for classes that have invariants.
class HasInvariants
{
public:
/// Check invariants are met, throw if not.
void checkInvariants() const;
protected:
/// Reimplement to specify the invariants.
virtual bool invariants() const = 0;
};
/// RAII checker for invariant assertions.
class InvariantChecker
{
public:
InvariantChecker(HasInvariants* _this): m_this(_this) { m_this->checkInvariants(); }
~InvariantChecker() { m_this->checkInvariants(); }
private:
HasInvariants const* m_this;
};
/// Scope guard for invariant check in a class derived from HasInvariants.
#if ETH_DEBUG
#define DEV_INVARIANT_CHECK ::dev::InvariantChecker __dev_invariantCheck(this)
#else
#define DEV_INVARIANT_CHECK (void)0;
#endif
class TimerHelper
{
public:
TimerHelper(char const* _id): id(_id) {}
~TimerHelper();
private:
boost::timer t;
char const* id;
};
#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(#S, true); __eth_t.second; __eth_t.second = false)
#define DEV_TIMED_SCOPE(S) ::dev::TimerHelper __eth_t(S)
#if WIN32
#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__FUNCSIG__)
#else
#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__PRETTY_FUNCTION__)
#endif
enum class WithExisting: int enum class WithExisting: int
{ {
Trust = 0, Trust = 0,
@ -145,7 +197,8 @@ enum class WithExisting: int
} }
namespace std { namespace std
{
inline dev::WithExisting max(dev::WithExisting _a, dev::WithExisting _b) inline dev::WithExisting max(dev::WithExisting _a, dev::WithExisting _b)
{ {

1
libdevcore/Exceptions.h

@ -53,6 +53,7 @@ struct BadRoot: virtual Exception {};
struct FileError: virtual Exception {}; struct FileError: virtual Exception {};
struct Overflow: virtual Exception {}; struct Overflow: virtual Exception {};
struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} }; struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} };
struct FailedInvariant: virtual Exception {};
// error information to be added to exceptions // error information to be added to exceptions
using errinfo_invalidSymbol = boost::error_info<struct tag_invalidSymbol, char>; using errinfo_invalidSymbol = boost::error_info<struct tag_invalidSymbol, char>;

5
libdevcore/FixedHash.h

@ -64,6 +64,9 @@ public:
/// Convert from the corresponding arithmetic type. /// Convert from the corresponding arithmetic type.
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }
/// Convert from unsigned
explicit FixedHash(unsigned _u) { toBigEndian(_u, m_data); }
/// Explicitly construct, copying from a byte array. /// Explicitly construct, copying from a byte array.
explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } } explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
@ -80,7 +83,7 @@ public:
operator Arith() const { return fromBigEndian<Arith>(m_data); } operator Arith() const { return fromBigEndian<Arith>(m_data); }
/// @returns true iff this is the empty hash. /// @returns true iff this is the empty hash.
explicit operator bool() const { return ((Arith)*this) != 0; } explicit operator bool() const { return std::any_of(m_data.begin(), m_data.end(), [](byte _b) { return _b != 0; }); }
// The obvious comparison operators. // The obvious comparison operators.
bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; }

13
libdevcore/Guards.h

@ -22,6 +22,7 @@
#pragma once #pragma once
#include <mutex> #include <mutex>
#include <atomic>
#include <boost/thread.hpp> #include <boost/thread.hpp>
namespace dev namespace dev
@ -61,6 +62,18 @@ struct GenericUnguardSharedBool
MutexType& m; MutexType& m;
}; };
/** @brief Simple lock that waits for release without making context switch */
class SpinLock
{
public:
SpinLock() { m_lock.clear(); }
void lock() { while (m_lock.test_and_set(std::memory_order_acquire)) {} }
void unlock() { m_lock.clear(std::memory_order_release); }
private:
std::atomic_flag m_lock;
};
using SpinGuard = std::lock_guard<SpinLock>;
/** @brief Simple block guard. /** @brief Simple block guard.
* The expression/block following is guarded though the given mutex. * The expression/block following is guarded though the given mutex.
* Usage: * Usage:

4
libdevcore/Log.cpp

@ -158,8 +158,8 @@ void dev::setThreadName(string const& _n)
void dev::simpleDebugOut(std::string const& _s, char const*) void dev::simpleDebugOut(std::string const& _s, char const*)
{ {
static Mutex s_lock; static SpinLock s_lock;
Guard l(s_lock); SpinGuard l(s_lock);
cerr << _s << endl << flush; cerr << _s << endl << flush;

2
libethcore/BlockInfo.cpp

@ -23,10 +23,10 @@
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h> #include <libdevcrypto/TrieDB.h>
#include <libethcore/Common.h> #include <libethcore/Common.h>
#include <libethcore/Params.h>
#include "EthashAux.h" #include "EthashAux.h"
#include "ProofOfWork.h" #include "ProofOfWork.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "Params.h"
#include "BlockInfo.h" #include "BlockInfo.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;

2
libethcore/CMakeLists.txt

@ -28,7 +28,7 @@ add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ethash) target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} evmcore)
if (ETHASHCL) if (ETHASHCL)
target_link_libraries(${EXECUTABLE} ethash-cl) target_link_libraries(${EXECUTABLE} ethash-cl)

12
libethcore/EthashAux.cpp

@ -33,7 +33,6 @@
#include <libdevcrypto/CryptoPP.h> #include <libdevcrypto/CryptoPP.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libethcore/Params.h>
#include "BlockInfo.h" #include "BlockInfo.h"
using namespace std; using namespace std;
using namespace chrono; using namespace chrono;
@ -87,13 +86,10 @@ ethash_params EthashAux::params(h256 const& _seedHash)
{ {
Guard l(get()->x_epochs); Guard l(get()->x_epochs);
unsigned epoch = 0; unsigned epoch = 0;
try auto epochIter = get()->m_epochs.find(_seedHash);
if (epochIter == get()->m_epochs.end())
{ {
epoch = get()->m_epochs.at(_seedHash); // cdebug << "Searching for seedHash " << _seedHash;
}
catch (...)
{
// cdebug << "Searching for seedHash " << _seedHash;
for (h256 h; h != _seedHash && epoch < 2048; ++epoch, h = sha3(h), get()->m_epochs[h] = epoch) {} for (h256 h; h != _seedHash && epoch < 2048; ++epoch, h = sha3(h), get()->m_epochs[h] = epoch) {}
if (epoch == 2048) if (epoch == 2048)
{ {
@ -102,6 +98,8 @@ ethash_params EthashAux::params(h256 const& _seedHash)
throw std::invalid_argument(error.str()); throw std::invalid_argument(error.str());
} }
} }
else
epoch = epochIter->second;
return params(epoch * ETHASH_EPOCH_LENGTH); return params(epoch * ETHASH_EPOCH_LENGTH);
} }

2
libethcore/ICAP.h

@ -51,8 +51,6 @@ public:
ICAP() = default; ICAP() = default;
/// Construct a direct ICAP object for given target address. Must have a zero first byte. /// Construct a direct ICAP object for given target address. Must have a zero first byte.
ICAP(Address const& _target): m_type(Direct), m_direct(_target) {} ICAP(Address const& _target): m_type(Direct), m_direct(_target) {}
/// Construct an indirect ICAP object for given target name.
ICAP(std::string const& _target): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_target)), m_asset("ETH") {}
/// Construct an indirect ICAP object for given client and institution names. /// Construct an indirect ICAP object for given client and institution names.
ICAP(std::string const& _client, std::string const& _inst): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_client)), m_institution(boost::algorithm::to_upper_copy(_inst)), m_asset("XET") {} ICAP(std::string const& _client, std::string const& _inst): m_type(Indirect), m_client(boost::algorithm::to_upper_copy(_client)), m_institution(boost::algorithm::to_upper_copy(_inst)), m_asset("XET") {}
/// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this. /// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this.

36
libethcore/Params.cpp

@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file FeeStructure.cpp /** @file Params.cpp
* @author Gav Wood <i@gavwood.com> * @author Gav Wood <i@gavwood.com>
* @date 2014 * @date 2014
*/ */
@ -36,40 +36,6 @@ u256 const c_gasLimitBoundDivisor = 1024;
u256 const c_minimumDifficulty = 131072; u256 const c_minimumDifficulty = 131072;
u256 const c_difficultyBoundDivisor = 2048; u256 const c_difficultyBoundDivisor = 2048;
u256 const c_durationLimit = 8; u256 const c_durationLimit = 8;
u256 const c_stackLimit = 1024;
u256 const c_tierStepGas[] = {0, 2, 3, 5, 8, 10, 20, 0};
u256 const c_expGas = 10;
u256 const c_expByteGas = 10;
u256 const c_sha3Gas = 30;
u256 const c_sha3WordGas = 6;
u256 const c_sloadGas = 50;
u256 const c_sstoreSetGas = 20000;
u256 const c_sstoreResetGas = 5000;
u256 const c_sstoreRefundGas = 15000;
u256 const c_jumpdestGas = 1;
u256 const c_logGas = 375;
u256 const c_logDataGas = 8;
u256 const c_logTopicGas = 375;
u256 const c_createGas = 32000;
u256 const c_callGas = 40;
u256 const c_callStipend = 2300;
u256 const c_callValueTransferGas = 9000;
u256 const c_callNewAccountGas = 25000;
u256 const c_suicideRefundGas = 24000;
u256 const c_memoryGas = 3;
u256 const c_quadCoeffDiv = 512;
u256 const c_createDataGas = 200;
u256 const c_txGas = 21000;
u256 const c_txDataZeroGas = 4;
u256 const c_txDataNonZeroGas = 68;
u256 const c_copyGas = 3;
u256 const c_ecrecoverGas = 3000;
u256 const c_sha256Gas = 60;
u256 const c_sha256WordGas = 12;
u256 const c_ripemd160Gas = 600;
u256 const c_ripemd160WordGas = 120;
u256 const c_identityGas = 15;
u256 const c_identityWordGas = 3;
//--- END: AUTOGENERATED FROM /feeStructure.json //--- END: AUTOGENERATED FROM /feeStructure.json
} }

37
libethcore/Params.h

@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file FeeStructure.h /** @file Params.h
* @author Gav Wood <i@gavwood.com> * @author Gav Wood <i@gavwood.com>
* @date 2014 * @date 2014
*/ */
@ -37,41 +37,6 @@ extern u256 const c_minimumDifficulty;
extern u256 const c_difficultyBoundDivisor; extern u256 const c_difficultyBoundDivisor;
extern u256 const c_durationLimit; extern u256 const c_durationLimit;
extern u256 const c_maximumExtraDataSize; extern u256 const c_maximumExtraDataSize;
extern u256 const c_stackLimit;
extern u256 const c_tierStepGas[8]; ///< Once per operation, for a selection of them.
extern u256 const c_expGas; ///< Once per EXP instuction.
extern u256 const c_expByteGas; ///< Times ceil(log256(exponent)) for the EXP instruction.
extern u256 const c_sha3Gas; ///< Once per SHA3 operation.
extern u256 const c_sha3WordGas; ///< Once per word of the SHA3 operation's data.
extern u256 const c_copyGas; ///< Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
extern u256 const c_sloadGas; ///< Once per SLOAD operation.
extern u256 const c_sstoreSetGas; ///< Once per SSTORE operation if the zeroness changes from zero.
extern u256 const c_sstoreResetGas; ///< Once per SSTORE operation if the zeroness does not change from zero. NOTE: when c_sstoreSetGas does not apply.
extern u256 const c_sstoreRefundGas; ///< Refunded gas, once per SSTORE operation if the zeroness changes to zero.
extern u256 const c_jumpdestGas; ///< Once per JUMPDEST operation.
extern u256 const c_logGas; ///< Per LOG* operation.
extern u256 const c_logDataGas; ///< Per byte in a LOG* operation's data.
extern u256 const c_logTopicGas; ///< Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
extern u256 const c_createGas; ///< Once per CREATE operation & contract-creation transaction.
extern u256 const c_createDataGas;
extern u256 const c_callGas; ///< Once per CALL operation & message call transaction.
extern u256 const c_callStipend; ///< Free gas given at beginning of call.
extern u256 const c_callNewAccountGas; ///< Paid for CALL when the destination address didn't exist prior.
extern u256 const c_callValueTransferGas; ///< Paid for CALL when the value transfor is non-zero.
extern u256 const c_suicideRefundGas; ///< Refunded following a suicide operation.
extern u256 const c_memoryGas; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
extern u256 const c_quadCoeffDiv; ///< Divisor for the quadratic particle of the memory cost equation.
extern u256 const c_txGas; ///< Per transaction. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataZeroGas; ///< Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataNonZeroGas; ///< Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_ecrecoverGas;
extern u256 const c_sha256Gas;
extern u256 const c_sha256WordGas;
extern u256 const c_ripemd160Gas;
extern u256 const c_ripemd160WordGas;
extern u256 const c_identityGas;
extern u256 const c_identityWordGas;
} }
} }

7
libethereum/BlockChain.cpp

@ -37,6 +37,7 @@
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include <libethcore/Params.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include "GenesisInfo.h" #include "GenesisInfo.h"
#include "State.h" #include "State.h"
@ -47,7 +48,7 @@ using namespace dev::eth;
namespace js = json_spirit; namespace js = json_spirit;
#define ETH_CATCH 1 #define ETH_CATCH 1
#define ETH_TIMED_IMPORTS 1 #define ETH_TIMED_IMPORTS 0
#ifdef _WIN32 #ifdef _WIN32
const char* BlockChainDebug::name() { return EthBlue "8" EthWhite " <>"; } const char* BlockChainDebug::name() { return EthBlue "8" EthWhite " <>"; }
@ -767,7 +768,7 @@ void BlockChain::noteUsed(h256 const& _h, unsigned _extra) const
m_inUse.insert(id); m_inUse.insert(id);
} }
template <class T> static unsigned getHashSize(map<h256, T> const& _map) template <class T> static unsigned getHashSize(unordered_map<h256, T> const& _map)
{ {
unsigned ret = 0; unsigned ret = 0;
for (auto const& i: _map) for (auto const& i: _map)
@ -855,7 +856,7 @@ void BlockChain::garbageCollect(bool _force)
} }
} }
m_cacheUsage.pop_back(); m_cacheUsage.pop_back();
m_cacheUsage.push_front(std::set<CacheID>{}); m_cacheUsage.push_front(std::unordered_set<CacheID>{});
} }
void BlockChain::checkConsistency() void BlockChain::checkConsistency()

20
libethereum/BlockChain.h

@ -28,6 +28,8 @@
#include <deque> #include <deque>
#include <chrono> #include <chrono>
#include <unordered_map>
#include <unordered_set>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
@ -40,6 +42,14 @@
#include "BlockQueue.h" #include "BlockQueue.h"
namespace ldb = leveldb; namespace ldb = leveldb;
namespace std
{
template <> struct hash<pair<dev::h256, unsigned>>
{
size_t operator()(pair<dev::h256, unsigned> const& _x) const { return hash<dev::h256>()(_x.first) ^ hash<unsigned>()(_x.second); }
};
}
namespace dev namespace dev
{ {
@ -66,7 +76,7 @@ std::map<Address, Account> const& genesisState();
ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0); ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0);
using BlocksHash = std::map<h256, bytes>; using BlocksHash = std::unordered_map<h256, bytes>;
using TransactionHashes = h256s; using TransactionHashes = h256s;
using UncleHashes = h256s; using UncleHashes = h256s;
using ImportRoute = std::pair<h256s, h256s>; using ImportRoute = std::pair<h256s, h256s>;
@ -144,7 +154,7 @@ public:
UncleHashes uncleHashes() const { return uncleHashes(currentHash()); } UncleHashes uncleHashes() const { return uncleHashes(currentHash()); }
/// Get the hash for a given block's number. /// Get the hash for a given block's number.
h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras<BlockHash, ExtraBlockHash>(h256(u256(_i)), m_blockHashes, x_blockHashes, NullBlockHash).value; } h256 numberHash(unsigned _i) const { if (!_i) return genesisHash(); return queryExtras<BlockHash, ExtraBlockHash>(h256(_i), m_blockHashes, x_blockHashes, NullBlockHash).value; }
/// Get the last N hashes for a given block. (N is determined by the LastHashes type.) /// Get the last N hashes for a given block. (N is determined by the LastHashes type.)
LastHashes lastHashes() const { return lastHashes(number()); } LastHashes lastHashes() const { return lastHashes(number()); }
@ -251,7 +261,7 @@ private:
void open(std::string const& _path, WithExisting _we = WithExisting::Trust); void open(std::string const& _path, WithExisting _we = WithExisting::Trust);
void close(); void close();
template<class T, unsigned N> T queryExtras(h256 const& _h, std::map<h256, T>& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const template<class T, unsigned N> T queryExtras(h256 const& _h, std::unordered_map<h256, T>& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const
{ {
{ {
ReadGuard l(_x); ReadGuard l(_x);
@ -295,8 +305,8 @@ private:
using CacheID = std::pair<h256, unsigned>; using CacheID = std::pair<h256, unsigned>;
mutable Mutex x_cacheUsage; mutable Mutex x_cacheUsage;
mutable std::deque<std::set<CacheID>> m_cacheUsage; mutable std::deque<std::unordered_set<CacheID>> m_cacheUsage;
mutable std::set<CacheID> m_inUse; mutable std::unordered_set<CacheID> m_inUse;
void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const; void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const;
std::chrono::system_clock::time_point m_lastCollection; std::chrono::system_clock::time_point m_lastCollection;

13
libethereum/BlockDetails.h

@ -21,6 +21,7 @@
#pragma once #pragma once
#include <unordered_map>
#pragma warning(push) #pragma warning(push)
#pragma warning(disable: 4100 4267) #pragma warning(disable: 4100 4267)
#include <leveldb/db.h> #include <leveldb/db.h>
@ -114,12 +115,12 @@ struct TransactionAddress
static const unsigned size = 67; static const unsigned size = 67;
}; };
using BlockDetailsHash = std::map<h256, BlockDetails>; using BlockDetailsHash = std::unordered_map<h256, BlockDetails>;
using BlockLogBloomsHash = std::map<h256, BlockLogBlooms>; using BlockLogBloomsHash = std::unordered_map<h256, BlockLogBlooms>;
using BlockReceiptsHash = std::map<h256, BlockReceipts>; using BlockReceiptsHash = std::unordered_map<h256, BlockReceipts>;
using TransactionAddressHash = std::map<h256, TransactionAddress>; using TransactionAddressHash = std::unordered_map<h256, TransactionAddress>;
using BlockHashHash = std::map<h256, BlockHash>; using BlockHashHash = std::unordered_map<h256, BlockHash>;
using BlocksBloomsHash = std::map<h256, BlocksBlooms>; using BlocksBloomsHash = std::unordered_map<h256, BlocksBlooms>;
static const BlockDetails NullBlockDetails; static const BlockDetails NullBlockDetails;
static const BlockLogBlooms NullBlockLogBlooms; static const BlockLogBlooms NullBlockLogBlooms;

26
libethereum/BlockQueue.cpp

@ -74,7 +74,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
} }
UpgradeGuard ul(l); UpgradeGuard ul(l);
invariants_WITH_LOCK(); DEV_INVARIANT_CHECK;
// Check it's not in the future // Check it's not in the future
(void)_isOurs; (void)_isOurs;
@ -86,7 +86,6 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
if (strftime(buf, 24, "%X", localtime(&bit)) == 0) if (strftime(buf, 24, "%X", localtime(&bit)) == 0)
buf[0] = '\0'; // empty if case strftime fails buf[0] = '\0'; // empty if case strftime fails
cblockq << "OK - queued for future [" << bi.timestamp << "vs" << time(0) << "] - will wait until" << buf; cblockq << "OK - queued for future [" << bi.timestamp << "vs" << time(0) << "] - will wait until" << buf;
invariants_WITH_LOCK();
return ImportResult::FutureTime; return ImportResult::FutureTime;
} }
else else
@ -96,7 +95,6 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
{ {
m_knownBad.insert(bi.hash()); m_knownBad.insert(bi.hash());
// bad parent; this is bad too, note it as such // bad parent; this is bad too, note it as such
invariants_WITH_LOCK();
return ImportResult::BadChain; return ImportResult::BadChain;
} }
else if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash)) else if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash))
@ -106,7 +104,6 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
m_unknown.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes()))); m_unknown.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes())));
m_unknownSet.insert(h); m_unknownSet.insert(h);
invariants_WITH_LOCK();
return ImportResult::UnknownParent; return ImportResult::UnknownParent;
} }
else else
@ -115,7 +112,6 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
cblockq << "OK - ready for chain insertion."; cblockq << "OK - ready for chain insertion.";
m_ready.push_back(make_pair(h, _block.toBytes())); m_ready.push_back(make_pair(h, _block.toBytes()));
m_readySet.insert(h); m_readySet.insert(h);
invariants_WITH_LOCK();
noteReady_WITH_LOCK(h); noteReady_WITH_LOCK(h);
m_onReady(); m_onReady();
@ -127,7 +123,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
bool BlockQueue::doneDrain(h256s const& _bad) bool BlockQueue::doneDrain(h256s const& _bad)
{ {
WriteGuard l(m_lock); WriteGuard l(m_lock);
invariants_WITH_LOCK(); DEV_INVARIANT_CHECK;
m_drainingSet.clear(); m_drainingSet.clear();
if (_bad.size()) if (_bad.size())
{ {
@ -146,8 +142,6 @@ bool BlockQueue::doneDrain(h256s const& _bad)
} }
} }
m_knownBad += _bad; m_knownBad += _bad;
// GAA!!!! NEVER EMPTY?!?!?! TODO: remove items from readySet!
invariants_WITH_LOCK();
return !m_readySet.empty(); return !m_readySet.empty();
} }
@ -169,12 +163,11 @@ void BlockQueue::tick(BlockChain const& _bc)
{ {
UpgradeGuard l2(l); UpgradeGuard l2(l);
invariants_WITH_LOCK(); DEV_INVARIANT_CHECK;
auto end = m_future.lower_bound(t); auto end = m_future.lower_bound(t);
for (auto i = m_future.begin(); i != end; ++i) for (auto i = m_future.begin(); i != end; ++i)
todo.push_back(move(i->second)); todo.push_back(move(i->second));
m_future.erase(m_future.begin(), end); m_future.erase(m_future.begin(), end);
invariants_WITH_LOCK();
} }
} }
cblockq << "Importing" << todo.size() << "past-future blocks."; cblockq << "Importing" << todo.size() << "past-future blocks.";
@ -207,7 +200,7 @@ QueueStatus BlockQueue::blockStatus(h256 const& _h) const
void BlockQueue::drain(std::vector<bytes>& o_out, unsigned _max) void BlockQueue::drain(std::vector<bytes>& o_out, unsigned _max)
{ {
WriteGuard l(m_lock); WriteGuard l(m_lock);
invariants_WITH_LOCK(); DEV_INVARIANT_CHECK;
if (m_drainingSet.empty()) if (m_drainingSet.empty())
{ {
o_out.resize(min<unsigned>(_max, m_ready.size())); o_out.resize(min<unsigned>(_max, m_ready.size()));
@ -224,17 +217,16 @@ void BlockQueue::drain(std::vector<bytes>& o_out, unsigned _max)
// swap(o_out, m_ready); // swap(o_out, m_ready);
// swap(m_drainingSet, m_readySet); // swap(m_drainingSet, m_readySet);
} }
invariants_WITH_LOCK();
} }
void BlockQueue::invariants_WITH_LOCK() const bool BlockQueue::invariants() const
{ {
assert(m_readySet.size() == m_ready.size()); return m_readySet.size() == m_ready.size();
} }
void BlockQueue::noteReady_WITH_LOCK(h256 const& _good) void BlockQueue::noteReady_WITH_LOCK(h256 const& _good)
{ {
invariants_WITH_LOCK(); DEV_INVARIANT_CHECK;
list<h256> goodQueue(1, _good); list<h256> goodQueue(1, _good);
while (!goodQueue.empty()) while (!goodQueue.empty())
{ {
@ -250,12 +242,11 @@ void BlockQueue::noteReady_WITH_LOCK(h256 const& _good)
} }
m_unknown.erase(r.first, r.second); m_unknown.erase(r.first, r.second);
} }
invariants_WITH_LOCK();
} }
void BlockQueue::retryAllUnknown() void BlockQueue::retryAllUnknown()
{ {
invariants_WITH_LOCK(); DEV_INVARIANT_CHECK;
for (auto it = m_unknown.begin(); it != m_unknown.end(); ++it) for (auto it = m_unknown.begin(); it != m_unknown.end(); ++it)
{ {
m_ready.push_back(it->second); m_ready.push_back(it->second);
@ -264,5 +255,4 @@ void BlockQueue::retryAllUnknown()
m_readySet.insert(newReady); m_readySet.insert(newReady);
} }
m_unknown.clear(); m_unknown.clear();
invariants_WITH_LOCK();
} }

8
libethereum/BlockQueue.h

@ -30,6 +30,7 @@
namespace dev namespace dev
{ {
namespace eth namespace eth
{ {
@ -60,7 +61,7 @@ enum class QueueStatus
* Sorts them ready for blockchain insertion (with the BlockChain::sync() method). * Sorts them ready for blockchain insertion (with the BlockChain::sync() method).
* @threadsafe * @threadsafe
*/ */
class BlockQueue class BlockQueue: HasInvariants
{ {
public: public:
/// Import a block into the queue. /// Import a block into the queue.
@ -87,7 +88,7 @@ public:
std::pair<unsigned, unsigned> items() const { ReadGuard l(m_lock); return std::make_pair(m_ready.size(), m_unknown.size()); } std::pair<unsigned, unsigned> items() const { ReadGuard l(m_lock); return std::make_pair(m_ready.size(), m_unknown.size()); }
/// Clear everything. /// Clear everything.
void clear() { WriteGuard l(m_lock); invariants_WITH_LOCK(); m_readySet.clear(); m_drainingSet.clear(); m_ready.clear(); m_unknownSet.clear(); m_unknown.clear(); m_future.clear(); invariants_WITH_LOCK(); } void clear() { WriteGuard l(m_lock); DEV_INVARIANT_CHECK; m_readySet.clear(); m_drainingSet.clear(); m_ready.clear(); m_unknownSet.clear(); m_unknown.clear(); m_future.clear(); }
/// Return first block with an unknown parent. /// Return first block with an unknown parent.
h256 firstUnknown() const { ReadGuard l(m_lock); return m_unknownSet.size() ? *m_unknownSet.begin() : h256(); } h256 firstUnknown() const { ReadGuard l(m_lock); return m_unknownSet.size() ? *m_unknownSet.begin() : h256(); }
@ -102,7 +103,8 @@ public:
private: private:
void noteReady_WITH_LOCK(h256 const& _b); void noteReady_WITH_LOCK(h256 const& _b);
void invariants_WITH_LOCK() const;
bool invariants() const override;
mutable boost::shared_mutex m_lock; ///< General lock. mutable boost::shared_mutex m_lock; ///< General lock.
std::set<h256> m_drainingSet; ///< All blocks being imported. std::set<h256> m_drainingSet; ///< All blocks being imported.

1
libethereum/CanonBlockChain.cpp

@ -29,6 +29,7 @@
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include <libethcore/Params.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include "GenesisInfo.h" #include "GenesisInfo.h"
#include "State.h" #include "State.h"

24
libethereum/Client.cpp

@ -36,12 +36,6 @@ using namespace dev;
using namespace dev::eth; using namespace dev::eth;
using namespace p2p; using namespace p2p;
namespace dev
{
struct TimerHelper { TimerHelper(char const* _id): id(_id) {} ~TimerHelper() { cdebug << "Timer" << id << t.elapsed() << "s"; } boost::timer t; char const* id; };
#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(#S, true); __eth_t.second; __eth_t.second = false)
}
VersionChecker::VersionChecker(string const& _dbPath): VersionChecker::VersionChecker(string const& _dbPath):
m_path(_dbPath.size() ? _dbPath : Defaults::dbPath()) m_path(_dbPath.size() ? _dbPath : Defaults::dbPath())
{ {
@ -582,12 +576,13 @@ void Client::onChainChanged(ImportRoute const& _ir)
m_preMine = newPreMine; m_preMine = newPreMine;
DEV_TIMED(working) ETH_WRITE_GUARDED(x_working) DEV_TIMED(working) ETH_WRITE_GUARDED(x_working)
m_working = newPreMine; m_working = newPreMine;
// Transactions ts = m_postMine.pending();
ETH_READ_GUARDED(x_postMine) ETH_READ_GUARDED(x_postMine)
for (auto const& t: m_postMine.pending()) for (auto const& t: m_postMine.pending())
{ {
clog(ClientNote) << "Resubmitting post-mine transaction " << t; clog(ClientNote) << "Resubmitting post-mine transaction " << t;
m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); auto ir = m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry);
if (ir != ImportResult::Success)
onTransactionQueueReady();
} }
ETH_READ_GUARDED(x_working) DEV_TIMED(post) ETH_WRITE_GUARDED(x_postMine) ETH_READ_GUARDED(x_working) DEV_TIMED(post) ETH_WRITE_GUARDED(x_postMine)
m_postMine = m_working; m_postMine = m_working;
@ -597,6 +592,10 @@ void Client::onChainChanged(ImportRoute const& _ir)
onPostStateChanged(); onPostStateChanged();
} }
// Quick hack for now - the TQ at this point already has the prior pending transactions in it;
// we should resync with it manually until we are stricter about what constitutes "knowing".
onTransactionQueueReady();
noteChanged(changeds); noteChanged(changeds);
} }
@ -659,11 +658,9 @@ void Client::noteChanged(h256Set const& _filters)
void Client::doWork() void Client::doWork()
{ {
// TODO: Use condition variable rather than this rubbish.
bool t = true; bool t = true;
if (m_syncBlockQueue.compare_exchange_strong(t, false)) if (m_syncBlockQueue.compare_exchange_strong(t, false))
syncBlockQueue(); // GAAA!!!!! CALLED TOO OFTEN!!! syncBlockQueue();
t = true; t = true;
if (m_syncTransactionQueue.compare_exchange_strong(t, false) && !m_remoteWorking) if (m_syncTransactionQueue.compare_exchange_strong(t, false) && !m_remoteWorking)
@ -672,7 +669,10 @@ void Client::doWork()
tick(); tick();
if (!m_syncBlockQueue && !m_syncTransactionQueue) if (!m_syncBlockQueue && !m_syncTransactionQueue)
this_thread::sleep_for(chrono::milliseconds(20)); {
std::unique_lock<std::mutex> l(x_signalled);
m_signalled.wait_for(l, chrono::seconds(1));
}
} }
void Client::tick() void Client::tick()

7
libethereum/Client.h

@ -22,6 +22,7 @@
#pragma once #pragma once
#include <thread> #include <thread>
#include <condition_variable>
#include <mutex> #include <mutex>
#include <list> #include <list>
#include <atomic> #include <atomic>
@ -258,10 +259,10 @@ private:
void syncTransactionQueue(); void syncTransactionQueue();
/// Magically called when m_tq needs syncing. Be nice and don't block. /// Magically called when m_tq needs syncing. Be nice and don't block.
void onTransactionQueueReady() { m_syncTransactionQueue = true; } void onTransactionQueueReady() { m_syncTransactionQueue = true; m_signalled.notify_all(); }
/// Magically called when m_tq needs syncing. Be nice and don't block. /// Magically called when m_tq needs syncing. Be nice and don't block.
void onBlockQueueReady() { m_syncBlockQueue = true; } void onBlockQueueReady() { m_syncBlockQueue = true; m_signalled.notify_all(); }
/// Called when the post state has changed (i.e. when more transactions are in it or we're mining on a new block). /// Called when the post state has changed (i.e. when more transactions are in it or we're mining on a new block).
/// This updates m_miningInfo. /// This updates m_miningInfo.
@ -309,6 +310,8 @@ private:
ActivityReport m_report; ActivityReport m_report;
// TODO!!!!!! REPLACE WITH A PROPER X-THREAD ASIO SIGNAL SYSTEM (could just be condition variables) // TODO!!!!!! REPLACE WITH A PROPER X-THREAD ASIO SIGNAL SYSTEM (could just be condition variables)
std::condition_variable m_signalled;
Mutex x_signalled;
std::atomic<bool> m_syncTransactionQueue = {false}; std::atomic<bool> m_syncTransactionQueue = {false};
std::atomic<bool> m_syncBlockQueue = {false}; std::atomic<bool> m_syncBlockQueue = {false};
}; };

5
libethereum/ClientBase.cpp

@ -142,6 +142,11 @@ bytes ClientBase::codeAt(Address _a, BlockNumber _block) const
return asOf(_block).code(_a); return asOf(_block).code(_a);
} }
h256 ClientBase::codeHashAt(Address _a, BlockNumber _block) const
{
return asOf(_block).codeHash(_a);
}
map<u256, u256> ClientBase::storageAt(Address _a, BlockNumber _block) const map<u256, u256> ClientBase::storageAt(Address _a, BlockNumber _block) const
{ {
return asOf(_block).storage(_a); return asOf(_block).storage(_a);

2
libethereum/ClientBase.h

@ -92,12 +92,14 @@ public:
using Interface::countAt; using Interface::countAt;
using Interface::stateAt; using Interface::stateAt;
using Interface::codeAt; using Interface::codeAt;
using Interface::codeHashAt;
using Interface::storageAt; using Interface::storageAt;
virtual u256 balanceAt(Address _a, BlockNumber _block) const override; virtual u256 balanceAt(Address _a, BlockNumber _block) const override;
virtual u256 countAt(Address _a, BlockNumber _block) const override; virtual u256 countAt(Address _a, BlockNumber _block) const override;
virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const override; virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const override;
virtual bytes codeAt(Address _a, BlockNumber _block) const override; virtual bytes codeAt(Address _a, BlockNumber _block) const override;
virtual h256 codeHashAt(Address _a, BlockNumber _block) const override;
virtual std::map<u256, u256> storageAt(Address _a, BlockNumber _block) const override; virtual std::map<u256, u256> storageAt(Address _a, BlockNumber _block) const override;
virtual LocalisedLogEntries logs(unsigned _watchId) const override; virtual LocalisedLogEntries logs(unsigned _watchId) const override;

2
libethereum/DownloadMan.cpp

@ -50,7 +50,7 @@ h256Set DownloadSub::nextFetch(unsigned _n)
m_indices.clear(); m_indices.clear();
m_remaining.clear(); m_remaining.clear();
if (!m_man || m_man->chain().empty()) if (!m_man || m_man->chainEmpty())
return h256Set(); return h256Set();
m_asked = (~(m_man->taken() + m_attempted)).lowest(_n); m_asked = (~(m_man->taken() + m_attempted)).lowest(_n);

3
libethereum/DownloadMan.h

@ -143,7 +143,8 @@ public:
return ret; return ret;
} }
h256s chain() const { ReadGuard l(m_lock); return m_chain; } size_t chainSize() const { ReadGuard l(m_lock); return m_chain.size(); }
size_t chainEmpty() const { ReadGuard l(m_lock); return m_chain.empty(); }
void foreachSub(std::function<void(DownloadSub const&)> const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); } void foreachSub(std::function<void(DownloadSub const&)> const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); }
unsigned subCount() const { ReadGuard l(x_subs); return m_subs.size(); } unsigned subCount() const { ReadGuard l(x_subs); return m_subs.size(); }
RangeMask<unsigned> blocksGot() const { ReadGuard l(m_lock); return m_blocksGot; } RangeMask<unsigned> blocksGot() const { ReadGuard l(m_lock); return m_blocksGot; }

2
libethereum/EthereumHost.cpp

@ -122,7 +122,7 @@ void EthereumHost::noteDoneBlocks(EthereumPeer* _who, bool _clemency)
// Done our chain-get. // Done our chain-get.
clog(NetNote) << "Chain download complete."; clog(NetNote) << "Chain download complete.";
// 1/100th for each useful block hash. // 1/100th for each useful block hash.
_who->addRating(m_man.chain().size() / 100); _who->addRating(m_man.chainSize() / 100);
m_man.reset(); m_man.reset();
} }
else if (_who->isSyncing()) else if (_who->isSyncing())

19
libethereum/EthereumPeer.cpp

@ -329,9 +329,10 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
case GetTransactionsPacket: break; // DEPRECATED. case GetTransactionsPacket: break; // DEPRECATED.
case TransactionsPacket: case TransactionsPacket:
{ {
clog(NetAllDetail) << "Transactions (" << dec << _r.itemCount() << "entries)"; unsigned itemCount = _r.itemCount();
clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)";
Guard l(x_knownTransactions); Guard l(x_knownTransactions);
for (unsigned i = 0; i < _r.itemCount(); ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
auto h = sha3(_r[i].data()); auto h = sha3(_r[i].data());
m_knownTransactions.insert(h); m_knownTransactions.insert(h);
@ -373,21 +374,22 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
} }
case BlockHashesPacket: case BlockHashesPacket:
{ {
clog(NetMessageSummary) << "BlockHashes (" << dec << _r.itemCount() << "entries)" << (_r.itemCount() ? "" : ": NoMoreHashes"); unsigned itemCount = _r.itemCount();
clog(NetMessageSummary) << "BlockHashes (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreHashes");
if (m_asking != Asking::Hashes) if (m_asking != Asking::Hashes)
{ {
cwarn << "Peer giving us hashes when we didn't ask for them."; cwarn << "Peer giving us hashes when we didn't ask for them.";
break; break;
} }
if (_r.itemCount() == 0) if (itemCount == 0)
{ {
transition(Asking::Blocks); transition(Asking::Blocks);
return true; return true;
} }
unsigned knowns = 0; unsigned knowns = 0;
unsigned unknowns = 0; unsigned unknowns = 0;
for (unsigned i = 0; i < _r.itemCount(); ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
addRating(1); addRating(1);
auto h = _r[i].toHash<h256>(); auto h = _r[i].toHash<h256>();
@ -454,12 +456,13 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
} }
case BlocksPacket: case BlocksPacket:
{ {
clog(NetMessageSummary) << "Blocks (" << dec << _r.itemCount() << "entries)" << (_r.itemCount() ? "" : ": NoMoreBlocks"); unsigned itemCount = _r.itemCount();
clog(NetMessageSummary) << "Blocks (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreBlocks");
if (m_asking != Asking::Blocks) if (m_asking != Asking::Blocks)
clog(NetWarn) << "Unexpected Blocks received!"; clog(NetWarn) << "Unexpected Blocks received!";
if (_r.itemCount() == 0) if (itemCount == 0)
{ {
// Got to this peer's latest block - just give up. // Got to this peer's latest block - just give up.
transition(Asking::Nothing); transition(Asking::Nothing);
@ -472,7 +475,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
unsigned got = 0; unsigned got = 0;
unsigned repeated = 0; unsigned repeated = 0;
for (unsigned i = 0; i < _r.itemCount(); ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
auto h = BlockInfo::headerHash(_r[i].data()); auto h = BlockInfo::headerHash(_r[i].data());
if (m_sub.noteBlock(h)) if (m_sub.noteBlock(h))

3
libethereum/Interface.h

@ -25,7 +25,6 @@
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>
#include <libethcore/Params.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include "LogFilter.h" #include "LogFilter.h"
#include "Transaction.h" #include "Transaction.h"
@ -100,12 +99,14 @@ public:
u256 countAt(Address _a) const { return countAt(_a, m_default); } u256 countAt(Address _a) const { return countAt(_a, m_default); }
u256 stateAt(Address _a, u256 _l) const { return stateAt(_a, _l, m_default); } u256 stateAt(Address _a, u256 _l) const { return stateAt(_a, _l, m_default); }
bytes codeAt(Address _a) const { return codeAt(_a, m_default); } bytes codeAt(Address _a) const { return codeAt(_a, m_default); }
h256 codeHashAt(Address _a) const { return codeHashAt(_a, m_default); }
std::map<u256, u256> storageAt(Address _a) const { return storageAt(_a, m_default); } std::map<u256, u256> storageAt(Address _a) const { return storageAt(_a, m_default); }
virtual u256 balanceAt(Address _a, BlockNumber _block) const = 0; virtual u256 balanceAt(Address _a, BlockNumber _block) const = 0;
virtual u256 countAt(Address _a, BlockNumber _block) const = 0; virtual u256 countAt(Address _a, BlockNumber _block) const = 0;
virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const = 0; virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const = 0;
virtual bytes codeAt(Address _a, BlockNumber _block) const = 0; virtual bytes codeAt(Address _a, BlockNumber _block) const = 0;
virtual h256 codeHashAt(Address _a, BlockNumber _block) const = 0;
virtual std::map<u256, u256> storageAt(Address _a, BlockNumber _block) const = 0; virtual std::map<u256, u256> storageAt(Address _a, BlockNumber _block) const = 0;
// [LOGS API] // [LOGS API]

2
libethereum/Precompiled.cpp

@ -24,7 +24,7 @@
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libdevcrypto/Common.h> #include <libdevcrypto/Common.h>
#include <libethcore/Common.h> #include <libethcore/Common.h>
#include <libethcore/Params.h> #include <libevmcore/Params.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;

1
libethereum/State.h

@ -31,7 +31,6 @@
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libethcore/Miner.h> #include <libethcore/Miner.h>
#include <libethcore/Params.h>
#include <libevm/ExtVMFace.h> #include <libevm/ExtVMFace.h>
#include "TransactionQueue.h" #include "TransactionQueue.h"
#include "Account.h" #include "Account.h"

2
libethereum/Transaction.h

@ -24,7 +24,7 @@
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libethcore/Common.h> #include <libethcore/Common.h>
#include <libethcore/Params.h> #include <libevmcore/Params.h>
namespace dev namespace dev
{ {
namespace eth namespace eth

1
libethereum/TransactionQueue.cpp

@ -36,7 +36,6 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb
h256 h = sha3(_transactionRLP); h256 h = sha3(_transactionRLP);
UpgradableGuard l(m_lock); UpgradableGuard l(m_lock);
// TODO: keep old transactions around and check in State for nonce validity
auto ir = check_WITH_LOCK(h, _ik); auto ir = check_WITH_LOCK(h, _ik);
if (ir != ImportResult::Success) if (ir != ImportResult::Success)

2
libevm/VM.h

@ -27,7 +27,7 @@
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include <libethcore/Params.h> #include <libevmcore/Params.h>
#include "VMFace.h" #include "VMFace.h"
namespace dev namespace dev

4
libevmcore/Assembly.cpp → libevmasm/Assembly.cpp

@ -22,8 +22,8 @@
#include "Assembly.h" #include "Assembly.h"
#include <fstream> #include <fstream>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libevmcore/CommonSubexpressionEliminator.h> #include <libevmasm/CommonSubexpressionEliminator.h>
#include <libevmcore/ControlFlowGraph.h> #include <libevmasm/ControlFlowGraph.h>
#include <json/json.h> #include <json/json.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

4
libevmcore/Assembly.h → libevmasm/Assembly.h

@ -25,9 +25,9 @@
#include <sstream> #include <sstream>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Assertions.h> #include <libdevcore/Assertions.h>
#include <libevmcore/SourceLocation.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevmcore/AssemblyItem.h> #include <libevmasm/SourceLocation.h>
#include <libevmasm/AssemblyItem.h>
#include "Exceptions.h" #include "Exceptions.h"
#include <json/json.h> #include <json/json.h>

0
libevmcore/AssemblyItem.cpp → libevmasm/AssemblyItem.cpp

2
libevmcore/AssemblyItem.h → libevmasm/AssemblyItem.h

@ -25,8 +25,8 @@
#include <sstream> #include <sstream>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Assertions.h> #include <libdevcore/Assertions.h>
#include <libevmcore/SourceLocation.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevmasm/SourceLocation.h>
#include "Exceptions.h" #include "Exceptions.h"
namespace dev namespace dev

33
libevmasm/CMakeLists.txt

@ -0,0 +1,33 @@
cmake_policy(SET CMP0015 NEW)
# this policy was introduced in cmake 3.0
# remove if, once 3.0 will be used on unix
if (${CMAKE_MAJOR_VERSION} GREATER 2)
# old policy do not use MACOSX_RPATH
cmake_policy(SET CMP0042 OLD)
endif()
set(CMAKE_AUTOMOC OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB")
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})
set(EXECUTABLE evmasm)
file(GLOB HEADERS "*.h")
if (ETH_STATIC)
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcrypto)
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

4
libevmcore/CommonSubexpressionEliminator.cpp → libevmasm/CommonSubexpressionEliminator.cpp

@ -24,8 +24,8 @@
#include <functional> #include <functional>
#include <boost/range/adaptor/reversed.hpp> #include <boost/range/adaptor/reversed.hpp>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libevmcore/CommonSubexpressionEliminator.h> #include <libevmasm/CommonSubexpressionEliminator.h>
#include <libevmcore/AssemblyItem.h> #include <libevmasm/AssemblyItem.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

4
libevmcore/CommonSubexpressionEliminator.h → libevmasm/CommonSubexpressionEliminator.h

@ -30,8 +30,8 @@
#include <ostream> #include <ostream>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libevmcore/ExpressionClasses.h> #include <libevmasm/ExpressionClasses.h>
#include <libevmcore/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
namespace dev namespace dev
{ {

8
libevmcore/ControlFlowGraph.cpp → libevmasm/ControlFlowGraph.cpp

@ -21,11 +21,11 @@
* Control flow analysis for the optimizer. * Control flow analysis for the optimizer.
*/ */
#include <libevmcore/ControlFlowGraph.h> #include <libevmasm/ControlFlowGraph.h>
#include <map> #include <map>
#include <libevmcore/Exceptions.h> #include <libevmasm/Exceptions.h>
#include <libevmcore/AssemblyItem.h> #include <libevmasm/AssemblyItem.h>
#include <libevmcore/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

0
libevmcore/ControlFlowGraph.h → libevmasm/ControlFlowGraph.h

36
libevmasm/Exceptions.h

@ -0,0 +1,36 @@
/*
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 Exceptions.h
* @author Christian <c@ethdev.com>
* @date 2014
*/
#pragma once
#include <libdevcore/Exceptions.h>
namespace dev
{
namespace eth
{
struct AssemblyException: virtual Exception {};
struct OptimizerException: virtual AssemblyException {};
struct StackTooDeepException: virtual OptimizerException {};
}
}

6
libevmcore/ExpressionClasses.cpp → libevmasm/ExpressionClasses.cpp

@ -21,14 +21,14 @@
* Container for equivalence classes of expressions for use in common subexpression elimination. * Container for equivalence classes of expressions for use in common subexpression elimination.
*/ */
#include <libevmcore/ExpressionClasses.h> #include <libevmasm/ExpressionClasses.h>
#include <utility> #include <utility>
#include <tuple> #include <tuple>
#include <functional> #include <functional>
#include <boost/range/adaptor/reversed.hpp> #include <boost/range/adaptor/reversed.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <libevmcore/Assembly.h> #include <libevmasm/Assembly.h>
#include <libevmcore/CommonSubexpressionEliminator.h> #include <libevmasm/CommonSubexpressionEliminator.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

2
libevmcore/ExpressionClasses.h → libevmasm/ExpressionClasses.h

@ -27,7 +27,7 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libevmcore/AssemblyItem.h> #include <libevmasm/AssemblyItem.h>
namespace dev namespace dev
{ {

4
libevmcore/SemanticInformation.cpp → libevmasm/SemanticInformation.cpp

@ -21,8 +21,8 @@
* Helper to provide semantic information about assembly items. * Helper to provide semantic information about assembly items.
*/ */
#include <libevmcore/SemanticInformation.h> #include <libevmasm/SemanticInformation.h>
#include <libevmcore/AssemblyItem.h> #include <libevmasm/AssemblyItem.h>
using namespace std; using namespace std;
using namespace dev; using namespace dev;

0
libevmcore/SemanticInformation.h → libevmasm/SemanticInformation.h

0
libevmcore/SourceLocation.h → libevmasm/SourceLocation.h

4
libevmcore/CMakeLists.txt

@ -7,11 +7,8 @@ if (${CMAKE_MAJOR_VERSION} GREATER 2)
endif() endif()
set(CMAKE_AUTOMOC OFF) set(CMAKE_AUTOMOC OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB")
aux_source_directory(. SRC_LIST) aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
@ -22,7 +19,6 @@ file(GLOB HEADERS "*.h")
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} devcrypto)
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

7
libevmcore/Exceptions.h

@ -28,11 +28,8 @@ namespace dev
namespace eth namespace eth
{ {
struct AssemblyException: virtual Exception {}; struct InvalidDeposit: virtual Exception {};
struct InvalidDeposit: virtual AssemblyException {}; struct InvalidOpcode: virtual Exception {};
struct InvalidOpcode: virtual AssemblyException {};
struct OptimizerException: virtual AssemblyException {};
struct StackTooDeepException: virtual OptimizerException {};
} }
} }

69
libevmcore/Params.cpp

@ -0,0 +1,69 @@
/*
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 Params.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "Params.h"
using namespace std;
namespace dev
{
namespace eth
{
//--- BEGIN: AUTOGENERATED FROM github.com/ethereum/common/params.json
u256 const c_stackLimit = 1024;
u256 const c_tierStepGas[] = {0, 2, 3, 5, 8, 10, 20, 0};
u256 const c_expGas = 10;
u256 const c_expByteGas = 10;
u256 const c_sha3Gas = 30;
u256 const c_sha3WordGas = 6;
u256 const c_sloadGas = 50;
u256 const c_sstoreSetGas = 20000;
u256 const c_sstoreResetGas = 5000;
u256 const c_sstoreRefundGas = 15000;
u256 const c_jumpdestGas = 1;
u256 const c_logGas = 375;
u256 const c_logDataGas = 8;
u256 const c_logTopicGas = 375;
u256 const c_createGas = 32000;
u256 const c_callGas = 40;
u256 const c_callStipend = 2300;
u256 const c_callValueTransferGas = 9000;
u256 const c_callNewAccountGas = 25000;
u256 const c_suicideRefundGas = 24000;
u256 const c_memoryGas = 3;
u256 const c_quadCoeffDiv = 512;
u256 const c_createDataGas = 200;
u256 const c_txGas = 21000;
u256 const c_txDataZeroGas = 4;
u256 const c_txDataNonZeroGas = 68;
u256 const c_copyGas = 3;
u256 const c_ecrecoverGas = 3000;
u256 const c_sha256Gas = 60;
u256 const c_sha256WordGas = 12;
u256 const c_ripemd160Gas = 600;
u256 const c_ripemd160WordGas = 120;
u256 const c_identityGas = 15;
u256 const c_identityWordGas = 3;
//--- END: AUTOGENERATED FROM /feeStructure.json
}
}

69
libevmcore/Params.h

@ -0,0 +1,69 @@
/*
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 Params.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <libdevcore/Common.h>
namespace dev
{
namespace eth
{
//--- BEGIN: AUTOGENERATED FROM /feeStructure.json
extern u256 const c_stackLimit;
extern u256 const c_tierStepGas[8]; ///< Once per operation, for a selection of them.
extern u256 const c_expGas; ///< Once per EXP instuction.
extern u256 const c_expByteGas; ///< Times ceil(log256(exponent)) for the EXP instruction.
extern u256 const c_sha3Gas; ///< Once per SHA3 operation.
extern u256 const c_sha3WordGas; ///< Once per word of the SHA3 operation's data.
extern u256 const c_copyGas; ///< Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
extern u256 const c_sloadGas; ///< Once per SLOAD operation.
extern u256 const c_sstoreSetGas; ///< Once per SSTORE operation if the zeroness changes from zero.
extern u256 const c_sstoreResetGas; ///< Once per SSTORE operation if the zeroness does not change from zero. NOTE: when c_sstoreSetGas does not apply.
extern u256 const c_sstoreRefundGas; ///< Refunded gas, once per SSTORE operation if the zeroness changes to zero.
extern u256 const c_jumpdestGas; ///< Once per JUMPDEST operation.
extern u256 const c_logGas; ///< Per LOG* operation.
extern u256 const c_logDataGas; ///< Per byte in a LOG* operation's data.
extern u256 const c_logTopicGas; ///< Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
extern u256 const c_createGas; ///< Once per CREATE operation & contract-creation transaction.
extern u256 const c_createDataGas;
extern u256 const c_callGas; ///< Once per CALL operation & message call transaction.
extern u256 const c_callStipend; ///< Free gas given at beginning of call.
extern u256 const c_callNewAccountGas; ///< Paid for CALL when the destination address didn't exist prior.
extern u256 const c_callValueTransferGas; ///< Paid for CALL when the value transfor is non-zero.
extern u256 const c_suicideRefundGas; ///< Refunded following a suicide operation.
extern u256 const c_memoryGas; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
extern u256 const c_quadCoeffDiv; ///< Divisor for the quadratic particle of the memory cost equation.
extern u256 const c_txGas; ///< Per transaction. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataZeroGas; ///< Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataNonZeroGas; ///< Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_ecrecoverGas;
extern u256 const c_sha256Gas;
extern u256 const c_sha256WordGas;
extern u256 const c_ripemd160Gas;
extern u256 const c_ripemd160WordGas;
extern u256 const c_identityGas;
extern u256 const c_identityWordGas;
}
}

2
libjsqrc/setup.js

@ -21,5 +21,5 @@
*/ */
var web3 = require('web3'); var web3 = require('web3');
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8080")); web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));

3
liblll/CMakeLists.txt

@ -21,8 +21,7 @@ file(GLOB HEADERS "*.h")
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmasm)
target_link_libraries(${EXECUTABLE} devcore)
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

2
liblll/CodeFragment.h

@ -23,7 +23,7 @@
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevmcore/Assembly.h> #include <libevmasm/Assembly.h>
#include "Exceptions.h" #include "Exceptions.h"
namespace boost { namespace spirit { class utree; } } namespace boost { namespace spirit { class utree; } }

6
libp2p/Host.cpp

@ -226,7 +226,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io
return; return;
} }
if (peerCount() > 2 * m_idealPeerCount) if (peerCount() > 9 * m_idealPeerCount)
{ {
ps->disconnect(TooManyPeers); ps->disconnect(TooManyPeers);
return; return;
@ -341,7 +341,7 @@ void Host::runAcceptor()
auto socket = make_shared<RLPXSocket>(new bi::tcp::socket(m_ioService)); auto socket = make_shared<RLPXSocket>(new bi::tcp::socket(m_ioService));
m_tcp4Acceptor.async_accept(socket->ref(), [=](boost::system::error_code ec) m_tcp4Acceptor.async_accept(socket->ref(), [=](boost::system::error_code ec)
{ {
if (peerCount() > 2 * m_idealPeerCount) if (peerCount() > 9 * m_idealPeerCount)
{ {
clog(NetConnect) << "Dropping incoming connect due to maximum peer count (2 * ideal peer count): " << socket->remoteEndpoint(); clog(NetConnect) << "Dropping incoming connect due to maximum peer count (2 * ideal peer count): " << socket->remoteEndpoint();
socket->close(); socket->close();
@ -464,7 +464,7 @@ void Host::connect(std::shared_ptr<Peer> const& _p)
return; return;
} }
if (!m_nodeTable->haveNode(_p->id)) if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id))
{ {
clog(NetWarn) << "Aborted connect. Node not in node table."; clog(NetWarn) << "Aborted connect. Node not in node table.";
m_nodeTable->addNode(*_p.get()); m_nodeTable->addNode(*_p.get());

28
libsolidity/AST.cpp

@ -96,8 +96,8 @@ void ContractDefinition::checkTypeRequirements()
FixedHash<4> const& hash = it.first; FixedHash<4> const& hash = it.first;
if (hashes.count(hash)) if (hashes.count(hash))
BOOST_THROW_EXCEPTION(createTypeError( BOOST_THROW_EXCEPTION(createTypeError(
std::string("Function signature hash collision for ") + string("Function signature hash collision for ") + it.second->externalSignature()
it.second->externalSignature())); ));
hashes.insert(hash); hashes.insert(hash);
} }
} }
@ -140,12 +140,22 @@ void ContractDefinition::checkDuplicateFunctions() const
map<string, vector<FunctionDefinition const*>> functions; map<string, vector<FunctionDefinition const*>> functions;
for (ASTPointer<FunctionDefinition> const& function: getDefinedFunctions()) for (ASTPointer<FunctionDefinition> const& function: getDefinedFunctions())
functions[function->getName()].push_back(function.get()); functions[function->getName()].push_back(function.get());
if (functions[getName()].size() > 1) if (functions[getName()].size() > 1)
{
SecondarySourceLocation ssl;
auto it = functions[getName()].begin();
++it;
for (; it != functions[getName()].end(); ++it)
ssl.append("Another declaration is here:", (*it)->getLocation());
BOOST_THROW_EXCEPTION( BOOST_THROW_EXCEPTION(
DeclarationError() << DeclarationError() <<
errinfo_sourceLocation(getLocation()) << errinfo_sourceLocation(functions[getName()].front()->getLocation()) <<
errinfo_comment("More than one constructor defined.") errinfo_comment("More than one constructor defined.") <<
errinfo_secondarySourceLocation(ssl)
); );
}
for (auto const& it: functions) for (auto const& it: functions)
{ {
vector<FunctionDefinition const*> const& overloads = it.second; vector<FunctionDefinition const*> const& overloads = it.second;
@ -155,7 +165,9 @@ void ContractDefinition::checkDuplicateFunctions() const
BOOST_THROW_EXCEPTION( BOOST_THROW_EXCEPTION(
DeclarationError() << DeclarationError() <<
errinfo_sourceLocation(overloads[j]->getLocation()) << errinfo_sourceLocation(overloads[j]->getLocation()) <<
errinfo_comment("Function with same name and arguments already defined.") errinfo_comment("Function with same name and arguments defined twice.") <<
errinfo_secondarySourceLocation(SecondarySourceLocation().append(
"Other declaration is here:", overloads[i]->getLocation()))
); );
} }
} }
@ -299,12 +311,12 @@ void ContractDefinition::checkExternalTypeClashes() const
)); ));
} }
std::vector<ASTPointer<EventDefinition>> const& ContractDefinition::getInterfaceEvents() const vector<ASTPointer<EventDefinition>> const& ContractDefinition::getInterfaceEvents() const
{ {
if (!m_interfaceEvents) if (!m_interfaceEvents)
{ {
set<string> eventsSeen; set<string> eventsSeen;
m_interfaceEvents.reset(new std::vector<ASTPointer<EventDefinition>>()); m_interfaceEvents.reset(new vector<ASTPointer<EventDefinition>>());
for (ContractDefinition const* contract: getLinearizedBaseContracts()) for (ContractDefinition const* contract: getLinearizedBaseContracts())
for (ASTPointer<EventDefinition> const& e: contract->getEvents()) for (ASTPointer<EventDefinition> const& e: contract->getEvents())
if (eventsSeen.count(e->getName()) == 0) if (eventsSeen.count(e->getName()) == 0)
@ -944,7 +956,7 @@ void Identifier::overloadResolution(TypePointers const& _argumentTypes)
solAssert(!m_referencedDeclaration, "Referenced declaration should be null before overload resolution."); solAssert(!m_referencedDeclaration, "Referenced declaration should be null before overload resolution.");
solAssert(!m_overloadedDeclarations.empty(), "No candidates for overload resolution found."); solAssert(!m_overloadedDeclarations.empty(), "No candidates for overload resolution found.");
std::vector<Declaration const*> possibles; vector<Declaration const*> possibles;
if (m_overloadedDeclarations.size() == 1) if (m_overloadedDeclarations.size() == 1)
m_referencedDeclaration = *m_overloadedDeclarations.begin(); m_referencedDeclaration = *m_overloadedDeclarations.begin();

2
libsolidity/AST.h

@ -27,7 +27,7 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
#include <libsolidity/Utils.h> #include <libsolidity/Utils.h>
#include <libsolidity/ASTForward.h> #include <libsolidity/ASTForward.h>
#include <libsolidity/Token.h> #include <libsolidity/Token.h>

2
libsolidity/ASTUtils.h

@ -22,7 +22,7 @@
#pragma once #pragma once
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
#include <libsolidity/ASTVisitor.h> #include <libsolidity/ASTVisitor.h>
namespace dev namespace dev

2
libsolidity/CMakeLists.txt

@ -22,7 +22,7 @@ file(GLOB HEADERS "*.h")
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmasm)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )

7
libsolidity/Compiler.cpp

@ -24,7 +24,7 @@
#include <algorithm> #include <algorithm>
#include <boost/range/adaptor/reversed.hpp> #include <boost/range/adaptor/reversed.hpp>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevmcore/Assembly.h> #include <libevmasm/Assembly.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include <libsolidity/ExpressionCompiler.h> #include <libsolidity/ExpressionCompiler.h>
#include <libsolidity/CompilerUtils.h> #include <libsolidity/CompilerUtils.h>
@ -431,7 +431,8 @@ bool Compiler::visit(ForStatement const& _forStatement)
CompilerContext::LocationSetter locationSetter(m_context, _forStatement); CompilerContext::LocationSetter locationSetter(m_context, _forStatement);
eth::AssemblyItem loopStart = m_context.newTag(); eth::AssemblyItem loopStart = m_context.newTag();
eth::AssemblyItem loopEnd = m_context.newTag(); eth::AssemblyItem loopEnd = m_context.newTag();
m_continueTags.push_back(loopStart); eth::AssemblyItem loopNext = m_context.newTag();
m_continueTags.push_back(loopNext);
m_breakTags.push_back(loopEnd); m_breakTags.push_back(loopEnd);
if (_forStatement.getInitializationExpression()) if (_forStatement.getInitializationExpression())
@ -449,6 +450,8 @@ bool Compiler::visit(ForStatement const& _forStatement)
_forStatement.getBody().accept(*this); _forStatement.getBody().accept(*this);
m_context << loopNext;
// for's loop expression if existing // for's loop expression if existing
if (_forStatement.getLoopExpression()) if (_forStatement.getLoopExpression())
_forStatement.getLoopExpression()->accept(*this); _forStatement.getLoopExpression()->accept(*this);

2
libsolidity/Compiler.h

@ -26,7 +26,7 @@
#include <functional> #include <functional>
#include <libsolidity/ASTVisitor.h> #include <libsolidity/ASTVisitor.h>
#include <libsolidity/CompilerContext.h> #include <libsolidity/CompilerContext.h>
#include <libevmcore/Assembly.h> #include <libevmasm/Assembly.h>
namespace dev { namespace dev {
namespace solidity { namespace solidity {

2
libsolidity/CompilerContext.h

@ -26,7 +26,7 @@
#include <stack> #include <stack>
#include <utility> #include <utility>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevmcore/Assembly.h> #include <libevmasm/Assembly.h>
#include <libsolidity/ASTForward.h> #include <libsolidity/ASTForward.h>
#include <libsolidity/Types.h> #include <libsolidity/Types.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>

42
libsolidity/DeclarationContainer.cpp

@ -28,6 +28,28 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace dev::solidity; using namespace dev::solidity;
Declaration const* DeclarationContainer::conflictingDeclaration(Declaration const& _declaration) const
{
ASTString const& name(_declaration.getName());
solAssert(!name.empty(), "");
vector<Declaration const*> declarations;
if (m_declarations.count(name))
declarations += m_declarations.at(name);
if (m_invisibleDeclarations.count(name))
declarations += m_invisibleDeclarations.at(name);
if (dynamic_cast<FunctionDefinition const*>(&_declaration))
{
// check that all other declarations with the same name are functions
for (Declaration const* declaration: declarations)
if (!dynamic_cast<FunctionDefinition const*>(declaration))
return declaration;
}
else if (!declarations.empty())
return declarations.front();
return nullptr;
}
bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _invisible, bool _update) bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _invisible, bool _update)
{ {
ASTString const& name(_declaration.getName()); ASTString const& name(_declaration.getName());
@ -40,24 +62,8 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration,
m_declarations.erase(name); m_declarations.erase(name);
m_invisibleDeclarations.erase(name); m_invisibleDeclarations.erase(name);
} }
else else if (conflictingDeclaration(_declaration))
{ return false;
vector<Declaration const*> declarations;
if (m_declarations.count(name))
declarations += m_declarations.at(name);
if (m_invisibleDeclarations.count(name))
declarations += m_invisibleDeclarations.at(name);
if (dynamic_cast<FunctionDefinition const*>(&_declaration))
{
// check that all other declarations with the same name are functions
for (Declaration const* declaration: declarations)
if (!dynamic_cast<FunctionDefinition const*>(declaration))
return false;
}
else if (!declarations.empty())
return false;
}
if (_invisible) if (_invisible)
m_invisibleDeclarations[name].insert(&_declaration); m_invisibleDeclarations[name].insert(&_declaration);

4
libsolidity/DeclarationContainer.h

@ -34,7 +34,7 @@ namespace solidity
{ {
/** /**
* Container that stores mappings betwee names and declarations. It also contains a link to the * Container that stores mappings between names and declarations. It also contains a link to the
* enclosing scope. * enclosing scope.
*/ */
class DeclarationContainer class DeclarationContainer
@ -51,6 +51,8 @@ public:
std::set<Declaration const*> resolveName(ASTString const& _name, bool _recursive = false) const; std::set<Declaration const*> resolveName(ASTString const& _name, bool _recursive = false) const;
Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; } Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; }
std::map<ASTString, std::set<Declaration const*>> const& getDeclarations() const { return m_declarations; } std::map<ASTString, std::set<Declaration const*>> const& getDeclarations() const { return m_declarations; }
/// @returns whether declaration is valid, and if not also returns previous declaration.
Declaration const* conflictingDeclaration(Declaration const& _declaration) const;
private: private:
Declaration const* m_enclosingDeclaration; Declaration const* m_enclosingDeclaration;

18
libsolidity/Exceptions.h

@ -23,8 +23,9 @@
#pragma once #pragma once
#include <string> #include <string>
#include <utility>
#include <libdevcore/Exceptions.h> #include <libdevcore/Exceptions.h>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
namespace dev namespace dev
{ {
@ -38,7 +39,22 @@ struct CompilerError: virtual Exception {};
struct InternalCompilerError: virtual Exception {}; struct InternalCompilerError: virtual Exception {};
struct DocstringParsingError: virtual Exception {}; struct DocstringParsingError: virtual Exception {};
using errorSourceLocationInfo = std::pair<std::string, SourceLocation>;
class SecondarySourceLocation
{
public:
SecondarySourceLocation& append(std::string const& _errMsg, SourceLocation const& _sourceLocation)
{
infos.push_back(std::make_pair(_errMsg, _sourceLocation));
return *this;
}
std::vector<errorSourceLocationInfo> infos;
};
using errinfo_sourceLocation = boost::error_info<struct tag_sourceLocation, SourceLocation>; using errinfo_sourceLocation = boost::error_info<struct tag_sourceLocation, SourceLocation>;
using errinfo_secondarySourceLocation = boost::error_info<struct tag_secondarySourceLocation, SecondarySourceLocation>;
} }
} }

2
libsolidity/ExpressionCompiler.h

@ -25,7 +25,7 @@
#include <memory> #include <memory>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
#include <libsolidity/Utils.h> #include <libsolidity/Utils.h>
#include <libsolidity/ASTVisitor.h> #include <libsolidity/ASTVisitor.h>
#include <libsolidity/LValue.h> #include <libsolidity/LValue.h>

2
libsolidity/LValue.h

@ -23,7 +23,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
#include <libsolidity/ArrayUtils.h> #include <libsolidity/ArrayUtils.h>
namespace dev namespace dev

37
libsolidity/NameAndTypeResolver.cpp

@ -354,9 +354,33 @@ void DeclarationRegistrationHelper::closeCurrentScope()
void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope) void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope)
{ {
if (!m_scopes[m_currentScope].registerDeclaration(_declaration, !_declaration.isVisibleInContract())) if (!m_scopes[m_currentScope].registerDeclaration(_declaration, !_declaration.isVisibleInContract()))
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_declaration.getLocation()) {
<< errinfo_comment("Identifier already declared.")); SourceLocation firstDeclarationLocation;
//@todo the exception should also contain the location of the first declaration SourceLocation secondDeclarationLocation;
Declaration const* conflictingDeclaration = m_scopes[m_currentScope].conflictingDeclaration(_declaration);
solAssert(conflictingDeclaration, "");
if (_declaration.getLocation().start < conflictingDeclaration->getLocation().start)
{
firstDeclarationLocation = _declaration.getLocation();
secondDeclarationLocation = conflictingDeclaration->getLocation();
}
else
{
firstDeclarationLocation = conflictingDeclaration->getLocation();
secondDeclarationLocation = _declaration.getLocation();
}
BOOST_THROW_EXCEPTION(
DeclarationError() <<
errinfo_sourceLocation(secondDeclarationLocation) <<
errinfo_comment("Identifier already declared.") <<
errinfo_secondarySourceLocation(
SecondarySourceLocation().append("The previous declaration is here:", firstDeclarationLocation)
)
);
}
_declaration.setScope(m_currentScope); _declaration.setScope(m_currentScope);
if (_opensScope) if (_opensScope)
enterNewSubScope(_declaration); enterNewSubScope(_declaration);
@ -435,8 +459,11 @@ bool ReferencesResolver::visit(Identifier& _identifier)
{ {
auto declarations = m_resolver.getNameFromCurrentScope(_identifier.getName()); auto declarations = m_resolver.getNameFromCurrentScope(_identifier.getName());
if (declarations.empty()) if (declarations.empty())
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_identifier.getLocation()) BOOST_THROW_EXCEPTION(
<< errinfo_comment("Undeclared identifier.")); DeclarationError() <<
errinfo_sourceLocation(_identifier.getLocation()) <<
errinfo_comment("Undeclared identifier.")
);
else if (declarations.size() == 1) else if (declarations.size() == 1)
_identifier.setReferencedDeclaration(**declarations.begin(), m_currentContract); _identifier.setReferencedDeclaration(**declarations.begin(), m_currentContract);
else else

2
libsolidity/Parser.cpp

@ -22,7 +22,7 @@
#include <vector> #include <vector>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
#include <libsolidity/Parser.h> #include <libsolidity/Parser.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/Exceptions.h> #include <libsolidity/Exceptions.h>

2
libsolidity/Scanner.h

@ -55,7 +55,7 @@
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
#include <libsolidity/Token.h> #include <libsolidity/Token.h>
namespace dev namespace dev

74
libsolidity/SourceReferenceFormatter.cpp

@ -32,9 +32,11 @@ namespace dev
namespace solidity namespace solidity
{ {
void SourceReferenceFormatter::printSourceLocation(ostream& _stream, void SourceReferenceFormatter::printSourceLocation(
SourceLocation const& _location, ostream& _stream,
Scanner const& _scanner) SourceLocation const& _location,
Scanner const& _scanner
)
{ {
int startLine; int startLine;
int startColumn; int startColumn;
@ -46,11 +48,11 @@ void SourceReferenceFormatter::printSourceLocation(ostream& _stream,
{ {
string line = _scanner.getLineAtPosition(_location.start); string line = _scanner.getLineAtPosition(_location.start);
_stream << line << endl; _stream << line << endl;
std::for_each(line.cbegin(), line.cbegin() + startColumn, for_each(
[&_stream](char const& ch) line.cbegin(),
{ line.cbegin() + startColumn,
_stream << (ch == '\t' ? '\t' : ' '); [&_stream](char const& ch) { _stream << (ch == '\t' ? '\t' : ' '); }
}); );
_stream << "^"; _stream << "^";
if (endColumn > startColumn + 2) if (endColumn > startColumn + 2)
_stream << string(endColumn - startColumn - 2, '-'); _stream << string(endColumn - startColumn - 2, '-');
@ -59,33 +61,65 @@ void SourceReferenceFormatter::printSourceLocation(ostream& _stream,
_stream << endl; _stream << endl;
} }
else else
_stream << _scanner.getLineAtPosition(_location.start) << endl _stream <<
<< string(startColumn, ' ') << "^\n" _scanner.getLineAtPosition(_location.start) <<
<< "Spanning multiple lines.\n"; endl <<
string(startColumn, ' ') <<
"^\n" <<
"Spanning multiple lines.\n";
} }
void SourceReferenceFormatter::printExceptionInformation(ostream& _stream, void SourceReferenceFormatter::printSourceName(
Exception const& _exception, ostream& _stream,
string const& _name, SourceLocation const& _location,
CompilerStack const& _compiler) Scanner const& _scanner
)
{
int startLine;
int startColumn;
tie(startLine, startColumn) = _scanner.translatePositionToLineColumn(_location.start);
_stream << *_location.sourceName << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": ";
}
void SourceReferenceFormatter::printExceptionInformation(
ostream& _stream,
Exception const& _exception,
string const& _name,
CompilerStack const& _compiler
)
{ {
SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception); SourceLocation const* location = boost::get_error_info<errinfo_sourceLocation>(_exception);
Scanner const* scanner; auto secondarylocation = boost::get_error_info<errinfo_secondarySourceLocation>(_exception);
Scanner const* scanner = nullptr;
if (location) if (location)
{ {
scanner = &_compiler.getScanner(*location->sourceName); scanner = &_compiler.getScanner(*location->sourceName);
int startLine; printSourceName(_stream, *location, *scanner);
int startColumn;
tie(startLine, startColumn) = scanner->translatePositionToLineColumn(location->start);
_stream << *location->sourceName << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": ";
} }
_stream << _name; _stream << _name;
if (string const* description = boost::get_error_info<errinfo_comment>(_exception)) if (string const* description = boost::get_error_info<errinfo_comment>(_exception))
_stream << ": " << *description << endl; _stream << ": " << *description << endl;
if (location) if (location)
{
scanner = &_compiler.getScanner(*location->sourceName);
printSourceLocation(_stream, *location, *scanner); printSourceLocation(_stream, *location, *scanner);
}
if (secondarylocation && !secondarylocation->infos.empty())
{
for (auto info: secondarylocation->infos)
{
scanner = &_compiler.getScanner(*info.second.sourceName);
_stream << info.first << " ";
printSourceName(_stream, info.second, *scanner);
_stream << endl;
printSourceLocation(_stream, info.second, *scanner);
}
_stream << endl;
}
} }
} }

12
libsolidity/SourceReferenceFormatter.h

@ -23,7 +23,7 @@
#pragma once #pragma once
#include <ostream> #include <ostream>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
namespace dev namespace dev
{ {
@ -40,8 +40,14 @@ struct SourceReferenceFormatter
{ {
public: public:
static void printSourceLocation(std::ostream& _stream, SourceLocation const& _location, Scanner const& _scanner); static void printSourceLocation(std::ostream& _stream, SourceLocation const& _location, Scanner const& _scanner);
static void printExceptionInformation(std::ostream& _stream, Exception const& _exception, static void printExceptionInformation(
std::string const& _name, CompilerStack const& _compiler); std::ostream& _stream,
Exception const& _exception,
std::string const& _name,
CompilerStack const& _compiler
);
private:
static void printSourceName(std::ostream& _stream, SourceLocation const& _location, Scanner const& _scanner);
}; };
} }

2
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -54,7 +54,7 @@ const unsigned dev::SensibleHttpThreads = 1;
#else #else
const unsigned dev::SensibleHttpThreads = 4; const unsigned dev::SensibleHttpThreads = 4;
#endif #endif
const unsigned dev::SensibleHttpPort = 8080; const unsigned dev::SensibleHttpPort = 8545;
static Json::Value toJson(dev::eth::BlockInfo const& _bi) static Json::Value toJson(dev::eth::BlockInfo const& _bi)
{ {

14
mix/ClientModel.cpp

@ -422,7 +422,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
//try to resolve contract for source level debugging //try to resolve contract for source level debugging
auto nameIter = m_contractNames.find(code.address); auto nameIter = m_contractNames.find(code.address);
CompiledContract const* compilerRes = nullptr; CompiledContract const* compilerRes = nullptr;
if (nameIter != m_contractNames.end() && (compilerRes = m_codeModel->tryGetContract(nameIter->second))) if (nameIter != m_contractNames.end() && (compilerRes = m_codeModel->tryGetContract(nameIter->second))) //returned object is guaranteed to live till the end of event handler in main thread
{ {
eth::AssemblyItems assemblyItems = !_t.isConstructor() ? compilerRes->assemblyItems() : compilerRes->constructorAssemblyItems(); eth::AssemblyItems assemblyItems = !_t.isConstructor() ? compilerRes->assemblyItems() : compilerRes->constructorAssemblyItems();
codes.back()->setDocument(compilerRes->documentId()); codes.back()->setDocument(compilerRes->documentId());
@ -467,9 +467,9 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
{ {
//track calls into functions //track calls into functions
AssemblyItem const& prevInstruction = codeItems[s.codeIndex][prevInstructionIndex]; AssemblyItem const& prevInstruction = codeItems[s.codeIndex][prevInstructionIndex];
auto functionIter = contract->functions().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end)); QString functionName = m_codeModel->resolveFunctionName(instruction.getLocation());
if (functionIter != contract->functions().end() && ((prevInstruction.getJumpType() == AssemblyItem::JumpType::IntoFunction) || solCallStack.empty())) if (!functionName.isEmpty() && ((prevInstruction.getJumpType() == AssemblyItem::JumpType::IntoFunction) || solCallStack.empty()))
solCallStack.push_front(QVariant::fromValue(functionIter.value())); solCallStack.push_front(QVariant::fromValue(functionName));
else if (prevInstruction.getJumpType() == AssemblyItem::JumpType::OutOfFunction && !solCallStack.empty()) else if (prevInstruction.getJumpType() == AssemblyItem::JumpType::OutOfFunction && !solCallStack.empty())
solCallStack.pop_front(); solCallStack.pop_front();
} }
@ -521,11 +521,13 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
prevInstructionIndex = instructionIndex; prevInstructionIndex = instructionIndex;
// filter out locations that match whole function or contract
SourceLocation location = instruction.getLocation(); SourceLocation location = instruction.getLocation();
if (contract->contract()->location() == location || contract->functions().contains(LocationPair(location.start, location.end))) QString source = QString::fromUtf8(location.sourceName->c_str());
if (m_codeModel->isContractOrFunctionLocation(location))
location = dev::SourceLocation(-1, -1, location.sourceName); location = dev::SourceLocation(-1, -1, location.sourceName);
solState = new QSolState(debugData, move(storage), move(solCallStack), move(locals), location.start, location.end, QString::fromUtf8(location.sourceName->c_str())); solState = new QSolState(debugData, move(storage), move(solCallStack), move(locals), location.start, location.end, source);
} }
states.append(QVariant::fromValue(new QMachineState(debugData, instructionIndex, s, codes[s.codeIndex], data[s.dataIndex], solState))); states.append(QVariant::fromValue(new QMachineState(debugData, instructionIndex, s, codes[s.codeIndex], data[s.dataIndex], solState)));

96
mix/CodeModel.cpp

@ -26,7 +26,7 @@
#include <QApplication> #include <QApplication>
#include <QtQml> #include <QtQml>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include <libsolidity/Types.h> #include <libsolidity/Types.h>
#include <libsolidity/ASTVisitor.h> #include <libsolidity/ASTVisitor.h>
@ -51,30 +51,31 @@ const std::set<std::string> c_predefinedContracts =
namespace namespace
{ {
using namespace dev::solidity; using namespace dev::solidity;
class CollectDeclarationsVisitor: public ASTConstVisitor
class CollectLocalsVisitor: public ASTConstVisitor
{ {
public: public:
CollectDeclarationsVisitor(QHash<LocationPair, QString>* _functions, QHash<LocationPair, SolidityDeclaration>* _locals): CollectLocalsVisitor(QHash<LocationPair, SolidityDeclaration>* _locals):
m_functions(_functions), m_locals(_locals), m_functionScope(false) {} m_locals(_locals), m_functionScope(false) {}
private: private:
LocationPair nodeLocation(ASTNode const& _node) LocationPair nodeLocation(ASTNode const& _node)
{ {
return LocationPair(_node.getLocation().start, _node.getLocation().end); return LocationPair(_node.getLocation().start, _node.getLocation().end);
} }
virtual bool visit(FunctionDefinition const& _node) virtual bool visit(FunctionDefinition const&)
{ {
m_functions->insert(nodeLocation(_node), QString::fromStdString(_node.getName()));
m_functionScope = true; m_functionScope = true;
return true; return true;
} }
virtual void endVisit(FunctionDefinition const&) virtual void endVisit(FunctionDefinition const&) override
{ {
m_functionScope = false; m_functionScope = false;
} }
virtual bool visit(VariableDeclaration const& _node) virtual bool visit(VariableDeclaration const& _node) override
{ {
SolidityDeclaration decl; SolidityDeclaration decl;
decl.type = CodeModel::nodeType(_node.getType().get()); decl.type = CodeModel::nodeType(_node.getType().get());
@ -87,11 +88,38 @@ private:
} }
private: private:
QHash<LocationPair, QString>* m_functions;
QHash<LocationPair, SolidityDeclaration>* m_locals; QHash<LocationPair, SolidityDeclaration>* m_locals;
bool m_functionScope; bool m_functionScope;
}; };
class CollectLocationsVisitor: public ASTConstVisitor
{
public:
CollectLocationsVisitor(SourceMap* _sourceMap):
m_sourceMap(_sourceMap) {}
private:
LocationPair nodeLocation(ASTNode const& _node)
{
return LocationPair(_node.getLocation().start, _node.getLocation().end);
}
virtual bool visit(FunctionDefinition const& _node) override
{
m_sourceMap->functions.insert(nodeLocation(_node), QString::fromStdString(_node.getName()));
return true;
}
virtual bool visit(ContractDefinition const& _node) override
{
m_sourceMap->contracts.insert(nodeLocation(_node), QString::fromStdString(_node.getName()));
return true;
}
private:
SourceMap* m_sourceMap;
};
QHash<unsigned, SolidityDeclarations> collectStorage(dev::solidity::ContractDefinition const& _contract) QHash<unsigned, SolidityDeclarations> collectStorage(dev::solidity::ContractDefinition const& _contract)
{ {
QHash<unsigned, SolidityDeclarations> result; QHash<unsigned, SolidityDeclarations> result;
@ -132,7 +160,7 @@ CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler
if (contractDefinition.getLocation().sourceName.get()) if (contractDefinition.getLocation().sourceName.get())
m_documentId = QString::fromStdString(*contractDefinition.getLocation().sourceName); m_documentId = QString::fromStdString(*contractDefinition.getLocation().sourceName);
CollectDeclarationsVisitor visitor(&m_functions, &m_locals); CollectLocalsVisitor visitor(&m_locals);
m_storage = collectStorage(contractDefinition); m_storage = collectStorage(contractDefinition);
contractDefinition.accept(visitor); contractDefinition.accept(visitor);
m_assemblyItems = *_compiler.getRuntimeAssemblyItems(name); m_assemblyItems = *_compiler.getRuntimeAssemblyItems(name);
@ -243,6 +271,7 @@ void CodeModel::releaseContracts()
for (ContractMap::iterator c = m_contractMap.begin(); c != m_contractMap.end(); ++c) for (ContractMap::iterator c = m_contractMap.begin(); c != m_contractMap.end(); ++c)
c.value()->deleteLater(); c.value()->deleteLater();
m_contractMap.clear(); m_contractMap.clear();
m_sourceMaps.clear();
} }
void CodeModel::runCompilationJob(int _jobId) void CodeModel::runCompilationJob(int _jobId)
@ -253,13 +282,17 @@ void CodeModel::runCompilationJob(int _jobId)
try try
{ {
cs.addSource("configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xf025d81196b72fba60a1d4dddad12eeb8360d828;}})"); cs.addSource("configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xf025d81196b72fba60a1d4dddad12eeb8360d828;}})");
std::vector<std::string> sourceNames;
{ {
Guard l(x_pendingContracts); Guard l(x_pendingContracts);
for (auto const& c: m_pendingContracts) for (auto const& c: m_pendingContracts)
{
cs.addSource(c.first.toStdString(), c.second.toStdString()); cs.addSource(c.first.toStdString(), c.second.toStdString());
sourceNames.push_back(c.first.toStdString());
}
} }
cs.compile(false); cs.compile(false);
collectContracts(cs); collectContracts(cs, sourceNames);
} }
catch (dev::Exception const& _exception) catch (dev::Exception const& _exception)
{ {
@ -281,11 +314,20 @@ void CodeModel::runCompilationJob(int _jobId)
emit stateChanged(); emit stateChanged();
} }
void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs) void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector<std::string> const& _sourceNames)
{ {
Guard pl(x_pendingContracts); Guard pl(x_pendingContracts);
Guard l(x_contractMap); Guard l(x_contractMap);
ContractMap result; ContractMap result;
SourceMaps sourceMaps;
for (std::string const& sourceName: _sourceNames)
{
dev::solidity::SourceUnit const& source = _cs.getAST(sourceName);
SourceMap sourceMap;
CollectLocationsVisitor collector(&sourceMap);
source.accept(collector);
sourceMaps.insert(QString::fromStdString(sourceName), std::move(sourceMap));
}
for (std::string n: _cs.getContractNames()) for (std::string n: _cs.getContractNames())
{ {
if (c_predefinedContracts.count(n) != 0) if (c_predefinedContracts.count(n) != 0)
@ -326,6 +368,7 @@ void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs)
} }
releaseContracts(); releaseContracts();
m_contractMap.swap(result); m_contractMap.swap(result);
m_sourceMaps.swap(sourceMaps);
emit codeChanged(); emit codeChanged();
emit compilationComplete(); emit compilationComplete();
} }
@ -431,3 +474,32 @@ SolidityType CodeModel::nodeType(dev::solidity::Type const* _type)
return r; return r;
} }
bool CodeModel::isContractOrFunctionLocation(dev::SourceLocation const& _location)
{
if (!_location.sourceName)
return false;
Guard l(x_contractMap);
auto sourceMapIter = m_sourceMaps.find(QString::fromStdString(*_location.sourceName));
if (sourceMapIter != m_sourceMaps.cend())
{
LocationPair location(_location.start, _location.end);
return sourceMapIter.value().contracts.contains(location) || sourceMapIter.value().functions.contains(location);
}
return false;
}
QString CodeModel::resolveFunctionName(dev::SourceLocation const& _location)
{
if (!_location.sourceName)
return QString();
Guard l(x_contractMap);
auto sourceMapIter = m_sourceMaps.find(QString::fromStdString(*_location.sourceName));
if (sourceMapIter != m_sourceMaps.cend())
{
LocationPair location(_location.start, _location.end);
auto functionNameIter = sourceMapIter.value().functions.find(location);
if (functionNameIter != sourceMapIter.value().functions.cend())
return functionNameIter.value();
}
return QString();
}

22
mix/CodeModel.h

@ -30,7 +30,7 @@
#include <QHash> #include <QHash>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/Guards.h> #include <libdevcore/Guards.h>
#include <libevmcore/Assembly.h> #include <libevmasm/Assembly.h>
#include "SolidityType.h" #include "SolidityType.h"
class QTextDocument; class QTextDocument;
@ -97,7 +97,6 @@ public:
/// @returns contract source Id /// @returns contract source Id
QString documentId() const { return m_documentId; } QString documentId() const { return m_documentId; }
QHash<LocationPair, QString> const& functions() const { return m_functions; }
QHash<LocationPair, SolidityDeclaration> const& locals() const { return m_locals; } QHash<LocationPair, SolidityDeclaration> const& locals() const { return m_locals; }
QHash<unsigned, SolidityDeclarations> const& storage() const { return m_storage; } QHash<unsigned, SolidityDeclarations> const& storage() const { return m_storage; }
@ -110,7 +109,6 @@ private:
QString m_documentId; QString m_documentId;
eth::AssemblyItems m_assemblyItems; eth::AssemblyItems m_assemblyItems;
eth::AssemblyItems m_constructorAssemblyItems; eth::AssemblyItems m_constructorAssemblyItems;
QHash<LocationPair, QString> m_functions;
QHash<LocationPair, SolidityDeclaration> m_locals; QHash<LocationPair, SolidityDeclaration> m_locals;
QHash<unsigned, SolidityDeclarations> m_storage; QHash<unsigned, SolidityDeclarations> m_storage;
@ -119,6 +117,17 @@ private:
using ContractMap = QMap<QString, CompiledContract*>; //needs to be sorted using ContractMap = QMap<QString, CompiledContract*>; //needs to be sorted
/// Source map
using LocationMap = QHash<LocationPair, QString>;
struct SourceMap
{
LocationMap contracts;
LocationMap functions;
};
using SourceMaps = QMap<QString, SourceMap>; //by source id
/// Code compilation model. Compiles contracts in background an provides compiled contract data /// Code compilation model. Compiles contracts in background an provides compiled contract data
class CodeModel: public QObject class CodeModel: public QObject
{ {
@ -153,6 +162,10 @@ public:
Q_INVOKABLE void reset() { reset(QVariantMap()); } Q_INVOKABLE void reset() { reset(QVariantMap()); }
/// Convert solidity type info to mix type /// Convert solidity type info to mix type
static SolidityType nodeType(dev::solidity::Type const* _type); static SolidityType nodeType(dev::solidity::Type const* _type);
/// Check if given location belongs to contract or function
bool isContractOrFunctionLocation(dev::SourceLocation const& _location);
/// Get funciton name by location
QString resolveFunctionName(dev::SourceLocation const& _location);
signals: signals:
/// Emited on compilation state change /// Emited on compilation state change
@ -182,11 +195,12 @@ private:
void runCompilationJob(int _jobId); void runCompilationJob(int _jobId);
void stop(); void stop();
void releaseContracts(); void releaseContracts();
void collectContracts(solidity::CompilerStack const& _cs); void collectContracts(dev::solidity::CompilerStack const& _cs, std::vector<std::string> const& _sourceNames);
std::atomic<bool> m_compiling; std::atomic<bool> m_compiling;
mutable dev::Mutex x_contractMap; mutable dev::Mutex x_contractMap;
ContractMap m_contractMap; ContractMap m_contractMap;
SourceMaps m_sourceMaps;
std::unique_ptr<CodeHighlighterSettings> m_codeHighlighterSettings; std::unique_ptr<CodeHighlighterSettings> m_codeHighlighterSettings;
QThread m_backgroundThread; QThread m_backgroundThread;
BackgroundWorker m_backgroundWorker; BackgroundWorker m_backgroundWorker;

1
mix/MixClient.cpp

@ -28,6 +28,7 @@
#include <libethereum/Executive.h> #include <libethereum/Executive.h>
#include <libethereum/ExtVM.h> #include <libethereum/ExtVM.h>
#include <libethereum/BlockChain.h> #include <libethereum/BlockChain.h>
#include <libethcore/Params.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "Exceptions.h" #include "Exceptions.h"
using namespace std; using namespace std;

2
mix/QBasicNodeDefinition.h

@ -23,7 +23,7 @@
#include <string> #include <string>
#include <QObject> #include <QObject>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
namespace dev namespace dev
{ {

2
mix/qml/StateDialog.qml

@ -158,7 +158,7 @@ Dialog {
id: importJsonFileDialog id: importJsonFileDialog
visible: false visible: false
title: qsTr("Select State File") title: qsTr("Select State File")
nameFilters: [qsTr("JSON files (*.json)", "All files (*)")] nameFilters: Qt.platform.os === "osx" ? [] : [qsTr("JSON files (*.json)", "All files (*)")] //qt 5.4 segfaults with filter string on OSX
onAccepted: { onAccepted: {
var path = importJsonFileDialog.fileUrl.toString() var path = importJsonFileDialog.fileUrl.toString()
var jsonData = fileIo.readFile(path) var jsonData = fileIo.readFile(path)

5
mix/qml/html/codeeditor.js

@ -126,7 +126,10 @@ highlightExecution = function(start, end) {
executionMark.clear(); executionMark.clear();
if (debugWarning) if (debugWarning)
debugWarning.clear(); debugWarning.clear();
executionMark = editor.markText(editor.posFromIndex(start), editor.posFromIndex(end), { className: "CodeMirror-exechighlight" }); if (start > 0 && end > start) {
executionMark = editor.markText(editor.posFromIndex(start), editor.posFromIndex(end), { className: "CodeMirror-exechighlight" });
editor.scrollIntoView(editor.posFromIndex(start));
}
} }
var changeId; var changeId;

3
mix/qml/js/Debugger.js

@ -183,7 +183,8 @@ function selectState(stateIndex)
function highlightSelection(index) function highlightSelection(index)
{ {
statesList.positionViewAtRow(index, ListView.Center); if (statesList.visible)
statesList.positionViewAtRow(index, ListView.Visible);
statesList.selection.clear(); statesList.selection.clear();
statesList.selection.select(index); statesList.selection.select(index);
} }

2
mix/test/qml/js/TestTutorial.js

@ -52,7 +52,7 @@ function test_tutorial()
transactionDialog.selectFunction("setRating"); transactionDialog.selectFunction("setRating");
clickElement(transactionDialog, 200, 310); clickElement(transactionDialog, 200, 310);
ts.typeString("Titanic", transactionDialog); ts.typeString("Titanic", transactionDialog);
clickElement(transactionDialog, 200, 350); clickElement(transactionDialog, 200, 330);
ts.typeString("2", transactionDialog); ts.typeString("2", transactionDialog);
transactionDialog.acceptAndClose(); transactionDialog.acceptAndClose();
mainApplication.projectModel.stateDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.acceptAndClose();

48
solc/CommandLineInterface.cpp

@ -51,19 +51,18 @@ namespace dev
namespace solidity namespace solidity
{ {
// LTODO: Maybe some argument class pairing names with static string const g_argAbiStr = "json-abi";
// extensions and other attributes would be a better choice here? static string const g_argSolAbiStr = "sol-abi";
static string const g_argAbiStr = "json-abi"; static string const g_argSignatureHashes = "hashes";
static string const g_argSolAbiStr = "sol-abi"; static string const g_argAsmStr = "asm";
static string const g_argAsmStr = "asm"; static string const g_argAsmJsonStr = "asm-json";
static string const g_argAsmJsonStr = "asm-json"; static string const g_argAstStr = "ast";
static string const g_argAstStr = "ast"; static string const g_argAstJson = "ast-json";
static string const g_argAstJson = "ast-json"; static string const g_argBinaryStr = "binary";
static string const g_argBinaryStr = "binary"; static string const g_argOpcodesStr = "opcodes";
static string const g_argOpcodesStr = "opcodes"; static string const g_argNatspecDevStr = "natspec-dev";
static string const g_argNatspecDevStr = "natspec-dev";
static string const g_argNatspecUserStr = "natspec-user"; static string const g_argNatspecUserStr = "natspec-user";
static string const g_argAddStandard = "add-std"; static string const g_argAddStandard = "add-std";
/// Possible arguments to for --combined-json /// Possible arguments to for --combined-json
static set<string> const g_combinedJsonArgs{ static set<string> const g_combinedJsonArgs{
@ -96,6 +95,7 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args)
return return
humanTargetedStdout(_args, g_argAbiStr) || humanTargetedStdout(_args, g_argAbiStr) ||
humanTargetedStdout(_args, g_argSolAbiStr) || humanTargetedStdout(_args, g_argSolAbiStr) ||
humanTargetedStdout(_args, g_argSignatureHashes) ||
humanTargetedStdout(_args, g_argNatspecUserStr) || humanTargetedStdout(_args, g_argNatspecUserStr) ||
humanTargetedStdout(_args, g_argAstJson) || humanTargetedStdout(_args, g_argAstJson) ||
humanTargetedStdout(_args, g_argNatspecDevStr) || humanTargetedStdout(_args, g_argNatspecDevStr) ||
@ -173,6 +173,27 @@ void CommandLineInterface::handleBytecode(string const& _contract)
handleBinary(_contract); handleBinary(_contract);
} }
void CommandLineInterface::handleSignatureHashes(string const& _contract)
{
if (!m_args.count(g_argSignatureHashes))
return;
string out;
for (auto const& it: m_compiler->getContractDefinition(_contract).getInterfaceFunctions())
out += toHex(it.first.ref()) + ": " + it.second->externalSignature() + "\n";
auto choice = m_args[g_argSignatureHashes].as<OutputType>();
if (outputToStdout(choice))
cout << "Function signatures: " << endl << out;
if (outputToFile(choice))
{
ofstream outFile(_contract + ".signatures");
outFile << out;
outFile.close();
}
}
void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract) void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract)
{ {
std::string argName; std::string argName;
@ -254,6 +275,8 @@ bool CommandLineInterface::parseArguments(int argc, char** argv)
"Request to output the contract's JSON ABI interface.") "Request to output the contract's JSON ABI interface.")
(g_argSolAbiStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"), (g_argSolAbiStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
"Request to output the contract's Solidity ABI interface.") "Request to output the contract's Solidity ABI interface.")
(g_argSignatureHashes.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
"Request to output the contract's functions' signature hashes.")
(g_argNatspecUserStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"), (g_argNatspecUserStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
"Request to output the contract's Natspec user documentation.") "Request to output the contract's Natspec user documentation.")
(g_argNatspecDevStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"), (g_argNatspecDevStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
@ -516,6 +539,7 @@ void CommandLineInterface::actOnInput()
} }
handleBytecode(contract); handleBytecode(contract);
handleSignatureHashes(contract);
handleMeta(DocumentationType::ABIInterface, contract); handleMeta(DocumentationType::ABIInterface, contract);
handleMeta(DocumentationType::ABISolidityInterface, contract); handleMeta(DocumentationType::ABISolidityInterface, contract);
handleMeta(DocumentationType::NatspecDev, contract); handleMeta(DocumentationType::NatspecDev, contract);

1
solc/CommandLineInterface.h

@ -58,6 +58,7 @@ private:
void handleBinary(std::string const& _contract); void handleBinary(std::string const& _contract);
void handleOpcode(std::string const& _contract); void handleOpcode(std::string const& _contract);
void handleBytecode(std::string const& _contract); void handleBytecode(std::string const& _contract);
void handleSignatureHashes(std::string const& _contract);
void handleMeta(DocumentationType _type, void handleMeta(DocumentationType _type,
std::string const& _contract); std::string const& _contract);

55
test/libp2p/peer.cpp

@ -120,6 +120,61 @@ BOOST_AUTO_TEST_CASE(saveNodes)
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
BOOST_FIXTURE_TEST_SUITE(p2pPeer, P2PFixture)
BOOST_AUTO_TEST_CASE(requirePeer)
{
auto oldLogVerbosity = g_logVerbosity;
g_logVerbosity = 10;
const char* const localhost = "127.0.0.1";
NetworkPreferences prefs1(localhost, 30301, false);
NetworkPreferences prefs2(localhost, 30302, false);
Host host1("Test", prefs1);
host1.start();
Host host2("Test", prefs2);
host2.start();
auto node2 = host2.id();
host1.requirePeer(node2, NodeIPEndpoint(bi::address::from_string(localhost), prefs2.listenPort, prefs2.listenPort));
this_thread::sleep_for(chrono::seconds(3));
auto host1peerCount = host1.peerCount();
auto host2peerCount = host2.peerCount();
BOOST_REQUIRE_EQUAL(host1peerCount, 1);
BOOST_REQUIRE_EQUAL(host2peerCount, 1);
PeerSessionInfos sis1 = host1.peerSessionInfo();
PeerSessionInfos sis2 = host2.peerSessionInfo();
BOOST_REQUIRE_EQUAL(sis1.size(), 1);
BOOST_REQUIRE_EQUAL(sis2.size(), 1);
Peers peers1 = host1.getPeers();
Peers peers2 = host2.getPeers();
BOOST_REQUIRE_EQUAL(peers1.size(), 1);
BOOST_REQUIRE_EQUAL(peers2.size(), 1);
DisconnectReason disconnect1 = peers1[0].lastDisconnect();
DisconnectReason disconnect2 = peers2[0].lastDisconnect();
BOOST_REQUIRE_EQUAL(disconnect1, disconnect2);
host1.relinquishPeer(node2);
this_thread::sleep_for(chrono::seconds(1));
host1peerCount = host1.peerCount();
host2peerCount = host2.peerCount();
BOOST_REQUIRE_EQUAL(host1peerCount, 1);
BOOST_REQUIRE_EQUAL(host2peerCount, 1);
g_logVerbosity = oldLogVerbosity;
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE(peerTypes) BOOST_AUTO_TEST_SUITE(peerTypes)
BOOST_AUTO_TEST_CASE(emptySharedPeer) BOOST_AUTO_TEST_CASE(emptySharedPeer)

6
test/libsolidity/Assembly.cpp

@ -17,20 +17,20 @@
/** /**
* @author Lefteris Karapetsas <lefteris@ethdev.com> * @author Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015 * @date 2015
* Unit tests for Assembly Items from evmcore/Assembly.h * Unit tests for Assembly Items from evmasm/Assembly.h
*/ */
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libevmcore/SourceLocation.h> #include <libevmasm/SourceLocation.h>
#include <libevmasm/Assembly.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h> #include <libsolidity/Parser.h>
#include <libsolidity/NameAndTypeResolver.h> #include <libsolidity/NameAndTypeResolver.h>
#include <libsolidity/Compiler.h> #include <libsolidity/Compiler.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include <libevmcore/Assembly.h>
using namespace std; using namespace std;
using namespace dev::eth; using namespace dev::eth;

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save