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(libevmcore)
add_subdirectory(libevmasm)
add_subdirectory(liblll)
if (SERPENT)

3
alethzero/CMakeLists.txt

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

8
alethzero/Context.h

@ -59,10 +59,10 @@ class Context
public:
virtual ~Context();
virtual QString pretty(dev::Address _a) const = 0;
virtual QString prettyU256(dev::u256 _n) const = 0;
virtual QString render(dev::Address _a) const = 0;
virtual std::pair<dev::Address, dev::bytes> fromString(QString const& _a) const = 0;
virtual std::string pretty(dev::Address const& _a) const = 0;
virtual std::string prettyU256(dev::u256 const& _n) const = 0;
virtual std::pair<dev::Address, dev::bytes> fromString(std::string const& _a) 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;
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->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true)));
assert(m_session.codes.count(ws.code));
@ -246,7 +246,7 @@ void Debugger::update()
ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
stringstream s;
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()));
}
}

4
alethzero/DownloadView.cpp

@ -39,13 +39,13 @@ void DownloadView::paintEvent(QPaintEvent*)
QPainter p(this);
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;
double ratio = (double)rect().width() / rect().height();
if (ratio < 1)
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(n, n);

4
alethzero/ExportState.cpp

@ -129,8 +129,8 @@ void ExportStateDialog::fillContracts()
ui->contracts->setEnabled(true);
for (auto i: ethereum()->addresses(m_block))
{
QString 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))
string r = m_main->render(i);
(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));
}
}

121
alethzero/Main.ui

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

249
alethzero/MainWin.cpp

@ -80,29 +80,29 @@ using namespace dev::p2p;
using namespace dev::eth;
namespace js = json_spirit;
QString Main::fromRaw(h256 _n, unsigned* _inc)
string Main::fromRaw(h256 _n, unsigned* _inc)
{
if (_n)
{
string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0');
if (!l)
return QString();
return string();
if (l != string::npos)
{
auto p = s.find_first_not_of('\0', l);
if (!(p == string::npos || (_inc && p == 31)))
return QString();
return string();
if (_inc)
*_inc = (byte)s[31];
s.resize(l);
}
for (auto i: s)
if (i < 32)
return QString();
return QString::fromStdString(s);
return string();
return s;
}
return QString();
return string();
}
QString contentsOfQResource(string const& res)
@ -143,11 +143,6 @@ Main::Main(QWidget *parent) :
// ui->log->addItem(QString::fromStdString(s));
};
#if !ETH_FATDB
delete ui->dockWidget_accounts;
delete ui->dockWidget_contracts;
#endif
#if ETH_DEBUG
m_servers.append("127.0.0.1:30300");
#endif
@ -204,6 +199,9 @@ Main::Main(QWidget *parent) :
// QWebEngineInspector* inspector = new QWebEngineInspector();
// inspector->setPage(page);
readSettings();
#if !ETH_FATDB
removeDockWidget(ui->dockWidget_accounts);
#endif
installWatches();
startTimer(100);
@ -398,7 +396,7 @@ void Main::onNewBlock()
// update blockchain dependent views.
refreshBlockCount();
refreshBlockChain();
refreshAccounts();
ui->refreshAccounts->setEnabled(true);
// We must update balances since we can't filter updates to basic accounts.
refreshBalances();
@ -410,7 +408,7 @@ void Main::onNewPending()
// update any pending-transaction dependent views.
refreshPending();
refreshAccounts();
ui->refreshAccounts->setEnabled(true);
}
void Main::on_forceMining_triggered()
@ -510,33 +508,33 @@ static Public stringToPublic(QString const& _a)
return Public();
}
QString Main::pretty(dev::Address _a) const
std::string Main::pretty(dev::Address const& _a) const
{
auto g_newNameReg = getNameReg();
if (g_newNameReg)
{
QString s = QString::fromStdString(toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("getName(address)", _a)).output)));
if (s.size())
return s;
string n = toString(abiOut<string32>(ethereum()->call(g_newNameReg, abiIn("name(address)", _a)).output));
if (!n.empty())
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);
QString n;
try {
n = QString::fromStdString(ICAP(_a).encoded());
}
catch (...) {
n = QString::fromStdString(_a.abridged());
}
return p.isEmpty() ? n : (p + " " + n);
string p = pretty(_a);
string n;
if (p.size() == 9 && p.find_first_not_of("QWERYUOPASDFGHJKLZXCVBNM1234567890") == string::npos)
p = ICAP(p, "XREG").encoded();
else
DEV_IGNORE_EXCEPTIONS(n = ICAP(_a).encoded());
if (n.empty())
n = _a.abridged();
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)")
return make_pair(Address(), bytes());
@ -544,7 +542,7 @@ pair<Address, bytes> Main::fromString(QString const& _n) const
auto g_newNameReg = getNameReg();
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)
return make_pair(a, bytes());
}
@ -552,7 +550,7 @@ pair<Address, bytes> Main::fromString(QString const& _n) const
{
try
{
return make_pair(Address(fromHex(_n.toStdString(), WhenError::Throw)), bytes());
return make_pair(Address(fromHex(_n, WhenError::Throw)), bytes());
}
catch (BadHexCharacter& _e)
{
@ -568,7 +566,7 @@ pair<Address, bytes> Main::fromString(QString const& _n) const
}
else
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;
}, 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]);
// TODO: support IPv6.
else if (ret)
return fromRaw(ret);
return QString::fromStdString(fromRaw(ret));
else
return _a;
}
@ -817,7 +815,7 @@ void Main::on_exportKey_triggered()
if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size())
{
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)
{
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));
totalBalance += b;
@ -968,24 +966,24 @@ void Main::refreshNetwork()
map<h512, QString> sessions;
for (PeerSessionInfo const& i: ps)
ui->peers->addItem(QString("[%8 %7] %3 ms - %1:%2 - %4 %5 %6")
.arg(QString::fromStdString(i.host))
.arg(i.port)
.arg(chrono::duration_cast<chrono::milliseconds>(i.lastPing).count())
.arg(sessions[i.id] = QString::fromStdString(i.clientVersion))
.arg(QString::fromStdString(toString(i.caps)))
.arg(QString::fromStdString(toString(i.notes)))
.arg(i.socketId)
.arg(QString::fromStdString(i.id.abridged())));
.arg(QString::fromStdString(i.host))
.arg(i.port)
.arg(chrono::duration_cast<chrono::milliseconds>(i.lastPing).count())
.arg(sessions[i.id] = QString::fromStdString(i.clientVersion))
.arg(QString::fromStdString(toString(i.caps)))
.arg(QString::fromStdString(toString(i.notes)))
.arg(i.socketId)
.arg(QString::fromStdString(i.id.abridged())));
auto ns = web3()->nodes();
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")
.arg(QString::fromStdString(i.id.abridged()))
.arg(QString::fromStdString(i.endpoint.address.to_string()))
.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.rating())
);
.arg(QString::fromStdString(i.id.abridged()))
.arg(QString::fromStdString(i.endpoint.address.to_string()))
.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.rating())
);
}
}
@ -994,7 +992,7 @@ void Main::refreshAll()
refreshBlockChain();
refreshBlockCount();
refreshPending();
refreshAccounts();
ui->refreshAccounts->setEnabled(true);
refreshBalances();
}
@ -1007,40 +1005,66 @@ void Main::refreshPending()
QString s = t.receiveAddress() ?
QString("%2 %5> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender()))
.arg(render(t.receiveAddress()))
.arg(QString::fromStdString(render(t.safeSender())))
.arg(QString::fromStdString(render(t.receiveAddress())))
.arg((unsigned)t.nonce())
.arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') :
QString("%2 +> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender()))
.arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce())))))
.arg(QString::fromStdString(render(t.safeSender())))
.arg(QString::fromStdString(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))))
.arg((unsigned)t.nonce());
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()
{
#if ETH_FATDB
DEV_TIMED_FUNCTION;
#if ETH_FATDB || !ETH_TRUE
cwatch << "refreshAccounts()";
ui->accounts->clear();
ui->contracts->clear();
for (auto n = 0; n < 2; ++n)
for (auto i: ethereum()->addresses())
{
auto r = render(i);
if (r.contains('(') == !n)
{
if (n == 0 || ui->showAllAccounts->isChecked())
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
if (ethereum()->codeAt(i).size())
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(r).arg((unsigned)ethereum()->countAt(i)), ui->contracts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
}
bool showContract = ui->showContracts->isChecked();
bool showBasic = ui->showBasic->isChecked();
bool onlyNamed = ui->onlyNamed->isChecked();
for (auto const& i: ethereum()->addresses())
{
bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3);
if (!((showContract && isContract) || (showBasic && !isContract)))
continue;
string r = render(i);
if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE"))
continue;
(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));
}
#endif
ui->refreshAccounts->setEnabled(false);
}
void Main::refreshBlockCount()
@ -1057,6 +1081,7 @@ void Main::on_turboMining_triggered()
void Main::refreshBlockChain()
{
DEV_TIMED_FUNCTION;
cwatch << "refreshBlockChain()";
// TODO: keep the same thing highlighted.
@ -1105,14 +1130,14 @@ void Main::refreshBlockChain()
QString s = t.receiveAddress() ?
QString(" %2 %5> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender()))
.arg(render(t.receiveAddress()))
.arg(QString::fromStdString(render(t.safeSender())))
.arg(QString::fromStdString(render(t.receiveAddress())))
.arg((unsigned)t.nonce())
.arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') :
QString(" %2 +> %3: %1 [%4]")
.arg(formatBalance(t.value()).c_str())
.arg(render(t.safeSender()))
.arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce())))))
.arg(QString::fromStdString(render(t.safeSender())))
.arg(QString::fromStdString(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))))
.arg((unsigned)t.nonce());
QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks);
auto hba = QByteArray((char const*)h.data(), h.size);
@ -1256,7 +1281,7 @@ string Main::renderDiff(StateDiff const& _d) const
s << "<hr/>";
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())
continue;
@ -1289,7 +1314,7 @@ string Main::renderDiff(StateDiff const& _d) const
s << " * ";
s << " </code>";
s << prettyU256(i.first).toStdString();
s << prettyU256(i.first);
/* if (i.first > u256(1) << 246)
s << (h256)i.first;
else if (i.first > u160(1) << 150)
@ -1298,11 +1323,11 @@ string Main::renderDiff(StateDiff const& _d) const
s << hex << i.first;
*/
if (!i.second.from())
s << ": " << prettyU256(i.second.to()).toStdString();
s << ": " << prettyU256(i.second.to());
else if (!i.second.to())
s << " (" << prettyU256(i.second.from()).toStdString() << ")";
s << " (" << prettyU256(i.second.from()) << ")";
else
s << ": " << prettyU256(i.second.to()).toStdString() << " (" << prettyU256(i.second.from()).toStdString() << ")";
s << ": " << prettyU256(i.second.to()) << " (" << prettyU256(i.second.from()) << ")";
}
}
return s.str();
@ -1321,11 +1346,11 @@ void Main::on_transactionQueue_currentItemChanged()
auto ss = tx.safeSender();
h256 th = sha3(rlpList(ss, tx.nonce()));
s << "<h3>" << th << "</h3>";
s << "From: <b>" << pretty(ss).toStdString() << "</b> " << ss;
s << "From: <b>" << pretty(ss) << "</b> " << ss;
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
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 << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</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()
{
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 << "&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>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>Mix hash: <b>" << info.mixHash << "</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 << "Parent: <b>" << uncle.parentHash << "</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 << "Mix hash: <b>" << uncle.mixHash << "</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];
s << "<h3>" << th << "</h3>";
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())
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
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 << "&nbsp;&emsp;&nbsp;#<b>" << tx.nonce() << "</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();
if (auto item = ui->contracts->currentItem())
ui->accountInfo->clear();
if (auto item = ui->accounts->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20);
@ -1604,16 +1634,16 @@ void Main::on_contracts_currentItemChanged()
{
auto storage = ethereum()->storageAt(address);
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 << Div(Mono) << toHex(ethereum()->codeAt(address)) << "</div>";
ui->contractInfo->appendHtml(QString::fromStdString(s.str()));
ui->accountInfo->appendHtml(QString::fromStdString(s.str()));
}
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)
{
shh::BuildTopic ret;
@ -1885,7 +1905,12 @@ void Main::on_killAccount_triggered()
if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size())
{
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;
m_myKeys.erase(m_myKeys.begin() + ui->ourAccounts->currentRow());
keysChanged();
@ -1902,10 +1927,10 @@ void Main::on_go_triggered()
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;
QString raw;
string raw;
ostringstream s;
if (_n > szabo && _n < 1000000 * ether)
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)
{
Address a = right160(_n);
QString n = pretty(a);
if (n.isNull())
string n = pretty(a);
if (n.empty())
s << "<span style=\"color: #844\">0x</span><span style=\"color: #800\">" << a << "</span>";
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())
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
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()

20
alethzero/MainWin.h

@ -80,10 +80,10 @@ public:
bool confirm() const;
NatSpecFace* natSpec() { return &m_natSpecDB; }
QString pretty(dev::Address _a) const override;
QString prettyU256(dev::u256 _n) const override;
QString render(dev::Address _a) const override;
std::pair<dev::Address, dev::bytes> fromString(QString const& _a) const override;
std::string pretty(dev::Address const& _a) const override;
std::string prettyU256(dev::u256 const& _n) const override;
std::string render(dev::Address 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;
QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; }
@ -131,6 +131,13 @@ private slots:
void on_importKeyFile_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
void on_newTransaction_triggered();
void on_loadJS_triggered();
@ -140,8 +147,7 @@ private slots:
void ourAccountsRowsMoved();
void on_ourAccounts_doubleClicked();
void on_accounts_doubleClicked();
void on_contracts_doubleClicked();
void on_contracts_currentItemChanged();
void on_accounts_currentItemChanged();
void on_transactionQueue_currentItemChanged();
void on_blockChainFilter_textChanged();
void on_blocks_currentItemChanged();
@ -254,7 +260,7 @@ private:
std::unique_ptr<jsonrpc::HttpServer> m_httpConnector;
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;
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)
{
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) + ".");
}
@ -81,7 +81,7 @@ bool OurWebThreeStubServer::showUnknownCallNotice(TransactionSkeleton const& _t,
{
return showAuthenticationPopup("DANGEROUS! Unknown Contract Transaction!",
"Ð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" : "") +
"Call involves sending " +
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
return showAuthenticationPopup("Contract Transaction",
"ÐApp attempting to conduct contract interaction with " +
m_main->pretty(_t.to).toStdString() +
m_main->pretty(_t.to) +
": <b>" + userNotice + "</b>.\n\n" +
(_toProxy ? "This transaction is not executed directly, but forwarded to another ÐApp.\n\n" : "") +
(_t.value > 0 ?

14
alethzero/Transact.cpp

@ -110,12 +110,12 @@ void Transact::updateDestination()
cwatch << "updateDestination()";
QString s;
for (auto i: ethereum()->addresses())
if ((s = m_context->pretty(i)).size())
if ((s = QString::fromStdString(m_context->pretty(i))).size())
// A namereg address
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1)
ui->destination->addItem(s);
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--);
}
@ -142,9 +142,9 @@ void Transact::on_destination_currentTextChanged(QString)
{
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)
ui->calculatedName->setText(m_context->render(p.first));
ui->calculatedName->setText(QString::fromStdString(m_context->render(p.first)));
else
ui->calculatedName->setText("Unknown Address");
if (!p.second.empty())
@ -347,7 +347,7 @@ void Transact::rejigData()
else
{
// 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());
}
gasNeeded = (qint64)(er.gasUsed + er.gasRefunded);
@ -434,7 +434,7 @@ void Transact::on_send_clicked()
}
else
// 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();
}
@ -453,7 +453,7 @@ void Transact::on_debug_clicked()
State st(ethereum()->postState());
Transaction t = isCreation() ?
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);
Executive e(st, ethereum()->blockChain(), 0);
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_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(
COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
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.")
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"))
option(USE_LD_GOLD "Use GNU gold linker" ON)
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
<< " -r,--remote <host>(:<port>) Connect to remote host (default: none)." << 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
#if ETH_JSONRPC || !ETH_TRUE
<< "Work farming mode:" << endl
@ -515,6 +516,7 @@ int main(int argc, char** argv)
unsigned short remotePort = 30303;
unsigned peers = 5;
bool bootstrap = false;
unsigned networkId = 0;
/// Mining params
unsigned mining = 0;
@ -668,6 +670,15 @@ int main(int argc, char** argv)
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)
try {
benchmarkWarmup = stol(argv[++i]);
@ -1034,6 +1045,7 @@ int main(int argc, char** argv)
c->setForceMining(forceMining);
c->setTurboMining(minerType == MinerType::GPU);
c->setAddress(coinbase);
c->setNetworkId(networkId);
}
cout << "Transaction Signer: " << sigKey.address() << endl;

2
evmjit/libevmjit-cpp/Env.cpp

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

14
libdevcore/Common.cpp

@ -20,7 +20,8 @@
*/
#include "Common.h"
#include "Exceptions.h"
#include "Log.h"
using namespace std;
using namespace dev;
@ -29,5 +30,16 @@ namespace dev
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 <set>
#include <functional>
#include <boost/timer.hpp>
#pragma warning(push)
#pragma GCC diagnostic push
#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.
class ScopeGuard {
class ScopeGuard
{
public:
ScopeGuard(std::function<void(void)> _f): m_f(_f) {}
~ScopeGuard() { m_f(); }
private:
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
{
Trust = 0,
@ -145,7 +197,8 @@ enum class WithExisting: int
}
namespace std {
namespace std
{
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 Overflow: virtual Exception {};
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
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.
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.
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); }
/// @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.
bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; }

13
libdevcore/Guards.h

@ -22,6 +22,7 @@
#pragma once
#include <mutex>
#include <atomic>
#include <boost/thread.hpp>
namespace dev
@ -61,6 +62,18 @@ struct GenericUnguardSharedBool
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.
* The expression/block following is guarded though the given mutex.
* Usage:

4
libdevcore/Log.cpp

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

2
libethcore/BlockInfo.cpp

@ -23,10 +23,10 @@
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include <libethcore/Common.h>
#include <libethcore/Params.h>
#include "EthashAux.h"
#include "ProofOfWork.h"
#include "Exceptions.h"
#include "Params.h"
#include "BlockInfo.h"
using namespace std;
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} devcrypto)
target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} evmcore)
if (ETHASHCL)
target_link_libraries(${EXECUTABLE} ethash-cl)

12
libethcore/EthashAux.cpp

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

2
libethcore/ICAP.h

@ -51,8 +51,6 @@ public:
ICAP() = default;
/// 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) {}
/// 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.
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.

36
libethcore/Params.cpp

@ -14,7 +14,7 @@
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 FeeStructure.cpp
/** @file Params.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
@ -36,40 +36,6 @@ u256 const c_gasLimitBoundDivisor = 1024;
u256 const c_minimumDifficulty = 131072;
u256 const c_difficultyBoundDivisor = 2048;
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
}

37
libethcore/Params.h

@ -14,7 +14,7 @@
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 FeeStructure.h
/** @file Params.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
@ -37,41 +37,6 @@ extern u256 const c_minimumDifficulty;
extern u256 const c_difficultyBoundDivisor;
extern u256 const c_durationLimit;
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/ProofOfWork.h>
#include <libethcore/BlockInfo.h>
#include <libethcore/Params.h>
#include <liblll/Compiler.h>
#include "GenesisInfo.h"
#include "State.h"
@ -47,7 +48,7 @@ using namespace dev::eth;
namespace js = json_spirit;
#define ETH_CATCH 1
#define ETH_TIMED_IMPORTS 1
#define ETH_TIMED_IMPORTS 0
#ifdef _WIN32
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);
}
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;
for (auto const& i: _map)
@ -855,7 +856,7 @@ void BlockChain::garbageCollect(bool _force)
}
}
m_cacheUsage.pop_back();
m_cacheUsage.push_front(std::set<CacheID>{});
m_cacheUsage.push_front(std::unordered_set<CacheID>{});
}
void BlockChain::checkConsistency()

20
libethereum/BlockChain.h

@ -28,6 +28,8 @@
#include <deque>
#include <chrono>
#include <unordered_map>
#include <unordered_set>
#include <libdevcore/Log.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/Guards.h>
@ -40,6 +42,14 @@
#include "BlockQueue.h"
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
{
@ -66,7 +76,7 @@ std::map<Address, Account> const& genesisState();
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 UncleHashes = h256s;
using ImportRoute = std::pair<h256s, h256s>;
@ -144,7 +154,7 @@ public:
UncleHashes uncleHashes() const { return uncleHashes(currentHash()); }
/// 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.)
LastHashes lastHashes() const { return lastHashes(number()); }
@ -251,7 +261,7 @@ private:
void open(std::string const& _path, WithExisting _we = WithExisting::Trust);
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);
@ -295,8 +305,8 @@ private:
using CacheID = std::pair<h256, unsigned>;
mutable Mutex x_cacheUsage;
mutable std::deque<std::set<CacheID>> m_cacheUsage;
mutable std::set<CacheID> m_inUse;
mutable std::deque<std::unordered_set<CacheID>> m_cacheUsage;
mutable std::unordered_set<CacheID> m_inUse;
void noteUsed(h256 const& _h, unsigned _extra = (unsigned)-1) const;
std::chrono::system_clock::time_point m_lastCollection;

13
libethereum/BlockDetails.h

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

26
libethereum/BlockQueue.cpp

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

8
libethereum/BlockQueue.h

@ -30,6 +30,7 @@
namespace dev
{
namespace eth
{
@ -60,7 +61,7 @@ enum class QueueStatus
* Sorts them ready for blockchain insertion (with the BlockChain::sync() method).
* @threadsafe
*/
class BlockQueue
class BlockQueue: HasInvariants
{
public:
/// 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()); }
/// 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.
h256 firstUnknown() const { ReadGuard l(m_lock); return m_unknownSet.size() ? *m_unknownSet.begin() : h256(); }
@ -102,7 +103,8 @@ public:
private:
void noteReady_WITH_LOCK(h256 const& _b);
void invariants_WITH_LOCK() const;
bool invariants() const override;
mutable boost::shared_mutex m_lock; ///< General lock.
std::set<h256> m_drainingSet; ///< All blocks being imported.

1
libethereum/CanonBlockChain.cpp

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

24
libethereum/Client.cpp

@ -36,12 +36,6 @@ using namespace dev;
using namespace dev::eth;
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):
m_path(_dbPath.size() ? _dbPath : Defaults::dbPath())
{
@ -582,12 +576,13 @@ void Client::onChainChanged(ImportRoute const& _ir)
m_preMine = newPreMine;
DEV_TIMED(working) ETH_WRITE_GUARDED(x_working)
m_working = newPreMine;
// Transactions ts = m_postMine.pending();
ETH_READ_GUARDED(x_postMine)
for (auto const& t: m_postMine.pending())
{
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)
m_postMine = m_working;
@ -597,6 +592,10 @@ void Client::onChainChanged(ImportRoute const& _ir)
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);
}
@ -659,11 +658,9 @@ void Client::noteChanged(h256Set const& _filters)
void Client::doWork()
{
// TODO: Use condition variable rather than this rubbish.
bool t = true;
if (m_syncBlockQueue.compare_exchange_strong(t, false))
syncBlockQueue(); // GAAA!!!!! CALLED TOO OFTEN!!!
syncBlockQueue();
t = true;
if (m_syncTransactionQueue.compare_exchange_strong(t, false) && !m_remoteWorking)
@ -672,7 +669,10 @@ void Client::doWork()
tick();
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()

7
libethereum/Client.h

@ -22,6 +22,7 @@
#pragma once
#include <thread>
#include <condition_variable>
#include <mutex>
#include <list>
#include <atomic>
@ -258,10 +259,10 @@ private:
void syncTransactionQueue();
/// 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.
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).
/// This updates m_miningInfo.
@ -309,6 +310,8 @@ private:
ActivityReport m_report;
// 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_syncBlockQueue = {false};
};

5
libethereum/ClientBase.cpp

@ -142,6 +142,11 @@ bytes ClientBase::codeAt(Address _a, BlockNumber _block) const
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
{
return asOf(_block).storage(_a);

2
libethereum/ClientBase.h

@ -92,12 +92,14 @@ public:
using Interface::countAt;
using Interface::stateAt;
using Interface::codeAt;
using Interface::codeHashAt;
using Interface::storageAt;
virtual u256 balanceAt(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 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 LocalisedLogEntries logs(unsigned _watchId) const override;

2
libethereum/DownloadMan.cpp

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

3
libethereum/DownloadMan.h

@ -143,7 +143,8 @@ public:
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); }
unsigned subCount() const { ReadGuard l(x_subs); return m_subs.size(); }
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.
clog(NetNote) << "Chain download complete.";
// 1/100th for each useful block hash.
_who->addRating(m_man.chain().size() / 100);
_who->addRating(m_man.chainSize() / 100);
m_man.reset();
}
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 TransactionsPacket:
{
clog(NetAllDetail) << "Transactions (" << dec << _r.itemCount() << "entries)";
unsigned itemCount = _r.itemCount();
clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)";
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());
m_knownTransactions.insert(h);
@ -373,21 +374,22 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
}
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)
{
cwarn << "Peer giving us hashes when we didn't ask for them.";
break;
}
if (_r.itemCount() == 0)
if (itemCount == 0)
{
transition(Asking::Blocks);
return true;
}
unsigned knowns = 0;
unsigned unknowns = 0;
for (unsigned i = 0; i < _r.itemCount(); ++i)
for (unsigned i = 0; i < itemCount; ++i)
{
addRating(1);
auto h = _r[i].toHash<h256>();
@ -454,12 +456,13 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
}
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)
clog(NetWarn) << "Unexpected Blocks received!";
if (_r.itemCount() == 0)
if (itemCount == 0)
{
// Got to this peer's latest block - just give up.
transition(Asking::Nothing);
@ -472,7 +475,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
unsigned got = 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());
if (m_sub.noteBlock(h))

3
libethereum/Interface.h

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

2
libethereum/Precompiled.cpp

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

1
libethereum/State.h

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

2
libethereum/Transaction.h

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

1
libethereum/TransactionQueue.cpp

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

2
libevm/VM.h

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

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

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

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

@ -25,9 +25,9 @@
#include <sstream>
#include <libdevcore/Common.h>
#include <libdevcore/Assertions.h>
#include <libevmcore/SourceLocation.h>
#include <libevmcore/Instruction.h>
#include <libevmcore/AssemblyItem.h>
#include <libevmasm/SourceLocation.h>
#include <libevmasm/AssemblyItem.h>
#include "Exceptions.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 <libdevcore/Common.h>
#include <libdevcore/Assertions.h>
#include <libevmcore/SourceLocation.h>
#include <libevmcore/Instruction.h>
#include <libevmasm/SourceLocation.h>
#include "Exceptions.h"
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 <boost/range/adaptor/reversed.hpp>
#include <libdevcrypto/SHA3.h>
#include <libevmcore/CommonSubexpressionEliminator.h>
#include <libevmcore/AssemblyItem.h>
#include <libevmasm/CommonSubexpressionEliminator.h>
#include <libevmasm/AssemblyItem.h>
using namespace std;
using namespace dev;

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

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

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

@ -21,11 +21,11 @@
* Control flow analysis for the optimizer.
*/
#include <libevmcore/ControlFlowGraph.h>
#include <libevmasm/ControlFlowGraph.h>
#include <map>
#include <libevmcore/Exceptions.h>
#include <libevmcore/AssemblyItem.h>
#include <libevmcore/SemanticInformation.h>
#include <libevmasm/Exceptions.h>
#include <libevmasm/AssemblyItem.h>
#include <libevmasm/SemanticInformation.h>
using namespace std;
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.
*/
#include <libevmcore/ExpressionClasses.h>
#include <libevmasm/ExpressionClasses.h>
#include <utility>
#include <tuple>
#include <functional>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/noncopyable.hpp>
#include <libevmcore/Assembly.h>
#include <libevmcore/CommonSubexpressionEliminator.h>
#include <libevmasm/Assembly.h>
#include <libevmasm/CommonSubexpressionEliminator.h>
using namespace std;
using namespace dev;

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

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

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

@ -21,8 +21,8 @@
* Helper to provide semantic information about assembly items.
*/
#include <libevmcore/SemanticInformation.h>
#include <libevmcore/AssemblyItem.h>
#include <libevmasm/SemanticInformation.h>
#include <libevmasm/AssemblyItem.h>
using namespace std;
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()
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})
@ -22,7 +19,6 @@ file(GLOB HEADERS "*.h")
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} devcrypto)
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

7
libevmcore/Exceptions.h

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

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');
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})
target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} evmasm)
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

2
liblll/CodeFragment.h

@ -23,7 +23,7 @@
#include <libdevcore/Common.h>
#include <libevmcore/Instruction.h>
#include <libevmcore/Assembly.h>
#include <libevmasm/Assembly.h>
#include "Exceptions.h"
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;
}
if (peerCount() > 2 * m_idealPeerCount)
if (peerCount() > 9 * m_idealPeerCount)
{
ps->disconnect(TooManyPeers);
return;
@ -341,7 +341,7 @@ void Host::runAcceptor()
auto socket = make_shared<RLPXSocket>(new bi::tcp::socket(m_ioService));
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();
socket->close();
@ -464,7 +464,7 @@ void Host::connect(std::shared_ptr<Peer> const& _p)
return;
}
if (!m_nodeTable->haveNode(_p->id))
if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id))
{
clog(NetWarn) << "Aborted connect. Node not in node table.";
m_nodeTable->addNode(*_p.get());

28
libsolidity/AST.cpp

@ -96,8 +96,8 @@ void ContractDefinition::checkTypeRequirements()
FixedHash<4> const& hash = it.first;
if (hashes.count(hash))
BOOST_THROW_EXCEPTION(createTypeError(
std::string("Function signature hash collision for ") +
it.second->externalSignature()));
string("Function signature hash collision for ") + it.second->externalSignature()
));
hashes.insert(hash);
}
}
@ -140,12 +140,22 @@ void ContractDefinition::checkDuplicateFunctions() const
map<string, vector<FunctionDefinition const*>> functions;
for (ASTPointer<FunctionDefinition> const& function: getDefinedFunctions())
functions[function->getName()].push_back(function.get());
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(
DeclarationError() <<
errinfo_sourceLocation(getLocation()) <<
errinfo_comment("More than one constructor defined.")
errinfo_sourceLocation(functions[getName()].front()->getLocation()) <<
errinfo_comment("More than one constructor defined.") <<
errinfo_secondarySourceLocation(ssl)
);
}
for (auto const& it: functions)
{
vector<FunctionDefinition const*> const& overloads = it.second;
@ -155,7 +165,9 @@ void ContractDefinition::checkDuplicateFunctions() const
BOOST_THROW_EXCEPTION(
DeclarationError() <<
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)
{
set<string> eventsSeen;
m_interfaceEvents.reset(new std::vector<ASTPointer<EventDefinition>>());
m_interfaceEvents.reset(new vector<ASTPointer<EventDefinition>>());
for (ContractDefinition const* contract: getLinearizedBaseContracts())
for (ASTPointer<EventDefinition> const& e: contract->getEvents())
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_overloadedDeclarations.empty(), "No candidates for overload resolution found.");
std::vector<Declaration const*> possibles;
vector<Declaration const*> possibles;
if (m_overloadedDeclarations.size() == 1)
m_referencedDeclaration = *m_overloadedDeclarations.begin();

2
libsolidity/AST.h

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

2
libsolidity/ASTUtils.h

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

2
libsolidity/CMakeLists.txt

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

7
libsolidity/Compiler.cpp

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

2
libsolidity/Compiler.h

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

2
libsolidity/CompilerContext.h

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

42
libsolidity/DeclarationContainer.cpp

@ -28,6 +28,28 @@ using namespace std;
using namespace dev;
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)
{
ASTString const& name(_declaration.getName());
@ -40,24 +62,8 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration,
m_declarations.erase(name);
m_invisibleDeclarations.erase(name);
}
else
{
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;
}
else if (conflictingDeclaration(_declaration))
return false;
if (_invisible)
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.
*/
class DeclarationContainer
@ -51,6 +51,8 @@ public:
std::set<Declaration const*> resolveName(ASTString const& _name, bool _recursive = false) const;
Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; }
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:
Declaration const* m_enclosingDeclaration;

18
libsolidity/Exceptions.h

@ -23,8 +23,9 @@
#pragma once
#include <string>
#include <utility>
#include <libdevcore/Exceptions.h>
#include <libevmcore/SourceLocation.h>
#include <libevmasm/SourceLocation.h>
namespace dev
{
@ -38,7 +39,22 @@ struct CompilerError: virtual Exception {};
struct InternalCompilerError: 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_secondarySourceLocation = boost::error_info<struct tag_secondarySourceLocation, SecondarySourceLocation>;
}
}

2
libsolidity/ExpressionCompiler.h

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

2
libsolidity/LValue.h

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

37
libsolidity/NameAndTypeResolver.cpp

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

2
libsolidity/Parser.cpp

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

2
libsolidity/Scanner.h

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

74
libsolidity/SourceReferenceFormatter.cpp

@ -32,9 +32,11 @@ namespace dev
namespace solidity
{
void SourceReferenceFormatter::printSourceLocation(ostream& _stream,
SourceLocation const& _location,
Scanner const& _scanner)
void SourceReferenceFormatter::printSourceLocation(
ostream& _stream,
SourceLocation const& _location,
Scanner const& _scanner
)
{
int startLine;
int startColumn;
@ -46,11 +48,11 @@ void SourceReferenceFormatter::printSourceLocation(ostream& _stream,
{
string line = _scanner.getLineAtPosition(_location.start);
_stream << line << endl;
std::for_each(line.cbegin(), line.cbegin() + startColumn,
[&_stream](char const& ch)
{
_stream << (ch == '\t' ? '\t' : ' ');
});
for_each(
line.cbegin(),
line.cbegin() + startColumn,
[&_stream](char const& ch) { _stream << (ch == '\t' ? '\t' : ' '); }
);
_stream << "^";
if (endColumn > startColumn + 2)
_stream << string(endColumn - startColumn - 2, '-');
@ -59,33 +61,65 @@ void SourceReferenceFormatter::printSourceLocation(ostream& _stream,
_stream << endl;
}
else
_stream << _scanner.getLineAtPosition(_location.start) << endl
<< string(startColumn, ' ') << "^\n"
<< "Spanning multiple lines.\n";
_stream <<
_scanner.getLineAtPosition(_location.start) <<
endl <<
string(startColumn, ' ') <<
"^\n" <<
"Spanning multiple lines.\n";
}
void SourceReferenceFormatter::printExceptionInformation(ostream& _stream,
Exception const& _exception,
string const& _name,
CompilerStack const& _compiler)
void SourceReferenceFormatter::printSourceName(
ostream& _stream,
SourceLocation const& _location,
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);
Scanner const* scanner;
auto secondarylocation = boost::get_error_info<errinfo_secondarySourceLocation>(_exception);
Scanner const* scanner = nullptr;
if (location)
{
scanner = &_compiler.getScanner(*location->sourceName);
int startLine;
int startColumn;
tie(startLine, startColumn) = scanner->translatePositionToLineColumn(location->start);
_stream << *location->sourceName << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": ";
printSourceName(_stream, *location, *scanner);
}
_stream << _name;
if (string const* description = boost::get_error_info<errinfo_comment>(_exception))
_stream << ": " << *description << endl;
if (location)
{
scanner = &_compiler.getScanner(*location->sourceName);
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
#include <ostream>
#include <libevmcore/SourceLocation.h>
#include <libevmasm/SourceLocation.h>
namespace dev
{
@ -40,8 +40,14 @@ struct SourceReferenceFormatter
{
public:
static void printSourceLocation(std::ostream& _stream, SourceLocation const& _location, Scanner const& _scanner);
static void printExceptionInformation(std::ostream& _stream, Exception const& _exception,
std::string const& _name, CompilerStack const& _compiler);
static void printExceptionInformation(
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
const unsigned dev::SensibleHttpThreads = 4;
#endif
const unsigned dev::SensibleHttpPort = 8080;
const unsigned dev::SensibleHttpPort = 8545;
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
auto nameIter = m_contractNames.find(code.address);
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();
codes.back()->setDocument(compilerRes->documentId());
@ -467,9 +467,9 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
{
//track calls into functions
AssemblyItem const& prevInstruction = codeItems[s.codeIndex][prevInstructionIndex];
auto functionIter = contract->functions().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end));
if (functionIter != contract->functions().end() && ((prevInstruction.getJumpType() == AssemblyItem::JumpType::IntoFunction) || solCallStack.empty()))
solCallStack.push_front(QVariant::fromValue(functionIter.value()));
QString functionName = m_codeModel->resolveFunctionName(instruction.getLocation());
if (!functionName.isEmpty() && ((prevInstruction.getJumpType() == AssemblyItem::JumpType::IntoFunction) || solCallStack.empty()))
solCallStack.push_front(QVariant::fromValue(functionName));
else if (prevInstruction.getJumpType() == AssemblyItem::JumpType::OutOfFunction && !solCallStack.empty())
solCallStack.pop_front();
}
@ -521,11 +521,13 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
prevInstructionIndex = instructionIndex;
// filter out locations that match whole function or contract
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);
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)));

96
mix/CodeModel.cpp

@ -26,7 +26,7 @@
#include <QApplication>
#include <QtQml>
#include <libdevcore/Common.h>
#include <libevmcore/SourceLocation.h>
#include <libevmasm/SourceLocation.h>
#include <libsolidity/AST.h>
#include <libsolidity/Types.h>
#include <libsolidity/ASTVisitor.h>
@ -51,30 +51,31 @@ const std::set<std::string> c_predefinedContracts =
namespace
{
using namespace dev::solidity;
class CollectDeclarationsVisitor: public ASTConstVisitor
class CollectLocalsVisitor: public ASTConstVisitor
{
public:
CollectDeclarationsVisitor(QHash<LocationPair, QString>* _functions, QHash<LocationPair, SolidityDeclaration>* _locals):
m_functions(_functions), m_locals(_locals), m_functionScope(false) {}
CollectLocalsVisitor(QHash<LocationPair, SolidityDeclaration>* _locals):
m_locals(_locals), m_functionScope(false) {}
private:
LocationPair nodeLocation(ASTNode const& _node)
{
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;
return true;
}
virtual void endVisit(FunctionDefinition const&)
virtual void endVisit(FunctionDefinition const&) override
{
m_functionScope = false;
}
virtual bool visit(VariableDeclaration const& _node)
virtual bool visit(VariableDeclaration const& _node) override
{
SolidityDeclaration decl;
decl.type = CodeModel::nodeType(_node.getType().get());
@ -87,11 +88,38 @@ private:
}
private:
QHash<LocationPair, QString>* m_functions;
QHash<LocationPair, SolidityDeclaration>* m_locals;
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> result;
@ -132,7 +160,7 @@ CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler
if (contractDefinition.getLocation().sourceName.get())
m_documentId = QString::fromStdString(*contractDefinition.getLocation().sourceName);
CollectDeclarationsVisitor visitor(&m_functions, &m_locals);
CollectLocalsVisitor visitor(&m_locals);
m_storage = collectStorage(contractDefinition);
contractDefinition.accept(visitor);
m_assemblyItems = *_compiler.getRuntimeAssemblyItems(name);
@ -243,6 +271,7 @@ void CodeModel::releaseContracts()
for (ContractMap::iterator c = m_contractMap.begin(); c != m_contractMap.end(); ++c)
c.value()->deleteLater();
m_contractMap.clear();
m_sourceMaps.clear();
}
void CodeModel::runCompilationJob(int _jobId)
@ -253,13 +282,17 @@ void CodeModel::runCompilationJob(int _jobId)
try
{
cs.addSource("configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xf025d81196b72fba60a1d4dddad12eeb8360d828;}})");
std::vector<std::string> sourceNames;
{
Guard l(x_pendingContracts);
for (auto const& c: m_pendingContracts)
{
cs.addSource(c.first.toStdString(), c.second.toStdString());
sourceNames.push_back(c.first.toStdString());
}
}
cs.compile(false);
collectContracts(cs);
collectContracts(cs, sourceNames);
}
catch (dev::Exception const& _exception)
{
@ -281,11 +314,20 @@ void CodeModel::runCompilationJob(int _jobId)
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 l(x_contractMap);
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())
{
if (c_predefinedContracts.count(n) != 0)
@ -326,6 +368,7 @@ void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs)
}
releaseContracts();
m_contractMap.swap(result);
m_sourceMaps.swap(sourceMaps);
emit codeChanged();
emit compilationComplete();
}
@ -431,3 +474,32 @@ SolidityType CodeModel::nodeType(dev::solidity::Type const* _type)
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 <libdevcore/Common.h>
#include <libdevcore/Guards.h>
#include <libevmcore/Assembly.h>
#include <libevmasm/Assembly.h>
#include "SolidityType.h"
class QTextDocument;
@ -97,7 +97,6 @@ public:
/// @returns contract source Id
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<unsigned, SolidityDeclarations> const& storage() const { return m_storage; }
@ -110,7 +109,6 @@ private:
QString m_documentId;
eth::AssemblyItems m_assemblyItems;
eth::AssemblyItems m_constructorAssemblyItems;
QHash<LocationPair, QString> m_functions;
QHash<LocationPair, SolidityDeclaration> m_locals;
QHash<unsigned, SolidityDeclarations> m_storage;
@ -119,6 +117,17 @@ private:
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
class CodeModel: public QObject
{
@ -153,6 +162,10 @@ public:
Q_INVOKABLE void reset() { reset(QVariantMap()); }
/// Convert solidity type info to mix 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:
/// Emited on compilation state change
@ -182,11 +195,12 @@ private:
void runCompilationJob(int _jobId);
void stop();
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;
mutable dev::Mutex x_contractMap;
ContractMap m_contractMap;
SourceMaps m_sourceMaps;
std::unique_ptr<CodeHighlighterSettings> m_codeHighlighterSettings;
QThread m_backgroundThread;
BackgroundWorker m_backgroundWorker;

1
mix/MixClient.cpp

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

2
mix/QBasicNodeDefinition.h

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

2
mix/qml/StateDialog.qml

@ -158,7 +158,7 @@ Dialog {
id: importJsonFileDialog
visible: false
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: {
var path = importJsonFileDialog.fileUrl.toString()
var jsonData = fileIo.readFile(path)

5
mix/qml/html/codeeditor.js

@ -126,7 +126,10 @@ highlightExecution = function(start, end) {
executionMark.clear();
if (debugWarning)
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;

3
mix/qml/js/Debugger.js

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

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

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

48
solc/CommandLineInterface.cpp

@ -51,19 +51,18 @@ namespace dev
namespace solidity
{
// LTODO: Maybe some argument class pairing names with
// extensions and other attributes would be a better choice here?
static string const g_argAbiStr = "json-abi";
static string const g_argSolAbiStr = "sol-abi";
static string const g_argAsmStr = "asm";
static string const g_argAsmJsonStr = "asm-json";
static string const g_argAstStr = "ast";
static string const g_argAstJson = "ast-json";
static string const g_argBinaryStr = "binary";
static string const g_argOpcodesStr = "opcodes";
static string const g_argNatspecDevStr = "natspec-dev";
static string const g_argAbiStr = "json-abi";
static string const g_argSolAbiStr = "sol-abi";
static string const g_argSignatureHashes = "hashes";
static string const g_argAsmStr = "asm";
static string const g_argAsmJsonStr = "asm-json";
static string const g_argAstStr = "ast";
static string const g_argAstJson = "ast-json";
static string const g_argBinaryStr = "binary";
static string const g_argOpcodesStr = "opcodes";
static string const g_argNatspecDevStr = "natspec-dev";
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
static set<string> const g_combinedJsonArgs{
@ -96,6 +95,7 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args)
return
humanTargetedStdout(_args, g_argAbiStr) ||
humanTargetedStdout(_args, g_argSolAbiStr) ||
humanTargetedStdout(_args, g_argSignatureHashes) ||
humanTargetedStdout(_args, g_argNatspecUserStr) ||
humanTargetedStdout(_args, g_argAstJson) ||
humanTargetedStdout(_args, g_argNatspecDevStr) ||
@ -173,6 +173,27 @@ void CommandLineInterface::handleBytecode(string const& _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)
{
std::string argName;
@ -254,6 +275,8 @@ bool CommandLineInterface::parseArguments(int argc, char** argv)
"Request to output the contract's JSON ABI interface.")
(g_argSolAbiStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
"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"),
"Request to output the contract's Natspec user documentation.")
(g_argNatspecDevStr.c_str(), po::value<OutputType>()->value_name("stdout|file|both"),
@ -516,6 +539,7 @@ void CommandLineInterface::actOnInput()
}
handleBytecode(contract);
handleSignatureHashes(contract);
handleMeta(DocumentationType::ABIInterface, contract);
handleMeta(DocumentationType::ABISolidityInterface, contract);
handleMeta(DocumentationType::NatspecDev, contract);

1
solc/CommandLineInterface.h

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

55
test/libp2p/peer.cpp

@ -120,6 +120,61 @@ BOOST_AUTO_TEST_CASE(saveNodes)
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_CASE(emptySharedPeer)

6
test/libsolidity/Assembly.cpp

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

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

Loading…
Cancel
Save