Browse Source

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

cl-refactor
Genoil 10 years ago
parent
commit
92c747521d
  1. 294
      CMakeLists.txt
  2. 16
      CodingStandards.txt
  3. 6
      abi/main.cpp
  4. 4
      alethzero/CMakeLists.txt
  5. 5
      alethzero/Connect.cpp
  6. 3
      alethzero/Connect.ui
  7. 77
      alethzero/DappLoader.cpp
  8. 7
      alethzero/DappLoader.h
  9. 1
      alethzero/DownloadView.h
  10. 39
      alethzero/Main.ui
  11. 94
      alethzero/MainWin.cpp
  12. 2
      alethzero/MainWin.h
  13. 11
      alethzero/MiningView.cpp
  14. 4
      alethzero/MiningView.h
  15. 6
      alethzero/Transact.cpp
  16. 161
      cmake/CMakeParseArguments.cmake
  17. 10
      cmake/EthCompilerSettings.cmake
  18. 27
      cmake/EthDependencies.cmake
  19. 21
      cmake/EthExecutableHelper.cmake
  20. 8
      cmake/FindCURL.cmake
  21. 33
      cmake/FindCpuid.cmake
  22. 1
      cmake/FindJsoncpp.cmake
  23. 1
      cmake/FindLevelDB.cmake
  24. 16
      cmake/FindMHD.cmake
  25. 136
      cmake/FindOpenCL.cmake
  26. 382
      cmake/FindPackageHandleStandardArgs.cmake
  27. 57
      cmake/FindPackageMessage.cmake
  28. 1
      cmake/Findjson_rpc_cpp.cmake
  29. 18
      cmake/scripts/copydlls.cmake
  30. 5
      eth/CMakeLists.txt
  31. 38
      eth/Farm.h
  32. 28
      eth/PhoneHome.h
  33. 4
      eth/farm.json
  34. 702
      eth/main.cpp
  35. 3
      eth/phonehome.json
  36. 2
      ethrpctest/CMakeLists.txt
  37. 1
      evmjit/libevmjit/BasicBlock.cpp
  38. 4
      evmjit/libevmjit/BasicBlock.h
  39. 31
      evmjit/libevmjit/Cache.cpp
  40. 12
      evmjit/libevmjit/Cache.h
  41. 3
      evmjit/libevmjit/Compiler.cpp
  42. 21
      evmjit/libevmjit/ExecutionEngine.cpp
  43. 44
      evmjit/libevmjit/RuntimeManager.cpp
  44. 5
      evmjit/libevmjit/RuntimeManager.h
  45. 21
      exp/CMakeLists.txt
  46. 151
      exp/main.cpp
  47. 59
      extdep/CMakeLists.txt
  48. 16
      extdep/Readme.md
  49. 9
      extdep/cmake/FindCURL.cmake
  50. 13
      extdep/compile/argtable2.cmake
  51. 19
      extdep/compile/boost.cmake
  52. 33
      extdep/compile/cryptopp.cmake
  53. 29
      extdep/compile/curl.cmake
  54. 17
      extdep/compile/icu.cmake
  55. 16
      extdep/compile/jom.cmake
  56. 40
      extdep/compile/json-rpc-cpp.cmake
  57. 16
      extdep/compile/jsoncpp.cmake
  58. 23
      extdep/compile/leveldb.cmake
  59. 18
      extdep/compile/leveldb_osx.patch
  60. 32
      extdep/compile/qt.cmake
  61. 111
      extdep/compile/qt_configure.bat
  62. 11
      extdep/compile/qt_osx.patch
  63. 2
      extdep/compile/qt_tools.bat
  64. 14
      extdep/compile/snappy.cmake
  65. 74
      extdep/eth_download.cmake
  66. 32
      extdep/getstuff.bat
  67. 11
      extdep/miniupnpc.cmake
  68. 29
      extdep/scripts/json-rpc-cpp_osx.sh
  69. 12
      extdep/scripts/leveldb_osx.sh
  70. 8
      extdep/scripts/snappy_osx.sh
  71. 1
      libdevcore/CMakeLists.txt
  72. 2
      libdevcore/Common.cpp
  73. 16
      libdevcore/Common.h
  74. 32
      libdevcore/CommonData.h
  75. 6
      libdevcore/CommonIO.cpp
  76. 2
      libdevcore/CommonIO.h
  77. 71
      libdevcore/Guards.h
  78. 2
      libdevcore/Log.cpp
  79. 2
      libdevcore/RLP.cpp
  80. 5
      libdevcore/RLP.h
  81. 1
      libdevcore/RangeMask.h
  82. 4
      libdevcore/TransientDirectory.cpp
  83. 4
      libdevcore/TransientDirectory.h
  84. 50
      libdevcore/Worker.cpp
  85. 19
      libdevcore/Worker.h
  86. 6
      libdevcrypto/Common.cpp
  87. 6
      libdevcrypto/TrieDB.h
  88. 19
      libethash-cl/CMakeLists.txt
  89. 86
      libethash-cl/bin2h.cmake
  90. 4014
      libethash-cl/cl.hpp
  91. 366
      libethash-cl/ethash_cl_miner.cpp
  92. 55
      libethash-cl/ethash_cl_miner.h
  93. 460
      libethash-cl/ethash_cl_miner_kernel.cl
  94. 4
      libethash/ethash.h
  95. 6
      libethash/io.c
  96. 2
      libethash/util.h
  97. 75
      libethcore/BlockInfo.cpp
  98. 56
      libethcore/BlockInfo.h
  99. 16
      libethcore/CMakeLists.txt
  100. 8
      libethcore/Common.cpp

294
CMakeLists.txt

@ -14,35 +14,33 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# user defined, defaults # user defined, defaults
# Normally, set(...CACHE...) creates cache variables, but does not modify them. # Normally, set(...CACHE...) creates cache variables, but does not modify them.
function(createDefaultCacheConfig) function(createDefaultCacheConfig)
set(HEADLESS OFF CACHE BOOL "Do not compile GUI (AlethZero)")
set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)") set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)")
set(PARANOIA OFF CACHE BOOL "Additional run-time checks") set(PARANOID OFF CACHE BOOL "Additional run-time checks")
set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on") set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on")
set(EVMJIT OFF CACHE BOOL "Build a just-in-time compiler for EVM code (requires LLVM)")
set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.") set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.")
set(JUSTTESTS OFF CACHE BOOL "Build only for tests.")
set(SOLIDITY ON CACHE BOOL "Build the Solidity language components (requried unless HEADLESS)")
set(USENPM OFF CACHE BOOL "Use npm to recompile ethereum.js if it was changed") set(USENPM OFF CACHE BOOL "Use npm to recompile ethereum.js if it was changed")
set(PROFILING OFF CACHE BOOL "Build in support for profiling")
set(BUNDLE "none" CACHE STRING "Predefined bundle of software to build (none, full, user, tests, minimal).")
set(SOLIDITY ON CACHE BOOL "Build the Solidity language components")
set(SERPENT ON CACHE BOOL "Build the Serpent language components")
set(TOOLS ON CACHE BOOL "Build the tools components")
set(NCURSES ON CACHE BOOL "Build the NCurses components")
set(GUI ON CACHE BOOL "Build GUI components (AlethZero, Mix)")
set(TESTS ON CACHE BOOL "Build the tests.")
set(EVMJIT OFF CACHE BOOL "Build just-in-time compiler for EVM code (requires LLVM)")
set(ETHASHCL OFF CACHE BOOL "Build in support for GPU mining via OpenCL") set(ETHASHCL OFF CACHE BOOL "Build in support for GPU mining via OpenCL")
endfunction() endfunction()
# propagates CMake configuration options to the compiler # propagates CMake configuration options to the compiler
function(configureProject) function(configureProject)
if (PARANOIA) if (PARANOID)
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") add_definitions(-DETH_PARANOIA)
add_definitions(-DETH_PARANOIA)
else ()
message(FATAL_ERROR "Paranoia requires debug.")
endif ()
endif () endif ()
if (VMTRACE) if (VMTRACE)
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") add_definitions(-DETH_VMTRACE)
add_definitions(-DETH_VMTRACE)
else ()
message(FATAL_ERROR "VM tracing requires debug.")
endif ()
endif () endif ()
if (ETHASHCL) if (ETHASHCL)
@ -61,9 +59,19 @@ function(configureProject)
add_definitions(-DETH_SOLIDITY) add_definitions(-DETH_SOLIDITY)
endif() endif()
if (HEADLESS OR JUSTTESTS) if (GUI)
add_definitions(-DETH_HEADLESS) add_definitions(-DETH_GUI)
endif() endif()
if (CPUID_FOUND)
add_definitions(-DETH_CPUID)
endif()
if (CURL_FOUND)
add_definitions(-DETH_CURL)
endif()
add_definitions(-DETH_TRUE)
endfunction() endfunction()
set(CPPETHEREUM 1) set(CPPETHEREUM 1)
@ -91,7 +99,7 @@ function(createBuildInfo)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/int") set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/int")
endif () endif ()
if (PARANOIA) if (PARANOID)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/PARA") set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/PARA")
endif () endif ()
@ -123,33 +131,204 @@ endfunction()
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
cmake_policy(SET CMP0015 NEW) cmake_policy(SET CMP0015 NEW)
# Clear invalid option
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
if (PARANOID)
message("Paranoia requires debug - disabling for release build.")
set(PARANOID OFF)
endif ()
if (VMTRACE)
message("VM Tracing requires debug - disabling for release build.")
set (VMTRACE OFF)
endif ()
endif ()
createDefaultCacheConfig() createDefaultCacheConfig()
configureProject()
# Force chromium. # Force chromium.
set (ETH_HAVE_WEBENGINE 1) set (ETH_HAVE_WEBENGINE 1)
message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}") # Normalise build options
message("-- VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}; JSONRPC: ${JSONRPC}; EVMJIT: ${EVMJIT}; FATDB: ${FATDB}; CHROMIUM: ${ETH_HAVE_WEBENGINE}; USENPM: ${USENPM}; ETHASHCL: ${ETHASHCL}") # TODO: Abstract into something sensible and move into a function.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(DECENT_PLATFORM OFF)
else ()
set(DECENT_PLATFORM ON)
endif ()
# Backwards compatibility
if (HEADLESS)
message("*** WARNING: -DHEADLESS=1 option is DEPRECATED! Use -DBUNDLE=minimal or -DGUI=0")
set(BUNDLE "minimal")
endif ()
if (PARANOID)
set(PARANOID ON)
else ()
set(PARANOID OFF)
endif ()
if (VMTRACE)
set(VMTRACE ON)
else ()
set(VMTRACE OFF)
endif ()
if (EVMJIT)
set(EVMJIT ON)
else ()
set(EVMJIT OFF)
endif()
if (FATDB)
set(FATDB ON)
else ()
set(FATDB OFF)
endif()
if (JSONRPC)
set(JSONRPC ON)
else ()
set(JSONRPC OFF)
endif ()
if (USENPM)
set(USENPM ON)
else ()
set(USENPM OFF)
endif ()
if (PROFILING)
set(PROFILING ON)
else ()
set(PROFILING OFF)
endif ()
# Default TARGET_PLATFORM to "linux".
set(TARGET_PLATFORM CACHE STRING "linux") if (SOLIDITY)
if ("x${TARGET_PLATFORM}" STREQUAL "x") set(SOLIDITY ON)
set(TARGET_PLATFORM "linux") else ()
set(SOLIDITY OFF)
endif()
if (SERPENT)
set(SERPENT ${DECENT_PLATFORM})
else ()
set(SERPENT OFF)
endif()
if (GUI)
set(GUI ON)
set(JSONRPC ON)
else ()
set(GUI OFF)
endif ()
if (TESTS)
set(TESTS ON)
else ()
set(TESTS OFF)
endif ()
if (TOOLS)
set(TOOLS ON)
else ()
set(TOOLS OFF)
endif ()
if (ETHASHCL)
set(ETHASHCL ON)
else ()
set(ETHASHCL OFF)
endif()
if (NCURSES)
set(NCURSES ${DECENT_PLATFORM})
else ()
set(NCURSES OFF)
endif () endif ()
if ("${TARGET_PLATFORM}" STREQUAL "linux") if (BUNDLE STREQUAL "minimal")
set(CMAKE_THREAD_LIBS_INIT pthread) set(SERPENT OFF)
set(SOLIDITY OFF)
set(USENPM OFF)
set(GUI OFF)
set(NCURSES OFF)
set(TOOLS ON)
set(TESTS OFF)
elseif (BUNDLE STREQUAL "full")
set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON)
set(USENPM ON)
set(GUI ON)
set(NCURSES ${DECENT_PLATFORM})
set(TOOLS ON)
set(TESTS ON)
set(FATDB ON)
elseif (BUNDLE STREQUAL "core")
set(SERPENT OFF)
set(SOLIDITY ON)
set(USENPM OFF)
set(GUI ON)
set(NCURSES OFF)
set(TOOLS ON)
set(TESTS OFF)
set(FATDB ON)
elseif (BUNDLE STREQUAL "tests")
set(SERPENT ${DECENT_PLATFORM})
set(SOLIDITY ON)
set(USENPM OFF)
set(GUI OFF)
set(NCURSES OFF)
set(TOOLS OFF)
set(TESTS ON)
set(FATDB ON)
elseif (BUNDLE STREQUAL "user")
set(SERPENT OFF)
set(SOLIDITY OFF)
set(USENPM OFF)
set(GUI ON)
set(NCURSES ${DECENT_PLATFORM})
set(TOOLS ON)
set(TESTS OFF)
endif () endif ()
include(EthCompilerSettings) # Default CMAKE_BUILD_TYPE to "Release".
message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}") set(CMAKE_BUILD_TYPE CACHE STRING "Release")
if ("x${CMAKE_BUILD_TYPE}" STREQUAL "x")
set(CMAKE_BUILD_TYPE "Release")
endif ()
# Default TARGET_PLATFORM to ${CMAKE_SYSTEM}
# change this once we support cross compiling
set(TARGET_PLATFORM CACHE STRING ${CMAKE_SYSTEM})
if ("x${TARGET_PLATFORM}" STREQUAL "x")
set(TARGET_PLATFORM ${CMAKE_SYSTEM})
endif ()
# this must be an include, as a function it would messs up with variable scope!
include(EthDependencies) include(EthDependencies)
configureProject()
message("------------------------------------------------------------------------")
message("-- CMake Version ${CMAKE_VERSION}")
message("-- CMAKE_BUILD_TYPE Build type ${CMAKE_BUILD_TYPE}")
message("-- TARGET_PLATFORM Target platform ${TARGET_PLATFORM}")
message("-- BUNDLE Build bundle ${BUNDLE}")
message("--------------------------------------------------------------- features")
message("-- Chromium support ${ETH_HAVE_WEBENGINE}")
message("-- Hardware identification support ${CPUID_FOUND}")
message("-- HTTP Request support ${CURL_FOUND}")
message("-- VMTRACE VM execution tracing ${VMTRACE}")
message("-- PROFILING Profiling support ${PROFILING}")
message("-- FATDB Full database exploring ${FATDB}")
message("-- JSONRPC JSON-RPC support ${JSONRPC}")
message("-- USENPM Javascript source building ${USENPM}")
message("------------------------------------------------------------- components")
message("-- TOOLS Build basic tools ${TOOLS}")
message("-- SOLIDITY Build Solidity language components ${SOLIDITY}")
message("-- SERPENT Build Serpent language components ${SERPENT}")
message("-- GUI Build GUI components ${GUI}")
message("-- NCURSES Build NCurses components ${NCURSES}")
message("-- TESTS Build tests ${TESTS}")
message("-- ETHASHCL Build OpenCL components (experimental!) ${ETHASHCL}")
message("-- EVMJIT Build LLVM-based JIT EVM (experimental!) ${EVMJIT}")
message("------------------------------------------------------------------------")
message("")
set(CMAKE_THREAD_LIBS_INIT pthread)
include(EthCompilerSettings)
message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}")
# this must be an include, as a function it would mess up with variable scope!
include(EthExecutableHelper) include(EthExecutableHelper)
createBuildInfo() createBuildInfo()
@ -163,21 +342,24 @@ add_subdirectory(libdevcore)
add_subdirectory(libevmcore) add_subdirectory(libevmcore)
add_subdirectory(liblll) add_subdirectory(liblll)
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")) if (SERPENT)
add_subdirectory(libserpent) add_subdirectory(libserpent)
add_subdirectory(sc) add_subdirectory(sc)
endif () endif ()
add_subdirectory(libsolidity) if (SOLIDITY)
add_subdirectory(libsolidity)
endif ()
if (NOT JUSTTESTS) if (TOOLS)
add_subdirectory(lllc) add_subdirectory(lllc)
add_subdirectory(solc) if (SOLIDITY)
add_subdirectory(solc)
endif ()
endif() endif()
if (JSONRPC) if (JSONRPC)
add_subdirectory(libweb3jsonrpc) add_subdirectory(libweb3jsonrpc)
add_subdirectory(ethrpctest)
endif() endif()
add_subdirectory(secp256k1) add_subdirectory(secp256k1)
@ -193,12 +375,17 @@ endif ()
add_subdirectory(libethcore) add_subdirectory(libethcore)
add_subdirectory(libevm) add_subdirectory(libevm)
add_subdirectory(libethereum) add_subdirectory(libethereum)
add_subdirectory(libwebthree) add_subdirectory(libwebthree)
add_subdirectory(libtestutils)
add_subdirectory(test)
if (NOT JUSTTESTS) if (TESTS)
add_subdirectory(libtestutils)
add_subdirectory(test)
if (JSONRPC)
add_subdirectory(ethrpctest)
endif ()
endif ()
if (TOOLS)
add_subdirectory(rlp) add_subdirectory(rlp)
add_subdirectory(abi) add_subdirectory(abi)
@ -208,25 +395,26 @@ if (NOT JUSTTESTS)
add_subdirectory(exp) add_subdirectory(exp)
endif () endif ()
# TODO check msvc endif()
if(NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
add_subdirectory(neth)
endif ()
if (NOT HEADLESS)
add_subdirectory(libnatspec) if (NCURSES)
add_subdirectory(libjsqrc) add_subdirectory(neth)
endif ()
if (ETH_HAVE_WEBENGINE) if (GUI)
add_subdirectory(alethzero)
# add_subdirectory(third) // reenable once not qtwebkit.
endif()
add_subdirectory(mix) add_subdirectory(libnatspec)
add_subdirectory(libjsqrc)
if (ETH_HAVE_WEBENGINE)
add_subdirectory(alethzero)
# add_subdirectory(third) // reenable once not qtwebkit.
endif() endif()
if (SOLIDITY)
add_subdirectory(mix)
endif ()
endif() endif()
#unset(TARGET_PLATFORM CACHE) #unset(TARGET_PLATFORM CACHE)

16
CodingStandards.txt

@ -113,26 +113,33 @@ d. Favour declarations close to use; don't habitually declare at top of scope al
e. Always pass non-trivial parameters with a const& suffix. e. Always pass non-trivial parameters with a const& suffix.
f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires. f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires.
g. Never use a macro where adequate non-preprocessor C++ can be written. g. Never use a macro where adequate non-preprocessor C++ can be written.
h. Prefer "using NewType = OldType" to "typedef OldType NewType". h. Make use of auto whenever type is clear or unimportant:
i. Make use of auto whenever type is clear or unimportant:
- Always avoid doubly-stating the type. - Always avoid doubly-stating the type.
- Use to avoid vast and unimportant type declarations. - Use to avoid vast and unimportant type declarations.
i. Don't pass bools: prefer enumerations instead.
j. Prefer enum class to straight enum.
(WRONG) (WRONG)
const double d = 0; const double d = 0;
int i, j; int i, j;
char *s; char *s;
float meanAndSigma(std::vector<float> _v, float* _sigma); float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
Derived* x(dynamic_cast<Derived*>(base)); Derived* x(dynamic_cast<Derived*>(base));
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {} for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
(CORRECT) (CORRECT)
enum class Accuracy
{
Approximate,
Exact
};
double const d = 0; double const d = 0;
int i; int i;
int j; int j;
char* s; char* s;
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v); std::tuple<float, float> meanAndSigma(std::vector<float> const& _v, Accuracy _a);
auto x = dynamic_cast<Derived*>(base); auto x = dynamic_cast<Derived*>(base);
for (auto i = x.begin(); i != x.end(); ++i) {} for (auto i = x.begin(); i != x.end(); ++i) {}
@ -192,7 +199,6 @@ c. Where there are exceptions to this (due to excessive use and clear meaning),
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy. d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
11. Commenting 11. Commenting
a. Comments should be doxygen-compilable, using @notation rather than \notation. a. Comments should be doxygen-compilable, using @notation rather than \notation.

6
abi/main.cpp

@ -436,7 +436,7 @@ struct ABIMethod
if (_params[pi].second != Format::Open) if (_params[pi].second != Format::Open)
throw ExpectedOpen(); throw ExpectedOpen();
++pi; ++pi;
int l = a.dims[addr.size()]; int l = a.dims[a.dims.size() - 1 - addr.size()];
if (l == -1) if (l == -1)
{ {
// read ahead in params and discover the arity. // read ahead in params and discover the arity.
@ -486,7 +486,7 @@ struct ABIMethod
put(); put();
else else
{ {
int l = a.dims[addr.size()]; int l = a.dims[a.dims.size() - 1 - addr.size()];
if (l == -1) if (l == -1)
{ {
l = fromBigEndian<unsigned>(bytesConstRef(&_data).cropped(di, 32)); l = fromBigEndian<unsigned>(bytesConstRef(&_data).cropped(di, 32));
@ -525,7 +525,7 @@ struct ABIMethod
{ {
out << "["; out << "[";
addr.push_back(0); addr.push_back(0);
int l = a.dims[addr.size() - 1]; int l = a.dims[a.dims.size() - 1 - (addr.size() - 1)];
if (l == -1) if (l == -1)
l = catDims[d++]; l = catDims[d++];
for (addr.back() = 0; addr.back() < l; ++addr.back()) for (addr.back() = 0; addr.back() < l; ++addr.back())

4
alethzero/CMakeLists.txt

@ -59,10 +59,10 @@ target_link_libraries(${EXECUTABLE} jsqrc)
target_link_libraries(${EXECUTABLE} natspec) target_link_libraries(${EXECUTABLE} natspec)
target_link_libraries(${EXECUTABLE} ${MHD_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${MHD_LIBRARIES})
if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")) if (SERPENT)
target_link_libraries(${EXECUTABLE} serpent) target_link_libraries(${EXECUTABLE} serpent)
endif() endif()
# eth_install_executable is defined in cmake/EthExecutableHelper.cmake # eth_install_executable is defined in cmake/EthExecutableHelper.cmake
eth_install_executable(${EXECUTABLE} DLLS ${MHD_DLL_RELEASE}) eth_install_executable(${EXECUTABLE} DLLS MHD_DLLS)

5
alethzero/Connect.cpp

@ -38,13 +38,14 @@ Connect::~Connect()
void Connect::setEnvironment(QStringList const& _nodes) void Connect::setEnvironment(QStringList const& _nodes)
{ {
ui->host->addItems(_nodes); if (ui->host->count() == 0)
ui->host->addItems(_nodes);
} }
void Connect::reset() void Connect::reset()
{ {
ui->nodeId->clear(); ui->nodeId->clear();
ui->required->setChecked(false); ui->required->setChecked(true);
} }
QString Connect::host() QString Connect::host()

3
alethzero/Connect.ui

@ -59,6 +59,9 @@
<property name="text"> <property name="text">
<string>Required (Always Connect to this Peer)</string> <string>Required (Always Connect to this Peer)</string>
</property> </property>
<property name="checked">
<bool>true</bool>
</property>
<property name="tristate"> <property name="tristate">
<bool>false</bool> <bool>false</bool>
</property> </property>

77
alethzero/DappLoader.cpp

@ -25,6 +25,7 @@
#include <QStringList> #include <QStringList>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QMimeDatabase>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcrypto/CryptoPP.h> #include <libdevcrypto/CryptoPP.h>
@ -96,13 +97,31 @@ DappLocation DappLoader::resolveAppUri(QString const& _uri)
void DappLoader::downloadComplete(QNetworkReply* _reply) void DappLoader::downloadComplete(QNetworkReply* _reply)
{ {
QUrl requestUrl = _reply->request().url();
if (m_pageUrls.count(requestUrl) != 0)
{
//inject web3 js
QByteArray content = "<script>\n";
content.append(web3Content());
content.append("</script>\n");
content.append(_reply->readAll());
QString contentType = _reply->header(QNetworkRequest::ContentTypeHeader).toString();
if (contentType.isEmpty())
{
QMimeDatabase db;
contentType = db.mimeTypeForUrl(requestUrl).name();
}
pageReady(content, contentType, requestUrl);
return;
}
try try
{ {
//try to interpret as rlp //try to interpret as rlp
QByteArray data = _reply->readAll(); QByteArray data = _reply->readAll();
_reply->deleteLater(); _reply->deleteLater();
h256 expected = m_uriHashes[_reply->request().url()]; h256 expected = m_uriHashes[requestUrl];
bytes package(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size())); bytes package(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size()));
Secp256k1 dec; Secp256k1 dec;
dec.decrypt(expected, package); dec.decrypt(expected, package);
@ -144,15 +163,7 @@ void DappLoader::loadDapp(RLP const& _rlp)
if (entry->path == "/deployment.js") if (entry->path == "/deployment.js")
{ {
//inject web3 code //inject web3 code
QString code; bytes b(web3Content().data(), web3Content().data() + web3Content().size());
code += contentsOfQResource(":/js/bignumber.min.js");
code += "\n";
code += contentsOfQResource(":/js/webthree.js");
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
QByteArray res = code.toLatin1();
bytes b(res.data(), res.data() + res.size());
b.insert(b.end(), content.begin(), content.end()); b.insert(b.end(), content.begin(), content.end());
dapp.content[hash] = b; dapp.content[hash] = b;
} }
@ -165,6 +176,22 @@ void DappLoader::loadDapp(RLP const& _rlp)
emit dappReady(dapp); emit dappReady(dapp);
} }
QByteArray const& DappLoader::web3Content()
{
if (m_web3Js.isEmpty())
{
QString code;
code += contentsOfQResource(":/js/bignumber.min.js");
code += "\n";
code += contentsOfQResource(":/js/webthree.js");
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
m_web3Js = code.toLatin1();
}
return m_web3Js;
}
Manifest DappLoader::loadManifest(std::string const& _manifest) Manifest DappLoader::loadManifest(std::string const& _manifest)
{ {
/// https://github.com/ethereum/go-ethereum/wiki/URL-Scheme /// https://github.com/ethereum/go-ethereum/wiki/URL-Scheme
@ -193,10 +220,34 @@ Manifest DappLoader::loadManifest(std::string const& _manifest)
void DappLoader::loadDapp(QString const& _uri) void DappLoader::loadDapp(QString const& _uri)
{ {
DappLocation location = resolveAppUri(_uri); QUrl uri(_uri);
QUrl uri(location.contentUri); QUrl contentUri;
h256 hash;
if (uri.path().endsWith(".dapp") && uri.query().startsWith("hash="))
{
contentUri = uri;
QString query = uri.query();
query.remove("hash=");
if (!query.startsWith("0x"))
query.insert(0, "0x");
hash = jsToFixed<32>(query.toStdString());
}
else
{
DappLocation location = resolveAppUri(_uri);
contentUri = location.contentUri;
hash = location.contentHash;
}
QNetworkRequest request(contentUri);
m_uriHashes[uri] = hash;
m_net.get(request);
}
void DappLoader::loadPage(QString const& _uri)
{
QUrl uri(_uri);
QNetworkRequest request(uri); QNetworkRequest request(uri);
m_uriHashes[uri] = location.contentHash; m_pageUrls.insert(uri);
m_net.get(request); m_net.get(request);
} }

7
alethzero/DappLoader.h

@ -73,9 +73,13 @@ public:
///Load a new DApp. Resolves a name with a name reg contract. Asynchronous. dappReady is emitted once everything is read, dappError othervise ///Load a new DApp. Resolves a name with a name reg contract. Asynchronous. dappReady is emitted once everything is read, dappError othervise
///@param _uri Eth name path ///@param _uri Eth name path
void loadDapp(QString const& _uri); void loadDapp(QString const& _uri);
///Load a regular html page
///@param _uri Page Uri
void loadPage(QString const& _uri);
signals: signals:
void dappReady(Dapp& _dapp); void dappReady(Dapp& _dapp);
void pageReady(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri);
void dappError(); void dappError();
private slots: private slots:
@ -86,9 +90,12 @@ private:
DappLocation resolveAppUri(QString const& _uri); DappLocation resolveAppUri(QString const& _uri);
void loadDapp(dev::RLP const& _rlp); void loadDapp(dev::RLP const& _rlp);
Manifest loadManifest(std::string const& _manifest); Manifest loadManifest(std::string const& _manifest);
QByteArray const& web3Content();
dev::WebThreeDirect* m_web3; dev::WebThreeDirect* m_web3;
QNetworkAccessManager m_net; QNetworkAccessManager m_net;
std::map<QUrl, dev::h256> m_uriHashes; std::map<QUrl, dev::h256> m_uriHashes;
std::set<QUrl> m_pageUrls;
QByteArray m_web3Js;
}; };

1
alethzero/DownloadView.h

@ -32,7 +32,6 @@
#endif #endif
namespace dev { namespace eth { namespace dev { namespace eth {
struct MineInfo;
class DownloadMan; class DownloadMan;
}} }}

39
alethzero/Main.ui

@ -45,6 +45,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="chainStatus">
<property name="text">
<string>#0</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="balance"> <widget class="QLabel" name="balance">
<property name="text"> <property name="text">
@ -118,7 +125,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1617</width> <width>1617</width>
<height>22</height> <height>24</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menu_File"> <widget class="QMenu" name="menu_File">
@ -143,6 +150,7 @@
<string>&amp;Tools</string> <string>&amp;Tools</string>
</property> </property>
<addaction name="mine"/> <addaction name="mine"/>
<addaction name="turboMining"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="newTransaction"/> <addaction name="newTransaction"/>
<addaction name="newAccount"/> <addaction name="newAccount"/>
@ -169,10 +177,10 @@
<addaction name="killBlockchain"/> <addaction name="killBlockchain"/>
<addaction name="inject"/> <addaction name="inject"/>
<addaction name="forceMining"/> <addaction name="forceMining"/>
<addaction name="turboMining"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="usePrivate"/> <addaction name="usePrivate"/>
<addaction name="jitvm"/> <addaction name="jitvm"/>
<addaction name="retryUnknown"/>
</widget> </widget>
<widget class="QMenu" name="menu_View"> <widget class="QMenu" name="menu_View">
<property name="title"> <property name="title">
@ -563,7 +571,7 @@
<item> <item>
<widget class="QListWidget" name="ourAccounts"> <widget class="QListWidget" name="ourAccounts">
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::WheelFocus</enum>
</property> </property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
@ -630,7 +638,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::WheelFocus</enum>
</property> </property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
@ -708,7 +716,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::WheelFocus</enum>
</property> </property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
@ -1601,14 +1609,6 @@ font-size: 14pt</string>
<string>&amp;Enable LLL Optimizer</string> <string>&amp;Enable LLL Optimizer</string>
</property> </property>
</action> </action>
<action name="turboMining">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Reserved Debug 1</string>
</property>
</action>
<action name="localNetworking"> <action name="localNetworking">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
@ -1672,6 +1672,19 @@ font-size: 14pt</string>
<string>&amp;NatSpec Enabled</string> <string>&amp;NatSpec Enabled</string>
</property> </property>
</action> </action>
<action name="turboMining">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;GPU Mining</string>
</property>
</action>
<action name="retryUnknown">
<property name="text">
<string>Retry Unknown Parent Blocks</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>

94
alethzero/MainWin.cpp

@ -45,7 +45,7 @@
#endif #endif
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libethcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libethcore/Ethasher.h> #include <libethcore/EthashAux.h>
#include <liblll/Compiler.h> #include <liblll/Compiler.h>
#include <liblll/CodeFragment.h> #include <liblll/CodeFragment.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
@ -148,7 +148,7 @@ Main::Main(QWidget *parent) :
cerr << "State root: " << CanonBlockChain::genesis().stateRoot << endl; cerr << "State root: " << CanonBlockChain::genesis().stateRoot << endl;
auto block = CanonBlockChain::createGenesisBlock(); auto block = CanonBlockChain::createGenesisBlock();
cerr << "Block Hash: " << CanonBlockChain::genesis().hash << endl; cerr << "Block Hash: " << CanonBlockChain::genesis().hash() << endl;
cerr << "Block RLP: " << RLP(block) << endl; cerr << "Block RLP: " << RLP(block) << endl;
cerr << "Block Hex: " << toHex(block) << endl; cerr << "Block Hex: " << toHex(block) << endl;
cerr << "eth Network protocol version: " << eth::c_protocolVersion << endl; cerr << "eth Network protocol version: " << eth::c_protocolVersion << endl;
@ -161,14 +161,17 @@ Main::Main(QWidget *parent) :
statusBar()->addPermanentWidget(ui->balance); statusBar()->addPermanentWidget(ui->balance);
statusBar()->addPermanentWidget(ui->peerCount); statusBar()->addPermanentWidget(ui->peerCount);
statusBar()->addPermanentWidget(ui->mineStatus); statusBar()->addPermanentWidget(ui->mineStatus);
statusBar()->addPermanentWidget(ui->chainStatus);
statusBar()->addPermanentWidget(ui->blockCount); statusBar()->addPermanentWidget(ui->blockCount);
ui->blockCount->setText(QString("PV%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ProofOfWork::name())).arg(ProofOfWork::revision()).arg(dev::Version));
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
QSettings s("ethereum", "alethzero"); QSettings s("ethereum", "alethzero");
m_networkConfig = s.value("peers").toByteArray(); m_networkConfig = s.value("peers").toByteArray();
bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size()); bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size());
m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir(), false, {"eth", "shh"}, p2p::NetworkPreferences(), network)); m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir(), WithExisting::Trust, {"eth", "shh"}, p2p::NetworkPreferences(), network));
m_httpConnector.reset(new jsonrpc::HttpServer(SensibleHttpPort, "", "", dev::SensibleHttpThreads)); m_httpConnector.reset(new jsonrpc::HttpServer(SensibleHttpPort, "", "", dev::SensibleHttpThreads));
m_server.reset(new OurWebThreeStubServer(*m_httpConnector, *web3(), keysAsVector(m_myKeys), this)); m_server.reset(new OurWebThreeStubServer(*m_httpConnector, *web3(), keysAsVector(m_myKeys), this));
@ -180,13 +183,6 @@ Main::Main(QWidget *parent) :
m_webPage = webPage; m_webPage = webPage;
connect(webPage, &WebPage::consoleMessage, [this](QString const& _msg) { Main::addConsoleMessage(_msg, QString()); }); connect(webPage, &WebPage::consoleMessage, [this](QString const& _msg) { Main::addConsoleMessage(_msg, QString()); });
ui->webView->setPage(m_webPage); ui->webView->setPage(m_webPage);
connect(ui->webView, &QWebEngineView::loadFinished, [this]()
{
auto f = ui->webView->page();
f->runJavaScript(contentsOfQResource(":/js/bignumber.min.js"));
f->runJavaScript(contentsOfQResource(":/js/webthree.js"));
f->runJavaScript(contentsOfQResource(":/js/setup.js"));
});
connect(ui->webView, &QWebEngineView::titleChanged, [=]() connect(ui->webView, &QWebEngineView::titleChanged, [=]()
{ {
@ -196,6 +192,7 @@ Main::Main(QWidget *parent) :
m_dappHost.reset(new DappHost(8081)); m_dappHost.reset(new DappHost(8081));
m_dappLoader = new DappLoader(this, web3()); m_dappLoader = new DappLoader(this, web3());
connect(m_dappLoader, &DappLoader::dappReady, this, &Main::dappLoaded); connect(m_dappLoader, &DappLoader::dappReady, this, &Main::dappLoaded);
connect(m_dappLoader, &DappLoader::pageReady, this, &Main::pageLoaded);
// ui->webView->page()->settings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, true); // ui->webView->page()->settings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, true);
// QWebEngineInspector* inspector = new QWebEngineInspector(); // QWebEngineInspector* inspector = new QWebEngineInspector();
// inspector->setPage(page); // inspector->setPage(page);
@ -261,7 +258,7 @@ NetworkPreferences Main::netPrefs() const
{ {
listenIP.clear(); listenIP.clear();
} }
auto publicIP = ui->forcePublicIP->text().toStdString(); auto publicIP = ui->forcePublicIP->text().toStdString();
try try
{ {
@ -271,7 +268,7 @@ NetworkPreferences Main::netPrefs() const
{ {
publicIP.clear(); publicIP.clear();
} }
if (isPublicAddress(publicIP)) if (isPublicAddress(publicIP))
return NetworkPreferences(publicIP, listenIP, ui->port->value(), ui->upnp->isChecked()); return NetworkPreferences(publicIP, listenIP, ui->port->value(), ui->upnp->isChecked());
else else
@ -285,7 +282,7 @@ void Main::onKeysChanged()
unsigned Main::installWatch(LogFilter const& _tf, WatchHandler const& _f) unsigned Main::installWatch(LogFilter const& _tf, WatchHandler const& _f)
{ {
auto ret = ethereum()->installWatch(_tf); auto ret = ethereum()->installWatch(_tf, Reaping::Manual);
m_handlers[ret] = _f; m_handlers[ret] = _f;
_f(LocalisedLogEntries()); _f(LocalisedLogEntries());
return ret; return ret;
@ -301,16 +298,25 @@ unsigned Main::installWatch(dev::h256 _tf, WatchHandler const& _f)
void Main::uninstallWatch(unsigned _w) void Main::uninstallWatch(unsigned _w)
{ {
cdebug << "!!! Main: uninstalling watch" << _w;
ethereum()->uninstallWatch(_w); ethereum()->uninstallWatch(_w);
m_handlers.erase(_w); m_handlers.erase(_w);
} }
void Main::installWatches() void Main::installWatches()
{ {
auto newBlockId = installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){
onNewBlock();
});
auto newPendingId = installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){
onNewPending();
});
cdebug << "newBlock watch ID: " << newBlockId;
cdebug << "newPending watch ID: " << newPendingId;
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); });
installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); });
installWatch(PendingChangedFilter, [=](LocalisedLogEntries const&){ onNewPending(); });
installWatch(ChainChangedFilter, [=](LocalisedLogEntries const&){ onNewBlock(); });
} }
Address Main::getNameReg() const Address Main::getNameReg() const
@ -701,6 +707,7 @@ void Main::writeSettings()
s.setValue("upnp", ui->upnp->isChecked()); s.setValue("upnp", ui->upnp->isChecked());
s.setValue("forceAddress", ui->forcePublicIP->text()); s.setValue("forceAddress", ui->forcePublicIP->text());
s.setValue("forceMining", ui->forceMining->isChecked()); s.setValue("forceMining", ui->forceMining->isChecked());
s.setValue("turboMining", ui->turboMining->isChecked());
s.setValue("paranoia", ui->paranoia->isChecked()); s.setValue("paranoia", ui->paranoia->isChecked());
s.setValue("natSpec", ui->natSpec->isChecked()); s.setValue("natSpec", ui->natSpec->isChecked());
s.setValue("showAll", ui->showAll->isChecked()); s.setValue("showAll", ui->showAll->isChecked());
@ -771,6 +778,8 @@ void Main::readSettings(bool _skipGeometry)
ui->dropPeers->setChecked(false); ui->dropPeers->setChecked(false);
ui->forceMining->setChecked(s.value("forceMining", false).toBool()); ui->forceMining->setChecked(s.value("forceMining", false).toBool());
on_forceMining_triggered(); on_forceMining_triggered();
ui->turboMining->setChecked(s.value("turboMining", false).toBool());
on_turboMining_triggered();
ui->paranoia->setChecked(s.value("paranoia", false).toBool()); ui->paranoia->setChecked(s.value("paranoia", false).toBool());
ui->natSpec->setChecked(s.value("natSpec", true).toBool()); ui->natSpec->setChecked(s.value("natSpec", true).toBool());
ui->showAll->setChecked(s.value("showAll", false).toBool()); ui->showAll->setChecked(s.value("showAll", false).toBool());
@ -881,12 +890,16 @@ void Main::on_usePrivate_triggered()
{ {
m_privateChain = QInputDialog::getText(this, "Enter Name", "Enter the name of your private chain", QLineEdit::Normal, QString("NewChain-%1").arg(time(0))); m_privateChain = QInputDialog::getText(this, "Enter Name", "Enter the name of your private chain", QLineEdit::Normal, QString("NewChain-%1").arg(time(0)));
if (m_privateChain.isEmpty()) if (m_privateChain.isEmpty())
ui->usePrivate->setChecked(false); {
if (ui->usePrivate->isChecked())
ui->usePrivate->setChecked(false);
else
// was cancelled.
return;
}
} }
else else
{
m_privateChain.clear(); m_privateChain.clear();
}
on_killBlockchain_triggered(); on_killBlockchain_triggered();
} }
@ -900,12 +913,13 @@ void Main::on_urlEdit_returnPressed()
{ {
QString s = ui->urlEdit->text(); QString s = ui->urlEdit->text();
QUrl url(s); QUrl url(s);
if (url.scheme().isEmpty() || url.scheme() == "eth") if (url.scheme().isEmpty() || url.scheme() == "eth" || url.path().endsWith(".dapp"))
{ {
try try
{ {
//try do resolve dapp url //try do resolve dapp url
m_dappLoader->loadDapp(s); m_dappLoader->loadDapp(s);
return;
} }
catch (...) catch (...)
{ {
@ -919,8 +933,7 @@ void Main::on_urlEdit_returnPressed()
else else
url.setScheme("http"); url.setScheme("http");
else {} else {}
qDebug() << url.toString(); m_dappLoader->loadPage(url.toString());
ui->webView->page()->setUrl(url);
} }
void Main::on_nameReg_textChanged() void Main::on_nameReg_textChanged()
@ -943,7 +956,7 @@ void Main::on_preview_triggered()
void Main::refreshMining() void Main::refreshMining()
{ {
MineProgress p = ethereum()->miningProgress(); MiningProgress p = ethereum()->miningProgress();
ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining"); ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining");
if (!ui->miningView->isVisible()) if (!ui->miningView->isVisible())
return; return;
@ -1018,7 +1031,7 @@ void Main::refreshNetwork()
.arg(sessions[i.id] = QString::fromStdString(i.clientVersion)) .arg(sessions[i.id] = QString::fromStdString(i.clientVersion))
.arg(QString::fromStdString(toString(i.caps))) .arg(QString::fromStdString(toString(i.caps)))
.arg(QString::fromStdString(toString(i.notes))) .arg(QString::fromStdString(toString(i.notes)))
.arg(i.socket) .arg(i.socketId)
.arg(QString::fromStdString(i.id.abridged()))); .arg(QString::fromStdString(i.id.abridged())));
auto ns = web3()->nodes(); auto ns = web3()->nodes();
@ -1089,9 +1102,9 @@ void Main::refreshAccounts()
void Main::refreshBlockCount() void Main::refreshBlockCount()
{ {
cwatch << "refreshBlockCount()";
auto d = ethereum()->blockChain().details(); auto d = ethereum()->blockChain().details();
ui->blockCount->setText(QString("%4 #%1 PV%2 D%3 H%5").arg(d.number).arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(c_ethashVersion)); BlockQueueStatus b = ethereum()->blockQueueStatus();
ui->chainStatus->setText(QString("%3 ready %4 future %5 unknown %6 bad %1 #%2").arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(d.number).arg(b.ready).arg(b.future).arg(b.unknown).arg(b.bad));
} }
void Main::on_turboMining_triggered() void Main::on_turboMining_triggered()
@ -1144,7 +1157,7 @@ void Main::refreshBlockChain()
auto b = bc.block(h); auto b = bc.block(h);
for (auto const& i: RLP(b)[1]) for (auto const& i: RLP(b)[1])
{ {
Transaction t(i.data(), CheckSignature::Sender); Transaction t(i.data(), CheckTransaction::Everything);
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())
@ -1270,6 +1283,7 @@ void Main::timerEvent(QTimerEvent*)
refreshNetwork(); refreshNetwork();
refreshWhispers(); refreshWhispers();
refreshCache(); refreshCache();
refreshBlockCount();
poll(); poll();
} }
else else
@ -1471,7 +1485,7 @@ void Main::on_blocks_currentItemChanged()
s << "<div>Difficulty: <b>" << info.difficulty << "</b>" << "</div>"; s << "<div>Difficulty: <b>" << info.difficulty << "</b>" << "</div>";
if (info.number) if (info.number)
{ {
auto e = Ethasher::eval(info); auto e = EthashAux::eval(info);
s << "<div>Proof-of-Work: <b>" << e.value << " &lt;= " << (h256)u256((bigint(1) << 256) / info.difficulty) << "</b> (mixhash: " << e.mixHash.abridged() << ")" << "</div>"; s << "<div>Proof-of-Work: <b>" << e.value << " &lt;= " << (h256)u256((bigint(1) << 256) / info.difficulty) << "</b> (mixhash: " << e.mixHash.abridged() << ")" << "</div>";
s << "<div>Parent: <b>" << info.parentHash << "</b>" << "</div>"; s << "<div>Parent: <b>" << info.parentHash << "</b>" << "</div>";
} }
@ -1491,7 +1505,7 @@ void Main::on_blocks_currentItemChanged()
{ {
BlockInfo uncle = BlockInfo::fromHeader(u.data()); BlockInfo uncle = BlockInfo::fromHeader(u.data());
char const* line = "<div><span style=\"margin-left: 2em\">&nbsp;</span>"; char const* line = "<div><span style=\"margin-left: 2em\">&nbsp;</span>";
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>" << pretty(uncle.coinbaseAddress).toHtmlEscaped().toStdString() << " " << uncle.coinbaseAddress << "</b>" << "</div>";
@ -1500,7 +1514,7 @@ void Main::on_blocks_currentItemChanged()
s << line << "Nonce: <b>" << uncle.nonce << "</b>" << "</div>"; s << line << "Nonce: <b>" << uncle.nonce << "</b>" << "</div>";
s << line << "Hash w/o nonce: <b>" << uncle.headerHash(WithoutNonce) << "</b>" << "</div>"; s << line << "Hash w/o nonce: <b>" << uncle.headerHash(WithoutNonce) << "</b>" << "</div>";
s << line << "Difficulty: <b>" << uncle.difficulty << "</b>" << "</div>"; s << line << "Difficulty: <b>" << uncle.difficulty << "</b>" << "</div>";
auto e = Ethasher::eval(uncle); auto e = EthashAux::eval(uncle);
s << line << "Proof-of-Work: <b>" << e.value << " &lt;= " << (h256)u256((bigint(1) << 256) / uncle.difficulty) << "</b> (mixhash: " << e.mixHash.abridged() << ")" << "</div>"; s << line << "Proof-of-Work: <b>" << e.value << " &lt;= " << (h256)u256((bigint(1) << 256) / uncle.difficulty) << "</b> (mixhash: " << e.mixHash.abridged() << ")" << "</div>";
} }
if (info.parentHash) if (info.parentHash)
@ -1523,7 +1537,7 @@ void Main::on_blocks_currentItemChanged()
else else
{ {
unsigned txi = item->data(Qt::UserRole + 1).toInt(); unsigned txi = item->data(Qt::UserRole + 1).toInt();
Transaction tx(block[1][txi].data(), CheckSignature::Sender); Transaction tx(block[1][txi].data(), CheckTransaction::Everything);
auto ss = tx.safeSender(); auto ss = tx.safeSender();
h256 th = sha3(rlpList(ss, tx.nonce())); h256 th = sha3(rlpList(ss, tx.nonce()));
TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi]; TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi];
@ -1582,9 +1596,9 @@ void Main::on_debugCurrent_triggered()
unsigned txi = item->data(Qt::UserRole + 1).toInt(); unsigned txi = item->data(Qt::UserRole + 1).toInt();
bytes t = ethereum()->blockChain().transaction(h, txi); bytes t = ethereum()->blockChain().transaction(h, txi);
State s(ethereum()->state(txi, h)); State s(ethereum()->state(txi, h));
Executive e(s, ethereum()->blockChain(), PendingBlock); Executive e(s, ethereum()->blockChain());
Debugger dw(this, this); Debugger dw(this, this);
dw.populate(e, Transaction(t, CheckSignature::Sender)); dw.populate(e, Transaction(t, CheckTransaction::Everything));
dw.exec(); dw.exec();
} }
} }
@ -1742,6 +1756,11 @@ void Main::on_clearPending_triggered()
refreshAll(); refreshAll();
} }
void Main::on_retryUnknown_triggered()
{
ethereum()->retryUnkonwn();
}
void Main::on_killBlockchain_triggered() void Main::on_killBlockchain_triggered()
{ {
writeSettings(); writeSettings();
@ -1786,7 +1805,7 @@ void Main::on_connect_triggered()
ui->net->setChecked(true); ui->net->setChecked(true);
on_net_triggered(); on_net_triggered();
} }
m_connect.setEnvironment(m_servers); m_connect.setEnvironment(m_servers);
if (m_connect.exec() == QDialog::Accepted) if (m_connect.exec() == QDialog::Accepted)
{ {
@ -1798,9 +1817,9 @@ void Main::on_connect_triggered()
nodeID = NodeId(fromHex(m_connect.nodeId().toStdString())); nodeID = NodeId(fromHex(m_connect.nodeId().toStdString()));
} }
catch (BadHexCharacter&) {} catch (BadHexCharacter&) {}
m_connect.reset(); m_connect.reset();
if (required) if (required)
web3()->requirePeer(nodeID, host); web3()->requirePeer(nodeID, host);
else else
@ -2003,3 +2022,8 @@ void Main::dappLoaded(Dapp& _dapp)
QUrl url = m_dappHost->hostDapp(std::move(_dapp)); QUrl url = m_dappHost->hostDapp(std::move(_dapp));
ui->webView->page()->setUrl(url); ui->webView->page()->setUrl(url);
} }
void Main::pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri)
{
ui->webView->page()->setContent(_content, _mimeType, _uri);
}

2
alethzero/MainWin.h

@ -163,6 +163,7 @@ private slots:
void on_usePrivate_triggered(); void on_usePrivate_triggered();
void on_turboMining_triggered(); void on_turboMining_triggered();
void on_jitvm_triggered(); void on_jitvm_triggered();
void on_retryUnknown_triggered();
// Debugger // Debugger
void on_debugCurrent_triggered(); void on_debugCurrent_triggered();
@ -179,6 +180,7 @@ private slots:
// Dapps // Dapps
void dappLoaded(Dapp& _dapp); //qt does not support rvalue refs for signals void dappLoaded(Dapp& _dapp); //qt does not support rvalue refs for signals
void pageLoaded(QByteArray const& _content, QString const& _mimeType, QUrl const& _uri);
signals: signals:
void poll(); void poll();

11
alethzero/MiningView.cpp

@ -36,7 +36,7 @@ using namespace dev::eth;
// types // types
using dev::eth::MineInfo; using dev::eth::MineInfo;
using dev::eth::MineProgress; using dev::eth::MiningProgress;
// functions // functions
using dev::toString; using dev::toString;
@ -50,12 +50,13 @@ MiningView::MiningView(QWidget* _p): QWidget(_p)
{ {
} }
void MiningView::appendStats(list<MineInfo> const& _i, MineProgress const& _p) void MiningView::appendStats(list<MineInfo> const& _i, MiningProgress const& _p)
{ {
(void)_p;
if (_i.empty()) if (_i.empty())
return; return;
unsigned o = m_values.size(); /* unsigned o = m_values.size();
for (MineInfo const& i: _i) for (MineInfo const& i: _i)
{ {
m_values.push_back(i.best); m_values.push_back(i.best);
@ -91,7 +92,7 @@ void MiningView::appendStats(list<MineInfo> const& _i, MineProgress const& _p)
m_completes.erase(remove_if(m_completes.begin(), m_completes.end(), [](int i){return i < 0;}), m_completes.end()); m_completes.erase(remove_if(m_completes.begin(), m_completes.end(), [](int i){return i < 0;}), m_completes.end());
m_progress = _p; m_progress = _p;
update(); update();*/
} }
void MiningView::resetStats() void MiningView::resetStats()
@ -101,6 +102,7 @@ void MiningView::resetStats()
void MiningView::paintEvent(QPaintEvent*) void MiningView::paintEvent(QPaintEvent*)
{ {
/*
Grapher g; Grapher g;
QPainter p(this); QPainter p(this);
@ -115,4 +117,5 @@ void MiningView::paintEvent(QPaintEvent*)
g.ruleY(r - 1, QColor(128, 128, 128)); g.ruleY(r - 1, QColor(128, 128, 128));
for (auto r: m_completes) for (auto r: m_completes)
g.ruleY(r, QColor(192, 64, 64)); g.ruleY(r, QColor(192, 64, 64));
*/
} }

4
alethzero/MiningView.h

@ -42,14 +42,14 @@ class MiningView: public QWidget
public: public:
MiningView(QWidget* _p = nullptr); MiningView(QWidget* _p = nullptr);
void appendStats(std::list<dev::eth::MineInfo> const& _l, dev::eth::MineProgress const& _p); void appendStats(std::list<dev::eth::MineInfo> const& _l, dev::eth::MiningProgress const& _p);
void resetStats(); void resetStats();
protected: protected:
virtual void paintEvent(QPaintEvent*); virtual void paintEvent(QPaintEvent*);
private: private:
dev::eth::MineProgress m_progress; dev::eth::MiningProgress m_progress;
unsigned m_duration = 300; unsigned m_duration = 300;
std::vector<float> m_values; std::vector<float> m_values;
std::vector<float> m_bests; std::vector<float> m_bests;

6
alethzero/Transact.cpp

@ -37,7 +37,7 @@
#include <libnatspec/NatspecExpressionEvaluator.h> #include <libnatspec/NatspecExpressionEvaluator.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include <libethereum/Utility.h> #include <libethereum/Utility.h>
#ifndef _MSC_VER #if ETH_SERPENT
#include <libserpent/funcs.h> #include <libserpent/funcs.h>
#include <libserpent/util.h> #include <libserpent/util.h>
#endif #endif
@ -220,7 +220,7 @@ static tuple<vector<string>, bytes, string> userInputToCode(string const& _user,
errors.push_back("Solidity: Uncaught exception"); errors.push_back("Solidity: Uncaught exception");
} }
} }
#ifndef _MSC_VER #if ETH_SERPENT
else if (sourceIsSerpent(_user)) else if (sourceIsSerpent(_user))
{ {
try try
@ -306,7 +306,7 @@ void Transact::rejigData()
htmlInfo += "<h4>Hex</h4>" + QString(Div(Mono)) + QString::fromStdString(toHex(m_data)) + "</div>"; htmlInfo += "<h4>Hex</h4>" + QString(Div(Mono)) + QString::fromStdString(toHex(m_data)) + "</div>";
// Determine the minimum amount of gas we need to play... // Determine the minimum amount of gas we need to play...
qint64 baseGas = (qint64)Interface::txGas(m_data, 0); qint64 baseGas = (qint64)Transaction::gasRequired(m_data, 0);
qint64 gasNeeded = 0; qint64 gasNeeded = 0;
if (b < value() + baseGas * gasPrice()) if (b < value() + baseGas * gasPrice())

161
cmake/CMakeParseArguments.cmake

@ -0,0 +1,161 @@
#.rst:
# CMakeParseArguments
# -------------------
#
#
#
# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords>
# <multi_value_keywords> args...)
#
# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions
# for parsing the arguments given to that macro or function. It
# processes the arguments and defines a set of variables which hold the
# values of the respective options.
#
# The <options> argument contains all options for the respective macro,
# i.e. keywords which can be used when calling the macro without any
# value following, like e.g. the OPTIONAL keyword of the install()
# command.
#
# The <one_value_keywords> argument contains all keywords for this macro
# which are followed by one value, like e.g. DESTINATION keyword of the
# install() command.
#
# The <multi_value_keywords> argument contains all keywords for this
# macro which can be followed by more than one value, like e.g. the
# TARGETS or FILES keywords of the install() command.
#
# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
# keywords listed in <options>, <one_value_keywords> and
# <multi_value_keywords> a variable composed of the given <prefix>
# followed by "_" and the name of the respective keyword. These
# variables will then hold the respective value from the argument list.
# For the <options> keywords this will be TRUE or FALSE.
#
# All remaining arguments are collected in a variable
# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see
# whether your macro was called with unrecognized parameters.
#
# As an example here a my_install() macro, which takes similar arguments
# as the real install() command:
#
# ::
#
# function(MY_INSTALL)
# set(options OPTIONAL FAST)
# set(oneValueArgs DESTINATION RENAME)
# set(multiValueArgs TARGETS CONFIGURATIONS)
# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}"
# "${multiValueArgs}" ${ARGN} )
# ...
#
#
#
# Assume my_install() has been called like this:
#
# ::
#
# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
#
#
#
# After the cmake_parse_arguments() call the macro will have set the
# following variables:
#
# ::
#
# MY_INSTALL_OPTIONAL = TRUE
# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
# MY_INSTALL_DESTINATION = "bin"
# MY_INSTALL_RENAME = "" (was not used)
# MY_INSTALL_TARGETS = "foo;bar"
# MY_INSTALL_CONFIGURATIONS = "" (was not used)
# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
#
#
#
# You can then continue and process these variables.
#
# Keywords terminate lists of values, e.g. if directly after a
# one_value_keyword another recognized keyword follows, this is
# interpreted as the beginning of the new option. E.g.
# my_install(TARGETS foo DESTINATION OPTIONAL) would result in
# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION
# would be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
#=============================================================================
# Copyright 2010 Alexander Neundorf <neundorf@kde.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
return()
endif()
set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
# first set all result variables to empty/FALSE
foreach(arg_name ${_singleArgNames} ${_multiArgNames})
set(${prefix}_${arg_name})
endforeach()
foreach(option ${_optionNames})
set(${prefix}_${option} FALSE)
endforeach()
set(${prefix}_UNPARSED_ARGUMENTS)
set(insideValues FALSE)
set(currentArgName)
# now iterate over all arguments and fill the result variables
foreach(currentArg ${ARGN})
list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword
list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword
list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword
if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1)
if(insideValues)
if("${insideValues}" STREQUAL "SINGLE")
set(${prefix}_${currentArgName} ${currentArg})
set(insideValues FALSE)
elseif("${insideValues}" STREQUAL "MULTI")
list(APPEND ${prefix}_${currentArgName} ${currentArg})
endif()
else()
list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
endif()
else()
if(NOT ${optionIndex} EQUAL -1)
set(${prefix}_${currentArg} TRUE)
set(insideValues FALSE)
elseif(NOT ${singleArgIndex} EQUAL -1)
set(currentArgName ${currentArg})
set(${prefix}_${currentArgName})
set(insideValues "SINGLE")
elseif(NOT ${multiArgIndex} EQUAL -1)
set(currentArgName ${currentArg})
set(${prefix}_${currentArgName})
set(insideValues "MULTI")
endif()
endif()
endforeach()
# propagate the result variables to the caller:
foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
endforeach()
set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
endfunction()

10
cmake/EthCompilerSettings.cmake

@ -7,9 +7,17 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
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_DEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE")
set(ETH_SHARED 1) set(ETH_SHARED 1)
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))

27
cmake/EthDependencies.cmake

@ -4,7 +4,11 @@
# by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... # by defining this variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ...
# this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory
string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name) string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name)
set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}") if (CMAKE_CL_64)
set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}/x64")
else ()
set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extdep/install/${_system_name}/Win32")
endif()
set (CMAKE_PREFIX_PATH ${ETH_DEPENDENCY_INSTALL_DIR}) set (CMAKE_PREFIX_PATH ${ETH_DEPENDENCY_INSTALL_DIR})
# setup directory for cmake generated files and include it globally # setup directory for cmake generated files and include it globally
@ -59,7 +63,7 @@ if (JSONRPC)
find_package(MHD) find_package(MHD)
message(" - microhttpd header: ${MHD_INCLUDE_DIRS}") message(" - microhttpd header: ${MHD_INCLUDE_DIRS}")
message(" - microhttpd lib : ${MHD_LIBRARIES}") message(" - microhttpd lib : ${MHD_LIBRARIES}")
message(" - microhttpd dll : ${MHD_DLLS}")
endif() #JSONRPC endif() #JSONRPC
# TODO readline package does not yet check for correct version number # TODO readline package does not yet check for correct version number
@ -86,7 +90,7 @@ endif()
# TODO it is also not required in msvc build # TODO it is also not required in msvc build
find_package (Gmp 6.0.0) find_package (Gmp 6.0.0)
if (GMP_FOUND) if (GMP_FOUND)
message(" - gmp Header: ${GMP_INCLUDE_DIRS}") message(" - gmp header: ${GMP_INCLUDE_DIRS}")
message(" - gmp lib : ${GMP_LIBRARIES}") message(" - gmp lib : ${GMP_LIBRARIES}")
endif() endif()
@ -96,12 +100,25 @@ find_package (CURL)
message(" - curl header: ${CURL_INCLUDE_DIRS}") message(" - curl header: ${CURL_INCLUDE_DIRS}")
message(" - curl lib : ${CURL_LIBRARIES}") message(" - curl lib : ${CURL_LIBRARIES}")
# cpuid required for eth
find_package (Cpuid)
if (CPUID_FOUND)
message(" - cpuid header: ${CPUID_INCLUDE_DIRS}")
message(" - cpuid lib : ${CPUID_LIBRARIES}")
endif()
find_package (OpenCL)
if (OpenCL_FOUND)
message(" - opencl header: ${OpenCL_INCLUDE_DIRS}")
message(" - opencl lib : ${OpenCL_LIBRARIES}")
endif()
# find location of jsonrpcstub # find location of jsonrpcstub
find_program(ETH_JSON_RPC_STUB jsonrpcstub) find_program(ETH_JSON_RPC_STUB jsonrpcstub)
message(" - jsonrpcstub location : ${ETH_JSON_RPC_STUB}") message(" - jsonrpcstub location : ${ETH_JSON_RPC_STUB}")
# do not compile GUI # do not compile GUI
if (NOT HEADLESS) if (GUI)
# we need json rpc to build alethzero # we need json rpc to build alethzero
if (NOT JSON_RPC_CPP_FOUND) if (NOT JSON_RPC_CPP_FOUND)
@ -153,7 +170,7 @@ if (NOT HEADLESS)
endif() endif()
endif() endif()
endif() #HEADLESS endif() #GUI
# use multithreaded boost libraries, with -mt suffix # use multithreaded boost libraries, with -mt suffix
set(Boost_USE_MULTITHREADED ON) set(Boost_USE_MULTITHREADED ON)

21
cmake/EthExecutableHelper.cmake

@ -43,6 +43,22 @@ macro(eth_add_executable EXECUTABLE)
endmacro() endmacro()
macro(eth_copy_dlls EXECUTABLE DLLS)
# dlls must be unsubstitud list variable (without ${}) in format
# optimized;path_to_dll.dll;debug;path_to_dlld.dll
list(GET ${DLLS} 1 DLL_RELEASE)
list(GET ${DLLS} 3 DLL_DEBUG)
add_custom_command(TARGET ${EXECUTABLE}
POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS
-DDLL_RELEASE="${DLL_RELEASE}"
-DDLL_DEBUG="${DLL_DEBUG}"
-DCONF="$<CONFIGURATION>"
-DDESTINATION="${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
-P "${ETH_SCRIPTS_DIR}/copydlls.cmake"
)
endmacro()
# #
# this function requires the following variables to be specified: # this function requires the following variables to be specified:
# ETH_DEPENDENCY_INSTALL_DIR # ETH_DEPENDENCY_INSTALL_DIR
@ -107,10 +123,7 @@ macro(eth_install_executable EXECUTABLE)
#copy additional dlls #copy additional dlls
foreach(dll ${ETH_INSTALL_EXECUTABLE_DLLS}) foreach(dll ${ETH_INSTALL_EXECUTABLE_DLLS})
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD eth_copy_dlls(${EXECUTABLE} ${dll})
COMMAND ${CMAKE_COMMAND}
ARGS -E copy ${dll} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
)
endforeach(dll) endforeach(dll)
install( TARGETS ${EXECUTABLE} RUNTIME install( TARGETS ${EXECUTABLE} RUNTIME

8
cmake/FindCURL.cmake

@ -30,6 +30,7 @@ set(CURL_LIBRARIES ${CURL_LIBRARY})
# same naming convention as in qt (appending debug library with d) # same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug" # boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
find_library( find_library(
CURL_LIBRARY_DEBUG CURL_LIBRARY_DEBUG
NAMES curld libcurld NAMES curld libcurld
@ -38,6 +39,13 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(CURL_LIBRARIES optimized ${CURL_LIBRARIES} debug ${CURL_LIBRARY_DEBUG}) set(CURL_LIBRARIES optimized ${CURL_LIBRARIES} debug ${CURL_LIBRARY_DEBUG})
# prepare dlls
string(REPLACE ".lib" ".dll" CURL_DLL ${CURL_LIBRARY})
string(REPLACE "/lib/" "/bin/" CURL_DLL ${CURL_DLL})
string(REPLACE ".lib" ".dll" CURL_DLL_DEBUG ${CURL_LIBRARY_DEBUG})
string(REPLACE "/lib/" "/bin/" CURL_DLL_DEBUG ${CURL_DLL_DEBUG})
set(CURL_DLLS optimized ${CURL_DLL} debug ${CURL_DLL_DEBUG})
endif() endif()
# handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE # handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE

33
cmake/FindCpuid.cmake

@ -0,0 +1,33 @@
# Find libcpuid
#
# Find the libcpuid includes and library
#
# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH
#
# This module defines
# CPUID_INCLUDE_DIRS, where to find header, etc.
# CPUID_LIBRARIES, the libraries needed to use cpuid.
# CPUID_FOUND, If false, do not try to use cpuid.
# only look in default directories
find_path(
CPUID_INCLUDE_DIR
NAMES libcpuid/libcpuid.h
DOC "libcpuid include dir"
)
find_library(
CPUID_LIBRARY
NAMES cpuid
DOC "libcpuid library"
)
set(CPUID_INCLUDE_DIRS ${CPUID_INCLUDE_DIR})
set(CPUID_LIBRARIES ${CPUID_LIBRARY})
# handle the QUIETLY and REQUIRED arguments and set CPUID_FOUND to TRUE
# if all listed variables are TRUE, hide their existence from configuration view
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(cpuid DEFAULT_MSG CPUID_INCLUDE_DIR CPUID_LIBRARY)
mark_as_advanced (CPUID_INCLUDE_DIR CPUID_LIBRARY)

1
cmake/FindJsoncpp.cmake

@ -30,6 +30,7 @@ set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY})
# same naming convention as in qt (appending debug library with d) # same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug" # boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
find_library( find_library(
JSONCPP_LIBRARY_DEBUG JSONCPP_LIBRARY_DEBUG
NAMES jsoncppd NAMES jsoncppd

1
cmake/FindLevelDB.cmake

@ -29,6 +29,7 @@ set(LEVELDB_LIBRARIES ${LEVELDB_LIBRARY})
# same naming convention as in qt (appending debug library with d) # same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug" # boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
find_library( find_library(
LEVELDB_LIBRARY_DEBUG LEVELDB_LIBRARY_DEBUG
NAMES leveldbd NAMES leveldbd

16
cmake/FindMHD.cmake

@ -30,18 +30,20 @@ set(MHD_LIBRARIES ${MHD_LIBRARY})
# official MHD project actually uses _d suffix # official MHD project actually uses _d suffix
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
#TODO: place dlls into CMAKE_CFG_INTDIR subfolders
string(REPLACE ".lib" ".dll" MHD_DLL_RELEASE ${MHD_LIBRARY})
string(REPLACE "/lib/" "/bin/" MHD_DLL_RELEASE ${MHD_DLL_RELEASE})
find_library( find_library(
MHD_LIBRARY_DEBUG MHD_LIBRARY_DEBUG
NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d NAMES microhttpd_d microhttpd-10_d libmicrohttpd_d libmicrohttpd-dll_d
DOC "mhd debug library" DOC "mhd debug library"
) )
# always use release for now
#string(REPLACE ".lib" ".dll" MHD_DLL_DEBUG ${MHD_LIBRARY_DEBUG}) set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG})
#set(MHD_LIBRARIES optimized ${MHD_LIBRARIES} debug ${MHD_LIBRARY_DEBUG})
# prepare dlls
string(REPLACE ".lib" ".dll" MHD_DLL ${MHD_LIBRARY})
string(REPLACE "/lib/" "/bin/" MHD_DLL ${MHD_DLL})
string(REPLACE ".lib" ".dll" MHD_DLL_DEBUG ${MHD_LIBRARY_DEBUG})
string(REPLACE "/lib/" "/bin/" MHD_DLL_DEBUG ${MHD_DLL_DEBUG})
set(MHD_DLLS optimized ${MHD_DLL} debug ${MHD_DLL_DEBUG})
endif() endif()

136
cmake/FindOpenCL.cmake

@ -0,0 +1,136 @@
#.rst:
# FindOpenCL
# ----------
#
# Try to find OpenCL
#
# Once done this will define::
#
# OpenCL_FOUND - True if OpenCL was found
# OpenCL_INCLUDE_DIRS - include directories for OpenCL
# OpenCL_LIBRARIES - link against this library to use OpenCL
# OpenCL_VERSION_STRING - Highest supported OpenCL version (eg. 1.2)
# OpenCL_VERSION_MAJOR - The major version of the OpenCL implementation
# OpenCL_VERSION_MINOR - The minor version of the OpenCL implementation
#
# The module will also define two cache variables::
#
# OpenCL_INCLUDE_DIR - the OpenCL include directory
# OpenCL_LIBRARY - the path to the OpenCL library
#
#=============================================================================
# Copyright 2014 Matthaeus G. Chajdas
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
function(_FIND_OPENCL_VERSION)
include(CheckSymbolExists)
include(CMakePushCheckState)
set(CMAKE_REQUIRED_QUIET ${OpenCL_FIND_QUIETLY})
CMAKE_PUSH_CHECK_STATE()
foreach(VERSION "2_0" "1_2" "1_1" "1_0")
set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}")
if(APPLE)
CHECK_SYMBOL_EXISTS(
CL_VERSION_${VERSION}
"${OpenCL_INCLUDE_DIR}/OpenCL/cl.h"
OPENCL_VERSION_${VERSION})
else()
CHECK_SYMBOL_EXISTS(
CL_VERSION_${VERSION}
"${OpenCL_INCLUDE_DIR}/CL/cl.h"
OPENCL_VERSION_${VERSION})
endif()
if(OPENCL_VERSION_${VERSION})
string(REPLACE "_" "." VERSION "${VERSION}")
set(OpenCL_VERSION_STRING ${VERSION} PARENT_SCOPE)
string(REGEX MATCHALL "[0-9]+" version_components "${VERSION}")
list(GET version_components 0 major_version)
list(GET version_components 1 minor_version)
set(OpenCL_VERSION_MAJOR ${major_version} PARENT_SCOPE)
set(OpenCL_VERSION_MINOR ${minor_version} PARENT_SCOPE)
break()
endif()
endforeach()
CMAKE_POP_CHECK_STATE()
endfunction()
find_path(OpenCL_INCLUDE_DIR
NAMES
CL/cl.h OpenCL/cl.h
PATHS
ENV "PROGRAMFILES(X86)"
ENV AMDAPPSDKROOT
ENV INTELOCLSDKROOT
ENV NVSDKCOMPUTE_ROOT
ENV CUDA_PATH
ENV ATISTREAMSDKROOT
PATH_SUFFIXES
include
OpenCL/common/inc
"AMD APP/include")
_FIND_OPENCL_VERSION()
if(WIN32)
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
find_library(OpenCL_LIBRARY
NAMES OpenCL
PATHS
ENV "PROGRAMFILES(X86)"
ENV AMDAPPSDKROOT
ENV INTELOCLSDKROOT
ENV CUDA_PATH
ENV NVSDKCOMPUTE_ROOT
ENV ATISTREAMSDKROOT
PATH_SUFFIXES
"AMD APP/lib/x86"
lib/x86
lib/Win32
OpenCL/common/lib/Win32)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
find_library(OpenCL_LIBRARY
NAMES OpenCL
PATHS
ENV "PROGRAMFILES(X86)"
ENV AMDAPPSDKROOT
ENV INTELOCLSDKROOT
ENV CUDA_PATH
ENV NVSDKCOMPUTE_ROOT
ENV ATISTREAMSDKROOT
PATH_SUFFIXES
"AMD APP/lib/x86_64"
lib/x86_64
lib/x64
OpenCL/common/lib/x64)
endif()
else()
find_library(OpenCL_LIBRARY
NAMES OpenCL)
endif()
set(OpenCL_LIBRARIES ${OpenCL_LIBRARY})
set(OpenCL_INCLUDE_DIRS ${OpenCL_INCLUDE_DIR})
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(
OpenCL
FOUND_VAR OpenCL_FOUND
REQUIRED_VARS OpenCL_LIBRARY OpenCL_INCLUDE_DIR
VERSION_VAR OpenCL_VERSION_STRING)
mark_as_advanced(
OpenCL_INCLUDE_DIR
OpenCL_LIBRARY)

382
cmake/FindPackageHandleStandardArgs.cmake

@ -0,0 +1,382 @@
#.rst:
# FindPackageHandleStandardArgs
# -----------------------------
#
#
#
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> ... )
#
# This function is intended to be used in FindXXX.cmake modules files.
# It handles the REQUIRED, QUIET and version-related arguments to
# find_package(). It also sets the <packagename>_FOUND variable. The
# package is considered found if all variables <var1>... listed contain
# valid results, e.g. valid filepaths.
#
# There are two modes of this function. The first argument in both
# modes is the name of the Find-module where it is called (in original
# casing).
#
# The first simple mode looks like this:
#
# ::
#
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name>
# (DEFAULT_MSG|"Custom failure message") <var1>...<varN> )
#
# If the variables <var1> to <varN> are all valid, then
# <UPPERCASED_NAME>_FOUND will be set to TRUE. If DEFAULT_MSG is given
# as second argument, then the function will generate itself useful
# success and error messages. You can also supply a custom error
# message for the failure case. This is not recommended.
#
# The second mode is more powerful and also supports version checking:
#
# ::
#
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME
# [FOUND_VAR <resultVar>]
# [REQUIRED_VARS <var1>...<varN>]
# [VERSION_VAR <versionvar>]
# [HANDLE_COMPONENTS]
# [CONFIG_MODE]
# [FAIL_MESSAGE "Custom failure message"] )
#
# In this mode, the name of the result-variable can be set either to
# either <UPPERCASED_NAME>_FOUND or <OriginalCase_Name>_FOUND using the
# FOUND_VAR option. Other names for the result-variable are not
# allowed. So for a Find-module named FindFooBar.cmake, the two
# possible names are FooBar_FOUND and FOOBAR_FOUND. It is recommended
# to use the original case version. If the FOUND_VAR option is not
# used, the default is <UPPERCASED_NAME>_FOUND.
#
# As in the simple mode, if <var1> through <varN> are all valid,
# <packagename>_FOUND will be set to TRUE. After REQUIRED_VARS the
# variables which are required for this package are listed. Following
# VERSION_VAR the name of the variable can be specified which holds the
# version of the package which has been found. If this is done, this
# version will be checked against the (potentially) specified required
# version used in the find_package() call. The EXACT keyword is also
# handled. The default messages include information about the required
# version and the version which has been actually found, both if the
# version is ok or not. If the package supports components, use the
# HANDLE_COMPONENTS option to enable handling them. In this case,
# find_package_handle_standard_args() will report which components have
# been found and which are missing, and the <packagename>_FOUND variable
# will be set to FALSE if any of the required components (i.e. not the
# ones listed after OPTIONAL_COMPONENTS) are missing. Use the option
# CONFIG_MODE if your FindXXX.cmake module is a wrapper for a
# find_package(... NO_MODULE) call. In this case VERSION_VAR will be
# set to <NAME>_VERSION and the macro will automatically check whether
# the Config module was found. Via FAIL_MESSAGE a custom failure
# message can be specified, if this is not used, the default message
# will be displayed.
#
# Example for mode 1:
#
# ::
#
# find_package_handle_standard_args(LibXml2 DEFAULT_MSG
# LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
#
#
#
# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and
# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to
# TRUE. If it is not found and REQUIRED was used, it fails with
# FATAL_ERROR, independent whether QUIET was used or not. If it is
# found, success will be reported, including the content of <var1>. On
# repeated Cmake runs, the same message won't be printed again.
#
# Example for mode 2:
#
# ::
#
# find_package_handle_standard_args(LibXslt
# FOUND_VAR LibXslt_FOUND
# REQUIRED_VARS LibXslt_LIBRARIES LibXslt_INCLUDE_DIRS
# VERSION_VAR LibXslt_VERSION_STRING)
#
# In this case, LibXslt is considered to be found if the variable(s)
# listed after REQUIRED_VAR are all valid, i.e. LibXslt_LIBRARIES and
# LibXslt_INCLUDE_DIRS in this case. The result will then be stored in
# LibXslt_FOUND . Also the version of LibXslt will be checked by using
# the version contained in LibXslt_VERSION_STRING. Since no
# FAIL_MESSAGE is given, the default messages will be printed.
#
# Another example for mode 2:
#
# ::
#
# find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
# find_package_handle_standard_args(Automoc4 CONFIG_MODE)
#
# In this case, FindAutmoc4.cmake wraps a call to find_package(Automoc4
# NO_MODULE) and adds an additional search directory for automoc4. Here
# the result will be stored in AUTOMOC4_FOUND. The following
# FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper
# success/error message.
#=============================================================================
# Copyright 2007-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
# internal helper macro
macro(_FPHSA_FAILURE_MESSAGE _msg)
if (${_NAME}_FIND_REQUIRED)
message(FATAL_ERROR "${_msg}")
else ()
if (NOT ${_NAME}_FIND_QUIETLY)
message(STATUS "${_msg}")
endif ()
endif ()
endmacro()
# internal helper macro to generate the failure message when used in CONFIG_MODE:
macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
# <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
if(${_NAME}_CONFIG)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
else()
# If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
# List them all in the error message:
if(${_NAME}_CONSIDERED_CONFIGS)
set(configsText "")
list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
math(EXPR configsCount "${configsCount} - 1")
foreach(currentConfigIndex RANGE ${configsCount})
list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
set(configsText "${configsText} ${filename} (version ${version})\n")
endforeach()
if (${_NAME}_NOT_FOUND_MESSAGE)
set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
endif()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
else()
# Simple case: No Config-file was found at all:
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
endif()
endif()
endmacro()
function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
# new extended or in the "old" mode:
set(options CONFIG_MODE HANDLE_COMPONENTS)
set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR)
set(multiValueArgs REQUIRED_VARS)
set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
if(${INDEX} EQUAL -1)
set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
set(FPHSA_REQUIRED_VARS ${ARGN})
set(FPHSA_VERSION_VAR)
else()
CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
if(FPHSA_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
endif()
if(NOT FPHSA_FAIL_MESSAGE)
set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
endif()
endif()
# now that we collected all arguments, process them
if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
endif()
# In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
# when it successfully found the config-file, including version checking:
if(FPHSA_CONFIG_MODE)
list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
endif()
if(NOT FPHSA_REQUIRED_VARS)
message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
endif()
list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
string(TOUPPER ${_NAME} _NAME_UPPER)
string(TOLOWER ${_NAME} _NAME_LOWER)
if(FPHSA_FOUND_VAR)
if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$")
set(_FOUND_VAR ${FPHSA_FOUND_VAR})
else()
message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.")
endif()
else()
set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
endif()
# collect all variables which were not found, so they can be printed, so the
# user knows better what went wrong (#6375)
set(MISSING_VARS "")
set(DETAILS "")
# check if all passed variables are valid
unset(${_FOUND_VAR})
foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
if(NOT ${_CURRENT_VAR})
set(${_FOUND_VAR} FALSE)
set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
else()
set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]")
endif()
endforeach()
if(NOT "${${_FOUND_VAR}}" STREQUAL "FALSE")
set(${_FOUND_VAR} TRUE)
endif()
# component handling
unset(FOUND_COMPONENTS_MSG)
unset(MISSING_COMPONENTS_MSG)
if(FPHSA_HANDLE_COMPONENTS)
foreach(comp ${${_NAME}_FIND_COMPONENTS})
if(${_NAME}_${comp}_FOUND)
if(NOT DEFINED FOUND_COMPONENTS_MSG)
set(FOUND_COMPONENTS_MSG "found components: ")
endif()
set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
else()
if(NOT DEFINED MISSING_COMPONENTS_MSG)
set(MISSING_COMPONENTS_MSG "missing components: ")
endif()
set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
if(${_NAME}_FIND_REQUIRED_${comp})
set(${_FOUND_VAR} FALSE)
set(MISSING_VARS "${MISSING_VARS} ${comp}")
endif()
endif()
endforeach()
set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
endif()
# version handling:
set(VERSION_MSG "")
set(VERSION_OK TRUE)
set(VERSION ${${FPHSA_VERSION_VAR}})
# check with DEFINED here as the requested or found version may be "0"
if (DEFINED ${_NAME}_FIND_VERSION)
if(DEFINED ${FPHSA_VERSION_VAR})
if(${_NAME}_FIND_VERSION_EXACT) # exact version required
# count the dots in the version string
string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${VERSION}")
# add one dot because there is one dot more than there are components
string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS)
if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT)
# Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT
# is at most 4 here. Therefore a simple lookup table is used.
if (${_NAME}_FIND_VERSION_COUNT EQUAL 1)
set(_VERSION_REGEX "[^.]*")
elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2)
set(_VERSION_REGEX "[^.]*\\.[^.]*")
elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3)
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*")
else ()
set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
endif ()
string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${VERSION}")
unset(_VERSION_REGEX)
if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD)
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
endif ()
unset(_VERSION_HEAD)
else ()
if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
endif ()
endif ()
unset(_VERSION_DOTS)
else() # minimum version specified:
if ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")
set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
set(VERSION_OK FALSE)
else ()
set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
endif ()
endif()
else()
# if the package was not found, but a version was given, add that to the output:
if(${_NAME}_FIND_VERSION_EXACT)
set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
else()
set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
endif()
endif()
else ()
if(VERSION)
set(VERSION_MSG "(found version \"${VERSION}\")")
endif()
endif ()
if(VERSION_OK)
set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]")
else()
set(${_FOUND_VAR} FALSE)
endif()
# print the result:
if (${_FOUND_VAR})
FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
else ()
if(FPHSA_CONFIG_MODE)
_FPHSA_HANDLE_FAILURE_CONFIG_MODE()
else()
if(NOT VERSION_OK)
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
else()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
endif()
endif()
endif ()
set(${_FOUND_VAR} ${${_FOUND_VAR}} PARENT_SCOPE)
endfunction()

57
cmake/FindPackageMessage.cmake

@ -0,0 +1,57 @@
#.rst:
# FindPackageMessage
# ------------------
#
#
#
# FIND_PACKAGE_MESSAGE(<name> "message for user" "find result details")
#
# This macro is intended to be used in FindXXX.cmake modules files. It
# will print a message once for each unique find result. This is useful
# for telling the user where a package was found. The first argument
# specifies the name (XXX) of the package. The second argument
# specifies the message to display. The third argument lists details
# about the find result so that if they change the message will be
# displayed again. The macro also obeys the QUIET argument to the
# find_package command.
#
# Example:
#
# ::
#
# if(X11_FOUND)
# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}"
# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]")
# else()
# ...
# endif()
#=============================================================================
# Copyright 2008-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
function(FIND_PACKAGE_MESSAGE pkg msg details)
# Avoid printing a message repeatedly for the same find result.
if(NOT ${pkg}_FIND_QUIETLY)
string(REPLACE "\n" "" details "${details}")
set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg})
if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}")
# The message has not yet been printed.
message(STATUS "${msg}")
# Save the find details in the cache to avoid printing the same
# message again.
set("${DETAILS_VAR}" "${details}"
CACHE INTERNAL "Details about finding ${pkg}")
endif()
endif()
endfunction()

1
cmake/Findjson_rpc_cpp.cmake

@ -52,6 +52,7 @@ set (JSON_RPC_CPP_CLIENT_LIBRARIES ${JSON_RPC_CPP_COMMON_LIBRARY} ${JSON_RPC_CPP
# same naming convention as in qt (appending debug library with d) # same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug" # boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
find_library( find_library(
JSON_RPC_CPP_COMMON_LIBRARY_DEBUG JSON_RPC_CPP_COMMON_LIBRARY_DEBUG
NAMES jsonrpccpp-commond NAMES jsonrpccpp-commond

18
cmake/scripts/copydlls.cmake

@ -0,0 +1,18 @@
# this module expects
# DLLS
# CONF
# DESTINATION
# example usage:
# cmake -DDLL_DEBUG=xd.dll -DDLL_RELEASE=x.dll -DCONFIGURATION=Release -DDESTINATION=dest -P scripts/copydlls.cmake
# this script is created cause we do not know configuration in multiconfiguration generators at cmake configure phase ;)
if ("${CONF}" STREQUAL "Release")
set(DLL ${DLL_RELEASE})
else () # Debug
set(DLL ${DLL_DEBUG})
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${DLL}" "${DESTINATION}")

5
eth/CMakeLists.txt

@ -23,13 +23,16 @@ endif()
if (JSONRPC) if (JSONRPC)
target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} web3jsonrpc)
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES})
eth_copy_dlls(${EXECUTABLE} CURL_DLLS)
endif() endif()
target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethash) target_link_libraries(${EXECUTABLE} ethash)
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy ${MHD_DLL_RELEASE} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif() endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin ) install( TARGETS ${EXECUTABLE} DESTINATION bin )

38
eth/Farm.h

@ -0,0 +1,38 @@
/**
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!
*/
#ifndef JSONRPC_CPP_STUB_FARM_H_
#define JSONRPC_CPP_STUB_FARM_H_
#include <jsonrpccpp/client.h>
class Farm : public jsonrpc::Client
{
public:
Farm(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
Json::Value eth_getWork() throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p = Json::nullValue;
Json::Value result = this->CallMethod("eth_getWork",p);
if (result.isArray())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
bool eth_submitWork(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("eth_submitWork",p);
if (result.isBool())
return result.asBool();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
};
#endif //JSONRPC_CPP_STUB_FARM_H_

28
eth/PhoneHome.h

@ -0,0 +1,28 @@
/**
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!
*/
#ifndef JSONRPC_CPP_STUB_PHONEHOME_H_
#define JSONRPC_CPP_STUB_PHONEHOME_H_
#include <jsonrpccpp/client.h>
class PhoneHome : public jsonrpc::Client
{
public:
PhoneHome(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
int report_benchmark(const std::string& param1, int param2) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("report_benchmark",p);
if (result.isInt())
return result.asInt();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
};
#endif //JSONRPC_CPP_STUB_PHONEHOME_H_

4
eth/farm.json

@ -0,0 +1,4 @@
[
{ "name": "eth_getWork", "params": [], "order": [], "returns": []},
{ "name": "eth_submitWork", "params": ["", ""], "order": [], "returns": true}
]

702
eth/main.cpp

@ -32,19 +32,26 @@
#include <libdevcrypto/FileSystem.h> #include <libdevcrypto/FileSystem.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libdevcore/StructuredLogger.h> #include <libdevcore/StructuredLogger.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/EthashAux.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include <libevm/VMFactory.h> #include <libevm/VMFactory.h>
#include <libethereum/All.h> #include <libethereum/All.h>
#include <libwebthree/WebThree.h> #include <libwebthree/WebThree.h>
#if ETH_READLINE #if ETH_READLINE || !ETH_TRUE
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#endif #endif
#if ETH_JSONRPC #if ETH_JSONRPC || !ETH_TRUE
#include <libweb3jsonrpc/WebThreeStubServer.h> #include <libweb3jsonrpc/WebThreeStubServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h> #include <jsonrpccpp/server/connectors/httpserver.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#endif #endif
#include "BuildInfo.h" #include "BuildInfo.h"
#if ETH_JSONRPC || !ETH_TRUE
#include "PhoneHome.h"
#include "Farm.h"
#endif
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::p2p; using namespace dev::p2p;
@ -87,7 +94,7 @@ void interactiveHelp()
<< " send Execute a given transaction with current secret." << endl << " send Execute a given transaction with current secret." << endl
<< " contract Create a new contract with current secret." << endl << " contract Create a new contract with current secret." << endl
<< " peers List the peers that are connected" << endl << " peers List the peers that are connected" << endl
#if ETH_FATDB #if ETH_FATDB || !ETH_TRUE
<< " listaccounts List the accounts on the network." << endl << " listaccounts List the accounts on the network." << endl
<< " listcontracts List the contracts on the network." << endl << " listcontracts List the contracts on the network." << endl
#endif #endif
@ -105,39 +112,70 @@ void help()
{ {
cout cout
<< "Usage eth [OPTIONS]" << endl << "Usage eth [OPTIONS]" << endl
<< "Options:" << endl << "Options:" << endl << endl
<< " -a,--address <addr> Set the coinbase (mining payout) address to addr (default: auto)." << endl << "Client mode (default):" << endl
<< " -b,--bootstrap Connect to the default Ethereum peerserver." << endl << " -o,--mode <full/peer> Start a full node or a peer node (default: full)." << endl
<< " -B,--block-fees <n> Set the block fee profit in the reference unit e.g. ¢ (Default: 15)." << endl
<< " -c,--client-name <name> Add a name to your client's version string (default: blank)." << endl
<< " -d,--db-path <path> Load database from path (default: ~/.ethereum " << endl
<< " <APPDATA>/Etherum or Library/Application Support/Ethereum)." << endl
<< " -e,--ether-price <n> Set the ether price in the reference unit e.g. ¢ (Default: 30.679)." << endl
<< " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl
<< " -h,--help Show this help message and exit." << endl
<< " -i,--interactive Enter interactive mode (default: non-interactive)." << endl << " -i,--interactive Enter interactive mode (default: non-interactive)." << endl
#if ETH_JSONRPC #if ETH_JSONRPC || !ETH_TRUE
<< " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl << " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl
<< " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl << " --json-rpc-port <n> Specify JSON-RPC server port (implies '-j', default: " << SensibleHttpPort << ")." << endl
#endif #endif
<< " -K,--kill-blockchain First kill the blockchain." << endl << " -K,--kill First kill the blockchain." << endl
<< " --listen-ip <port> Listen on the given port for incoming connections (default: 30303)." << endl << " -R,--rebuild First rebuild the blockchain from the existing database." << endl
<< " -l,--listen <ip> Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl
<< " -u,--public-ip <ip> Force public ip to given (default: auto)." << endl
<< " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (Default: off)" << endl
<< " -n,--upnp <on/off> Use upnp for NAT (default: on)." << endl
<< " -o,--mode <full/peer> Start a full node or a peer node (Default: full)." << endl
<< " -p,--port <port> Connect to remote port (default: 30303)." << endl
<< " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl
<< " -r,--remote <host> Connect to remote host (default: none)." << endl
<< " -s,--secret <secretkeyhex> Set the secret key for use with send command (default: auto)." << endl << " -s,--secret <secretkeyhex> Set the secret key for use with send command (default: auto)." << endl
<< " -t,--miners <number> Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl << " -S,--session-secret <secretkeyhex> Set the secret key for use with send command, for this session only." << endl
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl << "Client transacting:" << endl
<< " -x,--peers <number> Attempt to connect to given number of peers (Default: 5)." << endl << " -B,--block-fees <n> Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl
<< " -V,--version Show the version and exit." << endl << " -e,--ether-price <n> Set the ether price in the reference unit e.g. ¢ (default: 30.679)." << endl
#if ETH_EVMJIT << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl
<< " --jit Use EVM JIT (default: off)." << endl << "Client mining:" << endl
<< " -a,--address <addr> Set the coinbase (mining payout) address to addr (default: auto)." << endl
<< " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (default: off)" << endl
<< " -f,--force-mining Mine even when there are no transactions to mine (default: off)" << endl
<< " -C,--cpu When mining, use the CPU." << endl
<< " -G,--opencl When mining use the GPU via OpenCL." << endl
<< " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl
<< "Client networking:" << endl
<< " --client-name <name> Add a name to your client's version string (default: blank)." << endl
<< " -b,--bootstrap Connect to the default Ethereum peerserver." << endl
<< " -x,--peers <number> Attempt to connect to given number of peers (default: 5)." << endl
<< " --public-ip <ip> Force public ip to given (default: auto)." << endl
<< " --listen-ip <ip>(:<port>) Listen on the given IP for incoming connections (default: 0.0.0.0)." << 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
<< " --port <port> Connect to remote port (default: 30303)." << endl
<< " --upnp <on/off> Use UPnP for NAT (default: on)." << endl
#if ETH_JSONRPC || !ETH_TRUE
<< "Work farming mode:" << endl
<< " -F,--farm <url> Put into mining farm mode with the work server at URL. Use with -G/--opencl." << endl
<< " --farm-recheck <n> Leave n ms between checks for changed work (default: 500)." << endl
#endif
<< "Ethash verify mode:" << endl
<< " -w,--check-pow <headerHash> <seedHash> <difficulty> <nonce> Check PoW credentials for validity." << endl
<< "Benchmarking mode:" << endl
<< " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl
<< " --benchmark-warmup <seconds> Set the duration of warmup for the benchmark tests (default: 3)." << endl
<< " --benchmark-trial <seconds> Set the duration for each trial for the benchmark tests (default: 3)." << endl
<< " --benchmark-trials <n> Set the duration of warmup for the benchmark tests (default: 5)." << endl
#if ETH_JSONRPC || !ETH_TRUE
<< " --phone-home <on/off> When benchmarking, publish results (default: on)" << endl
#endif #endif
<< "DAG creation mode:" << endl
<< " -D,--create-dag <this/next/number> Create the DAG in preparation for mining on given block and exit." << endl
<< "Import/export modes:" << endl
<< " -I,--import <file> Import file as a concatenated series of blocks and exit." << endl
<< " -E,--export <file> Export file as a concatenated series of blocks and exit." << endl
<< " --from <n> Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --to <n> Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --only <n> Equivalent to --export-from n --export-to n." << endl
<< "General Options:" << endl
<< " -d,--db-path <path> Load database from path (default: " << getDataDir() << ")" << endl
#if ETH_EVMJIT || !ETH_TRUE
<< " -J,--jit Enable EVM JIT (default: off)." << endl
#endif
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl
<< " -V,--version Show the version and exit." << endl
<< " -h,--help Show this help message and exit." << endl
; ;
exit(0); exit(0);
} }
@ -168,7 +206,7 @@ void version()
} }
Address c_config = Address("ccdeac59d35627b7de09332e819d5159e7bb7250"); Address c_config = Address("ccdeac59d35627b7de09332e819d5159e7bb7250");
string pretty(h160 _a, dev::eth::State _st) string pretty(h160 _a, dev::eth::State const& _st)
{ {
string ns; string ns;
h256 n; h256 n;
@ -197,55 +235,232 @@ enum class NodeMode
Full Full
}; };
void doInitDAG(unsigned _n)
{
BlockInfo bi;
bi.number = _n;
cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl;
Ethash::prep(bi);
exit(0);
}
enum class OperationMode
{
Node,
Import,
Export,
DAGInit,
Benchmark,
Farm
};
enum class Format
{
Binary,
Hex,
Human
};
enum class MinerType
{
CPU,
GPU
};
void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5)
{
BlockInfo genesis = CanonBlockChain::genesis();
genesis.difficulty = 1 << 18;
cdebug << genesis.boundary();
GenericFarm<Ethash> f;
f.onSolutionFound([&](ProofOfWork::Solution) { return false; });
string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : "";
cout << "Benchmarking on platform: " << platformInfo << endl;
cout << "Preparing DAG..." << endl;
Ethash::prep(genesis);
genesis.difficulty = u256(1) << 63;
genesis.noteDirty();
f.setWork(genesis);
if (_m == MinerType::CPU)
f.startCPU();
else if (_m == MinerType::GPU)
f.startGPU();
map<uint64_t, MiningProgress> results;
uint64_t mean = 0;
uint64_t innerMean = 0;
for (unsigned i = 0; i <= _trials; ++i)
{
if (!i)
cout << "Warming up..." << endl;
else
cout << "Trial " << i << "... " << flush;
this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration));
auto mp = f.miningProgress();
f.resetMiningProgress();
if (!i)
continue;
auto rate = mp.rate();
cout << rate << endl;
results[rate] = mp;
mean += rate;
if (i > 1 && i < 5)
innerMean += rate;
}
f.stop();
cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl;
cout << "inner mean: " << (innerMean / (_trials - 2)) << " H/s" << endl;
(void)_phoneHome;
#if ETH_JSONRPC || !ETH_TRUE
if (_phoneHome)
{
cout << "Phoning home to find world ranking..." << endl;
jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark");
PhoneHome rpc(client);
try
{
unsigned ranking = rpc.report_benchmark(platformInfo, innerMean);
cout << "Ranked: " << ranking << " of all benchmarks." << endl;
}
catch (...)
{
cout << "Error phoning home. ET is sad." << endl;
}
}
#endif
exit(0);
}
void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
{
(void)_m;
(void)_remote;
(void)_recheckPeriod;
#if ETH_JSONRPC || !ETH_TRUE
jsonrpc::HttpClient client(_remote);
Farm rpc(client);
GenericFarm<Ethash> f;
if (_m == MinerType::CPU)
f.startCPU();
else if (_m == MinerType::GPU)
f.startGPU();
ProofOfWork::WorkPackage current;
while (true)
{
bool completed = false;
ProofOfWork::Solution solution;
f.onSolutionFound([&](ProofOfWork::Solution sol)
{
solution = sol;
return completed = true;
});
for (unsigned i = 0; !completed; ++i)
{
Json::Value v = rpc.eth_getWork();
h256 hh(v[0].asString());
if (hh != current.headerHash)
{
current.headerHash = hh;
current.seedHash = h256(v[1].asString());
current.boundary = h256(v[2].asString());
f.setWork(current);
}
this_thread::sleep_for(chrono::milliseconds(_recheckPeriod));
}
rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(solution.mixHash));
}
#endif
exit(0);
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
// Init defaults
Defaults::get();
/// Operating mode.
OperationMode mode = OperationMode::Node;
string dbPath;
/// Mining options
MinerType minerType = MinerType::CPU;
unsigned openclDevice = 0;
/// File name for import/export.
string filename;
/// Hashes/numbers for export range.
string exportFrom = "1";
string exportTo = "latest";
Format exportFormat = Format::Binary;
/// DAG initialisation param.
unsigned initDAG = 0;
/// General params for Node operation
NodeMode nodeMode = NodeMode::Full;
bool interactive = false;
#if ETH_JSONRPC
int jsonrpc = -1;
#endif
bool upnp = true;
WithExisting killChain = WithExisting::Trust;
bool jit = false;
/// Networking params.
string clientName;
string listenIP; string listenIP;
unsigned short listenPort = 30303; unsigned short listenPort = 30303;
string publicIP; string publicIP;
string remoteHost; string remoteHost;
unsigned short remotePort = 30303; unsigned short remotePort = 30303;
string dbPath;
unsigned mining = ~(unsigned)0;
NodeMode mode = NodeMode::Full;
unsigned peers = 5; unsigned peers = 5;
int miners = -1;
bool interactive = false;
#if ETH_JSONRPC
int jsonrpc = -1;
#endif
bool bootstrap = false; bool bootstrap = false;
bool upnp = true;
/// Mining params
unsigned mining = ~(unsigned)0;
bool forceMining = false; bool forceMining = false;
bool killChain = false; KeyPair sigKey = KeyPair::create();
bool jit = false; Secret sessionSecret;
Address coinbase = sigKey.address();
/// Structured logging params
bool structuredLogging = false; bool structuredLogging = false;
string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S"; string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S";
string clientName;
/// Transaction params
TransactionPriority priority = TransactionPriority::Medium; TransactionPriority priority = TransactionPriority::Medium;
double etherPrice = 30.679; double etherPrice = 30.679;
double blockFees = 15.0; double blockFees = 15.0;
// Init defaults /// Benchmarking params
Defaults::get(); bool phoneHome = true;
unsigned benchmarkWarmup = 3;
unsigned benchmarkTrial = 3;
unsigned benchmarkTrials = 5;
// Our address. /// Farm params
KeyPair us = KeyPair::create(); string farmURL = "http://127.0.0.1:8080";
Address coinbase = us.address(); unsigned farmRecheckPeriod = 500;
string configFile = getDataDir() + "/config.rlp"; string configFile = getDataDir() + "/config.rlp";
bytes b = contents(configFile); bytes b = contents(configFile);
if (b.size()) if (b.size())
{ {
RLP config(b); RLP config(b);
us = KeyPair(config[0].toHash<Secret>()); sigKey = KeyPair(config[0].toHash<Secret>());
coinbase = config[1].toHash<Address>(); coinbase = config[1].toHash<Address>();
} }
else
{
RLPStream config(2);
config << us.secret() << coinbase;
writeFile(configFile, config.out());
}
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
{ {
@ -253,54 +468,230 @@ int main(int argc, char** argv)
if (arg == "--listen-ip" && i + 1 < argc) if (arg == "--listen-ip" && i + 1 < argc)
listenIP = argv[++i]; listenIP = argv[++i];
else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc) else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc)
{
if (arg == "-l")
cerr << "-l is DEPRECATED. It will be removed for the Frontier. Use --listen-port instead." << endl;
listenPort = (short)atoi(argv[++i]); listenPort = (short)atoi(argv[++i]);
}
else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc) else if ((arg == "-u" || arg == "--public-ip" || arg == "--public") && i + 1 < argc)
{
if (arg == "-u")
cerr << "-u is DEPRECATED. It will be removed for the Frontier. Use --public-ip instead." << endl;
publicIP = argv[++i]; publicIP = argv[++i];
}
else if ((arg == "-r" || arg == "--remote") && i + 1 < argc) else if ((arg == "-r" || arg == "--remote") && i + 1 < argc)
remoteHost = argv[++i]; remoteHost = argv[++i];
else if ((arg == "-p" || arg == "--port") && i + 1 < argc) else if ((arg == "-p" || arg == "--port") && i + 1 < argc)
{
if (arg == "-p")
cerr << "-p is DEPRECATED. It will be removed for the Frontier. Use --port instead (or place directly as host:port)." << endl;
remotePort = (short)atoi(argv[++i]); remotePort = (short)atoi(argv[++i]);
else if ((arg == "-n" || arg == "--upnp") && i + 1 < argc) }
else if ((arg == "-I" || arg == "--import") && i + 1 < argc)
{
mode = OperationMode::Import;
filename = argv[++i];
}
else if ((arg == "-E" || arg == "--export") && i + 1 < argc)
{
mode = OperationMode::Export;
filename = argv[++i];
}
else if ((arg == "-F" || arg == "--farm") && i + 1 < argc)
{
mode = OperationMode::Farm;
farmURL = argv[++i];
}
else if (arg == "--farm-recheck" && i + 1 < argc)
try {
farmRecheckPeriod = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--opencl-device" && i + 1 < argc)
try {
openclDevice = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--phone-home" && i + 1 < argc)
{
string m = argv[++i];
if (isTrue(m))
phoneHome = true;
else if (isFalse(m))
phoneHome = false;
else
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if (arg == "--format" && i + 1 < argc)
{ {
string m = argv[++i]; string m = argv[++i];
if (m == "binary")
exportFormat = Format::Binary;
else if (m == "hex")
exportFormat = Format::Hex;
else if (m == "human")
exportFormat = Format::Human;
else
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if (arg == "--to" && i + 1 < argc)
exportTo = argv[++i];
else if (arg == "--from" && i + 1 < argc)
exportFrom = argv[++i];
else if (arg == "--only" && i + 1 < argc)
exportTo = exportFrom = argv[++i];
else if ((arg == "-n" || arg == "-u" || arg == "--upnp") && i + 1 < argc)
{
if (arg == "-n")
cerr << "-n is DEPRECATED. It will be removed for the Frontier. Use --upnp instead." << endl;
string m = argv[++i];
if (isTrue(m)) if (isTrue(m))
upnp = true; upnp = true;
else if (isFalse(m)) else if (isFalse(m))
upnp = false; upnp = false;
else else
{ {
cerr << "Invalid -n/--upnp option: " << m << endl; cerr << "Bad " << arg << " option: " << m << endl;
return -1; return -1;
} }
} }
else if (arg == "-K" || arg == "--kill-blockchain") else if (arg == "--benchmark-warmup" && i + 1 < argc)
killChain = true; try {
benchmarkWarmup = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--benchmark-trial" && i + 1 < argc)
try {
benchmarkTrial = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--benchmark-trials" && i + 1 < argc)
try {
benchmarkTrials = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "-K" || arg == "--kill-blockchain" || arg == "--kill")
killChain = WithExisting::Kill;
else if (arg == "-B" || arg == "--rebuild")
killChain = WithExisting::Verify;
else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc) else if ((arg == "-c" || arg == "--client-name") && i + 1 < argc)
{
if (arg == "-c")
cerr << "-c is DEPRECATED. It will be removed for the Frontier. Use --client-name instead." << endl;
clientName = argv[++i]; clientName = argv[++i];
}
else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc) else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc)
try try {
{
coinbase = h160(fromHex(argv[++i], WhenError::Throw)); coinbase = h160(fromHex(argv[++i], WhenError::Throw));
} }
catch (BadHexCharacter& _e) catch (BadHexCharacter&)
{ {
cwarn << "invalid hex character, coinbase rejected"; cerr << "Bad hex in " << arg << " option: " << argv[i] << endl;
cwarn << boost::diagnostic_information(_e); return -1;
break;
} }
catch (...) catch (...)
{ {
cwarn << "coinbase rejected"; cerr << "Bad " << arg << " option: " << argv[i] << endl;
break; return -1;
} }
else if (arg == "-C" || arg == "--cpu")
minerType = MinerType::CPU;
else if (arg == "-G" || arg == "--opencl")
minerType = MinerType::GPU;
else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) else if ((arg == "-s" || arg == "--secret") && i + 1 < argc)
us = KeyPair(h256(fromHex(argv[++i]))); sigKey = KeyPair(h256(fromHex(argv[++i])));
else if ((arg == "-S" || arg == "--session-secret") && i + 1 < argc)
sessionSecret = h256(fromHex(argv[++i]));
else if (arg == "--structured-logging-format" && i + 1 < argc) else if (arg == "--structured-logging-format" && i + 1 < argc)
structuredLoggingFormat = string(argv[++i]); structuredLoggingFormat = string(argv[++i]);
else if (arg == "--structured-logging") else if (arg == "--structured-logging")
structuredLogging = true; structuredLogging = true;
else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc)
dbPath = argv[++i]; dbPath = argv[++i];
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc)
{
string m = boost::to_lower_copy(string(argv[++i]));
mode = OperationMode::DAGInit;
if (m == "next")
initDAG = PendingBlock;
else if (m == "this")
initDAG = LatestBlock;
else
try
{
initDAG = stol(m);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc)
{
string m;
try
{
BlockInfo bi;
m = boost::to_lower_copy(string(argv[++i]));
h256 powHash(m);
m = boost::to_lower_copy(string(argv[++i]));
h256 seedHash;
if (m.size() == 64 || m.size() == 66)
seedHash = h256(m);
else
seedHash = EthashAux::seedHash(stol(m));
m = boost::to_lower_copy(string(argv[++i]));
bi.difficulty = u256(m);
auto boundary = bi.boundary();
m = boost::to_lower_copy(string(argv[++i]));
bi.nonce = h64(m);
auto r = EthashAux::eval(seedHash, powHash, bi.nonce);
bool valid = r.value < boundary;
cout << (valid ? "VALID :-)" : "INVALID :-(") << endl;
cout << r.value << (valid ? " < " : " >= ") << boundary << endl;
cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl;
cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl;
cout << " with seed as " << seedHash << endl;
if (valid)
cout << "(mixHash = " << r.mixHash << ")" << endl;
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(seedHash)->data()) << endl;
exit(0);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
return -1;
}
}
else if (arg == "-M" || arg == "--benchmark")
mode = OperationMode::Benchmark;
else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc) else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc)
{ {
try try
@ -309,7 +700,7 @@ int main(int argc, char** argv)
} }
catch (...) catch (...)
{ {
cerr << "Bad " << arg << " option: " << argv[++i] << endl; cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1; return -1;
} }
} }
@ -321,7 +712,7 @@ int main(int argc, char** argv)
} }
catch (...) catch (...)
{ {
cerr << "Bad " << arg << " option: " << argv[++i] << endl; cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1; return -1;
} }
} }
@ -379,30 +770,25 @@ int main(int argc, char** argv)
g_logVerbosity = atoi(argv[++i]); g_logVerbosity = atoi(argv[++i]);
else if ((arg == "-x" || arg == "--peers") && i + 1 < argc) else if ((arg == "-x" || arg == "--peers") && i + 1 < argc)
peers = atoi(argv[++i]); peers = atoi(argv[++i]);
else if ((arg == "-t" || arg == "--miners") && i + 1 < argc)
miners = atoi(argv[++i]);
else if ((arg == "-o" || arg == "--mode") && i + 1 < argc) else if ((arg == "-o" || arg == "--mode") && i + 1 < argc)
{ {
string m = argv[++i]; string m = argv[++i];
if (m == "full") if (m == "full")
mode = NodeMode::Full; nodeMode = NodeMode::Full;
else if (m == "peer") else if (m == "peer")
mode = NodeMode::PeerServer; nodeMode = NodeMode::PeerServer;
else else
{ {
cerr << "Unknown mode: " << m << endl; cerr << "Unknown mode: " << m << endl;
return -1; return -1;
} }
} }
else if (arg == "--jit")
{
#if ETH_EVMJIT #if ETH_EVMJIT
else if (arg == "-J" || arg == "--jit")
{
jit = true; jit = true;
#else
cerr << "EVM JIT not enabled" << endl;
return -1;
#endif
} }
#endif
else if (arg == "-h" || arg == "--help") else if (arg == "-h" || arg == "--help")
help(); help();
else if (arg == "-V" || arg == "--version") else if (arg == "-V" || arg == "--version")
@ -414,11 +800,31 @@ int main(int argc, char** argv)
} }
} }
{
RLPStream config(2);
config << sigKey.secret() << coinbase;
writeFile(configFile, config.out());
}
if (sessionSecret)
sigKey = KeyPair(sessionSecret);
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice);
// Two codepaths is necessary since named block require database, but numbered
// blocks are superuseful to have when database is already open in another process.
if (mode == OperationMode::DAGInit && !(initDAG == LatestBlock || initDAG == PendingBlock))
doInitDAG(initDAG);
if (mode == OperationMode::Benchmark)
doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials);
if (mode == OperationMode::Farm)
doFarm(minerType, farmURL, farmRecheckPeriod);
if (!clientName.empty()) if (!clientName.empty())
clientName += "/"; clientName += "/";
cout << credits();
StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat); StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat);
VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp); auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
@ -428,23 +834,103 @@ int main(int argc, char** argv)
clientImplString, clientImplString,
dbPath, dbPath,
killChain, killChain,
mode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(), nodeMode == NodeMode::Full ? set<string>{"eth", "shh"} : set<string>(),
netPrefs, netPrefs,
&nodesState, &nodesState);
miners
); if (mode == OperationMode::DAGInit)
doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0));
auto toNumber = [&](string const& s) -> unsigned {
if (s == "latest")
return web3.ethereum()->number();
if (s.size() == 64 || (s.size() == 66 && s.substr(0, 2) == "0x"))
return web3.ethereum()->blockChain().number(h256(s));
try {
return stol(s);
}
catch (...)
{
cerr << "Bad block number/hash option: " << s << endl;
exit(-1);
}
};
if (mode == OperationMode::Export)
{
ofstream fout(filename, std::ofstream::binary);
ostream& out = (filename.empty() || filename == "--") ? cout : fout;
unsigned last = toNumber(exportTo);
for (unsigned i = toNumber(exportFrom); i <= last; ++i)
{
bytes block = web3.ethereum()->blockChain().block(web3.ethereum()->blockChain().numberHash(i));
switch (exportFormat)
{
case Format::Binary: out.write((char const*)block.data(), block.size()); break;
case Format::Hex: out << toHex(block) << endl; break;
case Format::Human: out << RLP(block) << endl; break;
default:;
}
}
return 0;
}
if (mode == OperationMode::Import)
{
ifstream fin(filename, std::ifstream::binary);
istream& in = (filename.empty() || filename == "--") ? cin : fin;
unsigned alreadyHave = 0;
unsigned good = 0;
unsigned futureTime = 0;
unsigned unknownParent = 0;
unsigned bad = 0;
while (in.peek() != -1)
{
bytes block(8);
in.read((char*)block.data(), 8);
block.resize(RLP(block, RLP::LaisezFaire).actualSize());
in.read((char*)block.data() + 8, block.size() - 8);
try
{
web3.ethereum()->injectBlock(block);
good++;
}
catch (AlreadyHaveBlock const&)
{
alreadyHave++;
}
catch (UnknownParent const&)
{
unknownParent++;
}
catch (FutureTime const&)
{
futureTime++;
}
catch (...)
{
bad++;
}
}
cout << (good + bad + futureTime + unknownParent + alreadyHave) << " total: " << good << " ok, " << alreadyHave << " got, " << futureTime << " future, " << unknownParent << " unknown parent, " << bad << " malformed." << endl;
return 0;
}
cout << credits();
web3.setIdealPeerCount(peers); web3.setIdealPeerCount(peers);
std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); std::shared_ptr<eth::BasicGasPricer> gasPricer = make_shared<eth::BasicGasPricer>(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000));
eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; eth::Client* c = nodeMode == NodeMode::Full ? web3.ethereum() : nullptr;
StructuredLogger::starting(clientImplString, dev::Version); StructuredLogger::starting(clientImplString, dev::Version);
if (c) if (c)
{ {
c->setGasPricer(gasPricer); c->setGasPricer(gasPricer);
c->setForceMining(forceMining); c->setForceMining(forceMining);
c->setTurboMining(minerType == MinerType::GPU);
c->setAddress(coinbase); c->setAddress(coinbase);
} }
cout << "Transaction Signer: " << us.address() << endl; cout << "Transaction Signer: " << sigKey.address() << endl;
cout << "Mining Benefactor: " << coinbase << endl; cout << "Mining Benefactor: " << coinbase << endl;
web3.startNetwork(); web3.startNetwork();
@ -459,8 +945,7 @@ int main(int argc, char** argv)
if (jsonrpc > -1) if (jsonrpc > -1)
{ {
jsonrpcConnector = unique_ptr<jsonrpc::AbstractServerConnector>(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); jsonrpcConnector = unique_ptr<jsonrpc::AbstractServerConnector>(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads));
jsonrpcServer = shared_ptr<WebThreeStubServer>(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector<KeyPair>({us}))); jsonrpcServer = shared_ptr<WebThreeStubServer>(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector<KeyPair>({sigKey})));
jsonrpcServer->setIdentities({us});
jsonrpcServer->StartListening(); jsonrpcServer->StartListening();
} }
#endif #endif
@ -508,10 +993,9 @@ int main(int argc, char** argv)
} }
else if (cmd == "connect") else if (cmd == "connect")
{ {
string addr; string addrPort;
unsigned port; iss >> addrPort;
iss >> addr >> port; web3.addNode(p2p::NodeId(), addrPort);
web3.addNode(p2p::NodeId(), addr + ":" + toString(port ? port : p2p::c_defaultIPPort));
} }
else if (cmd == "netstop") else if (cmd == "netstop")
{ {
@ -585,8 +1069,7 @@ int main(int argc, char** argv)
if (jsonrpc < 0) if (jsonrpc < 0)
jsonrpc = SensibleHttpPort; jsonrpc = SensibleHttpPort;
jsonrpcConnector = unique_ptr<jsonrpc::AbstractServerConnector>(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); jsonrpcConnector = unique_ptr<jsonrpc::AbstractServerConnector>(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads));
jsonrpcServer = shared_ptr<WebThreeStubServer>(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector<KeyPair>({us}))); jsonrpcServer = shared_ptr<WebThreeStubServer>(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector<KeyPair>({sigKey})));
jsonrpcServer->setIdentities({us});
jsonrpcServer->StartListening(); jsonrpcServer->StartListening();
} }
else if (cmd == "jsonstop") else if (cmd == "jsonstop")
@ -598,12 +1081,11 @@ int main(int argc, char** argv)
#endif #endif
else if (cmd == "address") else if (cmd == "address")
{ {
cout << "Current address:" << endl cout << "Current address:" << endl << sigKey.address() << endl;
<< toHex(us.address().asArray()) << endl;
} }
else if (cmd == "secret") else if (cmd == "secret")
{ {
cout << "Secret Key: " << toHex(us.secret().asArray()) << endl; cout << "Secret Key: " << sigKey.secret() << endl;
} }
else if (c && cmd == "block") else if (c && cmd == "block")
{ {
@ -618,7 +1100,7 @@ int main(int argc, char** argv)
} }
else if (c && cmd == "balance") else if (c && cmd == "balance")
{ {
cout << "Current balance: " << formatBalance( c->balanceAt(us.address())) << " = " <<c->balanceAt(us.address()) << " wei" << endl; cout << "Current balance: " << formatBalance( c->balanceAt(sigKey.address())) << " = " <<c->balanceAt(sigKey.address()) << " wei" << endl;
} }
else if (c && cmd == "transact") else if (c && cmd == "transact")
{ {
@ -651,7 +1133,7 @@ int main(int argc, char** argv)
cnote << ssbd.str(); cnote << ssbd.str();
int ssize = sechex.length(); int ssize = sechex.length();
int size = hexAddr.length(); int size = hexAddr.length();
u256 minGas = (u256)Client::txGas(data, 0); u256 minGas = (u256)Transaction::gasRequired(data, 0);
if (size < 40) if (size < 40)
{ {
if (size > 0) if (size > 0)
@ -730,11 +1212,11 @@ int main(int argc, char** argv)
auto h = bc.currentHash(); auto h = bc.currentHash();
auto blockData = bc.block(h); auto blockData = bc.block(h);
BlockInfo info(blockData); BlockInfo info(blockData);
u256 minGas = (u256)Client::txGas(bytes(), 0); u256 minGas = (u256)Transaction::gasRequired(bytes(), 0);
try try
{ {
Address dest = h160(fromHex(hexAddr, WhenError::Throw)); Address dest = h160(fromHex(hexAddr, WhenError::Throw));
c->submitTransaction(us.secret(), amount, dest, bytes(), minGas); c->submitTransaction(sigKey.secret(), amount, dest, bytes(), minGas);
} }
catch (BadHexCharacter& _e) catch (BadHexCharacter& _e)
{ {
@ -795,7 +1277,7 @@ int main(int argc, char** argv)
cnote << "Init:"; cnote << "Init:";
cnote << ssc.str(); cnote << ssc.str();
} }
u256 minGas = (u256)Client::txGas(init, 0); u256 minGas = (u256)Transaction::gasRequired(init, 0);
if (!init.size()) if (!init.size())
cwarn << "Contract creation aborted, no init code."; cwarn << "Contract creation aborted, no init code.";
else if (endowment < 0) else if (endowment < 0)
@ -803,7 +1285,7 @@ int main(int argc, char** argv)
else if (gas < minGas) else if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas; cwarn << "Minimum gas amount is" << minGas;
else else
c->submitTransaction(us.secret(), endowment, init, gas, gasPrice); c->submitTransaction(sigKey.secret(), endowment, init, gas, gasPrice);
} }
else else
cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX";
@ -920,7 +1402,7 @@ int main(int argc, char** argv)
{ {
string hexSec; string hexSec;
iss >> hexSec; iss >> hexSec;
us = KeyPair(h256(fromHex(hexSec))); sigKey = KeyPair(h256(fromHex(hexSec)));
} }
else else
cwarn << "Require parameter: setSecret HEXSECRETKEY"; cwarn << "Require parameter: setSecret HEXSECRETKEY";
@ -960,7 +1442,7 @@ int main(int argc, char** argv)
string path; string path;
iss >> path; iss >> path;
RLPStream config(2); RLPStream config(2);
config << us.secret() << coinbase; config << sigKey.secret() << coinbase;
writeFile(path, config.out()); writeFile(path, config.out());
} }
else else
@ -976,7 +1458,7 @@ int main(int argc, char** argv)
if (b.size()) if (b.size())
{ {
RLP config(b); RLP config(b);
us = KeyPair(config[0].toHash<Secret>()); sigKey = KeyPair(config[0].toHash<Secret>());
coinbase = config[1].toHash<Address>(); coinbase = config[1].toHash<Address>();
} }
else else

3
eth/phonehome.json

@ -0,0 +1,3 @@
[
{ "name": "report_benchmark", "params": [ "", 0 ], "order": [], "returns": 0 }
]

2
ethrpctest/CMakeLists.txt

@ -28,7 +28,7 @@ target_link_libraries(${EXECUTABLE} testutils)
target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} web3jsonrpc)
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy ${MHD_DLL_RELEASE} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif() endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin ) install( TARGETS ${EXECUTABLE} DESTINATION bin )

1
evmjit/libevmjit/BasicBlock.cpp

@ -49,6 +49,7 @@ void BasicBlock::LocalStack::push(llvm::Value* _value)
assert(_value->getType() == Type::Word); assert(_value->getType() == Type::Word);
m_bblock.m_currentStack.push_back(_value); m_bblock.m_currentStack.push_back(_value);
m_bblock.m_tosOffset += 1; m_bblock.m_tosOffset += 1;
m_maxSize = std::max(m_maxSize, m_bblock.m_currentStack.size());
} }
llvm::Value* BasicBlock::LocalStack::pop() llvm::Value* BasicBlock::LocalStack::pop()

4
evmjit/libevmjit/BasicBlock.h

@ -33,6 +33,9 @@ public:
/// @param _index Index of value to be swaped. Must be > 0. /// @param _index Index of value to be swaped. Must be > 0.
void swap(size_t _index); void swap(size_t _index);
size_t getMaxSize() const { return m_maxSize; }
int getDiff() const { return m_bblock.m_tosOffset; }
private: private:
LocalStack(BasicBlock& _owner); LocalStack(BasicBlock& _owner);
LocalStack(LocalStack const&) = delete; LocalStack(LocalStack const&) = delete;
@ -49,6 +52,7 @@ public:
private: private:
BasicBlock& m_bblock; BasicBlock& m_bblock;
size_t m_maxSize = 0; ///< Max size reached by the stack.
}; };
explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest);

31
evmjit/libevmjit/Cache.cpp

@ -4,6 +4,7 @@
#include <llvm/IR/Module.h> #include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h> #include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Instructions.h> #include <llvm/IR/Instructions.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/Support/Path.h> #include <llvm/Support/Path.h>
#include <llvm/Support/FileSystem.h> #include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_os_ostream.h> #include <llvm/Support/raw_os_ostream.h>
@ -59,6 +60,36 @@ void Cache::clear()
fs::remove(it->path()); fs::remove(it->path());
} }
void Cache::preload(llvm::ExecutionEngine& _ee, std::unordered_map<std::string, uint64_t>& _funcCache)
{
// TODO: Cache dir should be in one place
using namespace llvm::sys;
llvm::SmallString<256> cachePath;
path::system_temp_directory(false, cachePath);
path::append(cachePath, "evm_objs");
// Disable listener
auto listener = g_listener;
g_listener = nullptr;
std::error_code err;
for (auto it = fs::directory_iterator{cachePath.str(), err}; it != fs::directory_iterator{}; it.increment(err))
{
auto name = it->path().substr(cachePath.size() + 1);
if (auto module = getObject(name))
{
DLOG(cache) << "Preload: " << name << "\n";
_ee.addModule(module.get());
module.release();
auto addr = _ee.getFunctionAddress(name);
assert(addr);
_funcCache[std::move(name)] = addr;
}
}
g_listener = listener;
}
std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id) std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
{ {
if (g_mode != CacheMode::on && g_mode != CacheMode::read) if (g_mode != CacheMode::on && g_mode != CacheMode::read)

12
evmjit/libevmjit/Cache.h

@ -1,9 +1,15 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <unordered_map>
#include <llvm/ExecutionEngine/ObjectCache.h> #include <llvm/ExecutionEngine/ObjectCache.h>
namespace llvm
{
class ExecutionEngine;
}
namespace dev namespace dev
{ {
namespace eth namespace eth
@ -18,7 +24,8 @@ enum class CacheMode
off, off,
read, read,
write, write,
clear clear,
preload
}; };
class ObjectCache : public llvm::ObjectCache class ObjectCache : public llvm::ObjectCache
@ -43,6 +50,9 @@ public:
/// Clears cache storage /// Clears cache storage
static void clear(); static void clear();
/// Loads all available cached objects to ExecutionEngine
static void preload(llvm::ExecutionEngine& _ee, std::unordered_map<std::string, uint64_t>& _funcCache);
}; };
} }

3
evmjit/libevmjit/Compiler.cpp

@ -838,6 +838,9 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
// Block may have no terminator if the next instruction is a jump destination. // Block may have no terminator if the next instruction is a jump destination.
if (!_basicBlock.llvm()->getTerminator()) if (!_basicBlock.llvm()->getTerminator())
m_builder.CreateBr(_nextBasicBlock); m_builder.CreateBr(_nextBasicBlock);
m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI());
_runtimeManager.checkStackLimit(_basicBlock.localStack().getMaxSize(), _basicBlock.localStack().getDiff());
} }

21
evmjit/libevmjit/ExecutionEngine.cpp

@ -76,6 +76,7 @@ cl::opt<CacheMode> g_cache{"cache", cl::desc{"Cache compiled EVM code on disk"},
clEnumValN(CacheMode::read, "r", "Read only. No new objects are added to cache."), clEnumValN(CacheMode::read, "r", "Read only. No new objects are added to cache."),
clEnumValN(CacheMode::write, "w", "Write only. No objects are loaded from cache."), clEnumValN(CacheMode::write, "w", "Write only. No objects are loaded from cache."),
clEnumValN(CacheMode::clear, "c", "Clear the cache storage. Cache is disabled."), clEnumValN(CacheMode::clear, "c", "Clear the cache storage. Cache is disabled."),
clEnumValN(CacheMode::preload, "p", "Preload all cached objects."),
clEnumValEnd)}; clEnumValEnd)};
cl::opt<bool> g_stats{"st", cl::desc{"Statistics"}}; cl::opt<bool> g_stats{"st", cl::desc{"Statistics"}};
cl::opt<bool> g_dump{"dump", cl::desc{"Dump LLVM IR module"}}; cl::opt<bool> g_dump{"dump", cl::desc{"Dump LLVM IR module"}};
@ -87,10 +88,10 @@ void parseOptions()
//cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler"); //cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
// FIXME: LLVM workaround: // FIXME: LLVM workaround:
// Manually select instruction scheduler other than "source". // Manually select instruction scheduler. Confirmed bad schedulers: source, list-burr, list-hybrid.
// "source" scheduler has a bug: http://llvm.org/bugs/show_bug.cgi?id=22304 // "source" scheduler has a bug: http://llvm.org/bugs/show_bug.cgi?id=22304
auto envLine = std::getenv("EVMJIT"); auto envLine = std::getenv("EVMJIT");
auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-burr\0"; auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-ilp\0";
static const auto c_maxArgs = 20; static const auto c_maxArgs = 20;
char const* argv[c_maxArgs] = {nullptr, }; char const* argv[c_maxArgs] = {nullptr, };
auto arg = std::strtok(&*commandLine.begin(), " "); auto arg = std::strtok(&*commandLine.begin(), " ");
@ -111,8 +112,15 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
std::unique_ptr<ExecStats> listener{new ExecStats}; std::unique_ptr<ExecStats> listener{new ExecStats};
listener->stateChanged(ExecState::Started); listener->stateChanged(ExecState::Started);
bool preloadCache = g_cache == CacheMode::preload;
if (preloadCache)
g_cache = CacheMode::on;
// TODO: Do not pseudo-init the cache every time
auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, listener.get()) : nullptr; auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, listener.get()) : nullptr;
static std::unordered_map<std::string, uint64_t> funcCache;
static std::unique_ptr<llvm::ExecutionEngine> ee; static std::unique_ptr<llvm::ExecutionEngine> ee;
if (!ee) if (!ee)
{ {
@ -138,6 +146,9 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
return ReturnCode::LLVMConfigError; return ReturnCode::LLVMConfigError;
module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
ee->setObjectCache(objectCache); ee->setObjectCache(objectCache);
if (preloadCache)
Cache::preload(*ee, funcCache);
} }
static StatsCollector statsCollector; static StatsCollector statsCollector;
@ -146,10 +157,9 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
m_runtime.init(_data, _env); m_runtime.init(_data, _env);
EntryFuncPtr entryFuncPtr = nullptr; EntryFuncPtr entryFuncPtr = nullptr;
static std::unordered_map<std::string, EntryFuncPtr> funcCache;
auto it = funcCache.find(mainFuncName); auto it = funcCache.find(mainFuncName);
if (it != funcCache.end()) if (it != funcCache.end())
entryFuncPtr = it->second; entryFuncPtr = (EntryFuncPtr) it->second;
if (!entryFuncPtr) if (!entryFuncPtr)
{ {
@ -177,7 +187,8 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
if (!CHECK(entryFuncPtr)) if (!CHECK(entryFuncPtr))
return ReturnCode::LLVMLinkError; return ReturnCode::LLVMLinkError;
funcCache[mainFuncName] = entryFuncPtr; if (it == funcCache.end())
funcCache[mainFuncName] = (uint64_t) entryFuncPtr;
listener->stateChanged(ExecState::Execution); listener->stateChanged(ExecState::Execution);
auto returnCode = entryFuncPtr(&m_runtime); auto returnCode = entryFuncPtr(&m_runtime);

44
evmjit/libevmjit/RuntimeManager.cpp

@ -78,7 +78,7 @@ llvm::Twine getName(RuntimeData::Index _index)
case RuntimeData::CodeSize: return "code"; case RuntimeData::CodeSize: return "code";
case RuntimeData::CallDataSize: return "callDataSize"; case RuntimeData::CallDataSize: return "callDataSize";
case RuntimeData::Gas: return "gas"; case RuntimeData::Gas: return "gas";
case RuntimeData::Number: return "number"; case RuntimeData::Number: return "number";
case RuntimeData::Timestamp: return "timestamp"; case RuntimeData::Timestamp: return "timestamp";
} }
} }
@ -101,6 +101,48 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB
assert(m_memPtr->getType() == Array::getType()->getPointerTo()); assert(m_memPtr->getType() == Array::getType()->getPointerTo());
m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 1), "env"); m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 1), "env");
assert(m_envPtr->getType() == Type::EnvPtr); assert(m_envPtr->getType() == Type::EnvPtr);
m_stackSize = m_builder.CreateAlloca(Type::Size, nullptr, "stackSize");
m_builder.CreateStore(m_builder.getInt64(0), m_stackSize);
llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::BytePtr};
m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "stack.checkSize", getModule());
m_checkStackLimit->setDoesNotThrow();
m_checkStackLimit->setDoesNotCapture(1);
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_checkStackLimit);
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_checkStackLimit);
auto outOfStackBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfStack", m_checkStackLimit);
auto currSizePtr = &m_checkStackLimit->getArgumentList().front();
currSizePtr->setName("currSize");
auto max = currSizePtr->getNextNode();
max->setName("max");
auto diff = max->getNextNode();
diff->setName("diff");
auto jmpBuf = diff->getNextNode();
jmpBuf->setName("jmpBuf");
InsertPointGuard guard{m_builder};
m_builder.SetInsertPoint(checkBB);
auto currSize = m_builder.CreateLoad(currSizePtr, "cur");
auto maxSize = m_builder.CreateNUWAdd(currSize, max, "maxSize");
auto ok = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(1024), "ok");
m_builder.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue);
m_builder.SetInsertPoint(updateBB);
auto newSize = m_builder.CreateNSWAdd(currSize, diff);
m_builder.CreateStore(newSize, currSizePtr);
m_builder.CreateRetVoid();
m_builder.SetInsertPoint(outOfStackBB);
abort(jmpBuf);
m_builder.CreateUnreachable();
}
void RuntimeManager::checkStackLimit(size_t _max, int _diff)
{
createCall(m_checkStackLimit, {m_stackSize, m_builder.getInt64(_max), m_builder.getInt64(_diff), getJmpBuf()});
} }
llvm::Value* RuntimeManager::getRuntimePtr() llvm::Value* RuntimeManager::getRuntimePtr()

5
evmjit/libevmjit/RuntimeManager.h

@ -48,6 +48,8 @@ public:
static llvm::StructType* getRuntimeType(); static llvm::StructType* getRuntimeType();
static llvm::StructType* getRuntimeDataType(); static llvm::StructType* getRuntimeDataType();
void checkStackLimit(size_t _max, int _diff);
private: private:
llvm::Value* getPtr(RuntimeData::Index _index); llvm::Value* getPtr(RuntimeData::Index _index);
void set(RuntimeData::Index _index, llvm::Value* _value); void set(RuntimeData::Index _index, llvm::Value* _value);
@ -59,6 +61,9 @@ private:
llvm::Value* m_memPtr = nullptr; llvm::Value* m_memPtr = nullptr;
llvm::Value* m_envPtr = nullptr; llvm::Value* m_envPtr = nullptr;
llvm::Value* m_stackSize = nullptr;
llvm::Function* m_checkStackLimit = nullptr;
code_iterator m_codeBegin = {}; code_iterator m_codeBegin = {};
code_iterator m_codeEnd = {}; code_iterator m_codeEnd = {};

21
exp/CMakeLists.txt

@ -10,8 +10,27 @@ set(EXECUTABLE exp)
add_executable(${EXECUTABLE} ${SRC_LIST}) add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
if (READLINE_FOUND)
target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES})
endif()
if (JSONRPC)
target_link_libraries(${EXECUTABLE} web3jsonrpc)
endif()
target_link_libraries(${EXECUTABLE} webthree)
target_link_libraries(${EXECUTABLE} ethereum) target_link_libraries(${EXECUTABLE} ethereum)
target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} p2p)
if (ETHASHCL)
target_link_libraries(${EXECUTABLE} ethash-cl)
target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} OpenCL)
endif()
install( TARGETS ${EXECUTABLE} DESTINATION bin) install( TARGETS ${EXECUTABLE} DESTINATION bin)

151
exp/main.cpp

@ -19,18 +19,28 @@
* @date 2014 * @date 2014
* Ethereum client. * Ethereum client.
*/ */
#if ETH_ETHASHCL
#define __CL_ENABLE_EXCEPTIONS
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#include "libethash-cl/cl.hpp"
#endif
#include <functional> #include <functional>
#include <libethereum/AccountDiff.h> #include <boost/filesystem.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>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libdevcore/RLP.h> #include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h> #include <libdevcore/TransientDirectory.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcrypto/TrieDB.h>
#include <libp2p/All.h> #include <libp2p/All.h>
#include <libethereum/DownloadMan.h> #include <libethcore/ProofOfWork.h>
#include <libethereum/All.h> #include <libethereum/All.h>
#include <libethereum/Farm.h>
#include <libethereum/AccountDiff.h>
#include <libethereum/DownloadMan.h>
#include <libethereum/Client.h>
#include <liblll/All.h> #include <liblll/All.h>
#include <libwhisper/WhisperPeer.h> #include <libwhisper/WhisperPeer.h>
#include <libwhisper/WhisperHost.h> #include <libwhisper/WhisperHost.h>
@ -98,9 +108,144 @@ int main()
cnote << "State after transaction: " << s; cnote << "State after transaction: " << s;
cnote << before.diff(s); cnote << before.diff(s);
} }
#elif 0
int main()
{
GenericFarm<Ethash> f;
BlockInfo genesis = CanonBlockChain::genesis();
genesis.difficulty = 1 << 18;
cdebug << genesis.boundary();
auto mine = [](GenericFarm<Ethash>& f, BlockInfo const& g, unsigned timeout) {
BlockInfo bi = g;
bool completed = false;
f.onSolutionFound([&](ProofOfWork::Solution sol)
{
ProofOfWork::assignResult(sol, bi);
return completed = true;
});
f.setWork(bi);
for (unsigned i = 0; !completed && i < timeout * 10; ++i, cout << f.miningProgress() << "\r" << flush)
this_thread::sleep_for(chrono::milliseconds(100));
cout << endl << flush;
cdebug << bi.mixHash << bi.nonce << (Ethash::verify(bi) ? "GOOD" : "bad");
};
Ethash::prep(genesis);
genesis.difficulty = u256(1) << 40;
genesis.noteDirty();
f.startCPU();
mine(f, genesis, 10);
f.startGPU();
cdebug << "Good:";
genesis.difficulty = 1 << 18;
genesis.noteDirty();
mine(f, genesis, 30);
cdebug << "Bad:";
genesis.difficulty = (u256(1) << 40);
genesis.noteDirty();
mine(f, genesis, 30);
f.stop();
return 0;
}
#elif 0
void mine(State& s, BlockChain const& _bc)
{
s.commitToMine(_bc);
GenericFarm<ProofOfWork> f;
bool completed = false;
f.onSolutionFound([&](ProofOfWork::Solution sol)
{
return completed = s.completeMine<ProofOfWork>(sol);
});
f.setWork(s.info());
f.startCPU();
while (!completed)
this_thread::sleep_for(chrono::milliseconds(20));
}
#elif 0
int main()
{
cnote << "Testing State...";
KeyPair me = sha3("Gav Wood");
KeyPair myMiner = sha3("Gav's Miner");
// KeyPair you = sha3("123");
Defaults::setDBPath(boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count()));
OverlayDB stateDB = State::openDB();
CanonBlockChain bc;
cout << bc;
State s(stateDB, BaseState::CanonGenesis, myMiner.address());
cout << s;
// Sync up - this won't do much until we use the last state.
s.sync(bc);
cout << s;
// Mine to get some ether!
mine(s, bc);
bc.attemptImport(s.blockData(), stateDB);
cout << bc;
s.sync(bc);
cout << s;
// Inject a transaction to transfer funds from miner to me.
Transaction t(1000, 10000, 30000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
assert(t.sender() == myMiner.address());
s.execute(bc.lastHashes(), t);
cout << s;
// Mine to get some ether and set in stone.
s.commitToMine(bc);
s.commitToMine(bc);
mine(s, bc);
bc.attemptImport(s.blockData(), stateDB);
cout << bc;
s.sync(bc);
cout << s;
return 0;
}
#else #else
int main() int main()
{ {
string tempDir = boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count());
KeyPair myMiner = sha3("Gav's Miner");
p2p::Host net("Test");
cdebug << "Path:" << tempDir;
Client c(&net, tempDir);
c.setAddress(myMiner.address());
this_thread::sleep_for(chrono::milliseconds(1000));
c.startMining();
this_thread::sleep_for(chrono::milliseconds(6000));
c.stopMining();
return 0; return 0;
} }
#endif #endif

59
extdep/CMakeLists.txt

@ -1,59 +0,0 @@
cmake_minimum_required(VERSION 2.8.12)
include(ExternalProject)
include(CMakeParseArguments)
include(eth_download.cmake)
# all dependencies will be installed into this directory, separated by platform
string(TOLOWER ${CMAKE_SYSTEM_NAME} _system_name)
set(ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/install/${_system_name}")
set(ETH_DEPENDENCY_SERVER "https://build.ethdev.com/builds/${_system_name}-precompiled")
file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/lib)
file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include)
file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/bin)
if (ETH_COMPILE)
# json-rpc-cpp and its dependencies
include(compile/jsoncpp.cmake)
include(compile/argtable2.cmake)
include(compile/curl.cmake)
include(compile/json-rpc-cpp.cmake)
# qt and its dependencies
include(compile/icu.cmake)
include(compile/jom.cmake)
include(compile/qt.cmake)
# leveldb and its dependencies
include(compile/snappy.cmake)
include(compile/leveldb.cmake)
# cryptopp
include(compile/cryptopp.cmake)
# boost
include(compile/boost.cmake)
else()
eth_download(jsoncpp)
eth_download(microhttpd)
eth_download(json-rpc-cpp
VERSION 4.2
OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh
)
if (APPLE)
eth_download(snappy OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/snappy_osx.sh)
endif()
eth_download(leveldb OSX_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/leveldb_osx.sh)
eth_download(qt VERSION 5.4)
eth_download(cryptopp)
eth_download(boost)
eth_download(curl)
endif()
# will be re-eanbled later
# include(miniupnpc.cmake)
# if install phase of extep fails, even if libs are already created, the ethereum install will fail

16
extdep/Readme.md

@ -1,16 +0,0 @@
# cpp-ethereum external dependencies
**This is Work-in-Progress!**
This directory hosts the external libraries that are needed to build cpp-ethereum.
To automatically download, build, and link libraries, do
```
cd extdep; mkdir build; cd build; cmake ..; make
```
this will take some time.
To check which libraries are already included, check `CMakeLists.txt`. Other libraries still need to be fetched via the system's package manager.
Libraries will be installed in `cpp-ethereum/extdep/install/<platform-name>`

9
extdep/cmake/FindCURL.cmake

@ -1,9 +0,0 @@
# hacky way to resolve nested dependencies - needed for json-rpc-cpp
find_library(CURL_LIBRARY NAMES curl
PATHS
${ETH_DEPENDENCY_INSTALL_DIR}/lib
)
set(CURL_LIBRARIES ${CURL_LIBRARY})
set(CURL_INCLUDE_DIRS ${ETH_DEPENDENCY_INSTALL_DIR}/include)

13
extdep/compile/argtable2.cmake

@ -1,13 +0,0 @@
if (APPLE)
elseif (WIN32)
ExternalProject_Add(argtable2
GIT_REPOSITORY https://github.com/debris/argtable.git
GIT_TAG master
BINARY_DIR argtable2-prefix/src/argtable2
CONFIGURE_COMMAND cmake .
BUILD_COMMAND devenv argtable2.sln /build release
INSTALL_COMMAND cmd /c cp src/Release/argtable2.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp src/argtable2.h ${ETH_DEPENDENCY_INSTALL_DIR}/include
)
else()
endif()

19
extdep/compile/boost.cmake

@ -1,19 +0,0 @@
if (APPLE)
elseif (WIN32)
set(boost_address_model)
# on windows 64:
# set(boost_address_model address-model=64)
set(boost_targets --with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test --with-chrono --with-program_options)
ExternalProject_Add(boost
URL http://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.gz
BINARY_DIR boost-prefix/src/boost
CONFIGURE_COMMAND ./bootstrap.bat
BUILD_COMMAND ./b2.exe -j4 --build-type=complete link=static runtime-link=shared variant=debug,release threading=multi ${boost_addressModel} ${boost_targets} install --prefix=${ETH_DEPENDENCY_INSTALL_DIR}
INSTALL_COMMAND cmake -E rename ${ETH_DEPENDENCY_INSTALL_DIR}/include/boost-1_55/boost ${ETH_DEPENDENCY_INSTALL_DIR}/include/boost
)
else()
endif()

33
extdep/compile/cryptopp.cmake

@ -1,33 +0,0 @@
# CryptoPP does not have good cross-platform support, there exist several different other projects to make it work ...
# TODO the OS X build throws a lot of warnings, but compiles fine
if (APPLE)
ExternalProject_Add(cryptopp
URL https://downloads.sourceforge.net/project/cryptopp/cryptopp/5.6.2/cryptopp562.zip
BINARY_DIR cryptopp-prefix/src/cryptopp
CONFIGURE_COMMAND ""
BUILD_COMMAND make CXX=clang++ CXXFLAGS=-DCRYPTOPP_DISABLE_ASM
INSTALL_COMMAND make install PREFIX=${ETH_DEPENDENCY_INSTALL_DIR}
)
elseif (WIN32)
file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include/cryptopp)
ExternalProject_Add(cryptopp
SVN_REPOSITORY http://svn.code.sf.net/p/cryptopp/code/trunk/c5
SVN_REVISION -r "541"
BINARY_DIR cryptopp-prefix/src/cryptopp
CONFIGURE_COMMAND devenv cryptest.sln /upgrade
BUILD_COMMAND devenv cryptest.sln /build release
INSTALL_COMMAND cmd /c cp Win32/DLL_Output/Release/cryptopp.dll ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp Win32/DLL_Output/Release/cryptopp.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp *.h ${ETH_DEPENDENCY_INSTALL_DIR}/include/cryptopp
)
# on Linux, the default Makefile does not work.
else()
ExternalProject_Add(cryptopp
URL https://github.com/mmoss/cryptopp/archive/v5.6.2.zip
BINARY_DIR cryptopp-prefix/src/cryptopp
CONFIGURE_COMMAND ""
BUILD_COMMAND scons --shared --prefix=${ETH_DEPENDENCY_INSTALL_DIR}
INSTALL_COMMAND ""
)
endif()

29
extdep/compile/curl.cmake

@ -1,29 +0,0 @@
if (APPLE)
ExternalProject_Add(curl
URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2
BINARY_DIR curl-prefix/src/curl
CONFIGURE_COMMAND ./configure --with-darwinssl --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}
BUILD_COMMAND make -j 3
INSTALL_COMMAND make install
)
elseif (WIN32)
ExternalProject_Add(curl
GIT_REPOSITORY https://github.com/debris/libcurl-7.29
GIT_TAG master
BINARY_DIR curl-prefix/src/curl
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND cmd /c cp lib/release/libcurl.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/curl ${ETH_DEPENDENCY_INSTALL_DIR}/include
)
else()
ExternalProject_Add(curl
URL http://curl.haxx.se/download/curl-7.38.0.tar.bz2
BINARY_DIR curl-prefix/src/curl
CONFIGURE_COMMAND CONFIG_CMD ./configure --prefix=${ETH_DEPENDENCY_INSTALL_DIR} --exec-prefix=${ETH_DEPENDENCY_INSTALL_DIR}
BUILD_COMMAND make -j 3
INSTALL_COMMAND make install
)
endif()

17
extdep/compile/icu.cmake

@ -1,17 +0,0 @@
if (APPLE)
elseif (WIN32)
ExternalProject_Add(icu
GIT_REPOSITORY https://github.com/debris/icu-win32.git
GIT_TAG master
BINARY_DIR icu-prefix/src/icu
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR}
)
else()
endif()

16
extdep/compile/jom.cmake

@ -1,16 +0,0 @@
if (APPLE)
elseif (WIN32)
ExternalProject_Add(jom
URL http://download.qt-project.org/official_releases/jom/jom.zip
BINARY_DIR jom-prefix/src/jom
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND cmake -E copy jom.exe ${ETH_DEPENDENCY_INSTALL_DIR}/bin
)
else()
endif()

40
extdep/compile/json-rpc-cpp.cmake

@ -1,40 +0,0 @@
# json-rpc-cpp is under heavy development, not yet stable, and multiplatform builds are not yet available.
# DO NOT MESS WITH THESE SETTINGS! IF YOU HAVE TO MAKE CHANGES HERE, CONSULT sven@ethdev.com BEFOREHAND!!
# DO NOT CHANGE ANYTHING HERE!
if(APPLE)
ExternalProject_Add(json-rpc-cpp
# DEPENDS argtable2 jsoncpp
# DEPENDS curl # re-enable later, when we build curl again
GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git
GIT_TAG v0.3.2
BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp
CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST -Wno-dev .
BUILD_COMMAND make -j 3
INSTALL_COMMAND make install && ${CMAKE_CURRENT_SOURCE_DIR}/scripts/json-rpc-cpp_osx.sh . ${ETH_DEPENDENCY_INSTALL_DIR}
)
elseif (WIN32)
ExternalProject_Add(json-rpc-cpp
DEPENDS argtable2 jsoncpp curl
GIT_REPOSITORY https://github.com/debris/libjson-rpc-cpp.git
GIT_TAG windows
BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp
CONFIGURE_COMMAND cmake -DCMAKE_PREFIX_PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCURL_LIBRARIES=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libcurl.lib .
BUILD_COMMAND devenv libjson-rpc-cpp.sln /build release
INSTALL_COMMAND cmd /c cp lib/Release/* ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R src/jsonrpccpp ${ETH_DEPENDENCY_INSTALL_DIR}/include
)
else()
ExternalProject_Add(json-rpc-cpp
# DEPENDS argtable2 jsoncpp
# DEPENDS curl # re-enable later, when we build curl again
GIT_REPOSITORY https://github.com/cinemast/libjson-rpc-cpp.git
GIT_TAG v0.3.2
BINARY_DIR json-rpc-cpp-prefix/src/json-rpc-cpp
CONFIGURE_COMMAND cmake -DCMAKE_INSTALL_PREFIX=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_MODULE_PATH:PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DETH_DEPENDENCY_INSTALL_DIR:PATH=${ETH_DEPENDENCY_INSTALL_DIR} -DCMAKE_BUILD_TYPE=None -DCMAKE_FIND_FRAMEWORK=LAST .
BUILD_COMMAND make -j 3
INSTALL_COMMAND make install
)
endif()

16
extdep/compile/jsoncpp.cmake

@ -1,16 +0,0 @@
if (APPLE)
elseif (WIN32)
file(MAKE_DIRECTORY ${ETH_DEPENDENCY_INSTALL_DIR}/include/jsoncpp)
ExternalProject_Add(jsoncpp
GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp
GIT_TAG svn-import
BINARY_DIR jsoncpp-prefix/src/jsoncpp
CONFIGURE_COMMAND cmake .
BUILD_COMMAND devenv jsoncpp.sln /build release
INSTALL_COMMAND cmd /c cp lib/Release/jsoncpp.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp -R include/json ${ETH_DEPENDENCY_INSTALL_DIR}/include/jsoncpp
)
else()
endif()

23
extdep/compile/leveldb.cmake

@ -1,23 +0,0 @@
if (APPLE)
ExternalProject_Add(leveldb
#DEPENDS snappy
URL https://leveldb.googlecode.com/files/leveldb-1.15.0.tar.gz
BINARY_DIR leveldb-prefix/src/leveldb
#CONFIGURE_COMMAND patch < ${CMAKE_CURRENT_SOURCE_DIR}/compile/leveldb_osx.patch
CONFIGURE_COMMAND ""
BUILD_COMMAND export ETH_DEPENDENCY_INSTALL_DIR=${ETH_DEPENDENCY_INSTALL_DIR} && make -j 3
INSTALL_COMMAND cp -rf include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include/ && cp libleveldb.a ${ETH_DEPENDENCY_INSTALL_DIR}/lib && cp libleveldb.dylib.1.15 ${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib
)
elseif (WIN32)
ExternalProject_Add(leveldb
GIT_REPOSITORY https://github.com/debris/leveldb-win32.git
GIT_TAG master
BINARY_DIR leveldb-prefix/src/leveldb
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND cmd /c cp lib/LibLevelDB.lib ${ETH_DEPENDENCY_INSTALL_DIR}/lib/leveldb.lib && cp -R include/leveldb ${ETH_DEPENDENCY_INSTALL_DIR}/include
)
else()
endif()

18
extdep/compile/leveldb_osx.patch

@ -1,18 +0,0 @@
--- Makefile 2014-11-07 00:54:05.000000000 +0100
+++ MakefilePatch 2014-11-07 00:56:59.000000000 +0100
@@ -17,11 +17,11 @@
# this file is generated by the previous line to set build flags and sources
include build_config.mk
-CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
-CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT)
+CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
+CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) -DSNAPPY -I$(ETH_DEPENDENCY_INSTALL_DIR)/include
-LDFLAGS += $(PLATFORM_LDFLAGS)
-LIBS += $(PLATFORM_LIBS)
+LDFLAGS += $(PLATFORM_LDFLAGS) -L$(ETH_DEPENDENCY_INSTALL_DIR)/lib
+LIBS += $(PLATFORM_LIBS) -lsnappy
LIBOBJECTS = $(SOURCES:.cc=.o)
MEMENVOBJECTS = $(MEMENV_SOURCES:.cc=.o)

32
extdep/compile/qt.cmake

@ -1,32 +0,0 @@
if (APPLE)
ExternalProject_add(qt
URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz
BINARY_DIR qt-prefix/src/qt
PATCH_COMMAND patch -d qtmultimedia/src/plugins/avfoundation/mediaplayer < ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_osx.patch
CONFIGURE_COMMAND ./configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -system-zlib -qt-libpng -qt-libjpeg -confirm-license -opensource -nomake tests -release -nomake examples -no-xcb -arch x86_64
BUILD_COMMAND make
INSTALL_COMMAND make install
)
elseif(WIN32)
ExternalProject_Add(qt
DEPENDS icu jom
URL http://qtmirror.ics.com/pub/qtproject/official_releases/qt/5.3/5.3.2/single/qt-everywhere-opensource-src-5.3.2.tar.gz
BINARY_DIR qt-prefix/src/qt
UPDATE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_tools.bat
#PATCH_COMMAND cmake -E copy ${CMAKE_CURRENT_SOURCE_DIR}/compile/qt_configure.bat qtbase/configure.bat
CONFIGURE_COMMAND configure -prefix ${ETH_DEPENDENCY_INSTALL_DIR} -opensource -confirm-license -release -opengl desktop -platform win32-msvc2013 -icu -I ${ETH_DEPENDENCY_INSTALL_DIR}/include -L ${ETH_DEPENDENCY_INSTALL_DIR}/lib -nomake tests -nomake examples
BUILD_COMMAND nmake
INSTALL_COMMAND nmake install
)
ExternalProject_Add_Step(qt configure_paths
COMMAND set PATH=${ETH_DEPENDENCY_INSTALL_DIR}/bin;%cd%/gnuwin32/bin;%cd%/qtbase/bin;%PATH%
DEPENDEES patch
DEPENDERS configure
)
else()
endif()

111
extdep/compile/qt_configure.bat

@ -1,111 +0,0 @@
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
:: Contact: http://www.qt-project.org/legal
::
:: This file is part of the tools applications of the Qt Toolkit.
::
:: $QT_BEGIN_LICENSE:LGPL$
:: Commercial License Usage
:: Licensees holding valid commercial Qt licenses may use this file in
:: accordance with the commercial license agreement provided with the
:: Software or, alternatively, in accordance with the terms contained in
:: a written agreement between you and Digia. For licensing terms and
:: conditions see http://qt.digia.com/licensing. For further information
:: use the contact form at http://qt.digia.com/contact-us.
::
:: GNU Lesser General Public License Usage
:: Alternatively, this file may be used under the terms of the GNU Lesser
:: General Public License version 2.1 as published by the Free Software
:: Foundation and appearing in the file LICENSE.LGPL included in the
:: packaging of this file. Please review the following information to
:: ensure the GNU Lesser General Public License version 2.1 requirements
:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
::
:: In addition, as a special exception, Digia gives you certain additional
:: rights. These rights are described in the Digia Qt LGPL Exception
:: version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
::
:: GNU General Public License Usage
:: Alternatively, this file may be used under the terms of the GNU
:: General Public License version 3.0 as published by the Free Software
:: Foundation and appearing in the file LICENSE.GPL included in the
:: packaging of this file. Please review the following information to
:: ensure the GNU General Public License version 3.0 requirements will be
:: met: http://www.gnu.org/copyleft/gpl.html.
::
::
:: $QT_END_LICENSE$
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
set QTSRC=%~dp0
set QTDIR=%CD%
::if not exist %QTSRC%\.gitignore goto sconf
echo Please wait while bootstrapping configure ...
for %%C in (cl.exe icl.exe g++.exe perl.exe) do set %%C=%%~$PATH:C
if "%perl.exe%" == "" (
echo Perl not found in PATH. Aborting. >&2
exit /b 1
)
if not exist mkspecs (
md mkspecs
if errorlevel 1 goto exit
)
perl %QTSRC%bin\syncqt.pl -minimal -module QtCore -outdir %QTDIR% %QTSRC%
if errorlevel 1 goto exit
if not exist tools\configure (
md tools\configure
if errorlevel 1 goto exit
)
cd tools\configure
if errorlevel 1 goto exit
echo #### Generated by configure.bat - DO NOT EDIT! ####> Makefile
echo/>> Makefile
for /f "tokens=3 usebackq" %%V in (`findstr QT_VERSION_STR %QTSRC%\src\corelib\global\qglobal.h`) do @echo QTVERSION = %%~V>> Makefile
if not "%cl.exe%" == "" (
echo CXX = cl>>Makefile
echo EXTRA_CXXFLAGS =>>Makefile
rem This must have a trailing space.
echo QTSRC = %QTSRC% >> Makefile
set tmpl=win32
set make=nmake
) else if not "%icl.exe%" == "" (
echo CXX = icl>>Makefile
echo EXTRA_CXXFLAGS = /Zc:forScope>>Makefile
rem This must have a trailing space.
echo QTSRC = %QTSRC% >> Makefile
set tmpl=win32
set make=nmake
) else if not "%g++.exe%" == "" (
echo CXX = g++>>Makefile
echo EXTRA_CXXFLAGS =>>Makefile
rem This must NOT have a trailing space.
echo QTSRC = %QTSRC:\=/%>> Makefile
set tmpl=mingw
set make=mingw32-make
) else (
echo No suitable compiler found in PATH. Aborting. >&2
cd ..\..
exit /b 1
)
echo/>> Makefile
type %QTSRC%tools\configure\Makefile.%tmpl% >> Makefile
%make%
if errorlevel 1 (cd ..\.. & exit /b 1)
cd ..\..
:conf
configure.exe -srcdir %QTSRC% %*
goto exit
:sconf
%QTSRC%\configure.exe %*
:exit

11
extdep/compile/qt_osx.patch

@ -1,11 +0,0 @@
--- avfmediaplayersession.mm 2014-09-11 12:48:26.000000000 +0200
+++ avfmediaplayersessionPatch.mm 2014-12-01 12:53:14.000000000 +0100
@@ -295,7 +295,7 @@
//AVPlayerItem "status" property value observer.
if (context == AVFMediaPlayerSessionObserverStatusObservationContext)
{
- AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
+ AVPlayerStatus status = (AVPlayerStatus)[[change objectForKey:NSKeyValueChangeNewKey] integerValue];
switch (status)
{
//Indicates that the status of the player is not yet known because

2
extdep/compile/qt_tools.bat

@ -1,2 +0,0 @@
rem : import VC environment vars
call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86

14
extdep/compile/snappy.cmake

@ -1,14 +0,0 @@
if (APPLE)
ExternalProject_Add(snappy
URL https://snappy.googlecode.com/files/snappy-1.1.1.tar.gz
BINARY_DIR snappy-prefix/src/snappy
CONFIGURE_COMMAND ./configure --disable-dependency-tracking --prefix=${ETH_DEPENDENCY_INSTALL_DIR}
BUILD_COMMAND ""
INSTALL_COMMAND make install
)
elseif(WIN32)
else()
endif()

74
extdep/eth_download.cmake

@ -1,74 +0,0 @@
# this macro requires the following variables to be specified:
#
# ETH_DEPENDENCY_SERVER - server from which dependencies should be downloaded
# ETH_DEPENDENCY_INSTALL_DIR - install location for all dependencies
#
# usage:
#
# eth_download("json-rpc-cpp")
# eth_download("json-rpc-cpp" VERSION "0.3.2")
#
# params:
# VERSION - exact version we want to use
# OSX_SCRIPT - script which will be executed on apple in install phase
# UNIX_SCRIPT - script which will be executed on unix in install phase
# WIN_SCRIPT - script which will be executed on win in install phase
# OSX_SCRIPT, WIN_SCRIPT, UNIX_SCRIPT are taking 2 params:
# $1 is package_source,
# $2 is ETH_DEPENDENCY_INSTALL_DIR
#
# parsing arguments
# http://www.cmake.org/cmake/help/v3.0/module/CMakeParseArguments.html
#
# for macos you may need to specify OSX_SCRIPT with install_name_tool to fix dylib
# http://stackoverflow.com/questions/2985315/using-install-name-tool-whats-going-wrong
#
# TODO:
# check if install_command is handling symlinks correctly on linux and windows
macro(eth_download eth_package_name)
set (extra_macro_args ${ARGN})
set (options)
set (one_value_args VERSION OSX_SCRIPT UNIX_SCRIPT WIN_SCRIPT)
set (multi_value_args)
cmake_parse_arguments (ETH_DOWNLOAD "${options}" "${one_value_args}" "${multi_value_args}" ${extra_macro_args})
if (ETH_DOWNLOAD_VERSION)
set(eth_tar_name "${eth_package_name}-${ETH_DOWNLOAD_VERSION}.tar.gz")
else()
set(eth_tar_name "${eth_package_name}.tar.gz")
endif()
message(STATUS "download path for ${eth_package_name} is : ${ETH_DEPENDENCY_SERVER}/${eth_tar_name}")
# we need that to copy symlinks
# see http://superuser.com/questions/138587/how-to-copy-symbolic-links
if (APPLE)
set (eth_package_copy cp -a . ${ETH_DEPENDENCY_INSTALL_DIR})
set (eth_package_install ${ETH_DOWNLOAD_OSX_SCRIPT})
elseif (UNIX)
set (eth_package_copy cp -a . ${ETH_DEPENDENCY_INSTALL_DIR})
set (eth_package_install ${ETH_DOWNLOAD_UNIX_SCRIPT})
else ()
set (eth_package_copy cmake -E copy_directory . ${ETH_DEPENDENCY_INSTALL_DIR})
set (eth_package_install ${ETH_DOWNLOAD_WIN_SCRIPT})
endif()
if (eth_package_install)
message(STATUS "install script: ${eth_package_install}")
set (eth_package_install ${eth_package_install} . ${ETH_DEPENDENCY_INSTALL_DIR})
else ()
set (eth_package_install echo 0) # cause empty string is not handled properly
endif()
ExternalProject_Add(${eth_package_name}
URL ${ETH_DEPENDENCY_SERVER}/${eth_tar_name}
BINARY_DIR ${eth_package_name}-prefix/src/${eth_package_name}
CONFIGURE_COMMAND ""
BUILD_COMMAND ${eth_package_copy}
INSTALL_COMMAND ${eth_package_install}
)
endmacro()

32
extdep/getstuff.bat

@ -0,0 +1,32 @@
REM get stuff!
if not exist download mkdir download
if not exist install mkdir install
if not exist install\windows mkdir install\windows
set eth_server=https://build.ethdev.com/builds/windows-precompiled
call :download boost 1.55.0
call :download cryptopp 5.6.2
call :download curl 7.4.2
call :download jsoncpp 1.6.2
call :download json-rpc-cpp 0.5.0
call :download leveldb 1.2
call :download microhttpd 0.9.2
call :download qt 5.4.1
goto :EOF
:download
set eth_name=%1
set eth_version=%2
cd download
if not exist %eth_name%-%eth_version%.tar.gz curl -k -o %eth_name%-%eth_version%.tar.gz %eth_server%/%eth_name%-%eth_version%.tar.gz
if not exist %eth_name%-%eth_version% tar -zxvf %eth_name%-%eth_version%.tar.gz
cmake -E copy_directory %eth_name%-%eth_version% ..\install\windows
cd ..\download
goto :EOF

11
extdep/miniupnpc.cmake

@ -1,11 +0,0 @@
# TODO this file is not used yet, but will be in future
include(ExternalProject)
ExternalProject_Add(miniupnpc
URL http://miniupnp.tuxfamily.org/files/download.php?file=miniupnpc-1.9.20141027.tar.gz
BINARY_DIR miniupnpc-prefix/src/miniupnpc
CONFIGURE_COMMAND ""
BUILD_COMMAND make -j 3
INSTALL_COMMAND make install INSTALLPREFIX=${ETH_DEPENDENCY_INSTALL_DIR}
)

29
extdep/scripts/json-rpc-cpp_osx.sh

@ -1,29 +0,0 @@
#!/bin/bash
ETH_DEPENDENCY_SOURCE_DIR=$1
ETH_DEPENDENCY_INSTALL_DIR=$2
OLD_COMMON_DYLIB="libjsonrpccpp-common.0.dylib"
COMMON_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libjsonrpccpp-common.0.dylib
SERVER_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libjsonrpccpp-server.0.dylib
CLIENT_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libjsonrpccpp-client.0.dylib
# fix bin
STAB_EXEC=${ETH_DEPENDENCY_INSTALL_DIR}/bin/jsonrpcstub
install_name_tool -change ${OLD_COMMON_DYLIB} ${COMMON_DYLIB} ${STAB_EXEC}
# fix common
install_name_tool -id ${COMMON_DYLIB} ${COMMON_DYLIB}
# fix server
install_name_tool -id ${SERVER_DYLIB} ${SERVER_DYLIB}
install_name_tool -change ${OLD_COMMON_DYLIB} ${COMMON_DYLIB} ${SERVER_DYLIB}
# fix client
install_name_tool -id ${CLIENT_DYLIB} ${CLIENT_DYLIB}
install_name_tool -change ${OLD_COMMON_DYLIB} ${COMMON_DYLIB} ${CLIENT_DYLIB}
# TODO fix argtable and jsoncpp once they are downloaded as dependencies

12
extdep/scripts/leveldb_osx.sh

@ -1,12 +0,0 @@
#!/bin/bash
ETH_DEPENDENCY_SOURCE_DIR=$1
ETH_DEPENDENCY_INSTALL_DIR=$2
OLD_SNAPPY_DYLIB="/Users/marekkotewicz/ethereum/cpp-ethereum/extdep/install/darwin/lib/libsnappy.1.dylib"
SNAPPY_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libsnappy.dylib
LEVELDB_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libleveldb.dylib
install_name_tool -id ${LEVELDB_DYLIB} ${LEVELDB_DYLIB}
install_name_tool -change ${OLD_SNAPPY_DYLIB} ${SNAPPY_DYLIB} ${LEVELDB_DYLIB}

8
extdep/scripts/snappy_osx.sh

@ -1,8 +0,0 @@
#!/bin/bash
ETH_DEPENDENCY_SOURCE_DIR=$1
ETH_DEPENDENCY_INSTALL_DIR=$2
SNAPPY_DYLIB=${ETH_DEPENDENCY_INSTALL_DIR}/lib/libsnappy.dylib
install_name_tool -id ${SNAPPY_DYLIB} ${SNAPPY_DYLIB}

1
libdevcore/CMakeLists.txt

@ -28,6 +28,7 @@ endif()
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
# transitive dependencies for windows executables # transitive dependencies for windows executables

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev namespace dev
{ {
char const* Version = "0.9.1"; char const* Version = "0.9.9";
} }

16
libdevcore/Common.h

@ -134,4 +134,20 @@ private:
std::function<void(void)> m_f; std::function<void(void)> m_f;
}; };
enum class WithExisting: int
{
Trust = 0,
Verify,
Kill
};
}
namespace std {
inline dev::WithExisting max(dev::WithExisting _a, dev::WithExisting _b)
{
return static_cast<dev::WithExisting>(max(static_cast<int>(_a), static_cast<int>(_b)));
}
} }

32
libdevcore/CommonData.h

@ -116,9 +116,9 @@ inline void toBigEndian(_T _val, _Out& o_out)
template <class _T, class _In> template <class _T, class _In>
inline _T fromBigEndian(_In const& _bytes) inline _T fromBigEndian(_In const& _bytes)
{ {
_T ret = 0; _T ret = (_T)0;
for (auto i: _bytes) for (auto i: _bytes)
ret = (ret << 8) | (byte)(typename std::make_unsigned<typename _In::value_type>::type)i; ret = (_T)((ret << 8) | (byte)(typename std::make_unsigned<typename _In::value_type>::type)i);
return ret; return ret;
} }
@ -236,6 +236,34 @@ inline std::vector<_T>& operator+=(std::vector<typename std::enable_if<!std::is_
return _a; return _a;
} }
/// Insert the contents of a container into a set
template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U const& _b)
{
for (auto const& i: _b)
_a.insert(i);
return _a;
}
/// Concatenate the contents of a container onto a vector
template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U const& _b)
{
for (auto const& i: _b)
_a.push_back(i);
return _a;
}
/// Insert the contents of a container into a set
template <class T, class U> std::set<T> operator+(std::set<T> _a, U const& _b)
{
return _a += _b;
}
/// Concatenate the contents of a container onto a vector
template <class T, class U> std::vector<T> operator+(std::vector<T> _a, U const& _b)
{
return _a += _b;
}
/// Concatenate two vectors of elements. /// Concatenate two vectors of elements.
template <class _T> template <class _T>
inline std::vector<_T> operator+(std::vector<_T> const& _a, std::vector<_T> const& _b) inline std::vector<_T> operator+(std::vector<_T> const& _a, std::vector<_T> const& _b)

6
libdevcore/CommonIO.cpp

@ -58,7 +58,7 @@ string dev::memDump(bytes const& _bytes, unsigned _width, bool _html)
} }
// Don't forget to delete[] later. // Don't forget to delete[] later.
bytesRef dev::contentsNew(std::string const& _file) bytesRef dev::contentsNew(std::string const& _file, bytesRef _dest)
{ {
std::ifstream is(_file, std::ifstream::binary); std::ifstream is(_file, std::ifstream::binary);
if (!is) if (!is)
@ -68,8 +68,10 @@ bytesRef dev::contentsNew(std::string const& _file)
streamoff length = is.tellg(); streamoff length = is.tellg();
if (length == 0) // return early, MSVC does not like reading 0 bytes if (length == 0) // return early, MSVC does not like reading 0 bytes
return bytesRef(); return bytesRef();
if (!_dest.empty() && _dest.size() != (unsigned)length)
return bytesRef();
is.seekg (0, is.beg); is.seekg (0, is.beg);
bytesRef ret(new byte[length], length); bytesRef ret = _dest.empty() ? bytesRef(new byte[length], length) : _dest;
is.read((char*)ret.data(), length); is.read((char*)ret.data(), length);
is.close(); is.close();
return ret; return ret;

2
libdevcore/CommonIO.h

@ -46,7 +46,7 @@ namespace dev
bytes contents(std::string const& _file); bytes contents(std::string const& _file);
std::string contentsString(std::string const& _file); std::string contentsString(std::string const& _file);
/// Retrieve and returns the allocated contents of the given file. If the file doesn't exist or isn't readable, returns nullptr. Don't forget to delete [] when finished. /// Retrieve and returns the allocated contents of the given file. If the file doesn't exist or isn't readable, returns nullptr. Don't forget to delete [] when finished.
bytesRef contentsNew(std::string const& _file); bytesRef contentsNew(std::string const& _file, bytesRef _dest = bytesRef());
/// Retrieve and returns the allocated contents of the given file and load into buffer. Used to fill mapped OpenCL buffer. /// Retrieve and returns the allocated contents of the given file and load into buffer. Used to fill mapped OpenCL buffer.
uint64_t contentsToBuffer(std::string const& _file, void * buf); uint64_t contentsToBuffer(std::string const& _file, void * buf);

71
libdevcore/Guards.h

@ -38,4 +38,75 @@ using UpgradableGuard = boost::upgrade_lock<boost::shared_mutex>;
using UpgradeGuard = boost::upgrade_to_unique_lock<boost::shared_mutex>; using UpgradeGuard = boost::upgrade_to_unique_lock<boost::shared_mutex>;
using WriteGuard = boost::unique_lock<boost::shared_mutex>; using WriteGuard = boost::unique_lock<boost::shared_mutex>;
template <class GuardType, class MutexType>
struct GenericGuardBool: GuardType
{
GenericGuardBool(MutexType& _m): GuardType(_m) {}
bool b = true;
};
template <class MutexType>
struct GenericUnguardBool
{
GenericUnguardBool(MutexType& _m): m(_m) { m.unlock(); }
~GenericUnguardBool() { m.lock(); }
bool b = true;
MutexType& m;
};
template <class MutexType>
struct GenericUnguardSharedBool
{
GenericUnguardSharedBool(MutexType& _m): m(_m) { m.unlock_shared(); }
~GenericUnguardSharedBool() { m.lock_shared(); }
bool b = true;
MutexType& m;
};
/** @brief Simple block guard.
* The expression/block following is guarded though the given mutex.
* Usage:
* @code
* Mutex m;
* unsigned d;
* ...
* ETH_GUARDED(m) d = 1;
* ...
* ETH_GUARDED(m) { for (auto d = 10; d > 0; --d) foo(d); d = 0; }
* @endcode
*
* There are several variants of this basic mechanism for different Mutex types and Guards.
*
* There is also the UNGUARD variant which allows an unguarded expression/block to exist within a
* guarded expression. eg:
*
* @code
* Mutex m;
* int d;
* ...
* ETH_GUARDED(m)
* {
* for (auto d = 50; d > 25; --d)
* foo(d);
* ETH_UNGUARDED(m)
* bar();
* for (; d > 0; --d)
* foo(d);
* }
* @endcode
*/
#define ETH_GUARDED(MUTEX) \
for (GenericGuardBool<Guard, Mutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
#define ETH_READ_GUARDED(MUTEX) \
for (GenericGuardBool<ReadGuard, SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
#define ETH_WRITE_GUARDED(MUTEX) \
for (GenericGuardBool<WriteGuard, SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
#define ETH_RECURSIVE_GUARDED(MUTEX) \
for (GenericGuardBool<RecursiveGuard, RecursiveMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
#define ETH_UNGUARDED(MUTEX) \
for (GenericUnguardBool<Mutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
#define ETH_READ_UNGUARDED(MUTEX) \
for (GenericUnguardSharedBool<SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
#define ETH_WRITE_UNGUARDED(MUTEX) \
for (GenericUnguardBool<SharedMutex> __eth_l(MUTEX); __eth_l.b; __eth_l.b = false)
} }

2
libdevcore/Log.cpp

@ -43,7 +43,7 @@ void dev::simpleDebugOut(std::string const& _s, char const*)
static Mutex s_lock; static Mutex s_lock;
Guard l(s_lock); Guard l(s_lock);
cout << _s << endl << flush; cerr << _s << endl << flush;
// helpful to use OutputDebugString on windows // helpful to use OutputDebugString on windows
#ifdef _WIN32 #ifdef _WIN32

2
libdevcore/RLP.cpp

@ -107,7 +107,7 @@ unsigned RLP::actualSize() const
if (isSingleByte()) if (isSingleByte())
return 1; return 1;
if (isData() || isList()) if (isData() || isList())
return payload().data() - m_data.data() + length(); return payloadOffset() + length();
return 0; return 0;
} }

5
libdevcore/RLP.h

@ -290,7 +290,7 @@ public:
RLPs toList() const; RLPs toList() const;
/// @returns the data payload. Valid for all types. /// @returns the data payload. Valid for all types.
bytesConstRef payload() const { return isSingleByte() ? m_data.cropped(0, 1) : m_data.cropped(1 + lengthSize()); } bytesConstRef payload() const { return m_data.cropped(payloadOffset()); }
/// @returns the theoretical size of this item. /// @returns the theoretical size of this item.
/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work. /// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.
@ -309,6 +309,9 @@ private:
/// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data. /// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data.
unsigned length() const; unsigned length() const;
/// @returns the number of bytes into the data that the payload starts.
unsigned payloadOffset() const { return isSingleByte() ? 0 : (1 + lengthSize()); }
/// @returns the number of data items. /// @returns the number of data items.
unsigned items() const; unsigned items() const;

1
libdevcore/RangeMask.h

@ -25,6 +25,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <assert.h>
namespace dev namespace dev
{ {

4
libtestutils/TransientDirectory.cpp → libdevcore/TransientDirectory.cpp

@ -20,11 +20,11 @@
*/ */
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <libdevcore/Exceptions.h> #include "Exceptions.h"
#include "TransientDirectory.h" #include "TransientDirectory.h"
#include "CommonIO.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::test;
TransientDirectory::TransientDirectory(): TransientDirectory::TransientDirectory():
TransientDirectory((boost::filesystem::temp_directory_path() / "eth_transient" / toString(FixedHash<4>::random())).string()) TransientDirectory((boost::filesystem::temp_directory_path() / "eth_transient" / toString(FixedHash<4>::random())).string())

4
libtestutils/TransientDirectory.h → libdevcore/TransientDirectory.h

@ -22,12 +22,9 @@
#pragma once #pragma once
#include <string> #include <string>
#include "Common.h"
namespace dev namespace dev
{ {
namespace test
{
/** /**
* @brief temporary directory implementation * @brief temporary directory implementation
@ -48,4 +45,3 @@ private:
}; };
} }
}

50
libdevcore/Worker.cpp

@ -27,39 +27,55 @@
using namespace std; using namespace std;
using namespace dev; using namespace dev;
void Worker::startWorking() void Worker::startWorking(IfRunning _ir)
{ {
cdebug << "startWorking for thread" << m_name; // cnote << "startWorking for thread" << m_name;
Guard l(x_work); Guard l(x_work);
if (m_work)
return; if (m_work && m_work->joinable())
cdebug << "Spawning" << m_name; try {
if (_ir == IfRunning::Detach)
m_work->detach();
else if (_ir == IfRunning::Join)
m_work->join();
else
return;
} catch (...) {}
cnote << "Spawning" << m_name;
m_stop = false; m_stop = false;
m_work.reset(new thread([&]() m_work.reset(new thread([&]()
{ {
setThreadName(m_name.c_str()); setThreadName(m_name.c_str());
startedWorking(); startedWorking();
while (!m_stop) workLoop();
{ m_work->detach();
if (m_idleWaitMs) cnote << "Finishing up worker thread";
this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs));
doWork();
}
cdebug << "Finishing up worker thread";
doneWorking(); doneWorking();
})); }));
} }
void Worker::stopWorking() void Worker::stopWorking()
{ {
cdebug << "stopWorking for thread" << m_name; // cnote << "stopWorking for thread" << m_name;
Guard l(x_work); Guard l(x_work);
if (!m_work) if (!m_work || !m_work->joinable())
return; return;
cdebug << "Stopping" << m_name; cnote << "Stopping" << m_name;
m_stop = true; m_stop = true;
m_work->join(); try {
m_work->join();
}
catch (...) {}
m_work.reset(); m_work.reset();
cdebug << "Stopped" << m_name; cnote << "Stopped" << m_name;
} }
void Worker::workLoop()
{
while (!m_stop)
{
if (m_idleWaitMs)
this_thread::sleep_for(chrono::milliseconds(m_idleWaitMs));
doWork();
}
}

19
libdevcore/Worker.h

@ -23,11 +23,19 @@
#include <string> #include <string>
#include <thread> #include <thread>
#include <atomic>
#include "Guards.h" #include "Guards.h"
namespace dev namespace dev
{ {
enum class IfRunning
{
Fail,
Join,
Detach
};
class Worker class Worker
{ {
protected: protected:
@ -45,7 +53,7 @@ protected:
void setName(std::string _n) { if (!isWorking()) m_name = _n; } void setName(std::string _n) { if (!isWorking()) m_name = _n; }
/// Starts worker thread; causes startedWorking() to be called. /// Starts worker thread; causes startedWorking() to be called.
void startWorking(); void startWorking(IfRunning _ir = IfRunning::Fail);
/// Stop worker thread; causes call to stopWorking(). /// Stop worker thread; causes call to stopWorking().
void stopWorking(); void stopWorking();
@ -57,11 +65,18 @@ protected:
virtual void startedWorking() {} virtual void startedWorking() {}
/// Called continuously following sleep for m_idleWaitMs. /// Called continuously following sleep for m_idleWaitMs.
virtual void doWork() = 0; virtual void doWork() {}
/// Overrides doWork(); should call shouldStop() often and exit when true.
virtual void workLoop();
bool shouldStop() const { return m_stop; }
/// Called when is to be stopped, just prior to thread being joined. /// Called when is to be stopped, just prior to thread being joined.
virtual void doneWorking() {} virtual void doneWorking() {}
/// Blocks caller into worker thread has finished.
void join() const { Guard l(x_work); try { if (m_work) m_work->join(); } catch (...) {} }
private: private:
std::string m_name; std::string m_name;
unsigned m_idleWaitMs = 0; unsigned m_idleWaitMs = 0;

6
libdevcrypto/Common.cpp

@ -37,9 +37,9 @@ static Secp256k1 s_secp256k1;
bool dev::SignatureStruct::isValid() const bool dev::SignatureStruct::isValid() const
{ {
if (this->v > 1 || if (v > 1 ||
this->r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") || r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||
this->s >= h256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f")) s >= h256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"))
return false; return false;
return true; return true;
} }

6
libdevcrypto/TrieDB.h

@ -161,9 +161,15 @@ public:
} }
} }
std::string at(bytes const& _key) const { return at(&_key); }
std::string at(bytesConstRef _key) const; std::string at(bytesConstRef _key) const;
void insert(bytes const& _key, bytes const& _value) { insert(&_key, &_value); }
void insert(bytesConstRef _key, bytes const& _value) { insert(_key, &_value); }
void insert(bytes const& _key, bytesConstRef _value) { insert(&_key, _value); }
void insert(bytesConstRef _key, bytesConstRef _value); void insert(bytesConstRef _key, bytesConstRef _value);
void remove(bytes const& _key) { remove(&_key); }
void remove(bytesConstRef _key); void remove(bytesConstRef _key);
bool contains(bytes const& _key) { return contains(&_key); }
bool contains(bytesConstRef _key) { return !at(_key).empty(); } bool contains(bytesConstRef _key) { return !at(_key).empty(); }
class iterator class iterator

19
libethash-cl/CMakeLists.txt

@ -0,0 +1,19 @@
set(EXECUTABLE ethash-cl)
include(bin2h.cmake)
bin2h(SOURCE_FILE ethash_cl_miner_kernel.cl
VARIABLE_NAME ethash_cl_miner_kernel
HEADER_FILE ${CMAKE_CURRENT_BINARY_DIR}/ethash_cl_miner_kernel.h)
aux_source_directory(. SRC_LIST)
file(GLOB HEADERS "*.h")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${OpenCL_INCLUDE_DIRS})
include_directories(..)
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
TARGET_LINK_LIBRARIES(${EXECUTABLE} ${OpenCL_LIBRARIES} ethash)
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

86
libethash-cl/bin2h.cmake

@ -0,0 +1,86 @@
# https://gist.github.com/sivachandran/3a0de157dccef822a230
include(CMakeParseArguments)
# Function to wrap a given string into multiple lines at the given column position.
# Parameters:
# VARIABLE - The name of the CMake variable holding the string.
# AT_COLUMN - The column position at which string will be wrapped.
function(WRAP_STRING)
set(oneValueArgs VARIABLE AT_COLUMN)
cmake_parse_arguments(WRAP_STRING "${options}" "${oneValueArgs}" "" ${ARGN})
string(LENGTH ${${WRAP_STRING_VARIABLE}} stringLength)
math(EXPR offset "0")
while(stringLength GREATER 0)
if(stringLength GREATER ${WRAP_STRING_AT_COLUMN})
math(EXPR length "${WRAP_STRING_AT_COLUMN}")
else()
math(EXPR length "${stringLength}")
endif()
string(SUBSTRING ${${WRAP_STRING_VARIABLE}} ${offset} ${length} line)
set(lines "${lines}\n${line}")
math(EXPR stringLength "${stringLength} - ${length}")
math(EXPR offset "${offset} + ${length}")
endwhile()
set(${WRAP_STRING_VARIABLE} "${lines}" PARENT_SCOPE)
endfunction()
# Function to embed contents of a file as byte array in C/C++ header file(.h). The header file
# will contain a byte array and integer variable holding the size of the array.
# Parameters
# SOURCE_FILE - The path of source file whose contents will be embedded in the header file.
# VARIABLE_NAME - The name of the variable for the byte array. The string "_SIZE" will be append
# to this name and will be used a variable name for size variable.
# HEADER_FILE - The path of header file.
# APPEND - If specified appends to the header file instead of overwriting it
# NULL_TERMINATE - If specified a null byte(zero) will be append to the byte array. This will be
# useful if the source file is a text file and we want to use the file contents
# as string. But the size variable holds size of the byte array without this
# null byte.
# Usage:
# bin2h(SOURCE_FILE "Logo.png" HEADER_FILE "Logo.h" VARIABLE_NAME "LOGO_PNG")
function(BIN2H)
set(options APPEND NULL_TERMINATE)
set(oneValueArgs SOURCE_FILE VARIABLE_NAME HEADER_FILE)
cmake_parse_arguments(BIN2H "${options}" "${oneValueArgs}" "" ${ARGN})
# reads source file contents as hex string
file(READ ${BIN2H_SOURCE_FILE} hexString HEX)
string(LENGTH ${hexString} hexStringLength)
# appends null byte if asked
if(BIN2H_NULL_TERMINATE)
set(hexString "${hexString}00")
endif()
# wraps the hex string into multiple lines at column 32(i.e. 16 bytes per line)
wrap_string(VARIABLE hexString AT_COLUMN 32)
math(EXPR arraySize "${hexStringLength} / 2")
# adds '0x' prefix and comma suffix before and after every byte respectively
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " arrayValues ${hexString})
# removes trailing comma
string(REGEX REPLACE ", $" "" arrayValues ${arrayValues})
# converts the variable name into proper C identifier
IF (${CMAKE_VERSION} GREATER 2.8.10) # fix for legacy cmake
string(MAKE_C_IDENTIFIER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME)
ENDIF()
string(TOUPPER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME)
# declares byte array and the length variables
set(arrayDefinition "const unsigned char ${BIN2H_VARIABLE_NAME}[] = { ${arrayValues} };")
set(arraySizeDefinition "const size_t ${BIN2H_VARIABLE_NAME}_SIZE = ${arraySize};")
set(declarations "${arrayDefinition}\n\n${arraySizeDefinition}\n\n")
if(BIN2H_APPEND)
file(APPEND ${BIN2H_HEADER_FILE} "${declarations}")
else()
file(WRITE ${BIN2H_HEADER_FILE} "${declarations}")
endif()
endfunction()

4014
libethash-cl/cl.hpp

File diff suppressed because it is too large

366
libethash-cl/ethash_cl_miner.cpp

@ -0,0 +1,366 @@
/*
This file is part of c-ethash.
c-ethash 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.
c-ethash 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 ethash_cl_miner.cpp
* @author Tim Hughes <tim@twistedfury.com>
* @date 2015
*/
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <assert.h>
#include <queue>
#include <vector>
#include <libethash/util.h>
#include <libethash/ethash.h>
#include "ethash_cl_miner.h"
#include "ethash_cl_miner_kernel.h"
#define ETHASH_BYTES 32
// workaround lame platforms
#if !CL_VERSION_1_2
#define CL_MAP_WRITE_INVALIDATE_REGION CL_MAP_WRITE
#define CL_MEM_HOST_READ_ONLY 0
#endif
#undef min
#undef max
static void add_definition(std::string& source, char const* id, unsigned value)
{
char buf[256];
sprintf(buf, "#define %s %uu\n", id, value);
source.insert(source.begin(), buf, buf + strlen(buf));
}
ethash_cl_miner::search_hook::~search_hook() {}
ethash_cl_miner::ethash_cl_miner()
: m_opencl_1_1()
{
}
std::string ethash_cl_miner::platform_info()
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (platforms.empty())
{
debugf("No OpenCL platforms found.\n");
return std::string();
}
// get GPU device of the default platform
std::vector<cl::Device> devices;
platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices);
if (devices.empty())
{
debugf("No OpenCL devices found.\n");
return std::string();
}
// use default device
unsigned device_num = 0;
cl::Device& device = devices[device_num];
std::string device_version = device.getInfo<CL_DEVICE_VERSION>();
return "{ \"platform\": \"" + platforms[0].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }";
}
void ethash_cl_miner::finish()
{
if (m_queue())
{
m_queue.finish();
}
}
bool ethash_cl_miner::init(ethash_params const& params, std::function<void(void*)> _fillDAG, unsigned workgroup_size, unsigned _deviceId)
{
// store params
m_params = params;
// get all platforms
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (platforms.empty())
{
debugf("No OpenCL platforms found.\n");
return false;
}
// use default platform
fprintf(stderr, "Using platform: %s\n", platforms[0].getInfo<CL_PLATFORM_NAME>().c_str());
// get GPU device of the default platform
std::vector<cl::Device> devices;
platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices);
if (devices.empty())
{
debugf("No OpenCL devices found.\n");
return false;
}
// use default device
cl::Device& device = devices[std::min<unsigned>(_deviceId, devices.size() - 1)];
for (unsigned n = 0; n < devices.size(); ++n)
{
auto version = devices[n].getInfo<CL_DEVICE_VERSION>();
auto name = devices[n].getInfo<CL_DEVICE_NAME>();
fprintf(stderr, "%s %d: %s (%s)\n", n == _deviceId ? "USING " : " ", n, name.c_str(), version.c_str());
}
std::string device_version = device.getInfo<CL_DEVICE_VERSION>();
fprintf(stderr, "Using device: %s (%s)\n", device.getInfo<CL_DEVICE_NAME>().c_str(),device_version.c_str());
if (strncmp("OpenCL 1.0", device_version.c_str(), 10) == 0)
{
debugf("OpenCL 1.0 is not supported.\n");
return false;
}
if (strncmp("OpenCL 1.1", device_version.c_str(), 10) == 0)
{
m_opencl_1_1 = true;
}
// create context
m_context = cl::Context(std::vector<cl::Device>(&device, &device + 1));
m_queue = cl::CommandQueue(m_context, device);
// use requested workgroup size, but we require multiple of 8
m_workgroup_size = ((workgroup_size + 7) / 8) * 8;
// patch source code
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, "DAG_SIZE", (unsigned)(params.full_size / ETHASH_MIX_BYTES));
add_definition(code, "ACCESSES", ETHASH_ACCESSES);
add_definition(code, "MAX_OUTPUTS", c_max_search_results);
//debugf("%s", code.c_str());
// create miner OpenCL program
cl::Program::Sources sources;
sources.push_back({code.c_str(), code.size()});
cl::Program program(m_context, sources);
try
{
program.build({device});
}
catch (cl::Error err)
{
debugf("%s\n", program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str());
return false;
}
m_hash_kernel = cl::Kernel(program, "ethash_hash");
m_search_kernel = cl::Kernel(program, "ethash_search");
// create buffer for dag
m_dag = cl::Buffer(m_context, CL_MEM_READ_ONLY, params.full_size);
// create buffer for header
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32);
// compute dag on CPU
{
// 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);
// memcpying 1GB: horrible... really. horrible. but necessary since we can't mmap *and* gpumap.
_fillDAG(dag_ptr);
m_queue.enqueueUnmapMemObject(m_dag, dag_ptr);
}
// create mining buffers
for (unsigned i = 0; i != c_num_buffers; ++i)
{
m_hash_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY | (!m_opencl_1_1 ? CL_MEM_HOST_READ_ONLY : 0), 32*c_hash_batch_size);
m_search_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY, (c_max_search_results + 1) * sizeof(uint32_t));
}
return true;
}
void ethash_cl_miner::hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count)
{
struct pending_batch
{
unsigned base;
unsigned count;
unsigned buf;
};
std::queue<pending_batch> pending;
// update header constant buffer
m_queue.enqueueWriteBuffer(m_header, true, 0, 32, header);
/*
__kernel void ethash_combined_hash(
__global hash32_t* g_hashes,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
ulong start_nonce,
uint isolate
)
*/
m_hash_kernel.setArg(1, m_header);
m_hash_kernel.setArg(2, m_dag);
m_hash_kernel.setArg(3, nonce);
m_hash_kernel.setArg(4, ~0u); // have to pass this to stop the compile unrolling the loop
unsigned buf = 0;
for (unsigned i = 0; i < count || !pending.empty(); )
{
// how many this batch
if (i < count)
{
unsigned const this_count = std::min<unsigned>(count - i, c_hash_batch_size);
unsigned const batch_count = std::max<unsigned>(this_count, m_workgroup_size);
// supply output hash buffer to kernel
m_hash_kernel.setArg(0, m_hash_buf[buf]);
// execute it!
m_queue.enqueueNDRangeKernel(
m_hash_kernel,
cl::NullRange,
cl::NDRange(batch_count),
cl::NDRange(m_workgroup_size)
);
m_queue.flush();
pending.push({i, this_count, buf});
i += this_count;
buf = (buf + 1) % c_num_buffers;
}
// read results
if (i == count || pending.size() == c_num_buffers)
{
pending_batch const& batch = pending.front();
// could use pinned host pointer instead, but this path isn't that important.
uint8_t* hashes = (uint8_t*)m_queue.enqueueMapBuffer(m_hash_buf[batch.buf], true, CL_MAP_READ, 0, batch.count * ETHASH_BYTES);
memcpy(ret + batch.base*ETHASH_BYTES, hashes, batch.count*ETHASH_BYTES);
m_queue.enqueueUnmapMemObject(m_hash_buf[batch.buf], hashes);
pending.pop();
}
}
}
void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook)
{
struct pending_batch
{
uint64_t start_nonce;
unsigned buf;
};
std::queue<pending_batch> pending;
static uint32_t const c_zero = 0;
// update header constant buffer
m_queue.enqueueWriteBuffer(m_header, false, 0, 32, header);
for (unsigned i = 0; i != c_num_buffers; ++i)
{
m_queue.enqueueWriteBuffer(m_search_buf[i], false, 0, 4, &c_zero);
}
#if CL_VERSION_1_2 && 0
cl::Event pre_return_event;
if (!m_opencl_1_1)
{
m_queue.enqueueBarrierWithWaitList(NULL, &pre_return_event);
}
else
#endif
{
m_queue.finish();
}
/*
__kernel void ethash_combined_search(
__global hash32_t* g_hashes, // 0
__constant hash32_t const* g_header, // 1
__global hash128_t const* g_dag, // 2
ulong start_nonce, // 3
ulong target, // 4
uint isolate // 5
)
*/
m_search_kernel.setArg(1, m_header);
m_search_kernel.setArg(2, m_dag);
// pass these to stop the compiler unrolling the loops
m_search_kernel.setArg(4, target);
m_search_kernel.setArg(5, ~0u);
unsigned buf = 0;
for (uint64_t start_nonce = 0; ; start_nonce += c_search_batch_size)
{
// supply output buffer to kernel
m_search_kernel.setArg(0, m_search_buf[buf]);
m_search_kernel.setArg(3, start_nonce);
// execute it!
m_queue.enqueueNDRangeKernel(m_search_kernel, cl::NullRange, c_search_batch_size, m_workgroup_size);
pending.push({start_nonce, buf});
buf = (buf + 1) % c_num_buffers;
// read results
if (pending.size() == c_num_buffers)
{
pending_batch const& batch = pending.front();
// could use pinned host pointer instead
uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_search_buf[batch.buf], true, CL_MAP_READ, 0, (1+c_max_search_results) * sizeof(uint32_t));
unsigned num_found = std::min<unsigned>(results[0], c_max_search_results);
uint64_t nonces[c_max_search_results];
for (unsigned i = 0; i != num_found; ++i)
{
nonces[i] = batch.start_nonce + results[i+1];
}
m_queue.enqueueUnmapMemObject(m_search_buf[batch.buf], results);
bool exit = num_found && hook.found(nonces, num_found);
exit |= hook.searched(batch.start_nonce, c_search_batch_size); // always report searched before exit
if (exit)
break;
// reset search buffer if we're still going
if (num_found)
m_queue.enqueueWriteBuffer(m_search_buf[batch.buf], true, 0, 4, &c_zero);
pending.pop();
}
}
// not safe to return until this is ready
#if CL_VERSION_1_2 && 0
if (!m_opencl_1_1)
{
pre_return_event.wait();
}
#endif
}

55
libethash-cl/ethash_cl_miner.h

@ -0,0 +1,55 @@
#pragma once
#define __CL_ENABLE_EXCEPTIONS
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#include "cl.hpp"
#pragma clang diagnostic pop
#else
#include "cl.hpp"
#endif
#include <time.h>
#include <functional>
#include <libethash/ethash.h>
class ethash_cl_miner
{
public:
struct search_hook
{
virtual ~search_hook(); // always a virtual destructor for a class with virtuals.
// reports progress, return true to abort
virtual bool found(uint64_t const* nonces, uint32_t count) = 0;
virtual bool searched(uint64_t start_nonce, uint32_t count) = 0;
};
public:
ethash_cl_miner();
bool init(ethash_params const& params, std::function<void(void*)> _fillDAG, unsigned workgroup_size = 64, unsigned _deviceId = 0);
static std::string platform_info();
void finish();
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);
private:
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::CommandQueue m_queue;
cl::Kernel m_hash_kernel;
cl::Kernel m_search_kernel;
cl::Buffer m_dag;
cl::Buffer m_header;
cl::Buffer m_hash_buf[c_num_buffers];
cl::Buffer m_search_buf[c_num_buffers];
unsigned m_workgroup_size;
bool m_opencl_1_1;
};

460
libethash-cl/ethash_cl_miner_kernel.cl

@ -0,0 +1,460 @@
// author Tim Hughes <tim@twistedfury.com>
// Tested on Radeon HD 7850
// Hashrate: 15940347 hashes/s
// Bandwidth: 124533 MB/s
// search kernel should fit in <= 84 VGPRS (3 wavefronts)
#define THREADS_PER_HASH (128 / 16)
#define HASHES_PER_LOOP (GROUP_SIZE / THREADS_PER_HASH)
#define FNV_PRIME 0x01000193
__constant uint2 const Keccak_f1600_RC[24] = {
(uint2)(0x00000001, 0x00000000),
(uint2)(0x00008082, 0x00000000),
(uint2)(0x0000808a, 0x80000000),
(uint2)(0x80008000, 0x80000000),
(uint2)(0x0000808b, 0x00000000),
(uint2)(0x80000001, 0x00000000),
(uint2)(0x80008081, 0x80000000),
(uint2)(0x00008009, 0x80000000),
(uint2)(0x0000008a, 0x00000000),
(uint2)(0x00000088, 0x00000000),
(uint2)(0x80008009, 0x00000000),
(uint2)(0x8000000a, 0x00000000),
(uint2)(0x8000808b, 0x00000000),
(uint2)(0x0000008b, 0x80000000),
(uint2)(0x00008089, 0x80000000),
(uint2)(0x00008003, 0x80000000),
(uint2)(0x00008002, 0x80000000),
(uint2)(0x00000080, 0x80000000),
(uint2)(0x0000800a, 0x00000000),
(uint2)(0x8000000a, 0x80000000),
(uint2)(0x80008081, 0x80000000),
(uint2)(0x00008080, 0x80000000),
(uint2)(0x80000001, 0x00000000),
(uint2)(0x80008008, 0x80000000),
};
void keccak_f1600_round(uint2* a, uint r, uint out_size)
{
#if !__ENDIAN_LITTLE__
for (uint i = 0; i != 25; ++i)
a[i] = a[i].yx;
#endif
uint2 b[25];
uint2 t;
// Theta
b[0] = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20];
b[1] = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21];
b[2] = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22];
b[3] = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23];
b[4] = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24];
t = b[4] ^ (uint2)(b[1].x << 1 | b[1].y >> 31, b[1].y << 1 | b[1].x >> 31);
a[0] ^= t;
a[5] ^= t;
a[10] ^= t;
a[15] ^= t;
a[20] ^= t;
t = b[0] ^ (uint2)(b[2].x << 1 | b[2].y >> 31, b[2].y << 1 | b[2].x >> 31);
a[1] ^= t;
a[6] ^= t;
a[11] ^= t;
a[16] ^= t;
a[21] ^= t;
t = b[1] ^ (uint2)(b[3].x << 1 | b[3].y >> 31, b[3].y << 1 | b[3].x >> 31);
a[2] ^= t;
a[7] ^= t;
a[12] ^= t;
a[17] ^= t;
a[22] ^= t;
t = b[2] ^ (uint2)(b[4].x << 1 | b[4].y >> 31, b[4].y << 1 | b[4].x >> 31);
a[3] ^= t;
a[8] ^= t;
a[13] ^= t;
a[18] ^= t;
a[23] ^= t;
t = b[3] ^ (uint2)(b[0].x << 1 | b[0].y >> 31, b[0].y << 1 | b[0].x >> 31);
a[4] ^= t;
a[9] ^= t;
a[14] ^= t;
a[19] ^= t;
a[24] ^= t;
// Rho Pi
b[0] = a[0];
b[10] = (uint2)(a[1].x << 1 | a[1].y >> 31, a[1].y << 1 | a[1].x >> 31);
b[7] = (uint2)(a[10].x << 3 | a[10].y >> 29, a[10].y << 3 | a[10].x >> 29);
b[11] = (uint2)(a[7].x << 6 | a[7].y >> 26, a[7].y << 6 | a[7].x >> 26);
b[17] = (uint2)(a[11].x << 10 | a[11].y >> 22, a[11].y << 10 | a[11].x >> 22);
b[18] = (uint2)(a[17].x << 15 | a[17].y >> 17, a[17].y << 15 | a[17].x >> 17);
b[3] = (uint2)(a[18].x << 21 | a[18].y >> 11, a[18].y << 21 | a[18].x >> 11);
b[5] = (uint2)(a[3].x << 28 | a[3].y >> 4, a[3].y << 28 | a[3].x >> 4);
b[16] = (uint2)(a[5].y << 4 | a[5].x >> 28, a[5].x << 4 | a[5].y >> 28);
b[8] = (uint2)(a[16].y << 13 | a[16].x >> 19, a[16].x << 13 | a[16].y >> 19);
b[21] = (uint2)(a[8].y << 23 | a[8].x >> 9, a[8].x << 23 | a[8].y >> 9);
b[24] = (uint2)(a[21].x << 2 | a[21].y >> 30, a[21].y << 2 | a[21].x >> 30);
b[4] = (uint2)(a[24].x << 14 | a[24].y >> 18, a[24].y << 14 | a[24].x >> 18);
b[15] = (uint2)(a[4].x << 27 | a[4].y >> 5, a[4].y << 27 | a[4].x >> 5);
b[23] = (uint2)(a[15].y << 9 | a[15].x >> 23, a[15].x << 9 | a[15].y >> 23);
b[19] = (uint2)(a[23].y << 24 | a[23].x >> 8, a[23].x << 24 | a[23].y >> 8);
b[13] = (uint2)(a[19].x << 8 | a[19].y >> 24, a[19].y << 8 | a[19].x >> 24);
b[12] = (uint2)(a[13].x << 25 | a[13].y >> 7, a[13].y << 25 | a[13].x >> 7);
b[2] = (uint2)(a[12].y << 11 | a[12].x >> 21, a[12].x << 11 | a[12].y >> 21);
b[20] = (uint2)(a[2].y << 30 | a[2].x >> 2, a[2].x << 30 | a[2].y >> 2);
b[14] = (uint2)(a[20].x << 18 | a[20].y >> 14, a[20].y << 18 | a[20].x >> 14);
b[22] = (uint2)(a[14].y << 7 | a[14].x >> 25, a[14].x << 7 | a[14].y >> 25);
b[9] = (uint2)(a[22].y << 29 | a[22].x >> 3, a[22].x << 29 | a[22].y >> 3);
b[6] = (uint2)(a[9].x << 20 | a[9].y >> 12, a[9].y << 20 | a[9].x >> 12);
b[1] = (uint2)(a[6].y << 12 | a[6].x >> 20, a[6].x << 12 | a[6].y >> 20);
// Chi
a[0] = bitselect(b[0] ^ b[2], b[0], b[1]);
a[1] = bitselect(b[1] ^ b[3], b[1], b[2]);
a[2] = bitselect(b[2] ^ b[4], b[2], b[3]);
a[3] = bitselect(b[3] ^ b[0], b[3], b[4]);
if (out_size >= 4)
{
a[4] = bitselect(b[4] ^ b[1], b[4], b[0]);
a[5] = bitselect(b[5] ^ b[7], b[5], b[6]);
a[6] = bitselect(b[6] ^ b[8], b[6], b[7]);
a[7] = bitselect(b[7] ^ b[9], b[7], b[8]);
a[8] = bitselect(b[8] ^ b[5], b[8], b[9]);
if (out_size >= 8)
{
a[9] = bitselect(b[9] ^ b[6], b[9], b[5]);
a[10] = bitselect(b[10] ^ b[12], b[10], b[11]);
a[11] = bitselect(b[11] ^ b[13], b[11], b[12]);
a[12] = bitselect(b[12] ^ b[14], b[12], b[13]);
a[13] = bitselect(b[13] ^ b[10], b[13], b[14]);
a[14] = bitselect(b[14] ^ b[11], b[14], b[10]);
a[15] = bitselect(b[15] ^ b[17], b[15], b[16]);
a[16] = bitselect(b[16] ^ b[18], b[16], b[17]);
a[17] = bitselect(b[17] ^ b[19], b[17], b[18]);
a[18] = bitselect(b[18] ^ b[15], b[18], b[19]);
a[19] = bitselect(b[19] ^ b[16], b[19], b[15]);
a[20] = bitselect(b[20] ^ b[22], b[20], b[21]);
a[21] = bitselect(b[21] ^ b[23], b[21], b[22]);
a[22] = bitselect(b[22] ^ b[24], b[22], b[23]);
a[23] = bitselect(b[23] ^ b[20], b[23], b[24]);
a[24] = bitselect(b[24] ^ b[21], b[24], b[20]);
}
}
// Iota
a[0] ^= Keccak_f1600_RC[r];
#if !__ENDIAN_LITTLE__
for (uint i = 0; i != 25; ++i)
a[i] = a[i].yx;
#endif
}
void keccak_f1600_no_absorb(ulong* a, uint in_size, uint out_size, uint isolate)
{
for (uint i = in_size; i != 25; ++i)
{
a[i] = 0;
}
#if __ENDIAN_LITTLE__
a[in_size] ^= 0x0000000000000001;
a[24-out_size*2] ^= 0x8000000000000000;
#else
a[in_size] ^= 0x0100000000000000;
a[24-out_size*2] ^= 0x0000000000000080;
#endif
// Originally I unrolled the first and last rounds to interface
// better with surrounding code, however I haven't done this
// without causing the AMD compiler to blow up the VGPR usage.
uint r = 0;
do
{
// This dynamic branch stops the AMD compiler unrolling the loop
// and additionally saves about 33% of the VGPRs, enough to gain another
// wavefront. Ideally we'd get 4 in flight, but 3 is the best I can
// massage out of the compiler. It doesn't really seem to matter how
// much we try and help the compiler save VGPRs because it seems to throw
// that information away, hence the implementation of keccak here
// doesn't bother.
if (isolate)
{
keccak_f1600_round((uint2*)a, r++, 25);
}
}
while (r < 23);
// final round optimised for digest size
keccak_f1600_round((uint2*)a, r++, out_size);
}
#define copy(dst, src, count) for (uint i = 0; i != count; ++i) { (dst)[i] = (src)[i]; }
#define countof(x) (sizeof(x) / sizeof(x[0]))
uint fnv(uint x, uint y)
{
return x * FNV_PRIME ^ y;
}
uint4 fnv4(uint4 x, uint4 y)
{
return x * FNV_PRIME ^ y;
}
uint fnv_reduce(uint4 v)
{
return fnv(fnv(fnv(v.x, v.y), v.z), v.w);
}
typedef union
{
ulong ulongs[32 / sizeof(ulong)];
uint uints[32 / sizeof(uint)];
} hash32_t;
typedef union
{
ulong ulongs[64 / sizeof(ulong)];
uint4 uint4s[64 / sizeof(uint4)];
} hash64_t;
typedef union
{
uint uints[128 / sizeof(uint)];
uint4 uint4s[128 / sizeof(uint4)];
} hash128_t;
hash64_t init_hash(__constant hash32_t const* header, ulong nonce, uint isolate)
{
hash64_t init;
uint const init_size = countof(init.ulongs);
uint const hash_size = countof(header->ulongs);
// sha3_512(header .. nonce)
ulong state[25];
copy(state, header->ulongs, hash_size);
state[hash_size] = nonce;
keccak_f1600_no_absorb(state, hash_size + 1, init_size, isolate);
copy(init.ulongs, state, init_size);
return init;
}
uint inner_loop(uint4 init, uint thread_id, __local uint* share, __global hash128_t const* g_dag, uint isolate)
{
uint4 mix = init;
// share init0
if (thread_id == 0)
*share = mix.x;
barrier(CLK_LOCAL_MEM_FENCE);
uint init0 = *share;
uint a = 0;
do
{
bool update_share = thread_id == (a/4) % THREADS_PER_HASH;
#pragma unroll
for (uint i = 0; i != 4; ++i)
{
if (update_share)
{
uint m[4] = { mix.x, mix.y, mix.z, mix.w };
*share = fnv(init0 ^ (a+i), m[i]) % DAG_SIZE;
}
barrier(CLK_LOCAL_MEM_FENCE);
mix = fnv4(mix, g_dag[*share].uint4s[thread_id]);
}
}
while ((a += 4) != (ACCESSES & isolate));
return fnv_reduce(mix);
}
hash32_t final_hash(hash64_t const* init, hash32_t const* mix, uint isolate)
{
ulong state[25];
hash32_t hash;
uint const hash_size = countof(hash.ulongs);
uint const init_size = countof(init->ulongs);
uint const mix_size = countof(mix->ulongs);
// keccak_256(keccak_512(header..nonce) .. mix);
copy(state, init->ulongs, init_size);
copy(state + init_size, mix->ulongs, mix_size);
keccak_f1600_no_absorb(state, init_size+mix_size, hash_size, isolate);
// copy out
copy(hash.ulongs, state, hash_size);
return hash;
}
hash32_t compute_hash_simple(
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
ulong nonce,
uint isolate
)
{
hash64_t init = init_hash(g_header, nonce, isolate);
hash128_t mix;
for (uint i = 0; i != countof(mix.uint4s); ++i)
{
mix.uint4s[i] = init.uint4s[i % countof(init.uint4s)];
}
uint mix_val = mix.uints[0];
uint init0 = mix.uints[0];
uint a = 0;
do
{
uint pi = fnv(init0 ^ a, mix_val) % DAG_SIZE;
uint n = (a+1) % countof(mix.uints);
#pragma unroll
for (uint i = 0; i != countof(mix.uints); ++i)
{
mix.uints[i] = fnv(mix.uints[i], g_dag[pi].uints[i]);
mix_val = i == n ? mix.uints[i] : mix_val;
}
}
while (++a != (ACCESSES & isolate));
// reduce to output
hash32_t fnv_mix;
for (uint i = 0; i != countof(fnv_mix.uints); ++i)
{
fnv_mix.uints[i] = fnv_reduce(mix.uint4s[i]);
}
return final_hash(&init, &fnv_mix, isolate);
}
typedef union
{
struct
{
hash64_t init;
uint pad; // avoid lds bank conflicts
};
hash32_t mix;
} compute_hash_share;
hash32_t compute_hash(
__local compute_hash_share* share,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
ulong nonce,
uint isolate
)
{
uint const gid = get_global_id(0);
// Compute one init hash per work item.
hash64_t init = init_hash(g_header, nonce, isolate);
// Threads work together in this phase in groups of 8.
uint const thread_id = gid % THREADS_PER_HASH;
uint const hash_id = (gid % GROUP_SIZE) / THREADS_PER_HASH;
hash32_t mix;
uint i = 0;
do
{
// share init with other threads
if (i == thread_id)
share[hash_id].init = init;
barrier(CLK_LOCAL_MEM_FENCE);
uint4 thread_init = share[hash_id].init.uint4s[thread_id % (64 / sizeof(uint4))];
barrier(CLK_LOCAL_MEM_FENCE);
uint thread_mix = inner_loop(thread_init, thread_id, share[hash_id].mix.uints, g_dag, isolate);
share[hash_id].mix.uints[thread_id] = thread_mix;
barrier(CLK_LOCAL_MEM_FENCE);
if (i == thread_id)
mix = share[hash_id].mix;
barrier(CLK_LOCAL_MEM_FENCE);
}
while (++i != (THREADS_PER_HASH & isolate));
return final_hash(&init, &mix, isolate);
}
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1)))
__kernel void ethash_hash_simple(
__global hash32_t* g_hashes,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
ulong start_nonce,
uint isolate
)
{
uint const gid = get_global_id(0);
g_hashes[gid] = compute_hash_simple(g_header, g_dag, start_nonce + gid, isolate);
}
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1)))
__kernel void ethash_search_simple(
__global volatile uint* restrict g_output,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
ulong start_nonce,
ulong target,
uint isolate
)
{
uint const gid = get_global_id(0);
hash32_t hash = compute_hash_simple(g_header, g_dag, start_nonce + gid, isolate);
if (as_ulong(as_uchar8(hash.ulongs[0]).s76543210) < target)
{
uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1);
g_output[slot] = gid;
}
}
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1)))
__kernel void ethash_hash(
__global hash32_t* g_hashes,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
ulong start_nonce,
uint isolate
)
{
__local compute_hash_share share[HASHES_PER_LOOP];
uint const gid = get_global_id(0);
g_hashes[gid] = compute_hash(share, g_header, g_dag, start_nonce + gid, isolate);
}
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1)))
__kernel void ethash_search(
__global volatile uint* restrict g_output,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
ulong start_nonce,
ulong target,
uint isolate
)
{
__local compute_hash_share share[HASHES_PER_LOOP];
uint const gid = get_global_id(0);
hash32_t hash = compute_hash(share, g_header, g_dag, start_nonce + gid, isolate);
if (as_ulong(as_uchar8(hash.ulongs[0]).s76543210) < target)
{
uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1);
g_output[slot] = gid;
}
}

4
libethash/ethash.h

@ -85,7 +85,7 @@ typedef uint8_t const ethash_seedhash_t[32];
typedef void const* ethash_light_t; typedef void const* ethash_light_t;
static inline ethash_light_t ethash_new_light(ethash_params const* params, ethash_seedhash_t seed) { static inline ethash_light_t ethash_new_light(ethash_params const* params, ethash_seedhash_t seed) {
void* ret = malloc(params->cache_size); void* ret = malloc((size_t)params->cache_size);
ethash_mkcache(ret, params, seed); ethash_mkcache(ret, params, seed);
return ret; return ret;
} }
@ -98,7 +98,7 @@ static inline void ethash_delete_light(ethash_light_t light) {
typedef void const* ethash_full_t; typedef void const* ethash_full_t;
static inline ethash_full_t ethash_new_full(ethash_params const* params, ethash_light_t light) { static inline ethash_full_t ethash_new_full(ethash_params const* params, ethash_light_t light) {
void* ret = malloc(params->full_size); void* ret = malloc((size_t)params->full_size);
ethash_compute_full_data(ret, params, light); ethash_compute_full_data(ret, params, light);
return ret; return ret;
} }

6
libethash/io.c

@ -61,13 +61,13 @@ bool ethash_io_write(char const *dirname,
{ {
char info_buffer[DAG_MEMO_BYTESIZE]; char info_buffer[DAG_MEMO_BYTESIZE];
// allocate the bytes // allocate the bytes
uint8_t *temp_data_ptr = malloc(params->full_size); uint8_t *temp_data_ptr = malloc((size_t)params->full_size);
if (!temp_data_ptr) { if (!temp_data_ptr) {
goto end; goto end;
} }
ethash_compute_full_data(temp_data_ptr, params, cache); ethash_compute_full_data(temp_data_ptr, params, cache);
if (!ethash_io_write_file(dirname, PASS_ARR(DAG_FILE_NAME), temp_data_ptr, params->full_size)) { if (!ethash_io_write_file(dirname, PASS_ARR(DAG_FILE_NAME), temp_data_ptr, (size_t)params->full_size)) {
goto fail_free; goto fail_free;
} }
@ -77,7 +77,7 @@ bool ethash_io_write(char const *dirname,
} }
*data = temp_data_ptr; *data = temp_data_ptr;
*data_size = params->full_size; *data_size = (size_t)params->full_size;
return true; return true;
fail_free: fail_free:

2
libethash/util.h

@ -29,7 +29,7 @@ extern "C" {
#ifdef _MSC_VER #ifdef _MSC_VER
void debugf(const char *str, ...); void debugf(const char *str, ...);
#else #else
#define debugf printf #define debugf(...) fprintf(stderr, __VA_ARGS__)
#endif #endif
static inline uint32_t min_u32(uint32_t a, uint32_t b) static inline uint32_t min_u32(uint32_t a, uint32_t b)

75
libethcore/BlockInfo.cpp

@ -23,6 +23,7 @@
#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 "EthashAux.h"
#include "ProofOfWork.h" #include "ProofOfWork.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "Params.h" #include "Params.h"
@ -35,12 +36,12 @@ BlockInfo::BlockInfo(): timestamp(Invalid256)
{ {
} }
BlockInfo::BlockInfo(bytesConstRef _block, Strictness _s) BlockInfo::BlockInfo(bytesConstRef _block, Strictness _s, h256 const& _h)
{ {
populate(_block, _s); populate(_block, _s, _h);
} }
void BlockInfo::setEmpty() void BlockInfo::clear()
{ {
parentHash = h256(); parentHash = h256();
sha3Uncles = EmptyListSHA3; sha3Uncles = EmptyListSHA3;
@ -57,22 +58,34 @@ void BlockInfo::setEmpty()
extraData.clear(); extraData.clear();
mixHash = h256(); mixHash = h256();
nonce = Nonce(); nonce = Nonce();
m_seedHash = h256(); m_hash = m_seedHash = h256();
hash = headerHash(WithNonce);
} }
h256 const& BlockInfo::seedHash() const h256 const& BlockInfo::seedHash() const
{ {
if (!m_seedHash) if (!m_seedHash)
for (u256 n = number; n >= c_epochDuration; n -= c_epochDuration) m_seedHash = EthashAux::seedHash((unsigned)number);
m_seedHash = sha3(m_seedHash);
return m_seedHash; return m_seedHash;
} }
BlockInfo BlockInfo::fromHeader(bytesConstRef _block, Strictness _s) h256 const& BlockInfo::hash() const
{
if (!m_hash)
m_hash = headerHash(WithNonce);
return m_hash;
}
h256 const& BlockInfo::boundary() const
{
if (!m_boundary)
m_boundary = (h256)(u256)((bigint(1) << 256) / difficulty);
return m_boundary;
}
BlockInfo BlockInfo::fromHeader(bytesConstRef _header, Strictness _s, h256 const& _h)
{ {
BlockInfo ret; BlockInfo ret;
ret.populateFromHeader(RLP(_block), _s); ret.populateFromHeader(RLP(_header), _s, _h);
return ret; return ret;
} }
@ -97,9 +110,12 @@ h256 BlockInfo::headerHash(bytesConstRef _block)
return sha3(RLP(_block)[0].data()); return sha3(RLP(_block)[0].data());
} }
void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s) void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const& _h)
{ {
hash = dev::sha3(_header.data()); m_hash = _h;
if (_h)
assert(_h == dev::sha3(_header.data()));
m_seedHash = h256();
int field = 0; int field = 0;
try try
@ -129,9 +145,14 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s)
throw; throw;
} }
if (number > ~(unsigned)0)
throw InvalidNumber();
// check it hashes according to proof of work or that it's the genesis block. // check it hashes according to proof of work or that it's the genesis block.
if (_s == CheckEverything && parentHash && !ProofOfWork::verify(*this)) if (_s == CheckEverything && parentHash && !ProofOfWork::verify(*this))
BOOST_THROW_EXCEPTION(InvalidBlockNonce() << errinfo_hash256(headerHash(WithoutNonce)) << errinfo_nonce(nonce) << errinfo_difficulty(difficulty)); BOOST_THROW_EXCEPTION(InvalidBlockNonce() << errinfo_hash256(headerHash(WithoutNonce)) << errinfo_nonce(nonce) << errinfo_difficulty(difficulty));
else if (_s == QuickNonce && parentHash && !ProofOfWork::preVerify(*this))
BOOST_THROW_EXCEPTION(InvalidBlockNonce() << errinfo_hash256(headerHash(WithoutNonce)) << errinfo_nonce(nonce) << errinfo_difficulty(difficulty));
if (_s != CheckNothing) if (_s != CheckNothing)
{ {
@ -149,14 +170,14 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s)
} }
} }
void BlockInfo::populate(bytesConstRef _block, Strictness _s) void BlockInfo::populate(bytesConstRef _block, Strictness _s, h256 const& _h)
{ {
RLP root(_block); RLP root(_block);
RLP header = root[0]; RLP header = root[0];
if (!header.isList()) if (!header.isList())
BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block header needs to be a list") << BadFieldError(0, header.data().toString())); BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block header needs to be a list") << BadFieldError(0, header.data().toString()));
populateFromHeader(header, _s); populateFromHeader(header, _s, _h);
if (!root[1].isList()) if (!root[1].isList())
BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block transactions need to be a list") << BadFieldError(1, root[1].data().toString())); BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block transactions need to be a list") << BadFieldError(1, root[1].data().toString()));
@ -164,13 +185,21 @@ void BlockInfo::populate(bytesConstRef _block, Strictness _s)
BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block uncles need to be a list") << BadFieldError(2, root[2].data().toString())); BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block uncles need to be a list") << BadFieldError(2, root[2].data().toString()));
} }
template <class T, class U> h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue)
{
MemoryDB db;
GenericTrieDB<MemoryDB> t(&db);
t.init();
for (unsigned i = 0; i < _itemCount; ++i)
t.insert(_getKey(i), _getValue(i));
return t.root();
}
void BlockInfo::verifyInternals(bytesConstRef _block) const void BlockInfo::verifyInternals(bytesConstRef _block) const
{ {
RLP root(_block); RLP root(_block);
u256 mgp = (u256)-1; /*OverlayDB db;
OverlayDB db;
GenericTrieDB<OverlayDB> t(&db); GenericTrieDB<OverlayDB> t(&db);
t.init(); t.init();
unsigned i = 0; unsigned i = 0;
@ -178,12 +207,13 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const
{ {
bytes k = rlp(i); bytes k = rlp(i);
t.insert(&k, tr.data()); t.insert(&k, tr.data());
u256 gasprice = tr[1].toInt<u256>();
mgp = min(mgp, gasprice); // the minimum gas price is not used for anything //TODO delete?
++i; ++i;
} }
if (transactionsRoot != t.root()) if (transactionsRoot != t.root())*/
BOOST_THROW_EXCEPTION(InvalidTransactionsHash() << HashMismatchError(t.root(), transactionsRoot)); auto txList = root[1];
auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data(); });
if (transactionsRoot != expectedRoot)
BOOST_THROW_EXCEPTION(InvalidTransactionsHash() << HashMismatchError(expectedRoot, transactionsRoot));
if (sha3Uncles != sha3(root[2].data())) if (sha3Uncles != sha3(root[2].data()))
BOOST_THROW_EXCEPTION(InvalidUnclesHash()); BOOST_THROW_EXCEPTION(InvalidUnclesHash());
@ -191,8 +221,9 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const
void BlockInfo::populateFromParent(BlockInfo const& _parent) void BlockInfo::populateFromParent(BlockInfo const& _parent)
{ {
noteDirty();
stateRoot = _parent.stateRoot; stateRoot = _parent.stateRoot;
parentHash = _parent.hash; parentHash = _parent.hash();
number = _parent.number + 1; number = _parent.number + 1;
gasLimit = selectGasLimit(_parent); gasLimit = selectGasLimit(_parent);
gasUsed = 0; gasUsed = 0;
@ -230,7 +261,7 @@ void BlockInfo::verifyParent(BlockInfo const& _parent) const
// Check timestamp is after previous timestamp. // Check timestamp is after previous timestamp.
if (parentHash) if (parentHash)
{ {
if (parentHash != _parent.hash) if (parentHash != _parent.hash())
BOOST_THROW_EXCEPTION(InvalidParentHash()); BOOST_THROW_EXCEPTION(InvalidParentHash());
if (timestamp <= _parent.timestamp) if (timestamp <= _parent.timestamp)

56
libethcore/BlockInfo.h

@ -39,6 +39,7 @@ enum IncludeNonce
enum Strictness enum Strictness
{ {
CheckEverything, CheckEverything,
QuickNonce,
IgnoreNonce, IgnoreNonce,
CheckNothing CheckNothing
}; };
@ -68,7 +69,6 @@ struct BlockInfo
{ {
public: public:
// TODO: make them all private! // TODO: make them all private!
h256 hash; ///< SHA3 hash of the block header! Not serialised (the only member not contained in a block header).
h256 parentHash; h256 parentHash;
h256 sha3Uncles; h256 sha3Uncles;
Address coinbaseAddress; Address coinbaseAddress;
@ -80,48 +80,50 @@ public:
u256 number; u256 number;
u256 gasLimit; u256 gasLimit;
u256 gasUsed; u256 gasUsed;
u256 timestamp; u256 timestamp = Invalid256;
bytes extraData; bytes extraData;
h256 mixHash; h256 mixHash;
Nonce nonce; Nonce nonce;
BlockInfo(); BlockInfo();
explicit BlockInfo(bytes const& _block, Strictness _s = CheckEverything): BlockInfo(&_block, _s) {} explicit BlockInfo(bytes const& _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()): BlockInfo(&_block, _s, _h) {}
explicit BlockInfo(bytesConstRef _block, Strictness _s = CheckEverything); explicit BlockInfo(bytesConstRef _block, Strictness _s = IgnoreNonce, h256 const& _h = h256());
static h256 headerHash(bytes const& _block) { return headerHash(&_block); } static h256 headerHash(bytes const& _block) { return headerHash(&_block); }
static h256 headerHash(bytesConstRef _block); static h256 headerHash(bytesConstRef _block);
static BlockInfo fromHeader(bytes const& _block, Strictness _s = CheckEverything) { return fromHeader(bytesConstRef(&_block), _s); } static BlockInfo fromHeader(bytes const& _header, Strictness _s = IgnoreNonce, h256 const& _h = h256()) { return fromHeader(bytesConstRef(&_header), _s, _h); }
static BlockInfo fromHeader(bytesConstRef _block, Strictness _s = CheckEverything); static BlockInfo fromHeader(bytesConstRef _header, Strictness _s = IgnoreNonce, h256 const& _h = h256());
explicit operator bool() const { return timestamp != Invalid256; } explicit operator bool() const { return timestamp != Invalid256; }
bool operator==(BlockInfo const& _cmp) const bool operator==(BlockInfo const& _cmp) const
{ {
return parentHash == _cmp.parentHash && return parentHash == _cmp.parentHash &&
sha3Uncles == _cmp.sha3Uncles && sha3Uncles == _cmp.sha3Uncles &&
coinbaseAddress == _cmp.coinbaseAddress && coinbaseAddress == _cmp.coinbaseAddress &&
stateRoot == _cmp.stateRoot && stateRoot == _cmp.stateRoot &&
transactionsRoot == _cmp.transactionsRoot && transactionsRoot == _cmp.transactionsRoot &&
receiptsRoot == _cmp.receiptsRoot && receiptsRoot == _cmp.receiptsRoot &&
logBloom == _cmp.logBloom && logBloom == _cmp.logBloom &&
difficulty == _cmp.difficulty && difficulty == _cmp.difficulty &&
number == _cmp.number && number == _cmp.number &&
gasLimit == _cmp.gasLimit && gasLimit == _cmp.gasLimit &&
gasUsed == _cmp.gasUsed && gasUsed == _cmp.gasUsed &&
timestamp == _cmp.timestamp && timestamp == _cmp.timestamp &&
extraData == _cmp.extraData && extraData == _cmp.extraData &&
mixHash == _cmp.mixHash && mixHash == _cmp.mixHash &&
nonce == _cmp.nonce; nonce == _cmp.nonce;
} }
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); } bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); }
void setEmpty(); void clear();
void populateFromHeader(RLP const& _header, Strictness _s = CheckEverything); void noteDirty() const { m_hash = m_seedHash = m_boundary = h256(); }
void populate(bytesConstRef _block, Strictness _s = CheckEverything);
void populate(bytes const& _block, Strictness _s = CheckEverything) { populate(&_block, _s); } void populateFromHeader(RLP const& _header, Strictness _s = IgnoreNonce, h256 const& _h = h256());
void populate(bytesConstRef _block, Strictness _s = IgnoreNonce, h256 const& _h = h256());
void populate(bytes const& _block, Strictness _s = IgnoreNonce, h256 const& _h = h256()) { populate(&_block, _s, _h); }
void verifyInternals(bytesConstRef _block) const; void verifyInternals(bytesConstRef _block) const;
void verifyParent(BlockInfo const& _parent) const; void verifyParent(BlockInfo const& _parent) const;
void populateFromParent(BlockInfo const& parent); void populateFromParent(BlockInfo const& parent);
@ -129,6 +131,8 @@ public:
u256 calculateDifficulty(BlockInfo const& _parent) const; u256 calculateDifficulty(BlockInfo const& _parent) const;
u256 selectGasLimit(BlockInfo const& _parent) const; u256 selectGasLimit(BlockInfo const& _parent) const;
h256 const& seedHash() const; h256 const& seedHash() const;
h256 const& hash() const;
h256 const& boundary() const;
/// sha3 of the header only. /// sha3 of the header only.
h256 headerHash(IncludeNonce _n) const; h256 headerHash(IncludeNonce _n) const;
@ -136,11 +140,13 @@ public:
private: private:
mutable h256 m_seedHash; mutable h256 m_seedHash;
mutable h256 m_hash; ///< SHA3 hash of the block header! Not serialised.
mutable h256 m_boundary; ///< 2^256 / difficulty
}; };
inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi) inline std::ostream& operator<<(std::ostream& _out, BlockInfo const& _bi)
{ {
_out << _bi.hash << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " << _out << _bi.hash() << " " << _bi.parentHash << " " << _bi.sha3Uncles << " " << _bi.coinbaseAddress << " " << _bi.stateRoot << " " << _bi.transactionsRoot << " " <<
_bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.gasLimit << " " << _bi.receiptsRoot << " " << _bi.logBloom << " " << _bi.difficulty << " " << _bi.number << " " << _bi.gasLimit << " " <<
_bi.gasUsed << " " << _bi.timestamp << " " << _bi.mixHash << " " << _bi.nonce << " (" << _bi.seedHash() << ")"; _bi.gasUsed << " " << _bi.timestamp << " " << _bi.mixHash << " " << _bi.nonce << " (" << _bi.seedHash() << ")";
return _out; return _out;

16
libethcore/CMakeLists.txt

@ -12,6 +12,14 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..) include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
if (ETHASHCL)
include_directories(${OpenCL_INCLUDE_DIRS})
endif ()
if (CPUID_FOUND)
include_directories(${Cpuid_INCLUDE_DIRS})
endif ()
set(EXECUTABLE ethcore) set(EXECUTABLE ethcore)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
@ -26,6 +34,14 @@ target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
if (ETHASHCL)
target_link_libraries(${EXECUTABLE} ethash-cl)
endif ()
if (CPUID_FOUND)
target_link_libraries(${EXECUTABLE} ${CPUID_LIBRARIES})
endif ()
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} )

8
libethcore/Common.cpp

@ -22,8 +22,8 @@
#include "Common.h" #include "Common.h"
#include <random> #include <random>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include "Ethasher.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "ProofOfWork.h"
using namespace std; using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
@ -33,16 +33,16 @@ namespace dev
namespace eth namespace eth
{ {
const unsigned c_ethashVersion = c_ethashRevision;
const unsigned c_protocolVersion = 60; const unsigned c_protocolVersion = 60;
const unsigned c_databaseBaseVersion = 8; const unsigned c_minorProtocolVersion = 0;
const unsigned c_databaseBaseVersion = 9;
#if ETH_FATDB #if ETH_FATDB
const unsigned c_databaseVersionModifier = 1; const unsigned c_databaseVersionModifier = 1;
#else #else
const unsigned c_databaseVersionModifier = 0; const unsigned c_databaseVersionModifier = 0;
#endif #endif
const unsigned c_databaseVersion = c_databaseBaseVersion + (c_databaseVersionModifier << 8) + (c_ethashVersion << 9); const unsigned c_databaseVersion = c_databaseBaseVersion + (c_databaseVersionModifier << 8) + (ProofOfWork::revision() << 9);
vector<pair<u256, string>> const& units() vector<pair<u256, string>> const& units()
{ {

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

Loading…
Cancel
Save