Browse Source

Merge remote-tracking branch 'upstream/develop' into walletTests

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

25
CMakeLists.txt

@ -305,6 +305,7 @@ endif()
add_subdirectory(libdevcore) add_subdirectory(libdevcore)
add_subdirectory(libevmcore) add_subdirectory(libevmcore)
add_subdirectory(libevmasm)
add_subdirectory(liblll) add_subdirectory(liblll)
if (SERPENT) if (SERPENT)
@ -388,23 +389,37 @@ endif()
if (WIN32) if (WIN32)
# packaging stuff # packaging stuff
include(InstallRequiredSystemLibraries) include(InstallRequiredSystemLibraries)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "ethereum") set(CPACK_PACKAGE_NAME "Ethereum")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Ethereum")
set(CPACK_PACKAGE_VENDOR "ethereum.org") set(CPACK_PACKAGE_VENDOR "ethereum.org")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION "0.7") set(CPACK_PACKAGE_VERSION "0.9")
set(CPACK_GENERATOR "NSIS") set(CPACK_GENERATOR "NSIS")
# seems to be not working # seems to be not working
# set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.bmp") # set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/alethzero/alethzero.bmp")
# our stuff # our stuff
set(CPACK_COMPONENT_ALETHZERO_GROUP "Applications") set(CPACK_COMPONENT_ALETHZERO_GROUP "Applications")
set(CPACK_COMPONENT_THIRD_GROUP "Applications")
set(CPACK_COMPONENT_MIX_GROUP "Applications") set(CPACK_COMPONENT_MIX_GROUP "Applications")
set(CPACK_COMPONENTS_ALL alethzero third mix) set(CPACK_COMPONENT_SOLC_GROUP "CLI")
set(CPACK_COMPONENT_ETH_GROUP "CLI")
set(CPACK_COMPONENT_ETHMINER_GROUP "CLI")
set(CPACK_COMPONENT_RLP_GROUP "CLI")
set(CPACK_COMPONENT_ABI_GROUP "CLI")
set(CPACK_COMPONENTS_ALL alethzero mix solc eth ethminer rlp abi)
# nsis specific stuff # nsis specific stuff
set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ethereum") if (CMAKE_CL_64)
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION} (Win64)")
else ()
set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}")
endif()
set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} Ethereum")
set(CPACK_NSIS_HELP_LINK "https://github.com/ethereum/cpp-ethereum") set(CPACK_NSIS_HELP_LINK "https://github.com/ethereum/cpp-ethereum")
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/ethereum/cpp-ethereum") set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/ethereum/cpp-ethereum")
set(CPACK_NSIS_CONTACT "ethereum.org") set(CPACK_NSIS_CONTACT "ethereum.org")

7
abi/CMakeLists.txt

@ -12,5 +12,8 @@ add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} ethereum)
install( TARGETS ${EXECUTABLE} DESTINATION bin) if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

3
alethzero/CMakeLists.txt

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

8
alethzero/Context.h

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

4
alethzero/DappLoader.cpp

@ -69,7 +69,11 @@ DappLocation DappLoader::resolveAppUri(QString const& _uri)
string32 name = ZeroString32; string32 name = ZeroString32;
QByteArray utf8 = parts[partIndex].toUtf8(); QByteArray utf8 = parts[partIndex].toUtf8();
std::copy(utf8.data(), utf8.data() + utf8.size(), name.data()); std::copy(utf8.data(), utf8.data() + utf8.size(), name.data());
if (address != m_nameReg)
address = abiOut<Address>(web3()->ethereum()->call(address, abiIn("subRegistrar(bytes32)", name)).output); address = abiOut<Address>(web3()->ethereum()->call(address, abiIn("subRegistrar(bytes32)", name)).output);
else
address = abiOut<Address>(web3()->ethereum()->call(address, abiIn("register(bytes32)", name)).output);
domainParts.append(parts[partIndex]); domainParts.append(parts[partIndex]);
if (!address) if (!address)
{ {

4
alethzero/Debugger.cpp

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

4
alethzero/DownloadView.cpp

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

4
alethzero/ExportState.cpp

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

189
alethzero/Main.ui

@ -53,23 +53,23 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="balance"> <widget class="QLabel" name="blockCount">
<property name="text"> <property name="text">
<string>0 wei</string> <string>1 block</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="peerCount"> <widget class="QLabel" name="balance">
<property name="text"> <property name="text">
<string>0 peers</string> <string>0 wei</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="blockCount"> <widget class="QLabel" name="peerCount">
<property name="text"> <property name="text">
<string>1 block</string> <string>0 peers</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -190,7 +190,6 @@
<string>&amp;View</string> <string>&amp;View</string>
</property> </property>
<addaction name="showAll"/> <addaction name="showAll"/>
<addaction name="showAllAccounts"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="preview"/> <addaction name="preview"/>
</widget> </widget>
@ -218,43 +217,6 @@
<addaction name="menu_Debug"/> <addaction name="menu_Debug"/>
</widget> </widget>
<widget class="QStatusBar" name="statusbar"/> <widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="dockWidget_accounts">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Accounts</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="accounts">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_3"> <widget class="QDockWidget" name="dockWidget_3">
<property name="features"> <property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set> <set>QDockWidget::DockWidgetFeatureMask</set>
@ -294,6 +256,19 @@
</widget> </widget>
<widget class="QWidget" name="layoutWidget"> <widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="1">
<widget class="QLineEdit" name="listenIP">
<property name="inputMask">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Automatic</string>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@ -304,16 +279,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1" colspan="2">
<widget class="QSpinBox" name="idealPeers">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item row="3" column="2"> <item row="3" column="2">
<widget class="QSpinBox" name="port"> <widget class="QSpinBox" name="port">
<property name="minimum"> <property name="minimum">
@ -327,20 +292,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="3">
<widget class="QLineEdit" name="listenIP"> <widget class="QLabel" name="label_2">
<property name="inputMask">
<string/>
</property>
<property name="text"> <property name="text">
<string/> <string>Public IP</string>
</property> </property>
</widget>
</item>
<item row="3" column="4">
<widget class="QLineEdit" name="forcePublicIP">
<property name="placeholderText"> <property name="placeholderText">
<string>Automatic</string> <string>Automatic</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="0" column="3">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Ideal &amp;Peers</string> <string>Ideal &amp;Peers</string>
@ -350,21 +316,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="0" column="0">
<widget class="QLineEdit" name="forcePublicIP">
<property name="placeholderText">
<string>Automatic</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Public IP</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>&amp;Client Name</string> <string>&amp;Client Name</string>
@ -374,13 +326,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="0" column="4">
<widget class="QSpinBox" name="idealPeers">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="clientName"> <widget class="QLineEdit" name="clientName">
<property name="placeholderText"> <property name="placeholderText">
<string>Anonymous</string> <string>Anonymous</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="5">
<widget class="QLineEdit" name="enode">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
@ -590,18 +559,21 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QDockWidget" name="dockWidget_contracts"> <widget class="QDockWidget" name="dockWidget_accounts">
<property name="features"> <property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set> <set>QDockWidget::DockWidgetFeatureMask</set>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Contracts</string> <string>Accounts</string>
</property> </property>
<attribute name="dockWidgetArea"> <attribute name="dockWidgetArea">
<number>2</number> <number>2</number>
</attribute> </attribute>
<widget class="QWidget" name="dockWidgetContents_6"> <widget class="QWidget" name="dockWidgetContents_6">
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -614,12 +586,66 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="accountsFilter">
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showBasic">
<property name="text">
<string>Basic</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showContracts">
<property name="text">
<string>Contracts</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<property name="text">
<string>Only Named</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshAccounts">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QSplitter" name="splitter_3"> <widget class="QSplitter" name="splitter_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QListWidget" name="contracts"> <widget class="QListWidget" name="accounts">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -633,7 +659,7 @@
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
</widget> </widget>
<widget class="QPlainTextEdit" name="contractInfo"> <widget class="QPlainTextEdit" name="accountInfo">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch> <horstretch>2</horstretch>
@ -1732,7 +1758,6 @@ font-size: 14pt</string>
<tabstop>verbosity</tabstop> <tabstop>verbosity</tabstop>
<tabstop>tabWidget</tabstop> <tabstop>tabWidget</tabstop>
<tabstop>urlEdit</tabstop> <tabstop>urlEdit</tabstop>
<tabstop>idealPeers</tabstop>
<tabstop>listenIP</tabstop> <tabstop>listenIP</tabstop>
<tabstop>port</tabstop> <tabstop>port</tabstop>
<tabstop>transactionQueue</tabstop> <tabstop>transactionQueue</tabstop>

216
alethzero/MainWin.cpp

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

20
alethzero/MainWin.h

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

6
alethzero/OurWebThreeStubServer.cpp

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

14
alethzero/Transact.cpp

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

16
cmake/EthCompilerSettings.cmake

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

12
cmake/EthExecutableHelper.cmake

@ -94,6 +94,7 @@ macro(eth_install_executable EXECUTABLE)
# This tool and next will inspect linked libraries in order to determine which dependencies are required # This tool and next will inspect linked libraries in order to determine which dependencies are required
if (${CMAKE_CFG_INTDIR} STREQUAL ".") if (${CMAKE_CFG_INTDIR} STREQUAL ".")
# TODO: This should only happen for GUI application
set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app")
else () else ()
set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app")
@ -126,8 +127,15 @@ macro(eth_install_executable EXECUTABLE)
eth_copy_dlls(${EXECUTABLE} ${dll}) eth_copy_dlls(${EXECUTABLE} ${dll})
endforeach(dll) endforeach(dll)
install( TARGETS ${EXECUTABLE} RUNTIME install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Debug"
DESTINATION bin DESTINATION .
CONFIGURATIONS Debug
COMPONENT ${EXECUTABLE}
)
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Release"
DESTINATION .
CONFIGURATIONS Release
COMPONENT ${EXECUTABLE} COMPONENT ${EXECUTABLE}
) )

7
eth/CMakeLists.txt

@ -37,5 +37,8 @@ if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS) eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif() endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin ) if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

16
eth/main.cpp

@ -146,6 +146,7 @@ void help()
<< " --listen <port> Listen on the given port for incoming connections (default: 30303)." << endl << " --listen <port> Listen on the given port for incoming connections (default: 30303)." << endl
<< " -r,--remote <host>(:<port>) Connect to remote host (default: none)." << endl << " -r,--remote <host>(:<port>) Connect to remote host (default: none)." << endl
<< " --port <port> Connect to remote port (default: 30303)." << endl << " --port <port> Connect to remote port (default: 30303)." << endl
<< " --network-id <n> Only connect to other hosts with this network id (default:0)." << endl
<< " --upnp <on/off> Use UPnP for NAT (default: on)." << endl << " --upnp <on/off> Use UPnP for NAT (default: on)." << endl
#if ETH_JSONRPC || !ETH_TRUE #if ETH_JSONRPC || !ETH_TRUE
<< "Work farming mode:" << endl << "Work farming mode:" << endl
@ -406,6 +407,7 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
#if 0
cout << "\x1b[30mEthBlack\x1b[0m" << endl; cout << "\x1b[30mEthBlack\x1b[0m" << endl;
cout << "\x1b[90mEthCoal\x1b[0m" << endl; cout << "\x1b[90mEthCoal\x1b[0m" << endl;
cout << "\x1b[37mEthGray\x1b[0m" << endl; cout << "\x1b[37mEthGray\x1b[0m" << endl;
@ -471,7 +473,7 @@ int main(int argc, char** argv)
cout << "\x1b[4;35mEthPurpleU\x1b[0m" << endl; cout << "\x1b[4;35mEthPurpleU\x1b[0m" << endl;
cout << "\x1b[4;36mEthCyanU\x1b[0m" << endl; cout << "\x1b[4;36mEthCyanU\x1b[0m" << endl;
cout << "\x1b[4;37mEthWhiteU\x1b[0m" << endl; cout << "\x1b[4;37mEthWhiteU\x1b[0m" << endl;
#endif
// Init defaults // Init defaults
Defaults::get(); Defaults::get();
@ -515,6 +517,7 @@ int main(int argc, char** argv)
unsigned short remotePort = 30303; unsigned short remotePort = 30303;
unsigned peers = 5; unsigned peers = 5;
bool bootstrap = false; bool bootstrap = false;
unsigned networkId = 0;
/// Mining params /// Mining params
unsigned mining = 0; unsigned mining = 0;
@ -668,6 +671,15 @@ int main(int argc, char** argv)
return -1; return -1;
} }
} }
else if (arg == "--network-id" && i + 1 < argc)
try {
networkId = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--benchmark-warmup" && i + 1 < argc) else if (arg == "--benchmark-warmup" && i + 1 < argc)
try { try {
benchmarkWarmup = stol(argv[++i]); benchmarkWarmup = stol(argv[++i]);
@ -1034,11 +1046,13 @@ int main(int argc, char** argv)
c->setForceMining(forceMining); c->setForceMining(forceMining);
c->setTurboMining(minerType == MinerType::GPU); c->setTurboMining(minerType == MinerType::GPU);
c->setAddress(coinbase); c->setAddress(coinbase);
c->setNetworkId(networkId);
} }
cout << "Transaction Signer: " << sigKey.address() << endl; cout << "Transaction Signer: " << sigKey.address() << endl;
cout << "Mining Benefactor: " << coinbase << endl; cout << "Mining Benefactor: " << coinbase << endl;
web3.startNetwork(); web3.startNetwork();
cout << "Node ID: " << web3.enode() << endl;
if (bootstrap) if (bootstrap)
web3.addNode(p2p::NodeId(), Host::pocHost()); web3.addNode(p2p::NodeId(), Host::pocHost());

6
ethminer/CMakeLists.txt

@ -37,5 +37,9 @@ if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS) eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif() endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin ) if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

2
evmjit/libevmjit-cpp/Env.cpp

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

90
exp/main.cpp

@ -33,6 +33,7 @@
#endif #endif
#include <functional> #include <functional>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <libdevcore/RangeMask.h> #include <libdevcore/RangeMask.h>
#include <libdevcore/Log.h> #include <libdevcore/Log.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
@ -43,6 +44,7 @@
#include <libdevcrypto/TrieDB.h> #include <libdevcrypto/TrieDB.h>
#include <libp2p/All.h> #include <libp2p/All.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libdevcrypto/FileSystem.h>
#include <libethereum/All.h> #include <libethereum/All.h>
#include <libethereum/Farm.h> #include <libethereum/Farm.h>
#include <libethereum/AccountDiff.h> #include <libethereum/AccountDiff.h>
@ -58,8 +60,94 @@ using namespace dev::eth;
using namespace dev::p2p; using namespace dev::p2p;
using namespace dev::shh; using namespace dev::shh;
namespace js = json_spirit; namespace js = json_spirit;
namespace fs = boost::filesystem;
#if 0 #if 1
inline h128 fromUUID(std::string const& _uuid) { return h128(boost::replace_all_copy(_uuid, "-", "")); }
class KeyManager: public Worker
{
public:
KeyManager() { readKeys(); }
~KeyManager() {}
Secret secret(h128 const& _uuid, std::string const& _pass)
{
auto it = m_keys.find(_uuid);
if (it == m_keys.end())
return Secret();
return Secret(decrypt(it->second, _pass));
}
private:
void readKeys(std::string const& _keysPath = getDataDir("web3") + "/keys")
{
fs::path p(_keysPath);
js::mValue v;
for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it)
if (is_regular_file(it->path()))
{
cdebug << "Reading" << it->path();
js::read_string(contentsString(it->path().string()), v);
js::mObject o = v.get_obj();
int version = o.count("Version") ? stoi(o["Version"].get_str()) : o.count("version") ? o["version"].get_int() : 0;
if (version == 2)
m_keys[fromUUID(o["id"].get_str())] = o["crypto"];
else
cwarn << "Cannot read key version" << version;
}
}
static bytes decrypt(js::mValue const& _v, std::string const& _pass)
{
js::mObject o = _v.get_obj();
bytes pKey;
if (o["kdf"].get_str() == "pbkdf2")
{
auto params = o["kdfparams"].get_obj();
unsigned iterations = params["c"].get_int();
bytes salt = fromHex(params["salt"].get_str());
pKey = pbkdf2(_pass, salt, iterations).asBytes();
}
else
{
cwarn << "Unknown KDF" << o["kdf"].get_str() << "not supported.";
return bytes();
}
// TODO check MAC
h256 mac(o["mac"].get_str());
(void)mac;
bytes cipherText = fromHex(o["ciphertext"].get_str());
bytes ret;
if (o["cipher"].get_str() == "aes-128-cbc")
{
auto params = o["cipherparams"].get_obj();
h128 key(sha3(h128(pKey, h128::AlignRight)), h128::AlignRight);
h128 iv(params["iv"].get_str());
decryptSymNoAuth(key, iv, &cipherText, ret);
}
else
{
cwarn << "Unknown cipher" << o["cipher"].get_str() << "not supported.";
return bytes();
}
return ret;
}
std::map<h128, js::mValue> m_keys;
};
int main()
{
KeyManager keyman;
cdebug << "Secret key for 0498f19a-59db-4d54-ac95-33901b4f1870 is " << keyman.secret(fromUUID("0498f19a-59db-4d54-ac95-33901b4f1870"), "foo");
}
#elif 0
int main() int main()
{ {
DownloadMan man; DownloadMan man;

8
libdevcore/Common.cpp

@ -21,13 +21,14 @@
#include "Common.h" #include "Common.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "Log.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
namespace dev namespace dev
{ {
char const* Version = "0.9.14"; char const* Version = "0.9.15";
void HasInvariants::checkInvariants() const void HasInvariants::checkInvariants() const
{ {
@ -35,5 +36,10 @@ void HasInvariants::checkInvariants() const
BOOST_THROW_EXCEPTION(FailedInvariant()); BOOST_THROW_EXCEPTION(FailedInvariant());
} }
TimerHelper::~TimerHelper()
{
cdebug << "Timer" << id << t.elapsed() << "s";
}
} }

20
libdevcore/Common.h

@ -37,6 +37,7 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include <functional> #include <functional>
#include <boost/timer.hpp>
#pragma warning(push) #pragma warning(push)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
@ -168,6 +169,25 @@ private:
#define DEV_INVARIANT_CHECK (void)0; #define DEV_INVARIANT_CHECK (void)0;
#endif #endif
class TimerHelper
{
public:
TimerHelper(char const* _id): id(_id) {}
~TimerHelper();
private:
boost::timer t;
char const* id;
};
#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(#S, true); __eth_t.second; __eth_t.second = false)
#define DEV_TIMED_SCOPE(S) ::dev::TimerHelper __eth_t(S)
#if WIN32
#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__FUNCSIG__)
#else
#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__PRETTY_FUNCTION__)
#endif
enum class WithExisting: int enum class WithExisting: int
{ {
Trust = 0, Trust = 0,

5
libdevcore/FixedHash.h

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

13
libdevcore/Guards.h

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

4
libdevcore/Log.cpp

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

14
libdevcrypto/Common.cpp

@ -112,13 +112,13 @@ bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain)
return decrypt(_k, _cipher, o_plain); return decrypt(_k, _cipher, o_plain);
} }
h128 dev::encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher) h128 dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher)
{ {
h128 iv(Nonce::get()); h128 iv(Nonce::get());
return encryptSymNoAuth(_k, _plain, o_cipher, iv); return encryptSymNoAuth(_k, _plain, o_cipher, iv);
} }
h128 dev::encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv) h128 dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv)
{ {
o_cipher.resize(_plain.size()); o_cipher.resize(_plain.size());
@ -139,7 +139,7 @@ h128 dev::encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_ciph
} }
} }
bool dev::decryptSymNoAuth(Secret const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext) bool dev::decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext)
{ {
o_plaintext.resize(_cipher.size()); o_plaintext.resize(_cipher.size());
@ -175,6 +175,14 @@ bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash)
return s_secp256k1.verify(_p, _s, _hash.ref(), true); return s_secp256k1.verify(_p, _s, _hash.ref(), true);
} }
h256 dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations)
{
h256 ret;
PKCS5_PBKDF2_HMAC<SHA256> pbkdf;
pbkdf.DeriveKey(ret.data(), ret.size, 0, (byte*)_pass.data(), _pass.size(), _salt.data(), _salt.size(), _iterations);
return ret;
}
KeyPair KeyPair::create() KeyPair KeyPair::create()
{ {
static boost::thread_specific_ptr<mt19937_64> s_eng; static boost::thread_specific_ptr<mt19937_64> s_eng;

11
libdevcrypto/Common.h

@ -103,13 +103,13 @@ void encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher);
bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext); bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
/// Encrypts payload with random IV/ctr using AES128-CTR. /// Encrypts payload with random IV/ctr using AES128-CTR.
h128 encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher); h128 encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher);
/// Encrypts payload with specified IV/ctr using AES128-CTR. /// Encrypts payload with specified IV/ctr using AES128-CTR.
h128 encryptSymNoAuth(Secret const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv); h128 encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv);
/// Decrypts payload with specified IV/ctr. /// Decrypts payload with specified IV/ctr using AES128-CTR.
bool decryptSymNoAuth(Secret const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext); bool decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext);
/// Recovers Public key from signed message hash. /// Recovers Public key from signed message hash.
Public recover(Signature const& _sig, h256 const& _hash); Public recover(Signature const& _sig, h256 const& _hash);
@ -120,6 +120,9 @@ Signature sign(Secret const& _k, h256 const& _hash);
/// Verify signature. /// Verify signature.
bool verify(Public const& _k, Signature const& _s, h256 const& _hash); bool verify(Public const& _k, Signature const& _s, h256 const& _hash);
/// Derive key via PBKDF2.
h256 pbkdf2(std::string const& _pass, bytes const& _salt, unsigned _iterations);
/// Simple class that represents a "key pair". /// Simple class that represents a "key pair".
/// All of the data of the class can be regenerated from the secret key (m_secret) alone. /// All of the data of the class can be regenerated from the secret key (m_secret) alone.
/// Actually stores a tuplet of secret, public and address (the right 160-bits of the public). /// Actually stores a tuplet of secret, public and address (the right 160-bits of the public).

4
libdevcrypto/CryptoPP.cpp

@ -79,7 +79,7 @@ void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher)
ctx.Final(mKey.data()); ctx.Final(mKey.data());
bytes cipherText; bytes cipherText;
encryptSymNoAuth(*(Secret*)eKey.data(), bytesConstRef(&io_cipher), cipherText, h128()); encryptSymNoAuth(h128(eKey), bytesConstRef(&io_cipher), cipherText, h128());
if (cipherText.empty()) if (cipherText.empty())
return; return;
@ -139,7 +139,7 @@ bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text)
if (mac[i] != msgMac[i]) if (mac[i] != msgMac[i])
return false; return false;
decryptSymNoAuth(*(Secret*)eKey.data(), iv, cipherNoIV, plain); decryptSymNoAuth(h128(eKey), iv, cipherNoIV, plain);
io_text.resize(plain.size()); io_text.resize(plain.size());
io_text.swap(plain); io_text.swap(plain);

24
libethash-cl/ethash_cl_miner.cpp

@ -88,6 +88,13 @@ std::string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _devic
return "{ \"platform\": \"" + platforms[platform_num].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }"; return "{ \"platform\": \"" + platforms[platform_num].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }";
} }
unsigned ethash_cl_miner::get_num_platforms()
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
return platforms.size();
}
unsigned ethash_cl_miner::get_num_devices(unsigned _platformId) unsigned ethash_cl_miner::get_num_devices(unsigned _platformId)
{ {
std::vector<cl::Platform> platforms; std::vector<cl::Platform> platforms;
@ -117,11 +124,8 @@ void ethash_cl_miner::finish()
} }
} }
bool ethash_cl_miner::init(ethash_params const& params, std::function<void(void*)> _fillDAG, unsigned workgroup_size, unsigned _platformId, unsigned _deviceId) bool ethash_cl_miner::init(uint8_t const* _dag, uint64_t _dagSize, unsigned workgroup_size, unsigned _platformId, unsigned _deviceId)
{ {
// store params
m_params = params;
// get all platforms // get all platforms
std::vector<cl::Platform> platforms; std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms); cl::Platform::get(&platforms);
@ -171,7 +175,7 @@ bool ethash_cl_miner::init(ethash_params const& params, std::function<void(void*
// patch source code // patch source code
std::string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE); std::string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE);
add_definition(code, "GROUP_SIZE", m_workgroup_size); add_definition(code, "GROUP_SIZE", m_workgroup_size);
add_definition(code, "DAG_SIZE", (unsigned)(params.full_size / ETHASH_MIX_BYTES)); add_definition(code, "DAG_SIZE", (unsigned)(_dagSize / ETHASH_MIX_BYTES));
add_definition(code, "ACCESSES", ETHASH_ACCESSES); add_definition(code, "ACCESSES", ETHASH_ACCESSES);
add_definition(code, "MAX_OUTPUTS", c_max_search_results); add_definition(code, "MAX_OUTPUTS", c_max_search_results);
//debugf("%s", code.c_str()); //debugf("%s", code.c_str());
@ -194,18 +198,20 @@ bool ethash_cl_miner::init(ethash_params const& params, std::function<void(void*
m_search_kernel = cl::Kernel(program, "ethash_search"); m_search_kernel = cl::Kernel(program, "ethash_search");
// create buffer for dag // create buffer for dag
m_dag = cl::Buffer(m_context, CL_MEM_READ_ONLY, params.full_size); m_dag = cl::Buffer(m_context, CL_MEM_READ_ONLY, _dagSize);
// create buffer for header // create buffer for header
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32); m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32);
// compute dag on CPU // compute dag on CPU
{ {
m_queue.enqueueWriteBuffer(m_dag, CL_TRUE, 0, _dagSize, _dag);
// if this throws then it's because we probably need to subdivide the dag uploads for compatibility // if this throws then it's because we probably need to subdivide the dag uploads for compatibility
void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, params.full_size); // void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, _dagSize);
// memcpying 1GB: horrible... really. horrible. but necessary since we can't mmap *and* gpumap. // memcpying 1GB: horrible... really. horrible. but necessary since we can't mmap *and* gpumap.
_fillDAG(dag_ptr); // _fillDAG(dag_ptr);
m_queue.enqueueUnmapMemObject(m_dag, dag_ptr); // m_queue.enqueueUnmapMemObject(m_dag, dag_ptr);
} }
// create mining buffers // create mining buffers

7
libethash-cl/ethash_cl_miner.h

@ -31,11 +31,11 @@ public:
public: public:
ethash_cl_miner(); ethash_cl_miner();
bool init(ethash_params const& params, std::function<void(void*)> _fillDAG, unsigned workgroup_size = 64, unsigned _platformId = 0, unsigned _deviceId = 0); static unsigned get_num_platforms();
static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0);
static unsigned get_num_devices(unsigned _platformId = 0); static unsigned get_num_devices(unsigned _platformId = 0);
static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0);
bool init(uint8_t const* _dag, uint64_t _dagSize, unsigned workgroup_size = 64, unsigned _platformId = 0, unsigned _deviceId = 0);
void finish(); void finish();
void hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count); void hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count);
void search(uint8_t const* header, uint64_t target, search_hook& hook); void search(uint8_t const* header, uint64_t target, search_hook& hook);
@ -43,7 +43,6 @@ public:
private: private:
enum { c_max_search_results = 63, c_num_buffers = 2, c_hash_batch_size = 1024, c_search_batch_size = 1024*256 }; enum { c_max_search_results = 63, c_num_buffers = 2, c_hash_batch_size = 1024, c_search_batch_size = 1024*256 };
ethash_params m_params;
cl::Context m_context; cl::Context m_context;
cl::CommandQueue m_queue; cl::CommandQueue m_queue;
cl::Kernel m_hash_kernel; cl::Kernel m_hash_kernel;

2
libethcore/BlockInfo.cpp

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

2
libethcore/CMakeLists.txt

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

6
libethcore/Ethash.cpp

@ -309,10 +309,10 @@ void Ethash::GPUMiner::workLoop()
delete m_miner; delete m_miner;
m_miner = new ethash_cl_miner; m_miner = new ethash_cl_miner;
auto p = EthashAux::params(m_minerSeed);
auto cb = [&](void* d) { EthashAux::full(m_minerSeed, bytesRef((byte*)d, p.full_size)); };
unsigned device = instances() > 1 ? index() : s_deviceId; unsigned device = instances() > 1 ? index() : s_deviceId;
m_miner->init(p, cb, 32, s_platformId, device);
EthashAux::FullType dag = EthashAux::full(m_minerSeed);
m_miner->init(dag->data.data(), dag->data.size(), 32, s_platformId, device);
} }
uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192); uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192);

13
libethcore/EthashAux.cpp

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

2
libethcore/ICAP.h

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

36
libethcore/Params.cpp

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

37
libethcore/Params.h

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

26
libethereum/BlockChain.cpp

@ -37,6 +37,7 @@
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libethcore/ProofOfWork.h> #include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h> #include <libethcore/BlockInfo.h>
#include <libethcore/Params.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include "GenesisInfo.h" #include "GenesisInfo.h"
#include "State.h" #include "State.h"
@ -47,7 +48,7 @@ using namespace dev::eth;
namespace js = json_spirit; namespace js = json_spirit;
#define ETH_CATCH 1 #define ETH_CATCH 1
#define ETH_TIMED_IMPORTS 1 #define ETH_TIMED_IMPORTS 0
#ifdef _WIN32 #ifdef _WIN32
const char* BlockChainDebug::name() { return EthBlue "8" EthWhite " <>"; } const char* BlockChainDebug::name() { return EthBlue "8" EthWhite " <>"; }
@ -473,7 +474,7 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
t.restart(); t.restart();
#endif #endif
#if ETH_PARANOIA #if ETH_PARANOIA || !ETH_TRUE
checkConsistency(); checkConsistency();
#endif #endif
@ -488,7 +489,7 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
ETH_WRITE_GUARDED(x_details) ETH_WRITE_GUARDED(x_details)
m_details[bi.parentHash].children.push_back(bi.hash()); m_details[bi.parentHash].children.push_back(bi.hash());
#if ETH_TIMED_IMPORTS #if ETH_TIMED_IMPORTS || !ETH_TRUE
collation = t.elapsed(); collation = t.elapsed();
t.restart(); t.restart();
#endif #endif
@ -496,18 +497,15 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
blocksBatch.Put(toSlice(bi.hash()), (ldb::Slice)ref(_block)); blocksBatch.Put(toSlice(bi.hash()), (ldb::Slice)ref(_block));
ETH_READ_GUARDED(x_details) ETH_READ_GUARDED(x_details)
extrasBatch.Put(toSlice(bi.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp())); extrasBatch.Put(toSlice(bi.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp()));
extrasBatch.Put(toSlice(bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, bi.parentHash, {}).rlp())); extrasBatch.Put(toSlice(bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, bi.parentHash, {}).rlp()));
extrasBatch.Put(toSlice(bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp())); extrasBatch.Put(toSlice(bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp()));
extrasBatch.Put(toSlice(bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp())); extrasBatch.Put(toSlice(bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp()));
#if ETH_TIMED_IMPORTS #if ETH_TIMED_IMPORTS || !ETH_TRUE
writing = t.elapsed(); writing = t.elapsed();
t.restart(); t.restart();
#endif #endif
#if ETH_PARANOIA
checkConsistency();
#endif
} }
#if ETH_CATCH #if ETH_CATCH
catch (InvalidNonce const& _e) catch (InvalidNonce const& _e)
@ -609,7 +607,6 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
} }
clog(BlockChainNote) << " Imported and best" << td << " (#" << bi.number << "). Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << route; clog(BlockChainNote) << " Imported and best" << td << " (#" << bi.number << "). Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << route;
noteCanonChanged();
StructuredLogger::chainNewHead( StructuredLogger::chainNewHead(
bi.headerHash(WithoutNonce).abridged(), bi.headerHash(WithoutNonce).abridged(),
@ -632,6 +629,10 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
m_lastBlockNumber = newLastBlockNumber; m_lastBlockNumber = newLastBlockNumber;
} }
#if ETH_PARANOIA || !ETH_TRUE
checkConsistency();
#endif
#if ETH_TIMED_IMPORTS #if ETH_TIMED_IMPORTS
checkBest = t.elapsed(); checkBest = t.elapsed();
cnote << "Import took:" << total.elapsed(); cnote << "Import took:" << total.elapsed();
@ -642,6 +643,9 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
cnote << "checkBest:" << checkBest; cnote << "checkBest:" << checkBest;
#endif #endif
if (!route.empty())
noteCanonChanged();
if (isKnown(bi.hash()) && !details(bi.hash())) if (isKnown(bi.hash()) && !details(bi.hash()))
{ {
clog(BlockChainDebug) << "Known block just inserted has no details."; clog(BlockChainDebug) << "Known block just inserted has no details.";
@ -767,7 +771,7 @@ void BlockChain::noteUsed(h256 const& _h, unsigned _extra) const
m_inUse.insert(id); m_inUse.insert(id);
} }
template <class T> static unsigned getHashSize(map<h256, T> const& _map) template <class T> static unsigned getHashSize(unordered_map<h256, T> const& _map)
{ {
unsigned ret = 0; unsigned ret = 0;
for (auto const& i: _map) for (auto const& i: _map)
@ -855,7 +859,7 @@ void BlockChain::garbageCollect(bool _force)
} }
} }
m_cacheUsage.pop_back(); m_cacheUsage.pop_back();
m_cacheUsage.push_front(std::set<CacheID>{}); m_cacheUsage.push_front(std::unordered_set<CacheID>{});
} }
void BlockChain::checkConsistency() void BlockChain::checkConsistency()

20
libethereum/BlockChain.h

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

13
libethereum/BlockDetails.h

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

1
libethereum/CanonBlockChain.cpp

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

14
libethereum/Client.cpp

@ -36,12 +36,6 @@ using namespace dev;
using namespace dev::eth; using namespace dev::eth;
using namespace p2p; using namespace p2p;
namespace dev
{
struct TimerHelper { TimerHelper(char const* _id): id(_id) {} ~TimerHelper() { cdebug << "Timer" << id << t.elapsed() << "s"; } boost::timer t; char const* id; };
#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(#S, true); __eth_t.second; __eth_t.second = false)
}
VersionChecker::VersionChecker(string const& _dbPath): VersionChecker::VersionChecker(string const& _dbPath):
m_path(_dbPath.size() ? _dbPath : Defaults::dbPath()) m_path(_dbPath.size() ? _dbPath : Defaults::dbPath())
{ {
@ -586,7 +580,9 @@ void Client::onChainChanged(ImportRoute const& _ir)
for (auto const& t: m_postMine.pending()) for (auto const& t: m_postMine.pending())
{ {
clog(ClientNote) << "Resubmitting post-mine transaction " << t; clog(ClientNote) << "Resubmitting post-mine transaction " << t;
m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry); auto ir = m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry);
if (ir != ImportResult::Success)
onTransactionQueueReady();
} }
ETH_READ_GUARDED(x_working) DEV_TIMED(post) ETH_WRITE_GUARDED(x_postMine) ETH_READ_GUARDED(x_working) DEV_TIMED(post) ETH_WRITE_GUARDED(x_postMine)
m_postMine = m_working; m_postMine = m_working;
@ -596,6 +592,10 @@ void Client::onChainChanged(ImportRoute const& _ir)
onPostStateChanged(); onPostStateChanged();
} }
// Quick hack for now - the TQ at this point already has the prior pending transactions in it;
// we should resync with it manually until we are stricter about what constitutes "knowing".
onTransactionQueueReady();
noteChanged(changeds); noteChanged(changeds);
} }

5
libethereum/ClientBase.cpp

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

2
libethereum/ClientBase.h

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

2
libethereum/CommonNet.h

@ -56,7 +56,7 @@ class EthereumPeer;
enum enum
{ {
StatusPacket = 0, StatusPacket = 0,
GetTransactionsPacket, NewBlockHashesPacket,
TransactionsPacket, TransactionsPacket,
GetBlockHashesPacket, GetBlockHashesPacket,
BlockHashesPacket, BlockHashesPacket,

2
libethereum/DownloadMan.cpp

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

3
libethereum/DownloadMan.h

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

39
libethereum/EthereumHost.cpp

@ -122,7 +122,7 @@ void EthereumHost::noteDoneBlocks(EthereumPeer* _who, bool _clemency)
// Done our chain-get. // Done our chain-get.
clog(NetNote) << "Chain download complete."; clog(NetNote) << "Chain download complete.";
// 1/100th for each useful block hash. // 1/100th for each useful block hash.
_who->addRating(m_man.chain().size() / 100); _who->addRating(m_man.chainSize() / 100);
m_man.reset(); m_man.reset();
} }
else if (_who->isSyncing()) else if (_who->isSyncing())
@ -189,7 +189,7 @@ void EthereumHost::maintainTransactions()
for (auto const& i: ts) for (auto const& i: ts)
{ {
bool unsent = !m_transactionsSent.count(i.first); bool unsent = !m_transactionsSent.count(i.first);
for (auto const& p: randomSelection(100, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); })) for (auto const& p: randomSelection(0, [&](EthereumPeer* p) { return p->m_requireTransactions || (unsent && !p->m_knownTransactions.count(i.first)); }).second)
peerTransactions[p].push_back(i.first); peerTransactions[p].push_back(i.first);
} }
for (auto const& t: ts) for (auto const& t: ts)
@ -218,28 +218,28 @@ void EthereumHost::maintainTransactions()
} }
} }
std::vector<std::shared_ptr<EthereumPeer>> EthereumHost::randomSelection(unsigned _percent, std::function<bool(EthereumPeer*)> const& _allow) pair<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>> EthereumHost::randomSelection(unsigned _percent, std::function<bool(EthereumPeer*)> const& _allow)
{ {
std::vector<std::shared_ptr<EthereumPeer>> candidates; pair<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>> ret;
candidates.reserve(peerSessions().size()); ret.second.reserve(peerSessions().size());
for (auto const& j: peerSessions()) for (auto const& j: peerSessions())
{ {
auto pp = j.first->cap<EthereumPeer>(); auto pp = j.first->cap<EthereumPeer>();
if (_allow(pp.get())) if (_allow(pp.get()))
candidates.push_back(pp); ret.second.push_back(pp);
} }
std::vector<std::shared_ptr<EthereumPeer>> ret; ret.second.reserve((peerSessions().size() * _percent + 99) / 100);
for (unsigned i = (peerSessions().size() * _percent + 99) / 100; i-- && candidates.size();) for (unsigned i = (peerSessions().size() * _percent + 99) / 100; i-- && ret.second.size();)
{ {
unsigned n = rand() % candidates.size(); unsigned n = rand() % ret.second.size();
ret.push_back(std::move(candidates[n])); ret.first.push_back(std::move(ret.second[n]));
candidates.erase(candidates.begin() + n); ret.second.erase(ret.second.begin() + n);
} }
return ret; return ret;
} }
void EthereumHost::maintainBlocks(h256 _currentHash) void EthereumHost::maintainBlocks(h256 const& _currentHash)
{ {
// Send any new blocks. // Send any new blocks.
auto detailsFrom = m_chain.details(m_latestBlockSent); auto detailsFrom = m_chain.details(m_latestBlockSent);
@ -253,13 +253,24 @@ void EthereumHost::maintainBlocks(h256 _currentHash)
h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true)); h256s blocks = get<0>(m_chain.treeRoute(m_latestBlockSent, _currentHash, false, false, true));
for (auto const& p: randomSelection(100, [&](EthereumPeer* p){return !p->m_knownBlocks.count(_currentHash); })) auto s = randomSelection(25, [&](EthereumPeer* p){ ETH_GUARDED(p->x_knownBlocks) return !p->m_knownBlocks.count(_currentHash); return false; });
for (shared_ptr<EthereumPeer> const& p: s.first)
for (auto const& b: blocks) for (auto const& b: blocks)
if (!p->m_knownBlocks.count(b))
{ {
RLPStream ts; RLPStream ts;
p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(b), 1).append(m_chain.details(b).totalDifficulty); p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(b), 1).append(m_chain.details(b).totalDifficulty);
Guard l(p->x_knownBlocks);
p->sealAndSend(ts);
p->m_knownBlocks.clear();
}
for (shared_ptr<EthereumPeer> const& p: s.second)
{
RLPStream ts;
p->prep(ts, NewBlockHashesPacket, blocks.size());
for (auto const& b: blocks)
ts.append(b);
Guard l(p->x_knownBlocks); Guard l(p->x_knownBlocks);
p->sealAndSend(ts); p->sealAndSend(ts);
p->m_knownBlocks.clear(); p->m_knownBlocks.clear();

4
libethereum/EthereumHost.h

@ -80,7 +80,7 @@ public:
void noteNewBlocks() { m_newBlocks = true; } void noteNewBlocks() { m_newBlocks = true; }
private: private:
std::vector<std::shared_ptr<EthereumPeer>> randomSelection(unsigned _percent = 25, std::function<bool(EthereumPeer*)> const& _allow = [](EthereumPeer const*){ return true; }); std::pair<std::vector<std::shared_ptr<EthereumPeer>>, std::vector<std::shared_ptr<EthereumPeer>>> randomSelection(unsigned _percent = 25, std::function<bool(EthereumPeer*)> const& _allow = [](EthereumPeer const*){ return true; });
/// Session is tell us that we may need (re-)syncing with the peer. /// Session is tell us that we may need (re-)syncing with the peer.
void noteNeedsSyncing(EthereumPeer* _who); void noteNeedsSyncing(EthereumPeer* _who);
@ -92,7 +92,7 @@ private:
void doWork(); void doWork();
void maintainTransactions(); void maintainTransactions();
void maintainBlocks(h256 _currentBlock); void maintainBlocks(h256 const& _currentBlock);
/// Get a bunch of needed blocks. /// Get a bunch of needed blocks.
/// Removes them from our list of needed blocks. /// Removes them from our list of needed blocks.

65
libethereum/EthereumPeer.cpp

@ -326,12 +326,12 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
transition(Asking::Nothing); transition(Asking::Nothing);
break; break;
} }
case GetTransactionsPacket: break; // DEPRECATED.
case TransactionsPacket: case TransactionsPacket:
{ {
clog(NetAllDetail) << "Transactions (" << dec << _r.itemCount() << "entries)"; unsigned itemCount = _r.itemCount();
clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)";
Guard l(x_knownTransactions); Guard l(x_knownTransactions);
for (unsigned i = 0; i < _r.itemCount(); ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
auto h = sha3(_r[i].data()); auto h = sha3(_r[i].data());
m_knownTransactions.insert(h); m_knownTransactions.insert(h);
@ -373,21 +373,22 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
} }
case BlockHashesPacket: case BlockHashesPacket:
{ {
clog(NetMessageSummary) << "BlockHashes (" << dec << _r.itemCount() << "entries)" << (_r.itemCount() ? "" : ": NoMoreHashes"); unsigned itemCount = _r.itemCount();
clog(NetMessageSummary) << "BlockHashes (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreHashes");
if (m_asking != Asking::Hashes) if (m_asking != Asking::Hashes)
{ {
cwarn << "Peer giving us hashes when we didn't ask for them."; cwarn << "Peer giving us hashes when we didn't ask for them.";
break; break;
} }
if (_r.itemCount() == 0) if (itemCount == 0)
{ {
transition(Asking::Blocks); transition(Asking::Blocks);
return true; return true;
} }
unsigned knowns = 0; unsigned knowns = 0;
unsigned unknowns = 0; unsigned unknowns = 0;
for (unsigned i = 0; i < _r.itemCount(); ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
addRating(1); addRating(1);
auto h = _r[i].toHash<h256>(); auto h = _r[i].toHash<h256>();
@ -454,12 +455,13 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
} }
case BlocksPacket: case BlocksPacket:
{ {
clog(NetMessageSummary) << "Blocks (" << dec << _r.itemCount() << "entries)" << (_r.itemCount() ? "" : ": NoMoreBlocks"); unsigned itemCount = _r.itemCount();
clog(NetMessageSummary) << "Blocks (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreBlocks");
if (m_asking != Asking::Blocks) if (m_asking != Asking::Blocks)
clog(NetWarn) << "Unexpected Blocks received!"; clog(NetWarn) << "Unexpected Blocks received!";
if (_r.itemCount() == 0) if (itemCount == 0)
{ {
// Got to this peer's latest block - just give up. // Got to this peer's latest block - just give up.
transition(Asking::Nothing); transition(Asking::Nothing);
@ -472,7 +474,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
unsigned got = 0; unsigned got = 0;
unsigned repeated = 0; unsigned repeated = 0;
for (unsigned i = 0; i < _r.itemCount(); ++i) for (unsigned i = 0; i < itemCount; ++i)
{ {
auto h = BlockInfo::headerHash(_r[i].data()); auto h = BlockInfo::headerHash(_r[i].data());
if (m_sub.noteBlock(h)) if (m_sub.noteBlock(h))
@ -557,11 +559,54 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
default:; default:;
} }
Guard l(x_knownBlocks); ETH_GUARDED(x_knownBlocks)
m_knownBlocks.insert(h); m_knownBlocks.insert(h);
} }
break; break;
} }
case NewBlockHashesPacket:
{
clog(NetMessageSummary) << "NewBlockHashes";
if (host()->isSyncing())
clog(NetMessageSummary) << "Ignoring since we're already downloading.";
else
{
unsigned knowns = 0;
unsigned unknowns = 0;
unsigned itemCount = _r.itemCount();
for (unsigned i = 0; i < itemCount; ++i)
{
addRating(1);
auto h = _r[i].toHash<h256>();
ETH_GUARDED(x_knownBlocks)
m_knownBlocks.insert(h);
auto status = host()->m_bq.blockStatus(h);
if (status == QueueStatus::Importing || status == QueueStatus::Ready || host()->m_chain.isKnown(h))
knowns++;
else if (status == QueueStatus::Bad)
{
cwarn << "block hash bad!" << h << ". Bailing...";
return true;
}
else if (status == QueueStatus::Unknown)
{
unknowns++;
m_syncingNeededBlocks.push_back(h);
}
else
knowns++;
}
clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns";
if (unknowns > 0)
{
host()->m_man.resetToChain(m_syncingNeededBlocks);
host()->changeSyncer(this);
transition(Asking::Blocks);
}
return true;
}
break;
}
default: default:
return false; return false;
} }

2
libethereum/EthereumPeer.h

@ -129,7 +129,7 @@ private:
/// This is built as we ask for hashes. Once no more hashes are given, we present this to the /// This is built as we ask for hashes. Once no more hashes are given, we present this to the
/// host who initialises the DownloadMan and m_sub becomes active for us to begin asking for blocks. /// host who initialises the DownloadMan and m_sub becomes active for us to begin asking for blocks.
h256s m_syncingNeededBlocks; ///< The blocks that we should download from this peer. h256s m_syncingNeededBlocks; ///< The blocks that we should download from this peer.
h256 m_syncingLastReceivedHash; ///< Hash more recently received from peer. h256 m_syncingLastReceivedHash; ///< Hash most recently received from peer.
h256 m_syncingLatestHash; ///< Peer's latest block's hash, as of the current sync. h256 m_syncingLatestHash; ///< Peer's latest block's hash, as of the current sync.
u256 m_syncingTotalDifficulty; ///< Peer's latest block's total difficulty, as of the current sync. u256 m_syncingTotalDifficulty; ///< Peer's latest block's total difficulty, as of the current sync.

3
libethereum/Interface.h

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

2
libethereum/Precompiled.cpp

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

1
libethereum/State.h

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

2
libethereum/Transaction.h

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

1
libethereum/TransactionQueue.cpp

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

2
libevm/VM.h

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

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

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

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

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

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

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

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

33
libevmasm/CMakeLists.txt

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

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

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

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

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

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

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

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

36
libevmasm/Exceptions.h

@ -0,0 +1,36 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Exceptions.h
* @author Christian <c@ethdev.com>
* @date 2014
*/
#pragma once
#include <libdevcore/Exceptions.h>
namespace dev
{
namespace eth
{
struct AssemblyException: virtual Exception {};
struct OptimizerException: virtual AssemblyException {};
struct StackTooDeepException: virtual OptimizerException {};
}
}

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

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

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

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

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

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

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

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

4
libevmcore/CMakeLists.txt

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

7
libevmcore/Exceptions.h

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

69
libevmcore/Params.cpp

@ -0,0 +1,69 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Params.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "Params.h"
using namespace std;
namespace dev
{
namespace eth
{
//--- BEGIN: AUTOGENERATED FROM github.com/ethereum/common/params.json
u256 const c_stackLimit = 1024;
u256 const c_tierStepGas[] = {0, 2, 3, 5, 8, 10, 20, 0};
u256 const c_expGas = 10;
u256 const c_expByteGas = 10;
u256 const c_sha3Gas = 30;
u256 const c_sha3WordGas = 6;
u256 const c_sloadGas = 50;
u256 const c_sstoreSetGas = 20000;
u256 const c_sstoreResetGas = 5000;
u256 const c_sstoreRefundGas = 15000;
u256 const c_jumpdestGas = 1;
u256 const c_logGas = 375;
u256 const c_logDataGas = 8;
u256 const c_logTopicGas = 375;
u256 const c_createGas = 32000;
u256 const c_callGas = 40;
u256 const c_callStipend = 2300;
u256 const c_callValueTransferGas = 9000;
u256 const c_callNewAccountGas = 25000;
u256 const c_suicideRefundGas = 24000;
u256 const c_memoryGas = 3;
u256 const c_quadCoeffDiv = 512;
u256 const c_createDataGas = 200;
u256 const c_txGas = 21000;
u256 const c_txDataZeroGas = 4;
u256 const c_txDataNonZeroGas = 68;
u256 const c_copyGas = 3;
u256 const c_ecrecoverGas = 3000;
u256 const c_sha256Gas = 60;
u256 const c_sha256WordGas = 12;
u256 const c_ripemd160Gas = 600;
u256 const c_ripemd160WordGas = 120;
u256 const c_identityGas = 15;
u256 const c_identityWordGas = 3;
//--- END: AUTOGENERATED FROM /feeStructure.json
}
}

69
libevmcore/Params.h

@ -0,0 +1,69 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Params.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <libdevcore/Common.h>
namespace dev
{
namespace eth
{
//--- BEGIN: AUTOGENERATED FROM /feeStructure.json
extern u256 const c_stackLimit;
extern u256 const c_tierStepGas[8]; ///< Once per operation, for a selection of them.
extern u256 const c_expGas; ///< Once per EXP instuction.
extern u256 const c_expByteGas; ///< Times ceil(log256(exponent)) for the EXP instruction.
extern u256 const c_sha3Gas; ///< Once per SHA3 operation.
extern u256 const c_sha3WordGas; ///< Once per word of the SHA3 operation's data.
extern u256 const c_copyGas; ///< Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added.
extern u256 const c_sloadGas; ///< Once per SLOAD operation.
extern u256 const c_sstoreSetGas; ///< Once per SSTORE operation if the zeroness changes from zero.
extern u256 const c_sstoreResetGas; ///< Once per SSTORE operation if the zeroness does not change from zero. NOTE: when c_sstoreSetGas does not apply.
extern u256 const c_sstoreRefundGas; ///< Refunded gas, once per SSTORE operation if the zeroness changes to zero.
extern u256 const c_jumpdestGas; ///< Once per JUMPDEST operation.
extern u256 const c_logGas; ///< Per LOG* operation.
extern u256 const c_logDataGas; ///< Per byte in a LOG* operation's data.
extern u256 const c_logTopicGas; ///< Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
extern u256 const c_createGas; ///< Once per CREATE operation & contract-creation transaction.
extern u256 const c_createDataGas;
extern u256 const c_callGas; ///< Once per CALL operation & message call transaction.
extern u256 const c_callStipend; ///< Free gas given at beginning of call.
extern u256 const c_callNewAccountGas; ///< Paid for CALL when the destination address didn't exist prior.
extern u256 const c_callValueTransferGas; ///< Paid for CALL when the value transfor is non-zero.
extern u256 const c_suicideRefundGas; ///< Refunded following a suicide operation.
extern u256 const c_memoryGas; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
extern u256 const c_quadCoeffDiv; ///< Divisor for the quadratic particle of the memory cost equation.
extern u256 const c_txGas; ///< Per transaction. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataZeroGas; ///< Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_txDataNonZeroGas; ///< Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
extern u256 const c_ecrecoverGas;
extern u256 const c_sha256Gas;
extern u256 const c_sha256WordGas;
extern u256 const c_ripemd160Gas;
extern u256 const c_ripemd160WordGas;
extern u256 const c_identityGas;
extern u256 const c_identityWordGas;
}
}

2
libjsqrc/setup.js

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

3
liblll/CMakeLists.txt

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

2
liblll/CodeFragment.h

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

23
libp2p/Host.cpp

@ -208,7 +208,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io
// create session so disconnects are managed // create session so disconnects are managed
auto ps = make_shared<Session>(this, _io, p, PeerSessionInfo({_id, clientVersion, _endpoint.address().to_string(), listenPort, chrono::steady_clock::duration(), _rlp[2].toSet<CapDesc>(), 0, map<string, string>()})); auto ps = make_shared<Session>(this, _io, p, PeerSessionInfo({_id, clientVersion, _endpoint.address().to_string(), listenPort, chrono::steady_clock::duration(), _rlp[2].toSet<CapDesc>(), 0, map<string, string>()}));
if (protocolVersion != dev::p2p::c_protocolVersion) if (protocolVersion < dev::p2p::c_protocolVersion)
{ {
ps->disconnect(IncompatibleProtocol); ps->disconnect(IncompatibleProtocol);
return; return;
@ -226,7 +226,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io
return; return;
} }
if (peerCount() > 2 * m_idealPeerCount) if (!peerSlotsAvailable(Ingress))
{ {
ps->disconnect(TooManyPeers); ps->disconnect(TooManyPeers);
return; return;
@ -271,7 +271,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e)
clog(NetNote) << "p2p.host.peers.events.peerAdded " << _n << p->endpoint; clog(NetNote) << "p2p.host.peers.events.peerAdded " << _n << p->endpoint;
} }
} }
if (peerCount() < m_idealPeerCount) if (peerSlotsAvailable(Egress))
connect(p); connect(p);
} }
} }
@ -341,7 +341,7 @@ void Host::runAcceptor()
auto socket = make_shared<RLPXSocket>(new bi::tcp::socket(m_ioService)); auto socket = make_shared<RLPXSocket>(new bi::tcp::socket(m_ioService));
m_tcp4Acceptor.async_accept(socket->ref(), [=](boost::system::error_code ec) m_tcp4Acceptor.async_accept(socket->ref(), [=](boost::system::error_code ec)
{ {
if (peerCount() > 2 * m_idealPeerCount) if (peerCount() > 9 * m_idealPeerCount)
{ {
clog(NetConnect) << "Dropping incoming connect due to maximum peer count (2 * ideal peer count): " << socket->remoteEndpoint(); clog(NetConnect) << "Dropping incoming connect due to maximum peer count (2 * ideal peer count): " << socket->remoteEndpoint();
socket->close(); socket->close();
@ -413,7 +413,6 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
// create or update m_peers entry // create or update m_peers entry
shared_ptr<Peer> p; shared_ptr<Peer> p;
ETH_RECURSIVE_GUARDED(x_sessions) ETH_RECURSIVE_GUARDED(x_sessions)
{
if (m_peers.count(_n)) if (m_peers.count(_n))
{ {
p = m_peers[_n]; p = m_peers[_n];
@ -425,7 +424,6 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
p.reset(new Peer(node)); p.reset(new Peer(node));
m_peers[_n] = p; m_peers[_n] = p;
} }
}
connect(p); connect(p);
} }
else if (m_nodeTable) else if (m_nodeTable)
@ -438,6 +436,7 @@ void Host::requirePeer(NodeId const& _n, NodeIPEndpoint const& _endpoint)
t->async_wait([this, _n](boost::system::error_code const& _ec) t->async_wait([this, _n](boost::system::error_code const& _ec)
{ {
if (!_ec && m_nodeTable) if (!_ec && m_nodeTable)
// FIXME RACE CONDITION (use weak_ptr or mutex).
if (auto n = m_nodeTable->node(_n)) if (auto n = m_nodeTable->node(_n))
requirePeer(n.id, n.endpoint); requirePeer(n.id, n.endpoint);
}); });
@ -464,7 +463,7 @@ void Host::connect(std::shared_ptr<Peer> const& _p)
return; return;
} }
if (!m_nodeTable->haveNode(_p->id)) if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id))
{ {
clog(NetWarn) << "Aborted connect. Node not in node table."; clog(NetWarn) << "Aborted connect. Node not in node table.";
m_nodeTable->addNode(*_p.get()); m_nodeTable->addNode(*_p.get());
@ -578,7 +577,11 @@ void Host::run(boost::system::error_code const&)
// is always live and to ensure reputation and fallback timers are properly // is always live and to ensure reputation and fallback timers are properly
// updated. // disconnectLatePeers(); // updated. // disconnectLatePeers();
int openSlots = m_idealPeerCount - peerCount(); // todo: update peerSlotsAvailable()
unsigned pendingCount = 0;
ETH_GUARDED(x_pendingNodeConns)
pendingCount = m_pendingPeerConns.size();
int openSlots = m_idealPeerCount - peerCount() - pendingCount;
if (openSlots > 0) if (openSlots > 0)
{ {
list<shared_ptr<Peer>> toConnect; list<shared_ptr<Peer>> toConnect;
@ -759,7 +762,7 @@ void Host::restoreNetwork(bytesConstRef _b)
// todo: ipv6, bi::address_v6(i[0].toArray<byte, 16>() // todo: ipv6, bi::address_v6(i[0].toArray<byte, 16>()
Node n((NodeId)i[2], NodeIPEndpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<uint16_t>(), i[1].toInt<uint16_t>())); Node n((NodeId)i[2], NodeIPEndpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<uint16_t>(), i[1].toInt<uint16_t>()));
if (i.itemCount() == 3 && n.endpoint.isAllowed()) if (i.itemCount() == 3 && n.endpoint.isAllowed())
m_nodeTable->addNode(n); m_nodeTable->addNode(n, NodeTable::NodeRelation::Known);
else if (i.itemCount() == 10) else if (i.itemCount() == 10)
{ {
n.required = i[3].toInt<bool>(); n.required = i[3].toInt<bool>();
@ -776,7 +779,7 @@ void Host::restoreNetwork(bytesConstRef _b)
if (p->required) if (p->required)
requirePeer(p->id, n.endpoint); requirePeer(p->id, n.endpoint);
else else
m_nodeTable->addNode(*p.get()); m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known);
} }
} }
} }

7
libp2p/Host.h

@ -135,6 +135,8 @@ public:
// TODO: P2P this should be combined with peers into a HostStat object of some kind; coalesce data, as it's only used for status information. // TODO: P2P this should be combined with peers into a HostStat object of some kind; coalesce data, as it's only used for status information.
Peers getPeers() const { RecursiveGuard l(x_sessions); Peers ret; for (auto const& i: m_peers) ret.push_back(*i.second); return ret; } Peers getPeers() const { RecursiveGuard l(x_sessions); Peers ret; for (auto const& i: m_peers) ret.push_back(*i.second); return ret; }
NetworkPreferences const& networkPreferences() const { return m_netPrefs; }
void setNetworkPreferences(NetworkPreferences const& _p, bool _dropPeers = false) { m_dropPeers = _dropPeers; auto had = isStarted(); if (had) stop(); m_netPrefs = _p; if (had) start(); } void setNetworkPreferences(NetworkPreferences const& _p, bool _dropPeers = false) { m_dropPeers = _dropPeers; auto had = isStarted(); if (had) stop(); m_netPrefs = _p; if (had) start(); }
/// Start network. @threadsafe /// Start network. @threadsafe
@ -162,6 +164,8 @@ protected:
void restoreNetwork(bytesConstRef _b); void restoreNetwork(bytesConstRef _b);
private: private:
enum PeerSlotRatio { Egress = 2, Ingress = 9 };
bool havePeerSession(NodeId _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? !!m_sessions[_id].lock() : false; } bool havePeerSession(NodeId _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? !!m_sessions[_id].lock() : false; }
/// Determines and sets m_tcpPublic to publicly advertised address. /// Determines and sets m_tcpPublic to publicly advertised address.
@ -169,6 +173,9 @@ private:
void connect(std::shared_ptr<Peer> const& _p); void connect(std::shared_ptr<Peer> const& _p);
/// Returns true if pending and connected peer count is less than maximum
bool peerSlotsAvailable(PeerSlotRatio _type) { Guard l(x_pendingNodeConns); return peerCount() + m_pendingPeerConns.size() < _type * m_idealPeerCount; }
/// Ping the peers to update the latency information and disconnect peers which have timed out. /// Ping the peers to update the latency information and disconnect peers which have timed out.
void keepAlivePeers(); void keepAlivePeers();

2
libp2p/Network.cpp

@ -226,7 +226,7 @@ bi::tcp::endpoint Network::resolveHost(string const& _addr)
boost::system::error_code ec; boost::system::error_code ec;
// resolve returns an iterator (host can resolve to multiple addresses) // resolve returns an iterator (host can resolve to multiple addresses)
bi::tcp::resolver r(s_resolverIoService); bi::tcp::resolver r(s_resolverIoService);
auto it = r.resolve({split[0], toString(port)}, ec); auto it = r.resolve({bi::tcp::v4(), split[0], toString(port)}, ec);
if (ec) if (ec)
clog(NetWarn) << "Error resolving host address..." << LogTag::Url << _addr << ":" << LogTag::Error << ec.message(); clog(NetWarn) << "Error resolving host address..." << LogTag::Url << _addr << ":" << LogTag::Error << ec.message();
else else

11
libp2p/NodeTable.cpp

@ -81,8 +81,17 @@ shared_ptr<NodeEntry> NodeTable::addNode(Public const& _pubk, NodeIPEndpoint con
return addNode(node); return addNode(node);
} }
shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node) shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node, NodeRelation _relation)
{ {
if (_relation == Known)
{
shared_ptr<NodeEntry> ret(new NodeEntry(m_node, _node.id, _node.endpoint));
ret->pending = false;
m_nodes[_node.id] = ret;
noteActiveNode(_node.id, _node.endpoint);
return ret;
}
// re-enable tcp checks when NAT hosts are handled by discover // re-enable tcp checks when NAT hosts are handled by discover
// we handle when tcp endpoint is 0 below // we handle when tcp endpoint is 0 below
if (_node.endpoint.address.to_string() == "0.0.0.0") if (_node.endpoint.address.to_string() == "0.0.0.0")

10
libp2p/NodeTable.h

@ -133,12 +133,14 @@ class NodeTable: UDPSocketEvents, public std::enable_shared_from_this<NodeTable>
using EvictionTimeout = std::pair<NodeIdTimePoint, NodeId>; ///< First NodeId (NodeIdTimePoint) may be evicted and replaced with second NodeId. using EvictionTimeout = std::pair<NodeIdTimePoint, NodeId>; ///< First NodeId (NodeIdTimePoint) may be evicted and replaced with second NodeId.
public: public:
enum NodeRelation { Unknown = 0, Known };
/// Constructor requiring host for I/O, credentials, and IP Address and port to listen on. /// Constructor requiring host for I/O, credentials, and IP Address and port to listen on.
NodeTable(ba::io_service& _io, KeyPair const& _alias, NodeIPEndpoint const& _endpoint); NodeTable(ba::io_service& _io, KeyPair const& _alias, NodeIPEndpoint const& _endpoint);
~NodeTable(); ~NodeTable();
/// Returns distance based on xor metric two node ids. Used by NodeEntry and NodeTable. /// Returns distance based on xor metric two node ids. Used by NodeEntry and NodeTable.
static unsigned distance(NodeId const& _a, NodeId const& _b) { u512 d = _a ^ _b; unsigned ret; for (ret = 0; d >>= 1; ++ret) {}; return ret; } static unsigned distance(NodeId const& _a, NodeId const& _b) { u256 d = sha3(_a) ^ sha3(_b); unsigned ret; for (ret = 0; d >>= 1; ++ret) {}; return ret; }
/// Set event handler for NodeEntryAdded and NodeEntryDropped events. /// Set event handler for NodeEntryAdded and NodeEntryDropped events.
void setEventHandler(NodeTableEventHandler* _handler) { m_nodeEventHandler.reset(_handler); } void setEventHandler(NodeTableEventHandler* _handler) { m_nodeEventHandler.reset(_handler); }
@ -149,8 +151,8 @@ public:
/// Add node. Node will be pinged and empty shared_ptr is returned if NodeId is uknown. /// Add node. Node will be pinged and empty shared_ptr is returned if NodeId is uknown.
std::shared_ptr<NodeEntry> addNode(Public const& _pubk, NodeIPEndpoint const& _ep); std::shared_ptr<NodeEntry> addNode(Public const& _pubk, NodeIPEndpoint const& _ep);
/// Add node. Node will be pinged and empty shared_ptr is returned if node has never been seen. /// Add node. Node will be pinged and empty shared_ptr is returned if node has never been seen or NodeId is empty.
std::shared_ptr<NodeEntry> addNode(Node const& _node); std::shared_ptr<NodeEntry> addNode(Node const& _node, NodeRelation _relation = NodeRelation::Unknown);
/// To be called when node table is empty. Runs node discovery with m_node.id as the target in order to populate node-table. /// To be called when node table is empty. Runs node discovery with m_node.id as the target in order to populate node-table.
void discover(); void discover();
@ -178,7 +180,7 @@ private:
/// Constants for Kademlia, derived from address space. /// Constants for Kademlia, derived from address space.
static unsigned const s_addressByteSize = sizeof(NodeId); ///< Size of address type in bytes. static unsigned const s_addressByteSize = h256::size; ///< Size of address type in bytes.
static unsigned const s_bits = 8 * s_addressByteSize; ///< Denoted by n in [Kademlia]. static unsigned const s_bits = 8 * s_addressByteSize; ///< Denoted by n in [Kademlia].
static unsigned const s_bins = s_bits - 1; ///< Size of m_state (excludes root, which is us). static unsigned const s_bins = s_bits - 1; ///< Size of m_state (excludes root, which is us).
static unsigned const s_maxSteps = boost::static_log2<s_bits>::value; ///< Max iterations of discovery. (discover) static unsigned const s_maxSteps = boost::static_log2<s_bits>::value; ///< Max iterations of discovery. (discover)

28
libsolidity/AST.cpp

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

2
libsolidity/AST.h

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

2
libsolidity/ASTUtils.h

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

2
libsolidity/CMakeLists.txt

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

7
libsolidity/Compiler.cpp

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

2
libsolidity/Compiler.h

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

2
libsolidity/CompilerContext.h

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

36
libsolidity/DeclarationContainer.cpp

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

4
libsolidity/DeclarationContainer.h

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

18
libsolidity/Exceptions.h

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

2
libsolidity/ExpressionCompiler.h

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

2
libsolidity/LValue.h

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

37
libsolidity/NameAndTypeResolver.cpp

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

2
libsolidity/Parser.cpp

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

2
libsolidity/Scanner.h

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

68
libsolidity/SourceReferenceFormatter.cpp

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

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

Loading…
Cancel
Save