diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ed54656f..3d055587c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,38 +1,82 @@ # cmake global -project(ethereum) cmake_minimum_required(VERSION 2.8.9) -set(CMAKE_AUTOMOC ON) -cmake_policy(SET CMP0015 NEW) + +project(ethereum) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + + +###################################################################################################### # user defined, defaults # Normally, set(...CACHE...) creates cache variables, but does not modify them. +function(createDefaultCacheConfig) + set(HEADLESS OFF CACHE BOOL "Do not compile GUI (AlethZero)") + set(LANGUAGES OFF CACHE BOOL "Limit build to Serpent/LLL tools") + 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") +endfunction() -set(HEADLESS OFF CACHE BOOL "Do not compile GUI (AlethZero)") -set(LANGUAGES OFF CACHE BOOL "Limit build to Serpent/LLL tools") -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") -if (LANGUAGES) +# propagates CMake configuration options to the compiler +function(configureProject) + if (LANGUAGES) add_definitions(-DETH_LANGUAGES) -endif () + endif () -if (PARANOIA) + if (PARANOIA) if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 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) else () message(FATAL_ERROR "VM tracing requires debug.") endif () -endif () + endif () +endfunction() + + +function(createBuildInfo) + # Set build platform; to be written to BuildInfo.h + if (CMAKE_COMPILER_IS_MINGW) + set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/mingw") + elseif (CMAKE_COMPILER_IS_MSYS) + set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/msys") + elseif (CMAKE_COMPILER_IS_GNUCXX) + set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/g++") + elseif (CMAKE_COMPILER_IS_MSVC) + set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/msvc") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/clang") + else () + set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/unknown") + endif () + + # Generate header file containing useful build information + add_custom_target(BuildInfo.h ALL COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/BuildInfo.sh ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BUILD_TYPE} ${ETH_BUILD_PLATFORM}) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(SRC_LIST BuildInfo.h) +endfunction() + +###################################################################################################### + + +set(CMAKE_AUTOMOC ON) +cmake_policy(SET CMP0015 NEW) + + +createDefaultCacheConfig() +configureProject() +message("-- LANGUAGES: ${LANGUAGES}; VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}") -message("LANGUAGES: ${LANGUAGES}; VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}") # Default TARGET_PLATFORM to "linux". set(TARGET_PLATFORM CACHE STRING "linux") @@ -49,290 +93,28 @@ endif () # set(CMAKE_BUILD_TYPE RelWithDebInfo) # endif() -# Initialize CXXFLAGS -set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") -set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") -set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") - -# Windows -if ("${TARGET_PLATFORM}" STREQUAL "w64") - set(CMAKE_SYSTEM_NAME Windows) - - set(CMAKE_CXX_LIBRARY_ARCHITECTURE x86_64-w64-mingw32) - set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) - set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) - set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) - set(CMAKE_AR x86_64-w64-mingw32-ar) - set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib) - - set(CMAKE_EXECUTABLE_SUFFIX .exe) - - set(CMAKE_FIND_ROOT_PATH - /usr/x86_64-w64-mingw32 - ) - - include_directories(/usr/x86_64-w64-mingw32/include/cryptopp) - - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - - set(CMAKE_INSTALL_PREFIX /usr/x86_64-w64-mingw32) - set(ETH_BUILD_PLATFORM "windows") - set(ETH_STATIC 1) -else () - set(ETH_BUILD_PLATFORM ${CMAKE_SYSTEM_NAME}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") - set(ETH_SHARED 1) -endif() -# Set build platform; to be written to BuildInfo.h -if (CMAKE_COMPILER_IS_MINGW) - set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/mingw") -elseif (CMAKE_COMPILER_IS_MSYS) - set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/msys") -elseif (CMAKE_COMPILER_IS_GNUCXX) - set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/g++") -elseif (CMAKE_COMPILER_IS_MSVC) - set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/msvc") -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/clang") -else () - set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/unknown") -endif () +include(EthCompilerSettings) +message("-- CXXFLAGS: ${CMAKE_CXX_FLAGS}") -message("CXXFLAGS: ${CMAKE_CXX_FLAGS}") #add_definitions("-DETH_BUILD_TYPE=${ETH_BUILD_TYPE}") #add_definitions("-DETH_BUILD_PLATFORM=${ETH_BUILD_PLATFORM}") -# C++11 check and activation -if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") - execute_process( - COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) - if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) - message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") - endif () -elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") -else () - message(FATAL_ERROR "Your C++ compiler does not support C++11.") -endif () - -if("${TARGET_PLATFORM}" STREQUAL "w64") -# set(MINIUPNPC_LS /usr/x86_64-w64-mingw32/lib/libminiupnpc.a) - set(LEVELDB_LS leveldb) - set(CRYPTOPP_LS cryptopp) - set(CRYPTOPP_ID /usr/x86_64-w64-mingw32/include/cryptopp) -else() - # Look for available Crypto++ version and if it is >= 5.6.2 - find_path(ID cryptlib.h - ../cryptopp/src - ../../cryptopp/src - /usr/include/cryptopp - /usr/include/crypto++ - /usr/local/include/cryptopp - /usr/local/include/crypto++ - /opt/local/include/cryptopp - /opt/local/include/crypto++ - ) - find_library(LS NAMES cryptoppeth cryptopp - ../cryptopp/src/../target/build/release - ../../cryptopp/src/../target/build/release - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - ) - - if (ID AND LS) - message(STATUS "Found Crypto++: ${ID}, ${LS}") - set(_CRYPTOPP_VERSION_HEADER ${ID}/config.h) - if(EXISTS ${_CRYPTOPP_VERSION_HEADER}) - file(STRINGS ${_CRYPTOPP_VERSION_HEADER} _CRYPTOPP_VERSION REGEX "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") - string(REGEX REPLACE "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION ${_CRYPTOPP_VERSION}) - if(${_CRYPTOPP_VERSION} LESS 562) - message(FATAL_ERROR "Crypto++ version found is smaller than 5.6.2.") - else() - set(CRYPTOPP_ID ${ID} CACHE FILEPATH "") - set(CRYPTOPP_LS ${LS} CACHE FILEPATH "") - message(STATUS "Crypto++ found and version greater or equal to 5.6.2") - endif() - endif() - else() - message(STATUS "Crypto++ Not Found: ${CRYPTOPP_ID}, ${CRYPTOPP_LS}") - endif() - - find_path( LEVELDB_ID leveldb/db.h - /usr/include - /usr/local/include - ) - if ( LEVELDB_ID STREQUAL "LEVELDB_ID-NOTFOUND" ) - message(FATAL_ERROR "Failed to find the LevelDB headers") - else () - message(STATUS "Found LevelDB Headers") - - # Check for accessory dev libraries leveldb and miniupnpc - find_library( LEVELDB_LS NAMES leveldb - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( LEVELDB_LS STREQUAL "LEVELDB_LS-NOTFOUND" ) - message(FATAL_ERROR "Failed to find the LevelDB Library!") - else () - message(STATUS "Found LevelDB Library: ${LEVELDB_LS}") - add_definitions(-DETH_LEVELDB) - endif () - endif () - - find_path( PYTHON_ID pyconfig.h - ${PYTHON_INCLUDE_DIR} - /usr/include/python2.7 - /usr/local/include/python2.7 - ) - if ( PYTHON_ID STREQUAL "PYTHON_ID-NOTFOUND" ) - message(STATUS "Failed to find the Python-2.7 headers") - else () - message(STATUS "Found Python-2.7 Headers: ${PYTHON_ID}") - - # Check for accessory dev libraries leveldb and miniupnpc - find_library( PYTHON_LS NAMES python2.7 - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( PYTHON_LS STREQUAL "PYTHON_LS-NOTFOUND" ) - message(STATUS "Failed to find the Python-2.7 Library!") - set(PYTHON_ID) - set(PYTHON_LS) - else () - message(STATUS "Found Python-2.7 Library: ${PYTHON_LS}") - add_definitions(-DETH_PYTHON) - endif () - endif () - - find_path( MINIUPNPC_ID miniupnpc/miniwget.h - /usr/include - /usr/local/include - ) - if ( MINIUPNPC_ID ) - message(STATUS "Found miniupnpc headers") - - find_library( MINIUPNPC_LS NAMES miniupnpc - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( MINIUPNPC_LS ) - message(STATUS "Found miniupnpc library: ${MINIUPNPC_LS}") - add_definitions(-DETH_MINIUPNPC) - else () - message(STATUS "Failed to find the miniupnpc library!") - endif () - else () - message(STATUS "Failed to find the miniupnpc headers!") - endif () - - find_path( JSONRPC_ID jsonrpc/rpc.h - /usr/include - /usr/local/include - ) - if ( JSONRPC_ID ) - message(STATUS "Found jsonrpc headers") - find_library( JSONRPC_LS NAMES jsonrpc - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( JSONRPC_LS ) - message(STATUS "Found jsonrpc library: ${JSONRPC_LS}") - add_definitions(-DETH_JSONRPC) - else () - message(STATUS "Failed to find the jsonrpc library!") - endif () - else () - message(STATUS "Failed to find the jsonrpc headers!") - endif () - find_path( READLINE_ID readline/readline.h - /usr/include - /usr/local/include - ) - if ( READLINE_ID ) - message(STATUS "Found readline headers") - find_library( READLINE_LS NAMES readline - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /usr/lib/*/ - ) - if ( READLINE_LS ) - message(STATUS "Found readline library: ${READLINE_LS}") - add_definitions(-DETH_READLINE) - else () - message(STATUS "Failed to find the readline library!") - endif () - else () - message(STATUS "Failed to find the readline headers!") - endif () +include(EthDependenciesDeprecated) - if (LANGUAGES) - find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time) - else() - find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time system regex) - endif() - - set(QTQML 1) -endif() - -if(CRYPTOPP_ID) - include_directories(${CRYPTOPP_ID}) -endif() -if(PYTHON_ID) - include_directories(${PYTHON_ID}) -endif() -if(MINIUPNPC_ID) - include_directories(${MINIUPNPC_ID}) -endif() -if(LEVELDB_ID) - include_directories(${LEVELDB_ID}) -endif() -if(READLINE_ID) - include_directories(${READLINE_ID}) -endif() -if(JSONRPC_ID) - include_directories(${JSONRPC_ID}) -endif() - -# Generate header file containing useful build information -add_custom_target(BuildInfo.h ALL COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/BuildInfo.sh ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BUILD_TYPE} ${ETH_BUILD_PLATFORM}) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - link_directories(/usr/local/lib) - include_directories(/usr/local/include) -endif() +createBuildInfo() add_subdirectory(libdevcore) add_subdirectory(libevmface) add_subdirectory(liblll) add_subdirectory(libserpent) if(NOT APPLE) -if(PYTHON_LS) -add_subdirectory(libpyserpent) -endif() + if(PYTHON_LS) + add_subdirectory(libpyserpent) + endif() endif() + add_subdirectory(lllc) add_subdirectory(sc) if (NOT LANGUAGES) @@ -379,9 +161,6 @@ if (EVMCC) endif() -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(SRC_LIST BuildInfo.h) - enable_testing() add_test(NAME alltests WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth) diff --git a/README.md b/README.md index 7529fed50..371b82097 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ By Gav Wood, 2014. -Based on a design by Vitalik Buterin. +[![Build ++Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20master%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20master%20branch/builds/-1) master [![Build ++Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20develop%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20develop%20branch/builds/-1) develop -Contributors, builders and testers include Eric Lombrozo (cross-compilation), Tim Hughes (MSVC compilation & Dagger testing), Alex Leverington (Clang & Mac building), Marko Simovic (CI) and several others. +Ethereum is based on a design in an original whitepaper by Vitalik Buterin. This implementation is based on the formal specification of a refinement of that idea detailed in the 'yellow paper' by Gavin Wood. Contributors, builders and testers include Alex Leverington (Clang & Mac building, client multiplexing), Tim Hughes (MSVC compilation & Dagger testing), Caktux (ongoing CI), Christoph Jentzsch (tests), Christian Reissweiner (Solidity), Marek Kotewicz (external JS & JSON-RPC), Eric Lombrozo (MinGW32 cross-compilation), Marko Simovic (original CI), and several others. ### Building diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index c5d1aa0be..4ad06f7a6 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -25,6 +25,7 @@ find_package(Qt5WebKitWidgets REQUIRED) qt5_wrap_ui(ui_Main.h Main.ui) # Set name of binary and add_executable() +file(GLOB HEADERS "*.h") if (APPLE) set(EXECUTEABLE AlethZero) set(BIN_INSTALL_DIR ".") @@ -41,14 +42,14 @@ if (APPLE) set(MACOSX_BUNDLE_ICON_FILE alethzero) include(BundleUtilities) - add_executable(${EXECUTEABLE} MACOSX_BUNDLE alethzero.icns Main.ui ${SRC_LIST}) + add_executable(${EXECUTEABLE} MACOSX_BUNDLE alethzero.icns Main.ui ${SRC_LIST} ${HEADERS}) set_target_properties(${EXECUTEABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") SET_SOURCE_FILES_PROPERTIES(${EXECUTEABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") else () set(EXECUTEABLE alethzero) - add_executable(${EXECUTEABLE} Main.ui ${SRC_LIST}) + add_executable(${EXECUTEABLE} Main.ui ${SRC_LIST} ${HEADERS}) endif () qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index a6533023c..88a595566 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -45,7 +45,7 @@ void DownloadView::paintEvent(QPaintEvent*) double ratio = (double)rect().width() / rect().height(); if (ratio < 1) ratio = 1 / ratio; - double n = min(rect().width(), rect().height()) / ceil(sqrt(m_man->chain().size() / ratio)); + double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chain().size() / ratio))); // QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n)); QSizeF area(n, n); diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 5e86ee59a..5a6eb6f32 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -1480,6 +1480,40 @@ font-size: 14pt + + + QDockWidget::DockWidgetFeatureMask + + + Nodes + + + 2 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + + + + &Quit diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 5455c27ea..8d69727f8 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -207,6 +206,12 @@ unsigned Main::installWatch(dev::h256 _tf, std::function const& _f) return ret; } +void Main::uninstallWatch(unsigned _w) +{ + ethereum()->uninstallWatch(_w); + m_handlers.erase(_w); +} + void Main::installWatches() { installWatch(dev::eth::MessageFilter().altered(c_config, 0), [=](){ installNameRegWatch(); }); @@ -217,13 +222,13 @@ void Main::installWatches() void Main::installNameRegWatch() { - ethereum()->uninstallWatch(m_nameRegFilter); + uninstallWatch(m_nameRegFilter); m_nameRegFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 0)), [=](){ onNameRegChange(); }); } void Main::installCurrenciesWatch() { - ethereum()->uninstallWatch(m_currenciesFilter); + uninstallWatch(m_currenciesFilter); m_currenciesFilter = installWatch(dev::eth::MessageFilter().altered((u160)ethereum()->stateAt(c_config, 1)), [=](){ onCurrenciesChange(); }); } @@ -242,7 +247,7 @@ void Main::installBalancesWatch() tf.altered(c, (u160)i.address()); } - ethereum()->uninstallWatch(m_balancesFilter); + uninstallWatch(m_balancesFilter); m_balancesFilter = installWatch(tf, [=](){ onBalancesChange(); }); } @@ -500,7 +505,7 @@ void Main::writeSettings() s.setValue("privateChain", m_privateChain); s.setValue("verbosity", ui->verbosity->value()); - bytes d = m_webThree->savePeers(); + bytes d = m_webThree->saveNodes(); if (d.size()) m_peers = QByteArray((char*)d.data(), (int)d.size()); s.setValue("peers", m_peers); @@ -745,10 +750,39 @@ void Main::refreshNetwork() { auto ps = web3()->peers(); + ui->peerCount->setText(QString::fromStdString(toString(ps.size())) + " peer(s)"); ui->peers->clear(); - for (PeerInfo const& i: ps) - ui->peers->addItem(QString("[%7] %3 ms - %1:%2 - %4 %5 %6").arg(i.host.c_str()).arg(i.port).arg(chrono::duration_cast(i.lastPing).count()).arg(i.clientVersion.c_str()).arg(QString::fromStdString(toString(i.caps))).arg(QString::fromStdString(toString(i.notes))).arg(i.socket)); + ui->nodes->clear(); + + if (web3()->haveNetwork()) + { + map clients; + for (PeerInfo const& i: ps) + ui->peers->addItem(QString("[%8 %7] %3 ms - %1:%2 - %4 %5 %6") + .arg(QString::fromStdString(i.host)) + .arg(i.port) + .arg(chrono::duration_cast(i.lastPing).count()) + .arg(clients[i.id] = QString::fromStdString(i.clientVersion)) + .arg(QString::fromStdString(toString(i.caps))) + .arg(QString::fromStdString(toString(i.notes))) + .arg(i.socket) + .arg(QString::fromStdString(i.id.abridged()))); + + auto ns = web3()->nodes(); + for (p2p::Node const& i: ns) + if (!i.dead) + ui->nodes->insertItem(clients.count(i.id) ? 0 : ui->nodes->count(), QString("[%1 %3] %2 - ( =%5s | /%4s%6 ) - *%7 $%8") + .arg(QString::fromStdString(i.id.abridged())) + .arg(QString::fromStdString(toString(i.address))) + .arg(i.id == web3()->id() ? "self" : clients.count(i.id) ? clients[i.id] : i.secondsSinceLastAttempted() == -1 ? "session-fail" : i.secondsSinceLastAttempted() >= (int)i.fallbackSeconds() ? "retrying..." : "retry-" + QString::number(i.fallbackSeconds() - i.secondsSinceLastAttempted()) + "s") + .arg(i.secondsSinceLastAttempted()) + .arg(i.secondsSinceLastConnected()) + .arg(i.isOffline() ? " | " + QString::fromStdString(reasonOf(i.lastDisconnect)) + " | " + QString::number(i.failedAttempts) + "x" : "") + .arg(i.rating) + .arg((int)i.idOrigin) + ); + } } void Main::refreshAll() @@ -866,7 +900,7 @@ void Main::refreshBlockChain() string filter = ui->blockChainFilter->text().toLower().toStdString(); auto const& bc = ethereum()->blockChain(); unsigned i = (ui->showAll->isChecked() || !filter.empty()) ? (unsigned)-1 : 10; - for (auto h = bc.currentHash(); h != bc.genesisHash() && bc.details(h) && i; h = bc.details(h).parent, --i) + for (auto h = bc.currentHash(); bc.details(h) && i; h = bc.details(h).parent, --i) { auto d = bc.details(h); auto bm = blockMatch(filter, d, h, bc); @@ -906,6 +940,8 @@ void Main::refreshBlockChain() } n++; } + if (h == bc.genesisHash()) + break; } if (!ui->blocks->currentItem()) @@ -940,7 +976,7 @@ void Main::timerEvent(QTimerEvent*) if (interval / 100 % 2 == 0) refreshMining(); - if (interval / 100 % 2 == 0 && m_webThree->ethereum()->isSyncing()) + if ((interval / 100 % 2 == 0 && m_webThree->ethereum()->isSyncing()) || interval == 1000) ui->downloadView->update(); if (m_logChanged) @@ -1132,7 +1168,10 @@ void Main::on_blocks_currentItemChanged() s << "
Bloom: " << details.bloom << ""; s << "
Transactions: " << block[1].itemCount() << " @" << info.transactionsRoot << ""; s << "
Uncles: " << block[2].itemCount() << " @" << info.sha3Uncles << ""; - s << "
Pre: " << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << ""; + if (info.parentHash) + s << "
Pre: " << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << ""; + else + s << "
Pre: Nothing is before the Gensesis"; for (auto const& i: block[1]) s << "
" << sha3(i[0].data()).abridged() << ": " << i[1].toHash() << " [" << i[2].toInt() << " used]"; s << "
Post: " << info.stateRoot << ""; @@ -1257,10 +1296,10 @@ void Main::populateDebugger(dev::bytesConstRef _r) if (!m_codes.count(lastDataHash)) m_codes[lastDataHash] = ext.data.toBytes(); } - if (levels.size() < ext.level) + if (levels.size() < ext.depth) levels.push_back(&m_history.back()); else - levels.resize(ext.level); + levels.resize(ext.depth); m_history.append(WorldState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), lastHash, lastDataHash, vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); }; m_currentExecution->go(onOp); @@ -1539,10 +1578,10 @@ void Main::on_net_triggered() web3()->setIdealPeerCount(ui->idealPeers->value()); web3()->setNetworkPreferences(netPrefs()); ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : 0); + if (m_peers.size()/* && ui->usePast->isChecked()*/) + web3()->restoreNodes(bytesConstRef((byte*)m_peers.data(), m_peers.size())); web3()->startNetwork(); ui->downloadView->setDownloadMan(ethereum()->downloadMan()); - if (m_peers.size() && ui->usePast->isChecked()) - web3()->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); } else { @@ -1701,9 +1740,9 @@ void Main::on_debugStepBack_triggered() void Main::on_debugStepBackOut_triggered() { - if (ui->debugTimeline->value() > 0) + if (ui->debugTimeline->value() > 0 && m_history.size() > 0) { - auto ls = m_history[ui->debugTimeline->value()].levels.size(); + auto ls = m_history[min(ui->debugTimeline->value(), m_history.size() - 1)].levels.size(); int l = ui->debugTimeline->value(); for (; l > 0 && m_history[l].levels.size() >= ls; --l) {} ui->debugTimeline->setValue(l); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index c83848cdd..55b8b4e0a 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -183,6 +183,7 @@ private: unsigned installWatch(dev::eth::MessageFilter const& _tf, std::function const& _f); unsigned installWatch(dev::h256 _tf, std::function const& _f); + void uninstallWatch(unsigned _w); void keysChanged(); diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake new file mode 100644 index 000000000..6103970c4 --- /dev/null +++ b/cmake/EthCompilerSettings.cmake @@ -0,0 +1,59 @@ +# Set necessary compile and link flags + + +# C++11 check and activation +if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) + if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) + message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") + endif () +elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +else () + message(FATAL_ERROR "Your C++ compiler does not support C++11.") +endif () + + + +# Initialize CXXFLAGS +set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB") +set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") +set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") +set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG -DETH_RELEASE") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") + +# Windows +if ("${TARGET_PLATFORM}" STREQUAL "w64") + set(CMAKE_SYSTEM_NAME Windows) + + set(CMAKE_CXX_LIBRARY_ARCHITECTURE x86_64-w64-mingw32) + set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) + set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) + set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) + set(CMAKE_AR x86_64-w64-mingw32-ar) + set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib) + + set(CMAKE_EXECUTABLE_SUFFIX .exe) + + set(CMAKE_FIND_ROOT_PATH + /usr/x86_64-w64-mingw32 + ) + + include_directories(/usr/x86_64-w64-mingw32/include/cryptopp) + + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + + set(CMAKE_INSTALL_PREFIX /usr/x86_64-w64-mingw32) + set(ETH_BUILD_PLATFORM "windows") + set(ETH_STATIC 1) +else () + set(ETH_BUILD_PLATFORM ${CMAKE_SYSTEM_NAME}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + set(ETH_SHARED 1) +endif() + + + diff --git a/cmake/EthDependenciesDeprecated.cmake b/cmake/EthDependenciesDeprecated.cmake new file mode 100644 index 000000000..d1c51f6c4 --- /dev/null +++ b/cmake/EthDependenciesDeprecated.cmake @@ -0,0 +1,208 @@ +# search for and configure dependencies + +# deprecated. TODO will rewrite to proper CMake packages + + + +if("${TARGET_PLATFORM}" STREQUAL "w64") +# set(MINIUPNPC_LS /usr/x86_64-w64-mingw32/lib/libminiupnpc.a) + set(LEVELDB_LS leveldb) + set(CRYPTOPP_LS cryptopp) + set(CRYPTOPP_ID /usr/x86_64-w64-mingw32/include/cryptopp) +else() + # Look for available Crypto++ version and if it is >= 5.6.2 + find_path(ID cryptlib.h + ../cryptopp/src + ../../cryptopp/src + /usr/include/cryptopp + /usr/include/crypto++ + /usr/local/include/cryptopp + /usr/local/include/crypto++ + /opt/local/include/cryptopp + /opt/local/include/crypto++ + ) + find_library(LS NAMES cryptoppeth cryptopp + ../cryptopp/src/../target/build/release + ../../cryptopp/src/../target/build/release + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + ) + + if (ID AND LS) + message(STATUS "Found Crypto++: ${ID}, ${LS}") + set(_CRYPTOPP_VERSION_HEADER ${ID}/config.h) + if(EXISTS ${_CRYPTOPP_VERSION_HEADER}) + file(STRINGS ${_CRYPTOPP_VERSION_HEADER} _CRYPTOPP_VERSION REGEX "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION ${_CRYPTOPP_VERSION}) + if(${_CRYPTOPP_VERSION} LESS 562) + message(FATAL_ERROR "Crypto++ version found is smaller than 5.6.2.") + else() + set(CRYPTOPP_ID ${ID} CACHE FILEPATH "") + set(CRYPTOPP_LS ${LS} CACHE FILEPATH "") + message(STATUS "Crypto++ found and version greater or equal to 5.6.2") + endif() + endif() + else() + message(STATUS "Crypto++ Not Found: ${CRYPTOPP_ID}, ${CRYPTOPP_LS}") + endif() + + find_path( LEVELDB_ID leveldb/db.h + /usr/include + /usr/local/include + ) + if ( LEVELDB_ID STREQUAL "LEVELDB_ID-NOTFOUND" ) + message(FATAL_ERROR "Failed to find the LevelDB headers") + else () + message(STATUS "Found LevelDB Headers") + + # Check for accessory dev libraries leveldb and miniupnpc + find_library( LEVELDB_LS NAMES leveldb + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + if ( LEVELDB_LS STREQUAL "LEVELDB_LS-NOTFOUND" ) + message(FATAL_ERROR "Failed to find the LevelDB Library!") + else () + message(STATUS "Found LevelDB Library: ${LEVELDB_LS}") + add_definitions(-DETH_LEVELDB) + endif () + endif () + + find_path( PYTHON_ID pyconfig.h + ${PYTHON_INCLUDE_DIR} + /usr/include/python2.7 + /usr/local/include/python2.7 + ) + if ( PYTHON_ID STREQUAL "PYTHON_ID-NOTFOUND" ) + message(STATUS "Failed to find the Python-2.7 headers") + else () + message(STATUS "Found Python-2.7 Headers: ${PYTHON_ID}") + + # Check for accessory dev libraries leveldb and miniupnpc + find_library( PYTHON_LS NAMES python2.7 + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + if ( PYTHON_LS STREQUAL "PYTHON_LS-NOTFOUND" ) + message(STATUS "Failed to find the Python-2.7 Library!") + set(PYTHON_ID) + set(PYTHON_LS) + else () + message(STATUS "Found Python-2.7 Library: ${PYTHON_LS}") + add_definitions(-DETH_PYTHON) + endif () + endif () + + find_path( MINIUPNPC_ID miniupnpc/miniwget.h + /usr/include + /usr/local/include + ) + if ( MINIUPNPC_ID ) + message(STATUS "Found miniupnpc headers") + + find_library( MINIUPNPC_LS NAMES miniupnpc + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + if ( MINIUPNPC_LS ) + message(STATUS "Found miniupnpc library: ${MINIUPNPC_LS}") + add_definitions(-DETH_MINIUPNPC) + else () + message(STATUS "Failed to find the miniupnpc library!") + endif () + else () + message(STATUS "Failed to find the miniupnpc headers!") + endif () + + find_path( JSONRPC_ID jsonrpc/rpc.h + /usr/include + /usr/local/include + ) + if ( JSONRPC_ID ) + message(STATUS "Found jsonrpc headers") + find_library( JSONRPC_LS NAMES jsonrpc + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + if ( JSONRPC_LS ) + message(STATUS "Found jsonrpc library: ${JSONRPC_LS}") + add_definitions(-DETH_JSONRPC) + else () + message(STATUS "Failed to find the jsonrpc library!") + endif () + else () + message(STATUS "Failed to find the jsonrpc headers!") + endif () + + find_path( READLINE_ID readline/readline.h + /usr/include + /usr/local/include + ) + if ( READLINE_ID ) + message(STATUS "Found readline headers") + find_library( READLINE_LS NAMES readline + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /usr/lib/*/ + ) + if ( READLINE_LS ) + message(STATUS "Found readline library: ${READLINE_LS}") + add_definitions(-DETH_READLINE) + else () + message(STATUS "Failed to find the readline library!") + endif () + else () + message(STATUS "Failed to find the readline headers!") + endif () + + if (LANGUAGES) + find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time) + else() + find_package(Boost 1.53 REQUIRED COMPONENTS thread date_time system regex) + endif() + + set(QTQML 1) +endif() + +if(CRYPTOPP_ID) + include_directories(${CRYPTOPP_ID}) +endif() +if(PYTHON_ID) + include_directories(${PYTHON_ID}) +endif() +if(MINIUPNPC_ID) + include_directories(${MINIUPNPC_ID}) +endif() +if(LEVELDB_ID) + include_directories(${LEVELDB_ID}) +endif() +if(READLINE_ID) + include_directories(${READLINE_ID}) +endif() +if(JSONRPC_ID) + include_directories(${JSONRPC_ID}) +endif() + + + + +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + link_directories(/usr/local/lib) + include_directories(/usr/local/include) +endif() diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index eee1d258b..087c5314a 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -8,7 +8,8 @@ link_directories(../libwebthree) set(EXECUTABLE eth) -add_executable(${EXECUTABLE} ${SRC_LIST}) +file(GLOB HEADERS "*.h") +add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) diff --git a/eth/main.cpp b/eth/main.cpp index 03be8b969..b5e8eb736 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #if ETH_JSONRPC @@ -166,6 +167,13 @@ string pretty(h160 _a, dev::eth::State _st) return ns; } +bool g_exit = false; + +void sighandler(int) +{ + g_exit = true; +} + int main(int argc, char** argv) { unsigned short listenPort = 30303; @@ -316,6 +324,9 @@ int main(int argc, char** argv) c->setAddress(coinbase); } + auto nodesState = contents(dbPath + "/nodeState.rlp"); + web3.restoreNodes(&nodesState); + cout << "Address: " << endl << toHex(us.address().asArray()) << endl; web3.startNetwork(); @@ -334,11 +345,15 @@ int main(int argc, char** argv) } #endif + signal(SIGABRT, &sighandler); + signal(SIGTERM, &sighandler); + signal(SIGINT, &sighandler); + if (interactive) { string logbuf; string l; - while (true) + while (!g_exit) { g_logPost = [](std::string const& a, char const*) { cout << "\r \r" << a << endl << "Press Enter" << flush; }; cout << logbuf << "Press Enter" << flush; @@ -612,42 +627,50 @@ int main(int argc, char** argv) Transaction t = state.pending()[index]; state = state.fromPending(index); bytes r = t.rlp(); - e.setup(&r); - - OnOpFunc oof; - if (format == "pretty") - oof = [&](uint64_t steps, Instruction instr, bigint newMemSize, bigint gasCost, void* vvm, void const* vextVM) - { - dev::eth::VM* vm = (VM*)vvm; - dev::eth::ExtVM const* ext = (ExtVM const*)vextVM; - f << endl << " STACK" << endl; - for (auto i: vm->stack()) - f << (h256)i << endl; - f << " MEMORY" << endl << dev::memDump(vm->memory()); - f << " STORAGE" << endl; - for (auto const& i: ext->state().storage(ext->myAddress)) - f << showbase << hex << i.first << ": " << i.second << endl; - f << dec << ext->level << " | " << ext->myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm->curPC() << " : " << dev::eth::instructionInfo(instr).name << " | " << dec << vm->gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32"; - }; - else if (format == "standard") - oof = [&](uint64_t, Instruction instr, bigint, bigint, void* vvm, void const* vextVM) - { - dev::eth::VM* vm = (VM*)vvm; - dev::eth::ExtVM const* ext = (ExtVM const*)vextVM; - f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)vm->gas(), 1)) << endl; - }; - else if (format == "standard+") - oof = [&](uint64_t, Instruction instr, bigint, bigint, void* vvm, void const* vextVM) - { - dev::eth::VM* vm = (VM*)vvm; - dev::eth::ExtVM const* ext = (ExtVM const*)vextVM; - if (instr == Instruction::STOP || instr == Instruction::RETURN || instr == Instruction::SUICIDE) + try + { + e.setup(&r); + + OnOpFunc oof; + if (format == "pretty") + oof = [&](uint64_t steps, Instruction instr, bigint newMemSize, bigint gasCost, void* vvm, void const* vextVM) + { + dev::eth::VM* vm = (VM*)vvm; + dev::eth::ExtVM const* ext = (ExtVM const*)vextVM; + f << endl << " STACK" << endl; + for (auto i: vm->stack()) + f << (h256)i << endl; + f << " MEMORY" << endl << dev::memDump(vm->memory()); + f << " STORAGE" << endl; for (auto const& i: ext->state().storage(ext->myAddress)) - f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl; - f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)vm->gas(), 1)) << endl; - }; - e.go(oof); - e.finalize(oof); + f << showbase << hex << i.first << ": " << i.second << endl; + f << dec << ext->depth << " | " << ext->myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm->curPC() << " : " << dev::eth::instructionInfo(instr).name << " | " << dec << vm->gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32"; + }; + else if (format == "standard") + oof = [&](uint64_t, Instruction instr, bigint, bigint, void* vvm, void const* vextVM) + { + dev::eth::VM* vm = (VM*)vvm; + dev::eth::ExtVM const* ext = (ExtVM const*)vextVM; + f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)vm->gas(), 1)) << endl; + }; + else if (format == "standard+") + oof = [&](uint64_t, Instruction instr, bigint, bigint, void* vvm, void const* vextVM) + { + dev::eth::VM* vm = (VM*)vvm; + dev::eth::ExtVM const* ext = (ExtVM const*)vextVM; + if (instr == Instruction::STOP || instr == Instruction::RETURN || instr == Instruction::SUICIDE) + for (auto const& i: ext->state().storage(ext->myAddress)) + f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl; + f << ext->myAddress << " " << hex << toHex(dev::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)vm->gas(), 1)) << endl; + }; + e.go(oof); + e.finalize(oof); + } + catch(Exception const& _e) + { + // TODO: a bit more information here. this is probably quite worrying as the transaction is already in the blockchain. + cwarn << diagnostic_information(_e); + } } } else if (c && cmd == "inspect") @@ -757,7 +780,7 @@ int main(int argc, char** argv) unsigned n =c->blockChain().details().number; if (mining) c->startMining(); - while (true) + while (!g_exit) { if ( c->isMining() &&c->blockChain().details().number - n == mining) c->stopMining(); @@ -765,9 +788,10 @@ int main(int argc, char** argv) } } else - while (true) + while (!g_exit) this_thread::sleep_for(chrono::milliseconds(1000)); + writeFile(dbPath + "/nodeState.rlp", web3.saveNodes()); return 0; } diff --git a/evmcc/bytecode/if1.evm b/evmcc/bytecode/if1.evm deleted file mode 100644 index ee9009294..000000000 --- a/evmcc/bytecode/if1.evm +++ /dev/null @@ -1 +0,0 @@ -600160805460006080530b6016596003608054601b586002608054 diff --git a/evmcc/evmcc.cpp b/evmcc/evmcc.cpp index 22ba1db50..9cf731419 100644 --- a/evmcc/evmcc.cpp +++ b/evmcc/evmcc.cpp @@ -12,9 +12,8 @@ #include #include #include - -#include "Compiler.h" -#include "ExecutionEngine.h" +#include +#include void show_usage() @@ -95,7 +94,7 @@ int main(int argc, char** argv) if (opt_compile) { auto compiler = eth::jit::Compiler(); - auto module = compiler.compile(bytecode); + auto module = compiler.compile({bytecode.data(), bytecode.size()}); llvm::raw_os_ostream out(std::cout); module->print(out, nullptr); @@ -111,9 +110,10 @@ int main(int argc, char** argv) if (opt_interpret) { auto engine = eth::jit::ExecutionEngine(); - auto module = eth::jit::Compiler().compile(bytecode); + auto module = eth::jit::Compiler().compile({bytecode.data(), bytecode.size()}); module->dump(); - auto result = engine.run(std::move(module)); + u256 gas = 10000; + auto result = engine.run(std::move(module), gas); return result; } diff --git a/evmcc/lll/if1.asm b/evmcc/lll/if1.asm deleted file mode 100644 index 4a938adce..000000000 --- a/evmcc/lll/if1.asm +++ /dev/null @@ -1,21 +0,0 @@ -.code: - PUSH 1 - PUSH 128 - MSTORE - PUSH 0 - PUSH 128 - MLOAD - GT - PUSH [tag0] - JUMPI - PUSH 3 - PUSH 128 - MSTORE - PUSH [tag1] - JUMP -tag0: - PUSH 2 - PUSH 128 - MSTORE -tag1: - diff --git a/evmcc/lll/if1.lll b/evmcc/lll/if1.lll deleted file mode 100644 index 7984807c1..000000000 --- a/evmcc/lll/if1.lll +++ /dev/null @@ -1,5 +0,0 @@ -{ - [i] 1 - - ( if (> @i 0) [i] 2 [i] 3 ) -} diff --git a/evmcc/bytecode/arithmetic_test.evm b/evmcc/test/arith/arith1.evm similarity index 100% rename from evmcc/bytecode/arithmetic_test.evm rename to evmcc/test/arith/arith1.evm diff --git a/evmcc/lll/arithmetic_test.lll b/evmcc/test/arith/arith1.lll similarity index 100% rename from evmcc/lll/arithmetic_test.lll rename to evmcc/test/arith/arith1.lll diff --git a/evmcc/bytecode/fib1.evm b/evmcc/test/arith/fib1.evm similarity index 100% rename from evmcc/bytecode/fib1.evm rename to evmcc/test/arith/fib1.evm diff --git a/evmcc/lll/fib1.lll b/evmcc/test/arith/fib1.lll similarity index 100% rename from evmcc/lll/fib1.lll rename to evmcc/test/arith/fib1.lll diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/test/ext/ext_test.evm similarity index 100% rename from evmcc/bytecode/ext_test.evm rename to evmcc/test/ext/ext_test.evm diff --git a/evmcc/lll/ext_test.lll b/evmcc/test/ext/ext_test.lll similarity index 100% rename from evmcc/lll/ext_test.lll rename to evmcc/test/ext/ext_test.lll diff --git a/evmcc/bytecode/store_test.evm b/evmcc/test/ext/store_test.evm similarity index 100% rename from evmcc/bytecode/store_test.evm rename to evmcc/test/ext/store_test.evm diff --git a/evmcc/lll/store_test.lll b/evmcc/test/ext/store_test.lll similarity index 100% rename from evmcc/lll/store_test.lll rename to evmcc/test/ext/store_test.lll diff --git a/evmcc/bytecode/for1.evm b/evmcc/test/jump/for1.evm similarity index 100% rename from evmcc/bytecode/for1.evm rename to evmcc/test/jump/for1.evm diff --git a/evmcc/lll/for1.lll b/evmcc/test/jump/for1.lll similarity index 100% rename from evmcc/lll/for1.lll rename to evmcc/test/jump/for1.lll diff --git a/evmcc/bytecode/for2.evm b/evmcc/test/jump/for2.evm similarity index 100% rename from evmcc/bytecode/for2.evm rename to evmcc/test/jump/for2.evm diff --git a/evmcc/lll/for2.lll b/evmcc/test/jump/for2.lll similarity index 100% rename from evmcc/lll/for2.lll rename to evmcc/test/jump/for2.lll diff --git a/evmcc/lll/when1.asm b/evmcc/test/jump/when1.asm similarity index 100% rename from evmcc/lll/when1.asm rename to evmcc/test/jump/when1.asm diff --git a/evmcc/bytecode/when1.evm b/evmcc/test/jump/when1.evm similarity index 100% rename from evmcc/bytecode/when1.evm rename to evmcc/test/jump/when1.evm diff --git a/evmcc/lll/when1.lll b/evmcc/test/jump/when1.lll similarity index 100% rename from evmcc/lll/when1.lll rename to evmcc/test/jump/when1.lll diff --git a/evmcc/bytecode/kv.evm b/evmcc/test/kv.evm similarity index 100% rename from evmcc/bytecode/kv.evm rename to evmcc/test/kv.evm diff --git a/evmcc/lll/kv.lll b/evmcc/test/kv.lll similarity index 100% rename from evmcc/lll/kv.lll rename to evmcc/test/kv.lll diff --git a/evmcc/bytecode/byte.evm b/evmcc/test/mem/byte.evm similarity index 100% rename from evmcc/bytecode/byte.evm rename to evmcc/test/mem/byte.evm diff --git a/evmcc/lll/byte.lll b/evmcc/test/mem/byte.lll similarity index 100% rename from evmcc/lll/byte.lll rename to evmcc/test/mem/byte.lll diff --git a/evmcc/bytecode/mem2.evm b/evmcc/test/mem/mem2.evm similarity index 100% rename from evmcc/bytecode/mem2.evm rename to evmcc/test/mem/mem2.evm diff --git a/evmcc/lll/mem2.lll b/evmcc/test/mem/mem2.lll similarity index 100% rename from evmcc/lll/mem2.lll rename to evmcc/test/mem/mem2.lll diff --git a/evmcc/bytecode/memtest1.evm b/evmcc/test/mem/memtest1.evm similarity index 100% rename from evmcc/bytecode/memtest1.evm rename to evmcc/test/mem/memtest1.evm diff --git a/evmcc/lll/memtest1.lll b/evmcc/test/mem/memtest1.lll similarity index 100% rename from evmcc/lll/memtest1.lll rename to evmcc/test/mem/memtest1.lll diff --git a/evmcc/bytecode/return1.evm b/evmcc/test/ret/return1.evm similarity index 100% rename from evmcc/bytecode/return1.evm rename to evmcc/test/ret/return1.evm diff --git a/evmcc/lll/return1.lll b/evmcc/test/ret/return1.lll similarity index 100% rename from evmcc/lll/return1.lll rename to evmcc/test/ret/return1.lll diff --git a/evmcc/bytecode/return2.evm b/evmcc/test/ret/return2.evm similarity index 100% rename from evmcc/bytecode/return2.evm rename to evmcc/test/ret/return2.evm diff --git a/evmcc/lll/return2.lll b/evmcc/test/ret/return2.lll similarity index 100% rename from evmcc/lll/return2.lll rename to evmcc/test/ret/return2.lll diff --git a/evmcc/bytecode/return_test.evm b/evmcc/test/ret/return_test.evm similarity index 100% rename from evmcc/bytecode/return_test.evm rename to evmcc/test/ret/return_test.evm diff --git a/evmcc/lll/return_test.lll b/evmcc/test/ret/return_test.lll similarity index 100% rename from evmcc/lll/return_test.lll rename to evmcc/test/ret/return_test.lll diff --git a/evmcc/bytecode/push_test.evm b/evmcc/test/stack/push_test.evm similarity index 100% rename from evmcc/bytecode/push_test.evm rename to evmcc/test/stack/push_test.evm diff --git a/evmcc/lll/push_test.lll b/evmcc/test/stack/push_test.lll similarity index 100% rename from evmcc/lll/push_test.lll rename to evmcc/test/stack/push_test.lll diff --git a/evmcc/bytecode/stack_test.evm b/evmcc/test/stack/stack_test.evm similarity index 100% rename from evmcc/bytecode/stack_test.evm rename to evmcc/test/stack/stack_test.evm diff --git a/evmcc/lll/stack_test.lll b/evmcc/test/stack/stack_test.lll similarity index 100% rename from evmcc/lll/stack_test.lll rename to evmcc/test/stack/stack_test.lll diff --git a/evmcc/bytecode/stackjump.evm b/evmcc/test/stack/stackjump.evm similarity index 100% rename from evmcc/bytecode/stackjump.evm rename to evmcc/test/stack/stackjump.evm diff --git a/evmcc/lll/stackjump.lll b/evmcc/test/stack/stackjump.lll similarity index 100% rename from evmcc/lll/stackjump.lll rename to evmcc/test/stack/stackjump.lll diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 3f3ecb619..81e210cad 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -10,13 +10,12 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE devcore) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") include_directories(..) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index fd1868539..335e2b387 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -27,7 +27,7 @@ using namespace dev; namespace dev { -char const* Version = "0.7.1"; +char const* Version = "0.7.4"; } diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 332081ec8..87cc069b3 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -38,6 +38,7 @@ #include #include #include "vector_ref.h" +#include "debugbreak.h" // CryptoPP defines byte in the global namespace, so must we. using byte = uint8_t; @@ -103,4 +104,45 @@ inline unsigned int toLog2(u256 _x) return ret; } +// Assertions... + +#if defined(_MSC_VER) +#define ETH_FUNC __FUNCSIG__ +#elif defined(__GNUC__) +#define ETH_FUNC __PRETTY_FUNCTION__ +#else +#define ETH_FUNC __func__ +#endif + +#define asserts(A) ::dev::assertAux(A, #A, __LINE__, __FILE__, ETH_FUNC) +#define assertsEqual(A, B) ::dev::assertEqualAux(A, B, #A, #B, __LINE__, __FILE__, ETH_FUNC) + +inline bool assertAux(bool _a, char const* _aStr, unsigned _line, char const* _file, char const* _func) +{ + bool ret = _a; + if (!ret) + { + std::cerr << "Assertion failed:" << _aStr << " [func=" << _func << ", line=" << _line << ", file=" << _file << "]" << std::endl; +#if ETH_DEBUG + debug_break(); +#endif + } + return !ret; +} + +template +inline bool assertEqualAux(A const& _a, B const& _b, char const* _aStr, char const* _bStr, unsigned _line, char const* _file, char const* _func) +{ + bool ret = _a == _b; + if (!ret) + { + std::cerr << "Assertion failed: " << _aStr << " == " << _bStr << " [func=" << _func << ", line=" << _line << ", file=" << _file << "]" << std::endl; + std::cerr << " Fail equality: " << _a << "==" << _b << std::endl; +#if ETH_DEBUG + debug_break(); +#endif + } + return !ret; +} + } diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index e6a66776c..ac58ec8b1 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -47,6 +47,7 @@ public: RangeMask(T _begin, T _end): m_all(_begin, _end) {} RangeMask(Range const& _c): m_all(_c) {} + RangeMask unionedWith(RangeMask const& _m) const { return operator+(_m); } RangeMask operator+(RangeMask const& _m) const { return RangeMask(*this) += _m; } RangeMask lowest(T _items) const @@ -57,7 +58,9 @@ public: return ret; } - RangeMask operator~() const + RangeMask operator~() const { return inverted(); } + + RangeMask inverted() const { RangeMask ret(m_all); T last = m_all.first; @@ -72,16 +75,28 @@ public: return ret; } - RangeMask& operator+=(RangeMask const& _m) + RangeMask& invert() { return *this = inverted(); } + + template RangeMask operator-(S const& _m) const { auto ret = *this; return ret -= _m; } + template RangeMask& operator-=(S const& _m) { return invert().unionWith(_m).invert(); } + + RangeMask& operator+=(RangeMask const& _m) { return unionWith(_m); } + + RangeMask& unionWith(RangeMask const& _m) { + m_all.first = std::min(_m.m_all.first, m_all.first); + m_all.second = std::max(_m.m_all.second, m_all.second); for (auto const& i: _m.m_ranges) - operator+=(i); + unionWith(i); return *this; } - RangeMask& operator+=(UnsignedRange const& _m) + RangeMask& operator+=(Range const& _m) { return unionWith(_m); } + RangeMask& unionWith(Range const& _m) { for (auto i = _m.first; i < _m.second;) { + assert(i >= m_all.first); + assert(i < m_all.second); // for each number, we find the element equal or next lower. this, if any, must contain the value. auto uit = m_ranges.upper_bound(i); auto it = uit == m_ranges.begin() ? m_ranges.end() : std::prev(uit); @@ -130,7 +145,8 @@ public: return *this; } - RangeMask& operator+=(T _i) + RangeMask& operator+=(T _m) { return unionWith(_m); } + RangeMask& unionWith(T _i) { return operator+=(Range(_i, _i + 1)); } @@ -165,6 +181,7 @@ public: } std::pair const& all() const { return m_all; } + void extendAll(T _i) { m_all = std::make_pair(std::min(m_all.first, _i), std::max(m_all.second, _i + 1)); } class const_iterator { diff --git a/libdevcore/debugbreak.h b/libdevcore/debugbreak.h new file mode 100644 index 000000000..57d9d8cde --- /dev/null +++ b/libdevcore/debugbreak.h @@ -0,0 +1,121 @@ +/* Copyright (c) 2013, Scott Tsai + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DEBUG_BREAK_H +#define DEBUG_BREAK_H + +#ifdef _MSC_VER + +#define debug_break __debugbreak + +#else + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* gcc optimizers consider code after __builtin_trap() dead. + * Making __builtin_trap() unsuitable for breaking into the debugger */ + DEBUG_BREAK_PREFER_BUILTIN_TRAP_TO_SIGTRAP = 0, +}; + +#if defined(__i386__) || defined(__x86_64__) +enum { HAVE_TRAP_INSTRUCTION = 1, }; +__attribute__((gnu_inline, always_inline)) +static void __inline__ trap_instruction(void) +{ + __asm__ volatile("int $0x03"); +} +#elif defined(__thumb__) +enum { HAVE_TRAP_INSTRUCTION = 1, }; +/* FIXME: handle __THUMB_INTERWORK__ */ +__attribute__((gnu_inline, always_inline)) +static void __inline__ trap_instruction(void) +{ + /* See 'arm-linux-tdep.c' in GDB source. + * Both instruction sequences below works. */ +#if 1 + /* 'eabi_linux_thumb_le_breakpoint' */ + __asm__ volatile(".inst 0xde01"); +#else + /* 'eabi_linux_thumb2_le_breakpoint' */ + __asm__ volatile(".inst.w 0xf7f0a000"); +#endif + + /* Known problem: + * After a breakpoint hit, can't stepi, step, or continue in GDB. + * 'step' stuck on the same instruction. + * + * Workaround: a new GDB command, + * 'debugbreak-step' is defined in debugbreak-gdb.py + * that does: + * (gdb) set $instruction_len = 2 + * (gdb) tbreak *($pc + $instruction_len) + * (gdb) jump *($pc + $instruction_len) + */ +} +#elif defined(__arm__) && !defined(__thumb__) +enum { HAVE_TRAP_INSTRUCTION = 1, }; +__attribute__((gnu_inline, always_inline)) +static void __inline__ trap_instruction(void) +{ + /* See 'arm-linux-tdep.c' in GDB source, + * 'eabi_linux_arm_le_breakpoint' */ + __asm__ volatile(".inst 0xe7f001f0"); + /* Has same known problem and workaround + * as Thumb mode */ +} +#else +enum { HAVE_TRAP_INSTRUCTION = 0, }; +#endif + +__attribute__((gnu_inline, always_inline)) +static void __inline__ debug_break(void) +{ + if (HAVE_TRAP_INSTRUCTION) { + trap_instruction(); + } else if (DEBUG_BREAK_PREFER_BUILTIN_TRAP_TO_SIGTRAP) { + /* raises SIGILL on Linux x86{,-64}, to continue in gdb: + * (gdb) handle SIGILL stop nopass + * */ + __builtin_trap(); + } else { + raise(SIGTRAP); + } +} + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index e7f112f95..cee7d130d 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -4,15 +4,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE devcrypto) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} devcore) diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index dd4d6961c..8863352a4 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -39,7 +39,8 @@ Address dev::toAddress(Secret _private) if (!ok) return Address(); ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, _private.data(), 0); - assert(pubkeylen == 65); + if (asserts(pubkeylen == 65)) + return Address(); if (!ok) return Address(); ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65); diff --git a/libdevcrypto/MemoryDB.h b/libdevcrypto/MemoryDB.h index 59435d3bf..446a947ec 100644 --- a/libdevcrypto/MemoryDB.h +++ b/libdevcrypto/MemoryDB.h @@ -32,7 +32,7 @@ namespace dev namespace eth { -struct DBChannel: public LogChannel { static const char* name() { return "TDB"; } static const int verbosity = 12; }; +struct DBChannel: public LogChannel { static const char* name() { return "TDB"; } static const int verbosity = 18; }; #define dbdebug clog(DBChannel) diff --git a/libdevcrypto/TrieDB.h b/libdevcrypto/TrieDB.h index d4583dc9b..3dd76899a 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcrypto/TrieDB.h @@ -42,7 +42,7 @@ namespace dev namespace eth { -struct TrieDBChannel: public LogChannel { static const char* name() { return "-T-"; } static const int verbosity = 6; }; +struct TrieDBChannel: public LogChannel { static const char* name() { return "-T-"; } static const int verbosity = 17; }; #define tdebug clog(TrieDBChannel) struct InvalidTrie: virtual dev::Exception {}; @@ -473,7 +473,7 @@ template void GenericTrieDB::insert(bytesConstRef _key, bytesCons assert(rv.size()); bytes b = mergeAt(RLP(rv), NibbleSlice(_key), _value); - // mergeAt won't attempt to delete the node is it's less than 32 bytes + // mergeAt won't attempt to delete the node if it's less than 32 bytes // However, we know it's the root node and thus always hashed. // So, if it's less than 32 (and thus should have been deleted but wasn't) then we delete it here. if (rv.size() < 32) diff --git a/libethcore/All.h b/libethcore/All.h index 4a6747ff0..7a1ca8f51 100644 --- a/libethcore/All.h +++ b/libethcore/All.h @@ -2,7 +2,7 @@ #include "BlockInfo.h" #include "CommonEth.h" -#include "Dagger.h" +#include "ProofOfWork.h" #include "CryptoHeaders.h" #include "Exceptions.h" diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index f6d5731b3..536f684f2 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "Dagger.h" +#include "ProofOfWork.h" #include "Exceptions.h" #include "BlockInfo.h" using namespace std; @@ -99,7 +99,7 @@ void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce) } // check it hashes according to proof of work or that it's the genesis block. - if (_checkNonce && parentHash && !Dagger::verify(headerHashWithoutNonce(), nonce, difficulty)) + if (_checkNonce && parentHash && !ProofOfWork::verify(headerHashWithoutNonce(), nonce, difficulty)) BOOST_THROW_EXCEPTION(InvalidBlockNonce(headerHashWithoutNonce(), nonce, difficulty)); if (gasUsed > gasLimit) diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 6aba644f1..f5cf00b57 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -4,15 +4,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE ethcore) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} devcrypto) diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 1526da1b0..40a86dba4 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -34,8 +34,8 @@ namespace dev namespace eth { -const unsigned c_protocolVersion = 34; -const unsigned c_databaseVersion = 2; +const unsigned c_protocolVersion = 35; +const unsigned c_databaseVersion = 3; static const vector> g_units = { diff --git a/libethcore/Dagger.h b/libethcore/Dagger.h deleted file mode 100644 index c32ef38be..000000000 --- a/libethcore/Dagger.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - This file is part of cpp-ethereum. - - cpp-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - cpp-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . -*/ -/** @file Dagger.h - * @author Gav Wood - * @date 2014 - * - * Dagger algorithm. Or not. - */ - -#pragma once - -#include -#include "CommonEth.h" - -#define FAKE_DAGGER 1 - -namespace dev -{ -namespace eth -{ - -struct MineInfo -{ - void combine(MineInfo const& _m) { requirement = std::max(requirement, _m.requirement); best = std::min(best, _m.best); hashes += _m.hashes; completed = completed || _m.completed; } - double requirement = 0; - double best = 1e99; - unsigned hashes = 0; - bool completed = false; -}; - -#if FAKE_DAGGER - -class Dagger -{ -public: - static h256 eval(h256 const& _root, h256 const& _nonce) { h256 b[2] = { _root, _nonce }; return sha3(bytesConstRef((byte const*)&b[0], 64)); } - static bool verify(h256 const& _root, h256 const& _nonce, u256 const& _difficulty) { return (bigint)(u256)eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; } - - MineInfo mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false); - - h256 m_last; -}; - -#else - -/// Functions are not re-entrant. If you want to multi-thread, then use different classes for each thread. -class Dagger -{ -public: - Dagger(); - ~Dagger(); - - static u256 bound(u256 const& _difficulty); - static h256 eval(h256 const& _root, u256 const& _nonce); - static bool verify(h256 const& _root, u256 const& _nonce, u256 const& _difficulty); - - bool mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool const& _continue = bool(true)); - -private: - - static h256 node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i); - - h256 m_root; - u256 m_nonce; -}; - -#endif - -} -} diff --git a/libethcore/Exceptions.cpp b/libethcore/Exceptions.cpp index 2936e9353..c6f35763e 100644 --- a/libethcore/Exceptions.cpp +++ b/libethcore/Exceptions.cpp @@ -22,14 +22,17 @@ #include "Exceptions.h" #include +using namespace std; using namespace dev; using namespace dev::eth; -const char* InvalidBlockFormat::what() const noexcept { return ("Invalid block format: Bad field " + toString(m_f) + " (" + toHex(m_d) + ")").c_str(); } -const char* UncleInChain::what() const noexcept { return ("Uncle in block already mentioned: Uncles " + toString(m_uncles) + " (" + m_block.abridged() + ")").c_str(); } -const char* InvalidTransactionsHash::what() const noexcept { return ("Invalid transactions hash: header says: " + toHex(m_head.ref()) + " block is:" + toHex(m_real.ref())).c_str(); } -const char* InvalidGasLimit::what() const noexcept { return ("Invalid gas limit (provided: " + toString(provided) + " valid:" + toString(valid) + ")").c_str(); } -const char* InvalidMinGasPrice::what() const noexcept { return ("Invalid minimum gas price (provided: " + toString(provided) + " limit:" + toString(limit) + ")").c_str(); } -const char* InvalidNonce::what() const noexcept { return ("Invalid nonce (r: " + toString(required) + " c:" + toString(candidate) + ")").c_str(); } -const char* InvalidBlockNonce::what() const noexcept { return ("Invalid nonce (h: " + toString(h) + " n:" + toString(n) + " d:" + toString(d) + ")").c_str(); } +#define ETH_RETURN_STRING(S) static string s_what; s_what = S; return s_what.c_str(); + +const char* InvalidBlockFormat::what() const noexcept { ETH_RETURN_STRING("Invalid block format: Bad field " + toString(m_f) + " (" + toHex(m_d) + ")"); } +const char* UncleInChain::what() const noexcept { ETH_RETURN_STRING("Uncle in block already mentioned: Uncles " + toString(m_uncles) + " (" + m_block.abridged() + ")"); } +const char* InvalidTransactionsHash::what() const noexcept { ETH_RETURN_STRING("Invalid transactions hash: header says: " + toHex(m_head.ref()) + " block is:" + toHex(m_real.ref())); } +const char* InvalidGasLimit::what() const noexcept { ETH_RETURN_STRING("Invalid gas limit (provided: " + toString(provided) + " valid:" + toString(valid) + ")"); } +const char* InvalidMinGasPrice::what() const noexcept { ETH_RETURN_STRING("Invalid minimum gas price (provided: " + toString(provided) + " limit:" + toString(limit) + ")"); } +const char* InvalidNonce::what() const noexcept { ETH_RETURN_STRING("Invalid nonce (r: " + toString(required) + " c:" + toString(candidate) + ")"); } +const char* InvalidBlockNonce::what() const noexcept { ETH_RETURN_STRING("Invalid nonce (h: " + toString(h) + " n:" + toString(n) + " d:" + toString(d) + ")"); } diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index f9207f795..8a4723696 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -48,7 +48,7 @@ class InvalidBlockFormat: public dev::Exception { public: InvalidBlockFormat(int struct InvalidUnclesHash: virtual dev::Exception {}; struct InvalidUncle: virtual dev::Exception {}; struct UncleTooOld: virtual dev::Exception {}; -class UncleInChain: public dev::Exception { public: UncleInChain(h256Set _uncles, h256 _block): m_uncles(_uncles), m_block(_block) {} h256Set m_uncles; h256 m_block;virtual const char* what() const noexcept; }; +class UncleInChain: public dev::Exception { public: UncleInChain(h256Set _uncles, h256 _block): m_uncles(_uncles), m_block(_block) {} h256Set m_uncles; h256 m_block; virtual const char* what() const noexcept; }; struct DuplicateUncleNonce: virtual dev::Exception {}; struct InvalidStateRoot: virtual dev::Exception {}; class InvalidTransactionsHash: public dev::Exception { public: InvalidTransactionsHash(h256 _head, h256 _real): m_head(_head), m_real(_real) {} h256 m_head; h256 m_real; virtual const char* what() const noexcept; }; diff --git a/libethcore/Dagger.cpp b/libethcore/ProofOfWork.cpp similarity index 50% rename from libethcore/Dagger.cpp rename to libethcore/ProofOfWork.cpp index 956557b64..7d3916fd3 100644 --- a/libethcore/Dagger.cpp +++ b/libethcore/ProofOfWork.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file Dagger.cpp +/** @file ProofOfWork.cpp * @author Gav Wood * @date 2014 */ @@ -28,7 +28,7 @@ #include #include #include -#include "Dagger.h" +#include "ProofOfWork.h" using namespace std; using namespace std::chrono; @@ -37,88 +37,8 @@ namespace dev namespace eth { -#if FAKE_DAGGER - -MineInfo Dagger::mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo) -{ - MineInfo ret; - static std::mt19937_64 s_eng((time(0) + (unsigned)m_last)); - u256 s = (m_last = h256::random(s_eng)); - - bigint d = (bigint(1) << 256) / _difficulty; - ret.requirement = log2((double)d); - - // 2^ 0 32 64 128 256 - // [--------*-------------------------] - // - // evaluate until we run out of time - auto startTime = steady_clock::now(); - if (!_turbo) - this_thread::sleep_for(chrono::milliseconds(_msTimeout * 90 / 100)); - for (; (steady_clock::now() - startTime) < milliseconds(_msTimeout) && _continue; s++, ret.hashes++) - { - o_solution = (h256)s; - auto e = (bigint)(u256)eval(_root, o_solution); - ret.best = min(ret.best, log2((double)e)); - if (e <= d) - { - ret.completed = true; - break; - } - } - - if (ret.completed) - assert(verify(_root, o_solution, _difficulty)); - - return ret; -} - -#else - -Dagger::Dagger() -{ -} - -Dagger::~Dagger() -{ -} - -u256 Dagger::bound(u256 const& _difficulty) -{ - return (u256)((bigint(1) << 256) / _difficulty); -} - -bool Dagger::verify(h256 const& _root, u256 const& _nonce, u256 const& _difficulty) -{ - return eval(_root, _nonce) < bound(_difficulty); -} - -bool Dagger::mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool const& _continue) -{ - // restart search if root has changed - if (m_root != _root) - { - m_root = _root; - m_nonce = 0; - } - - // compute bound - u256 const b = bound(_difficulty); - - // evaluate until we run out of time - for (auto startTime = steady_clock::now(); (steady_clock::now() - startTime) < milliseconds(_msTimeout) && _continue; m_nonce += 1) - { - if (eval(_root, m_nonce) < b) - { - o_solution = m_nonce; - return true; - } - } - return false; -} - template -inline void update(_T& _sha, u256 const& _value) +static inline void update(_T& _sha, u256 const& _value) { int i = 0; for (u256 v = _value; v; ++i, v >>= 8) {} @@ -129,7 +49,7 @@ inline void update(_T& _sha, u256 const& _value) } template -inline void update(_T& _sha, h256 const& _value) +static inline void update(_T& _sha, h256 const& _value) { int i = 0; byte const* data = _value.data(); @@ -138,14 +58,14 @@ inline void update(_T& _sha, h256 const& _value) } template -inline h256 get(_T& _sha) +static inline h256 get(_T& _sha) { h256 ret; _sha.TruncatedFinal(&ret[0], 32); return ret; } -h256 Dagger::node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i) +h256 DaggerEvaluator::node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i) { if (_L == _i) return _root; @@ -166,9 +86,9 @@ h256 Dagger::node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fas return get(bsha); } -h256 Dagger::eval(h256 const& _root, u256 const& _nonce) +h256 DaggerEvaluator::eval(h256 const& _root, h256 const& _nonce) { - h256 extranonce = _nonce >> 26; // with xn = floor(n / 2^26) -> assuming this is with xn = floor(N / 2^26) + h256 extranonce = (u256)_nonce >> 26; // with xn = floor(n / 2^26) -> assuming this is with xn = floor(N / 2^26) CryptoPP::SHA3_256 bsha; for (uint_fast32_t k = 0; k < 4; ++k) { @@ -185,7 +105,6 @@ h256 Dagger::eval(h256 const& _root, u256 const& _nonce) return get(bsha); } -#endif } } #endif diff --git a/libethcore/ProofOfWork.h b/libethcore/ProofOfWork.h new file mode 100644 index 000000000..d942d06f7 --- /dev/null +++ b/libethcore/ProofOfWork.h @@ -0,0 +1,117 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file ProofOfWork.h + * @author Gav Wood + * @date 2014 + * + * ProofOfWork algorithm. Or not. + */ + +#pragma once + +#include +#include +#include +#include +#include "CommonEth.h" + +#define FAKE_DAGGER 1 + +namespace dev +{ +namespace eth +{ + +struct MineInfo +{ + void combine(MineInfo const& _m) { requirement = std::max(requirement, _m.requirement); best = std::min(best, _m.best); hashes += _m.hashes; completed = completed || _m.completed; } + double requirement = 0; + double best = 1e99; + unsigned hashes = 0; + bool completed = false; +}; + +template +class ProofOfWorkEngine: public Evaluator +{ +public: + static bool verify(h256 const& _root, h256 const& _nonce, u256 const& _difficulty) { return (bigint)(u256)Evaluator::eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; } + + inline MineInfo mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false); + +protected: + h256 m_last; +}; + +class SHA3Evaluator +{ +public: + static h256 eval(h256 const& _root, h256 const& _nonce) { h256 b[2] = { _root, _nonce }; return sha3(bytesConstRef((byte const*)&b[0], 64)); } +}; + +// TODO: class ARPoWEvaluator + +class DaggerEvaluator +{ +public: + static h256 eval(h256 const& _root, h256 const& _nonce); + +private: + static h256 node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i); +}; + +using SHA3ProofOfWork = ProofOfWorkEngine; + +using ProofOfWork = SHA3ProofOfWork; + +template +MineInfo ProofOfWorkEngine::mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo) +{ + MineInfo ret; + static std::mt19937_64 s_eng((time(0) + (unsigned)m_last)); + u256 s = (m_last = h256::random(s_eng)); + + bigint d = (bigint(1) << 256) / _difficulty; + ret.requirement = log2((double)d); + + // 2^ 0 32 64 128 256 + // [--------*-------------------------] + // + // evaluate until we run out of time + auto startTime = std::chrono::steady_clock::now(); + if (!_turbo) + std::this_thread::sleep_for(std::chrono::milliseconds(_msTimeout * 90 / 100)); + for (; (std::chrono::steady_clock::now() - startTime) < std::chrono::milliseconds(_msTimeout) && _continue; s++, ret.hashes++) + { + o_solution = (h256)s; + auto e = (bigint)(u256)Evaluator::eval(_root, o_solution); + ret.best = std::min(ret.best, log2((double)e)); + if (e <= d) + { + ret.completed = true; + break; + } + } + + if (ret.completed) + assert(verify(_root, o_solution, _difficulty)); + + return ret; +} + +} +} diff --git a/libethcore/_libethcore.cpp b/libethcore/_libethcore.cpp index 477034b9e..93eaf0d16 100644 --- a/libethcore/_libethcore.cpp +++ b/libethcore/_libethcore.cpp @@ -2,6 +2,6 @@ #include "All.h" #include "BlockInfo.cpp" #include "CommonEth.cpp" -#include "Dagger.cpp" +#include "ProofOfWork.cpp" #include "Exceptions.cpp" #endif diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 0a66a0979..d07bb71f3 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include "State.h" #include "Defaults.h" @@ -43,7 +43,9 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc) for (it->SeekToFirst(); it->Valid(); it->Next()) if (it->key().ToString() != "best") { - BlockDetails d(RLP(it->value().ToString())); + string rlpString = it->value().ToString(); + RLP r(rlpString); + BlockDetails d(r); _out << toHex(it->key().ToString()) << ": " << d.number << " @ " << d.parent << (cmp == it->key().ToString() ? " BEST" : "") << std::endl; } delete it; @@ -426,7 +428,10 @@ h256s BlockChain::treeRoute(h256 _from, h256 _to, h256* o_common, bool _pre, boo void BlockChain::checkConsistency() { - m_details.clear(); + { + WriteGuard l(x_details); + m_details.clear(); + } ldb::Iterator* it = m_db->NewIterator(m_readOptions); for (it->SeekToFirst(); it->Valid(); it->Next()) if (it->key().size() == 32) @@ -434,11 +439,17 @@ void BlockChain::checkConsistency() h256 h((byte const*)it->key().data(), h256::ConstructFromPointer); auto dh = details(h); auto p = dh.parent; - if (p != h256()) + if (p != h256() && p != m_genesisHash) // TODO: for some reason the genesis details with the children get squished. not sure why. { auto dp = details(p); - assert(contains(dp.children, h)); - assert(dp.number == dh.number - 1); + if (asserts(contains(dp.children, h))) + { + cnote << "Apparently the database is corrupt. Not much we can do at this stage..."; + } + if (assertsEqual(dp.number, dh.number - 1)) + { + cnote << "Apparently the database is corrupt. Not much we can do at this stage..."; + } } } delete it; diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 128dd5999..cb2049886 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -6,15 +6,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE ethereum) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} evm) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index d22f7d873..717e2684c 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -323,23 +323,30 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) { - State temp; - Transaction t; -// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); + bytes out; + try { - ReadGuard l(x_stateDB); - temp = m_postMine; - t.nonce = temp.transactionsFrom(toAddress(_secret)); + State temp; + Transaction t; + // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); + { + ReadGuard l(x_stateDB); + temp = m_postMine; + t.nonce = temp.transactionsFrom(toAddress(_secret)); + } + t.value = _value; + t.gasPrice = _gasPrice; + t.gas = _gas; + t.receiveAddress = _dest; + t.data = _data; + t.sign(_secret); + u256 gasUsed = temp.execute(t.data, &out, false); + (void)gasUsed; // TODO: do something with gasused which it returns. + } + catch (...) + { + // TODO: Some sort of notification of failure. } - t.value = _value; - t.gasPrice = _gasPrice; - t.gas = _gas; - t.receiveAddress = _dest; - t.data = _data; - t.sign(_secret); - bytes out; - u256 gasUsed = temp.execute(t.data, &out, false); - (void)gasUsed; // TODO: do something with gasused which it returns. return out; } diff --git a/libethereum/Client.h b/libethereum/Client.h index e7bbc1ca3..8ec65c199 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include "BlockChain.h" #include "TransactionQueue.h" diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 8e92fa9e6..5daf67fb9 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -148,17 +148,19 @@ void EthereumHost::doWork() { bool netChange = ensureInitialised(); auto h = m_chain.currentHash(); - maintainTransactions(h); - maintainBlocks(h); + // If we've finished our initial sync (including getting all the blocks into the chain so as to reduce invalid transactions), start trading transactions & blocks + if (!isSyncing() && m_chain.isKnown(m_latestBlockSent)) + { + maintainTransactions(); + maintainBlocks(h); + } // return netChange; // TODO: Figure out what to do with netChange. (void)netChange; } -void EthereumHost::maintainTransactions(h256 _currentHash) +void EthereumHost::maintainTransactions() { - bool resendAll = (!isSyncing() && m_chain.isKnown(m_latestBlockSent) && _currentHash != m_latestBlockSent); - // Send any new transactions. for (auto const& p: peers()) if (auto ep = p->cap()) @@ -166,14 +168,14 @@ void EthereumHost::maintainTransactions(h256 _currentHash) bytes b; unsigned n = 0; for (auto const& i: m_tq.transactions()) - if ((!m_transactionsSent.count(i.first) && !ep->m_knownTransactions.count(i.first)) || ep->m_requireTransactions || resendAll) + if (ep->m_requireTransactions || (!m_transactionsSent.count(i.first) && !ep->m_knownTransactions.count(i.first))) { b += i.second; ++n; m_transactionsSent.insert(i.first); } ep->clearKnownTransactions(); - + if (n || ep->m_requireTransactions) { RLPStream ts; @@ -186,23 +188,17 @@ void EthereumHost::maintainTransactions(h256 _currentHash) void EthereumHost::maintainBlocks(h256 _currentHash) { - // If we've finished our initial sync send any new blocks. - if (!isSyncing() && m_chain.isKnown(m_latestBlockSent) && m_chain.details(m_latestBlockSent).totalDifficulty < m_chain.details(_currentHash).totalDifficulty) + // Send any new blocks. + if (m_chain.details(m_latestBlockSent).totalDifficulty < m_chain.details(_currentHash).totalDifficulty) { - // TODO: clean up - h256s hs; - hs.push_back(_currentHash); - bytes bs; - for (auto h: hs) - bs += m_chain.block(h); - clog(NetMessageSummary) << "Sending" << hs.size() << "new blocks (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; + clog(NetMessageSummary) << "Sending a new block (current is" << _currentHash << ", was" << m_latestBlockSent << ")"; for (auto j: peers()) { auto p = j->cap(); RLPStream ts; - p->prep(ts, NewBlockPacket, hs.size()).appendRaw(bs, hs.size()); + p->prep(ts, NewBlockPacket, 2).appendRaw(m_chain.block(), 1).append(m_chain.details().totalDifficulty); Guard l(p->x_knownBlocks); if (!p->m_knownBlocks.count(_currentHash)) diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index a4ccf5383..18ba765aa 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -72,7 +72,7 @@ public: DownloadMan const& downloadMan() const { return m_man; } bool isSyncing() const { return !!m_syncer; } - bool isBanned(h512 _id) const { return !!m_banned.count(_id); } + bool isBanned(p2p::NodeId _id) const { return !!m_banned.count(_id); } private: /// Session is tell us that we may need (re-)syncing with the peer. @@ -84,7 +84,7 @@ private: /// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network. void doWork(); - void maintainTransactions(h256 _currentBlock); + void maintainTransactions(); void maintainBlocks(h256 _currentBlock); /// Get a bunch of needed blocks. @@ -116,7 +116,7 @@ private: h256 m_latestBlockSent; h256Set m_transactionsSent; - std::set m_banned; + std::set m_banned; }; } diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index 5817aa434..24b400c1d 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -82,7 +82,11 @@ void EthereumPeer::transition(Asking _a, bool _force) { clogS(NetMessageSummary) << "Transition!" << ::toString(_a) << "from" << ::toString(m_asking) << ", " << (isSyncing() ? "syncing" : "holding") << (needsSyncing() ? "& needed" : ""); + if (m_asking == Asking::State && _a != Asking::State) + m_requireTransactions = true; + RLPStream s; + if (_a == Asking::State) { if (m_asking == Asking::Nothing) @@ -288,6 +292,8 @@ void EthereumPeer::attemptSync() bool EthereumPeer::interpret(unsigned _id, RLP const& _r) { + try + { switch (_id) { case StatusPacket: @@ -322,11 +328,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r) } break; } - case GetTransactionsPacket: - { - m_requireTransactions = true; - break; - } + case GetTransactionsPacket: break; // DEPRECATED. case TransactionsPacket: { clogS(NetMessageSummary) << "Transactions (" << dec << (_r.itemCount() - 1) << "entries)"; @@ -509,5 +511,11 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r) default: return false; } + } + catch (std::exception const& _e) + { + clogS(NetWarn) << "Peer causing an exception:" << _e.what() << _r; + } + return true; } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 61d179ed8..f31683be0 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -54,23 +54,23 @@ bool Executive::setup(bytesConstRef _rlp) auto nonceReq = m_s.transactionsFrom(m_sender); if (m_t.nonce != nonceReq) { - clog(StateChat) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce; + clog(StateDetail) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce; BOOST_THROW_EXCEPTION(InvalidNonce(nonceReq, m_t.nonce)); } // Don't like transactions whose gas price is too low. NOTE: this won't stay here forever - it's just until we get a proper gas price discovery protocol going. if (m_t.gasPrice < m_s.m_currentBlock.minGasPrice) { - clog(StateChat) << "Offered gas-price is too low: Require >" << m_s.m_currentBlock.minGasPrice << " Got" << m_t.gasPrice; + clog(StateDetail) << "Offered gas-price is too low: Require >" << m_s.m_currentBlock.minGasPrice << " Got" << m_t.gasPrice; BOOST_THROW_EXCEPTION(GasPriceTooLow()); } // Check gas cost is enough. - u256 gasCost = m_t.data.size() * c_txDataGas + c_txGas; + u256 gasCost = u256(m_t.data.size()) * FeeStructure::c_txDataGas + FeeStructure::c_txGas; if (m_t.gas < gasCost) { - clog(StateChat) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas; + clog(StateDetail) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas; BOOST_THROW_EXCEPTION(OutOfGas()); } @@ -79,14 +79,14 @@ bool Executive::setup(bytesConstRef _rlp) // Avoid unaffordable transactions. if (m_s.balance(m_sender) < cost) { - clog(StateChat) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender); + clog(StateDetail) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender); BOOST_THROW_EXCEPTION(NotEnoughCash()); } u256 startGasUsed = m_s.gasUsed(); if (startGasUsed + m_t.gas > m_s.m_currentBlock.gasLimit) { - clog(StateChat) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas; + clog(StateDetail) << "Too much gas used in this block: Require <" << (m_s.m_currentBlock.gasLimit - startGasUsed) << " Got" << m_t.gas; BOOST_THROW_EXCEPTION(BlockGasLimitReached()); } @@ -94,7 +94,7 @@ bool Executive::setup(bytesConstRef _rlp) m_s.noteSending(m_sender); // Pay... -// cnote << "Paying" << formatBalance(cost) << "from sender (includes" << m_t.gas << "gas at" << formatBalance(m_t.gasPrice) << ")"; + clog(StateDetail) << "Paying" << formatBalance(cost) << "from sender (includes" << m_t.gas << "gas at" << formatBalance(m_t.gasPrice) << ")"; m_s.subBalance(m_sender, cost); if (m_ms) @@ -158,7 +158,7 @@ OnOpFunc Executive::simpleTrace() for (auto const& i: ext.state().storage(ext.myAddress)) o << showbase << hex << i.first << ": " << i.second << endl; dev::LogOutputStream(true) << o.str(); - dev::LogOutputStream(false) << " | " << dec << ext.level << " | " << ext.myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << dec << vm.gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32" << " ]"; + dev::LogOutputStream(false) << " | " << dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << dec << vm.gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32" << " ]"; }; } diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 3b4b7161f..612164d13 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -39,8 +39,8 @@ class ExtVM: public ExtVMFace { public: /// Full constructor. - ExtVM(State& _s, Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, Manifest* o_ms, unsigned _level = 0): - ExtVMFace(_myAddress, _caller, _origin, _value, _gasPrice, _data, _code, _s.m_previousBlock, _s.m_currentBlock), level(_level), m_s(_s), m_origCache(_s.m_cache), m_ms(o_ms) + ExtVM(State& _s, Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, Manifest* o_ms, unsigned _depth = 0): + ExtVMFace(_myAddress, _caller, _origin, _value, _gasPrice, _data, _code, _s.m_previousBlock, _s.m_currentBlock, _depth), m_s(_s), m_origCache(_s.m_cache), m_ms(o_ms) { m_s.ensureCached(_myAddress, true, true); } @@ -61,7 +61,7 @@ public: m_s.noteSending(myAddress); if (m_ms) m_ms->internal.resize(m_ms->internal.size() + 1); - auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _code, origin, &suicides, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, level + 1); + auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _code, origin, &suicides, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, depth + 1); if (m_ms && !m_ms->internal.back().from) m_ms->internal.pop_back(); return ret; @@ -72,7 +72,7 @@ public: { if (m_ms) m_ms->internal.resize(m_ms->internal.size() + 1); - auto ret = m_s.call(_receiveAddress, _codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, _gas, _out, origin, &suicides, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, level + 1); + auto ret = m_s.call(_receiveAddress, _codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, _gas, _out, origin, &suicides, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, depth + 1); if (m_ms && !m_ms->internal.back().from) m_ms->internal.pop_back(); return ret; @@ -100,9 +100,6 @@ public: State& state() const { return m_s; } - /// @note not a part of the main API; just for use by tracing/debug stuff. - unsigned level = 0; - private: State& m_s; ///< A reference to the base state. std::map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 7ae650590..6a32e81c4 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -123,7 +123,7 @@ public: virtual Addresses addresses(int _block) const = 0; /// Get the fee associated for a transaction with the given data. - static u256 txGas(unsigned _dataCount, u256 _gas = 0) { return c_txDataGas * _dataCount + c_txGas + _gas; } + static u256 txGas(unsigned _dataCount, u256 _gas = 0) { return FeeStructure::c_txDataGas * u256(_dataCount) + FeeStructure::c_txGas + _gas; } /// Get the remaining gas limit in this block. virtual u256 gasLimitRemaining() const = 0; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 047b9dcd5..8f2794c12 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include "BlockChain.h" #include "Defaults.h" @@ -75,7 +74,9 @@ void ripemd160Code(bytesConstRef _in, bytesRef _out) { h256 ret; ripemd160(_in, bytesRef(ret.data(), 32)); - memcpy(_out.data(), &ret, min(_out.size(), sizeof(ret))); + memset(_out.data(), 0, std::min(12, _out.size())); + if (_out.size() > 12) + memcpy(_out.data() + 12, &ret, min(_out.size() - 12, sizeof(ret))); } const std::map State::c_precompiled = @@ -835,7 +836,7 @@ MineInfo State::mine(unsigned _msTimeout, bool _turbo) m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); // TODO: Miner class that keeps dagger between mine calls (or just non-polling mining). - auto ret = m_dagger.mine(/*out*/m_currentBlock.nonce, m_currentBlock.headerHashWithoutNonce(), m_currentBlock.difficulty, _msTimeout, true, _turbo); + auto ret = m_pow.mine(/*out*/m_currentBlock.nonce, m_currentBlock.headerHashWithoutNonce(), m_currentBlock.difficulty, _msTimeout, true, _turbo); if (!ret.completed) m_currentBytes.clear(); @@ -1284,8 +1285,8 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s) { auto it = _s.m_cache.find(i); AddressState* cache = it != _s.m_cache.end() ? &it->second : nullptr; - auto rlpString = trie.at(i); - RLP r(dtr.count(i) ? rlpString : ""); + string rlpString = dtr.count(i) ? trie.at(i) : ""; + RLP r(rlpString); assert(cache || r); if (cache && !cache->isAlive()) @@ -1298,7 +1299,8 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s) stringstream contout; - if ((!cache || cache->codeBearing()) && (!r || r[3].toHash() != EmptySHA3)) + /// For POC6, 3rd value of account is code and will be empty if code is not present. + if ((cache && cache->codeBearing()) || (!cache && r && !r[3].isEmpty())) { std::map mem; std::set back; diff --git a/libethereum/State.h b/libethereum/State.h index a28d8155c..5552ba454 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include "TransactionQueue.h" @@ -40,15 +40,16 @@ namespace dev { -namespace test{ class FakeExtVM;} +namespace test{ class FakeExtVM; class FakeState;} namespace eth { class BlockChain; -struct StateChat: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 4; }; +struct StateChat: public LogChannel { static const char* name() { return "-S-"; } static const int verbosity = 4; }; struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; }; +struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; }; struct TransactionReceipt { @@ -84,6 +85,7 @@ class State { friend class ExtVM; friend class test::FakeExtVM; + friend class test::FakeState; friend class Executive; public: @@ -321,7 +323,7 @@ private: Address m_ourAddress; ///< Our address (i.e. the address to which fees go). - Dagger m_dagger; + ProofOfWork m_pow; u256 m_blockReward; diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index f19119f83..0c31a9fc3 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -6,15 +6,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE evm) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} ethcore) diff --git a/libevm/ExtVMFace.cpp b/libevm/ExtVMFace.cpp index 7c938417a..da189d899 100644 --- a/libevm/ExtVMFace.cpp +++ b/libevm/ExtVMFace.cpp @@ -25,7 +25,7 @@ using namespace std; using namespace dev; using namespace dev::eth; -ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock): +ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, unsigned _depth): myAddress(_myAddress), caller(_caller), origin(_origin), @@ -34,6 +34,7 @@ ExtVMFace::ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 data(_data), code(_code), previousBlock(_previousBlock), - currentBlock(_currentBlock) + currentBlock(_currentBlock), + depth(_depth) {} diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index f78cb82cb..1b0f9eaf5 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -54,7 +54,7 @@ public: ExtVMFace() {} /// Full constructor. - ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock); + ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, unsigned _depth); /// Get the code at the given location in code ROM. byte getCode(u256 _n) const { return _n < code.size() ? code[(unsigned)_n] : 0; } @@ -99,6 +99,7 @@ public: BlockInfo previousBlock; ///< The previous block's information. BlockInfo currentBlock; ///< The current block's information. std::set
suicides; ///< Any accounts that have suicided. + unsigned depth; ///< Depth of the present call. }; } diff --git a/libevm/FeeStructure.cpp b/libevm/FeeStructure.cpp index d29b9fef9..aeeb19e27 100644 --- a/libevm/FeeStructure.cpp +++ b/libevm/FeeStructure.cpp @@ -16,22 +16,168 @@ */ /** @file FeeStructure.cpp * @author Gav Wood + * @author Pawel Bylica * @date 2014 */ #include "FeeStructure.h" -using namespace std; -using namespace dev; -using namespace dev::eth; - -u256 const dev::eth::c_stepGas = 1; -u256 const dev::eth::c_balanceGas = 20; -u256 const dev::eth::c_sha3Gas = 20; -u256 const dev::eth::c_sloadGas = 20; -u256 const dev::eth::c_sstoreGas = 100; -u256 const dev::eth::c_createGas = 100; -u256 const dev::eth::c_callGas = 20; -u256 const dev::eth::c_memoryGas = 1; -u256 const dev::eth::c_txDataGas = 5; -u256 const dev::eth::c_txGas = 500; +#include + +#include "VM.h" + +namespace dev +{ +namespace eth +{ + +uint32_t FeeStructure::getInstructionFee(Instruction _inst) +{ + switch (_inst) + { + default: + BOOST_THROW_EXCEPTION(BadInstruction()); + + case Instruction::STOP: + case Instruction::SUICIDE: + return 0; + + case Instruction::SSTORE: + return c_sstoreGas; + + case Instruction::SLOAD: + return c_sloadGas; + + case Instruction::SHA3: + return c_sha3Gas; + + case Instruction::BALANCE: + return c_sha3Gas; + + case Instruction::CALL: + case Instruction::CALLCODE: + return c_callGas; + + case Instruction::CREATE: + return c_createGas; + + case Instruction::ADD: + case Instruction::MUL: + case Instruction::SUB: + case Instruction::DIV: + case Instruction::SDIV: + case Instruction::MOD: + case Instruction::SMOD: + case Instruction::EXP: + case Instruction::NEG: + case Instruction::LT: + case Instruction::GT: + case Instruction::SLT: + case Instruction::SGT: + case Instruction::EQ: + case Instruction::NOT: + case Instruction::AND: + case Instruction::OR: + case Instruction::XOR: + case Instruction::BYTE: + case Instruction::ADDMOD: + case Instruction::MULMOD: + case Instruction::ADDRESS: + case Instruction::ORIGIN: + case Instruction::CALLER: + case Instruction::CALLVALUE: + case Instruction::CALLDATALOAD: + case Instruction::CALLDATASIZE: + case Instruction::CODESIZE: + case Instruction::EXTCODESIZE: + case Instruction::GASPRICE: + case Instruction::PREVHASH: + case Instruction::COINBASE: + case Instruction::TIMESTAMP: + case Instruction::NUMBER: + case Instruction::DIFFICULTY: + case Instruction::GASLIMIT: + case Instruction::PUSH1: + case Instruction::PUSH2: + case Instruction::PUSH3: + case Instruction::PUSH4: + case Instruction::PUSH5: + case Instruction::PUSH6: + case Instruction::PUSH7: + case Instruction::PUSH8: + case Instruction::PUSH9: + case Instruction::PUSH10: + case Instruction::PUSH11: + case Instruction::PUSH12: + case Instruction::PUSH13: + case Instruction::PUSH14: + case Instruction::PUSH15: + case Instruction::PUSH16: + case Instruction::PUSH17: + case Instruction::PUSH18: + case Instruction::PUSH19: + case Instruction::PUSH20: + case Instruction::PUSH21: + case Instruction::PUSH22: + case Instruction::PUSH23: + case Instruction::PUSH24: + case Instruction::PUSH25: + case Instruction::PUSH26: + case Instruction::PUSH27: + case Instruction::PUSH28: + case Instruction::PUSH29: + case Instruction::PUSH30: + case Instruction::PUSH31: + case Instruction::PUSH32: + case Instruction::POP: + case Instruction::DUP1: + case Instruction::DUP2: + case Instruction::DUP3: + case Instruction::DUP4: + case Instruction::DUP5: + case Instruction::DUP6: + case Instruction::DUP7: + case Instruction::DUP8: + case Instruction::DUP9: + case Instruction::DUP10: + case Instruction::DUP11: + case Instruction::DUP12: + case Instruction::DUP13: + case Instruction::DUP14: + case Instruction::DUP15: + case Instruction::DUP16: + case Instruction::SWAP1: + case Instruction::SWAP2: + case Instruction::SWAP3: + case Instruction::SWAP4: + case Instruction::SWAP5: + case Instruction::SWAP6: + case Instruction::SWAP7: + case Instruction::SWAP8: + case Instruction::SWAP9: + case Instruction::SWAP10: + case Instruction::SWAP11: + case Instruction::SWAP12: + case Instruction::SWAP13: + case Instruction::SWAP14: + case Instruction::SWAP15: + case Instruction::SWAP16: + case Instruction::JUMP: + case Instruction::JUMPI: + case Instruction::PC: + case Instruction::MSIZE: + case Instruction::GAS: + case Instruction::JUMPDEST: + case Instruction::RETURN: + case Instruction::MSTORE: + case Instruction::MSTORE8: + case Instruction::MLOAD: + case Instruction::CALLDATACOPY: + case Instruction::CODECOPY: + case Instruction::EXTCODECOPY: + return c_stepGas; + } +} + +} +} \ No newline at end of file diff --git a/libevm/FeeStructure.h b/libevm/FeeStructure.h index 76be9a398..60a158388 100644 --- a/libevm/FeeStructure.h +++ b/libevm/FeeStructure.h @@ -16,28 +16,40 @@ */ /** @file FeeStructure.h * @author Gav Wood + * @author Pawel Bylica * @date 2014 */ #pragma once -#include +#include + +#include namespace dev { namespace eth { -extern u256 const c_stepGas; ///< Once per operation, except for SSTORE, SLOAD, BALANCE, SHA3, CREATE, CALL. -extern u256 const c_balanceGas; ///< Once per BALANCE operation. -extern u256 const c_sha3Gas; ///< Once per SHA3 operation. -extern u256 const c_sloadGas; ///< Once per SLOAD operation. -extern u256 const c_sstoreGas; ///< Once per non-zero storage element in a CREATE call/transaction. Also, once/twice per SSTORE operation depending on whether the zeroness changes (twice iff it changes from zero; nothing at all if to zero) or doesn't (once). -extern u256 const c_createGas; ///< Once per CREATE operation & contract-creation transaction. -extern u256 const c_callGas; ///< Once per CALL operation & message call transaction. -extern u256 const c_memoryGas; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. -extern u256 const c_txDataGas; ///< Per byte of data attached to a transaction. NOTE: Not payable on data of calls between transactions. -extern u256 const c_txGas; ///< Per transaction. NOTE: Not payable on data of calls between transactions. +enum class Instruction: uint8_t; + +struct FeeStructure +{ + static uint32_t const c_stepGas = 1; ///< Once per operation, except for SSTORE, SLOAD, BALANCE, SHA3, CREATE, CALL. + static uint32_t const c_balanceGas = 20; ///< Once per BALANCE operation. + static uint32_t const c_sha3Gas = 20; ///< Once per SHA3 operation. + static uint32_t const c_sloadGas = 20; ///< Once per SLOAD operation. + static uint32_t const c_sstoreGas = 100; ///< Once per non-zero storage element in a CREATE call/transaction. Also, once/twice per SSTORE operation depending on whether the zeroness changes (twice iff it changes from zero; nothing at all if to zero) or doesn't (once). + static uint32_t const c_createGas = 100; ///< Once per CREATE operation & contract-creation transaction. + static uint32_t const c_callGas = 20; ///< Once per CALL operation & message call transaction. + static uint32_t const c_memoryGas = 1; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. + static uint32_t const c_txDataGas = 5; ///< Per byte of data attached to a transaction. NOTE: Not payable on data of calls between transactions. + static uint32_t const c_txGas = 500; ///< Per transaction. NOTE: Not payable on data of calls between transactions. + + /// Returns step fee of the instruction. + /// In case of bad instruction code, throws BadInstruction exception. + static uint32_t getInstructionFee(Instruction _inst); +}; } } diff --git a/libevm/VM.h b/libevm/VM.h index 399df72dd..e97e5c4eb 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -101,30 +101,17 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con Instruction inst = (Instruction)_ext.getCode(m_curPC); // FEES... - bigint runGas = c_stepGas; + bigint runGas = FeeStructure::getInstructionFee(inst); // throws BadInstruction bigint newTempSize = m_temp.size(); switch (inst) { - case Instruction::STOP: - runGas = 0; - break; - - case Instruction::SUICIDE: - runGas = 0; - break; case Instruction::SSTORE: require(2); if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2]) - runGas = c_sstoreGas * 2; + runGas = FeeStructure::c_sstoreGas * 2; else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2]) runGas = 0; - else - runGas = c_sstoreGas; - break; - - case Instruction::SLOAD: - runGas = c_sloadGas; break; // These all operate on memory and therefore potentially expand it: @@ -146,7 +133,6 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con break; case Instruction::SHA3: require(2); - runGas = c_sha3Gas; newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]); break; case Instruction::CALLDATACOPY: @@ -161,20 +147,11 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con require(4); newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]); break; - - case Instruction::BALANCE: - runGas = c_balanceGas; - break; case Instruction::CALL: - require(7); - runGas = c_callGas + m_stack[m_stack.size() - 1]; - newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); - break; - case Instruction::CALLCODE: require(7); - runGas = c_callGas + m_stack[m_stack.size() - 1]; + runGas += m_stack[m_stack.size() - 1]; newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5])); break; @@ -184,17 +161,14 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con auto inOff = m_stack[m_stack.size() - 2]; auto inSize = m_stack[m_stack.size() - 3]; newTempSize = inOff + inSize; - runGas = c_createGas; break; } - default: - break; } newTempSize = (newTempSize + 31) / 32 * 32; if (newTempSize > m_temp.size()) - runGas += c_memoryGas * (newTempSize - m_temp.size()) / 32; + runGas += FeeStructure::c_memoryGas * (newTempSize - m_temp.size()) / 32; if (_onOp) _onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext); @@ -567,7 +541,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con case Instruction::JUMP: require(1); nextPC = m_stack.back(); - if ((Instruction)_ext.getCode(nextPC) != Instruction::JUMPDEST) + if (nextPC && (Instruction)_ext.getCode(nextPC - 1) != Instruction::JUMPDEST) BOOST_THROW_EXCEPTION(BadJumpDestination()); m_stack.pop_back(); break; @@ -576,7 +550,7 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con if (m_stack[m_stack.size() - 2]) { nextPC = m_stack.back(); - if ((Instruction)_ext.getCode(nextPC) != Instruction::JUMPDEST) + if (nextPC && (Instruction)_ext.getCode(nextPC - 1) != Instruction::JUMPDEST) BOOST_THROW_EXCEPTION(BadJumpDestination()); } m_stack.pop_back(); @@ -606,6 +580,8 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con if (_ext.balance(_ext.myAddress) >= endowment) { + if (_ext.depth == 1024) + BOOST_THROW_EXCEPTION(OutOfGas()); _ext.subBalance(endowment); m_stack.push_back((u160)_ext.create(endowment, &m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); } @@ -636,6 +612,8 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con if (_ext.balance(_ext.myAddress) >= value) { + if (_ext.depth == 1024) + BOOST_THROW_EXCEPTION(OutOfGas()); _ext.subBalance(value); m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), &gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, Address(), receiveAddress)); } @@ -665,8 +643,6 @@ template dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con } case Instruction::STOP: return bytesConstRef(); - default: - BOOST_THROW_EXCEPTION(BadInstruction()); } } if (_steps == (uint64_t)-1) diff --git a/libevmface/CMakeLists.txt b/libevmface/CMakeLists.txt index 212ce825d..874b9e397 100644 --- a/libevmface/CMakeLists.txt +++ b/libevmface/CMakeLists.txt @@ -6,15 +6,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE evmface) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} devcore) diff --git a/evmcc/BasicBlock.cpp b/libevmjit/BasicBlock.cpp similarity index 100% rename from evmcc/BasicBlock.cpp rename to libevmjit/BasicBlock.cpp diff --git a/evmcc/BasicBlock.h b/libevmjit/BasicBlock.h similarity index 100% rename from evmcc/BasicBlock.h rename to libevmjit/BasicBlock.h diff --git a/evmcc/Compiler.cpp b/libevmjit/Compiler.cpp similarity index 94% rename from evmcc/Compiler.cpp rename to libevmjit/Compiler.cpp index c2c8376fd..f3e912125 100644 --- a/evmcc/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -29,7 +29,7 @@ Compiler::Compiler(): Type::init(m_builder.getContext()); } -void Compiler::createBasicBlocks(const bytes& bytecode) +void Compiler::createBasicBlocks(bytesConstRef bytecode) { std::set splitPoints; // Sorted collections of instruction indices where basic blocks start/end splitPoints.insert(0); // First basic block @@ -38,9 +38,9 @@ void Compiler::createBasicBlocks(const bytes& bytecode) std::vector indirectJumpTargets; boost::dynamic_bitset<> validJumpTargets(bytecode.size()); - for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) + for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) { - ProgramCounter currentPC = curr - bytecode.cbegin(); + ProgramCounter currentPC = curr - bytecode.begin(); validJumpTargets[currentPC] = 1; auto inst = static_cast(*curr); @@ -51,7 +51,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) { auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; auto next = curr + numBytes + 1; - if (next >= bytecode.cend()) + if (next >= bytecode.end()) break; auto nextInst = static_cast(*next); @@ -67,12 +67,10 @@ void Compiler::createBasicBlocks(const bytes& bytecode) } // Create a block for the JUMP target. - ProgramCounter targetPC = val.convert_to(); - if (targetPC > bytecode.size()) - targetPC = bytecode.size(); + ProgramCounter targetPC = val < bytecode.size() ? val.convert_to() : bytecode.size(); splitPoints.insert(targetPC); - ProgramCounter jumpPC = (next - bytecode.cbegin()); + ProgramCounter jumpPC = (next - bytecode.begin()); directJumpTargets[jumpPC] = targetPC; } @@ -95,7 +93,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) case Instruction::SUICIDE: { // Create a basic block starting at the following instruction. - if (curr + 1 < bytecode.cend()) + if (curr + 1 < bytecode.end()) { splitPoints.insert(currentPC + 1); } @@ -130,16 +128,23 @@ void Compiler::createBasicBlocks(const bytes& bytecode) for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) { + if (it->second >= bytecode.size()) + { + // Jumping out of code means STOP + m_directJumpTargets[it->first] = m_stopBB; + continue; + } + auto blockIter = basicBlocks.find(it->second); if (blockIter != basicBlocks.end()) { - m_directJumpTargets[it->first] = &(blockIter->second); + m_directJumpTargets[it->first] = blockIter->second.llvm(); } else { std::cerr << "Bad JUMP at PC " << it->first << ": " << it->second << " is not a valid PC\n"; - m_directJumpTargets[it->first] = m_badJumpBlock.get(); + m_directJumpTargets[it->first] = m_badJumpBlock->llvm(); } } @@ -149,7 +154,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode) } } -std::unique_ptr Compiler::compile(const bytes& bytecode) +std::unique_ptr Compiler::compile(bytesConstRef bytecode) { auto module = std::make_unique("main", m_builder.getContext()); @@ -214,7 +219,7 @@ std::unique_ptr Compiler::compile(const bytes& bytecode) } -void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) { auto& stack = basicBlock.getStack(); m_builder.SetInsertPoint(basicBlock.llvm()); @@ -567,7 +572,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, // 1. this is not the first instruction in the block // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) // Otherwise generate a indirect jump (a switch). - BasicBlock* targetBlock = nullptr; + llvm::BasicBlock* targetBlock = nullptr; if (currentPC != basicBlock.begin()) { auto pairIter = m_directJumpTargets.find(currentPC); @@ -584,7 +589,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, // The target address is computed at compile time, // just pop it without looking... stack.pop(); - m_builder.CreateBr(targetBlock->llvm()); + m_builder.CreateBr(targetBlock); } else { @@ -606,7 +611,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, if (targetBlock) { stack.pop(); - m_builder.CreateCondBr(cond, targetBlock->llvm(), nextBasicBlock); + m_builder.CreateCondBr(cond, targetBlock, nextBasicBlock); } else { @@ -923,10 +928,18 @@ void Compiler::linkBasicBlocks() for (auto it = llvm::po_ext_begin(bb.second.llvm(), visitSet), end = llvm::po_ext_end(bb.second.llvm(), visitSet); it != end; ++it) { - std::cerr << it->getName().str() << std::endl; + // TODO: Use logger + //std::cerr << it->getName().str() << std::endl; completePhiNodes(*it); } } + + // Remove jump table block if not predecessors + if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) + { + m_jumpTableBlock->llvm()->eraseFromParent(); + m_jumpTableBlock.reset(); + } } void Compiler::dumpBasicBlockGraph(std::ostream& out) diff --git a/evmcc/Compiler.h b/libevmjit/Compiler.h similarity index 75% rename from evmcc/Compiler.h rename to libevmjit/Compiler.h index bda154689..8972322ec 100644 --- a/evmcc/Compiler.h +++ b/libevmjit/Compiler.h @@ -22,16 +22,16 @@ public: Compiler(); - std::unique_ptr compile(const bytes& bytecode); + std::unique_ptr compile(bytesConstRef bytecode); void dumpBasicBlockGraph(std::ostream& out); private: - void createBasicBlocks(const bytes& bytecode); + void createBasicBlocks(bytesConstRef bytecode); - void compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); void linkBasicBlocks(); @@ -46,7 +46,7 @@ private: /** * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. */ - std::map m_directJumpTargets; + std::map m_directJumpTargets; /** * A list of possible blocks to which there may be indirect jumps. diff --git a/evmcc/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp similarity index 100% rename from evmcc/CompilerHelper.cpp rename to libevmjit/CompilerHelper.cpp diff --git a/evmcc/CompilerHelper.h b/libevmjit/CompilerHelper.h similarity index 100% rename from evmcc/CompilerHelper.h rename to libevmjit/CompilerHelper.h diff --git a/evmcc/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp similarity index 75% rename from evmcc/ExecutionEngine.cpp rename to libevmjit/ExecutionEngine.cpp index 6a494f42a..5390d82dd 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -36,7 +36,7 @@ ExecutionEngine::ExecutionEngine() extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } -int ExecutionEngine::run(std::unique_ptr _module) +int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtVMFace* _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -81,26 +81,28 @@ int ExecutionEngine::run(std::unique_ptr _module) exec->finalizeObject(); // Create fake ExtVM interface - auto ext = std::make_unique(); - ext->myAddress = Address(1122334455667788); - ext->caller = Address(0xfacefacefaceface); - ext->origin = Address(101010101010101010); - ext->value = 0xabcd; - ext->gasPrice = 1002; - ext->previousBlock.hash = u256(1003); - ext->currentBlock.coinbaseAddress = Address(1004); - ext->currentBlock.timestamp = 1005; - ext->currentBlock.number = 1006; - ext->currentBlock.difficulty = 1007; - ext->currentBlock.gasLimit = 1008; - std::string calldata = "Hello the Beautiful World of Ethereum!"; - ext->data = calldata; - unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; - ext->code = decltype(ext->code)(fakecode, 8); + if (!_ext) + { + _ext = new ExtVMFace; + _ext->myAddress = Address(1122334455667788); + _ext->caller = Address(0xfacefacefaceface); + _ext->origin = Address(101010101010101010); + _ext->value = 0xabcd; + _ext->gasPrice = 1002; + _ext->previousBlock.hash = u256(1003); + _ext->currentBlock.coinbaseAddress = Address(1004); + _ext->currentBlock.timestamp = 1005; + _ext->currentBlock.number = 1006; + _ext->currentBlock.difficulty = 1007; + _ext->currentBlock.gasLimit = 1008; + std::string calldata = "Hello the Beautiful World of Ethereum!"; + _ext->data = calldata; + unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; + _ext->code = decltype(_ext->code)(fakecode, 8); + } // Init runtime - uint64_t gas = 100; - Runtime runtime(gas, std::move(ext)); + Runtime runtime(_gas, *_ext); auto entryFunc = module->getFunction("main"); if (!entryFunc) @@ -121,11 +123,11 @@ int ExecutionEngine::run(std::unique_ptr _module) else returnCode = static_cast(r); - gas = static_cast(Runtime::getGas()); + _gas = Runtime::getGas(); if (returnCode == ReturnCode::Return) { - auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface + returnData = Memory::getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface std::cout << "RETURN [ "; for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) diff --git a/evmcc/ExecutionEngine.h b/libevmjit/ExecutionEngine.h similarity index 57% rename from evmcc/ExecutionEngine.h rename to libevmjit/ExecutionEngine.h index 158df0283..15a4e6ef7 100644 --- a/evmcc/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -4,6 +4,7 @@ #include #include +#include namespace dev { @@ -17,7 +18,9 @@ class ExecutionEngine public: ExecutionEngine(); - int run(std::unique_ptr module); + int run(std::unique_ptr module, u256& _gas, ExtVMFace* _ext = nullptr); + + bytes returnData; }; } diff --git a/evmcc/Ext.cpp b/libevmjit/Ext.cpp similarity index 99% rename from evmcc/Ext.cpp rename to libevmjit/Ext.cpp index 5307bc191..5c4bb7c59 100644 --- a/evmcc/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -61,7 +61,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder): m_arg5 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg5"); m_arg6 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg6"); m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); - m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); + m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { i256Ty, // i256 address; diff --git a/evmcc/Ext.h b/libevmjit/Ext.h similarity index 100% rename from evmcc/Ext.h rename to libevmjit/Ext.h diff --git a/evmcc/GasMeter.cpp b/libevmjit/GasMeter.cpp similarity index 87% rename from evmcc/GasMeter.cpp rename to libevmjit/GasMeter.cpp index 9c83ba8db..ac7f47d19 100644 --- a/evmcc/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -30,26 +30,26 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure return 0; case Instruction::SSTORE: - return static_cast(c_sstoreGas); + return static_cast(FeeStructure::c_sstoreGas); case Instruction::SLOAD: - return static_cast(c_sloadGas); + return static_cast(FeeStructure::c_sloadGas); case Instruction::SHA3: - return static_cast(c_sha3Gas); + return static_cast(FeeStructure::c_sha3Gas); case Instruction::BALANCE: - return static_cast(c_sha3Gas); + return static_cast(FeeStructure::c_sha3Gas); case Instruction::CALL: case Instruction::CALLCODE: - return static_cast(c_callGas); + return static_cast(FeeStructure::c_callGas); case Instruction::CREATE: - return static_cast(c_createGas); + return static_cast(FeeStructure::c_createGas); default: // Assumes instruction code is valid - return static_cast(c_stepGas); + return static_cast(FeeStructure::c_stepGas); } } @@ -134,7 +134,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu { assert(!m_checkCall); // Everything should've been commited before - static const auto sstoreCost = static_cast(c_sstoreGas); + static const auto sstoreCost = static_cast(FeeStructure::c_sstoreGas); // [ADD] if oldValue == 0 and newValue != 0 => 2*cost // [DEL] if oldValue != 0 and newValue == 0 => 0 @@ -165,19 +165,21 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) // If any uncommited block if (m_checkCall) { - if (m_blockCost == 0 && !_additionalCost) // Do not check 0 + if (m_blockCost == 0) // Do not check 0 { m_checkCall->eraseFromParent(); // Remove the gas check call + m_checkCall = nullptr; return; } - llvm::Value* cost = Constant::get(m_blockCost); - if (_additionalCost) - cost = m_builder.CreateAdd(cost, _additionalCost); - - m_checkCall->setArgOperand(0, cost); // Update block cost in gas check call + m_checkCall->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call m_checkCall = nullptr; // End cost-block m_blockCost = 0; + + if (_additionalCost) + { + m_builder.CreateCall(m_gasCheckFunc, _additionalCost); + } } assert(m_blockCost == 0); } @@ -185,7 +187,7 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) { // Memory uses other builder, but that can be changes later - auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast(c_memoryGas)), "memcost"); + auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast(FeeStructure::c_memoryGas)), "memcost"); _builder.CreateCall(m_gasCheckFunc, cost); } diff --git a/evmcc/GasMeter.h b/libevmjit/GasMeter.h similarity index 100% rename from evmcc/GasMeter.h rename to libevmjit/GasMeter.h diff --git a/evmcc/Memory.cpp b/libevmjit/Memory.cpp similarity index 100% rename from evmcc/Memory.cpp rename to libevmjit/Memory.cpp diff --git a/evmcc/Memory.h b/libevmjit/Memory.h similarity index 100% rename from evmcc/Memory.h rename to libevmjit/Memory.h diff --git a/evmcc/Runtime.cpp b/libevmjit/Runtime.cpp similarity index 81% rename from evmcc/Runtime.cpp rename to libevmjit/Runtime.cpp index d85f484b3..448d25f92 100644 --- a/evmcc/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -19,8 +19,8 @@ extern "C" EXPORT i256 gas; } -Runtime::Runtime(u256 _gas, std::unique_ptr _ext): - m_ext(std::move(_ext)) +Runtime::Runtime(u256 _gas, ExtVMFace& _ext): + m_ext(_ext) { assert(!g_runtime); g_runtime = this; @@ -44,7 +44,7 @@ MemoryImpl& Runtime::getMemory() ExtVMFace& Runtime::getExt() { - return *g_runtime->m_ext; + return g_runtime->m_ext; } u256 Runtime::getGas() diff --git a/evmcc/Runtime.h b/libevmjit/Runtime.h similarity index 86% rename from evmcc/Runtime.h rename to libevmjit/Runtime.h index 0312e305b..165f47e06 100644 --- a/evmcc/Runtime.h +++ b/libevmjit/Runtime.h @@ -27,7 +27,7 @@ using MemoryImpl = bytes; class Runtime { public: - Runtime(u256 _gas, std::unique_ptr _ext); + Runtime(u256 _gas, ExtVMFace& _ext); ~Runtime(); Runtime(const Runtime&) = delete; @@ -41,7 +41,7 @@ public: private: StackImpl m_stack; MemoryImpl m_memory; - std::unique_ptr m_ext; + ExtVMFace& m_ext; }; } diff --git a/evmcc/Type.cpp b/libevmjit/Type.cpp similarity index 100% rename from evmcc/Type.cpp rename to libevmjit/Type.cpp diff --git a/evmcc/Type.h b/libevmjit/Type.h similarity index 100% rename from evmcc/Type.h rename to libevmjit/Type.h diff --git a/evmcc/Utils.cpp b/libevmjit/Utils.cpp similarity index 100% rename from evmcc/Utils.cpp rename to libevmjit/Utils.cpp diff --git a/evmcc/Utils.h b/libevmjit/Utils.h similarity index 100% rename from evmcc/Utils.h rename to libevmjit/Utils.h diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp new file mode 100644 index 000000000..6b8b3e38b --- /dev/null +++ b/libevmjit/VM.cpp @@ -0,0 +1,36 @@ + +#include "VM.h" + +#include + +#include "ExecutionEngine.h" +#include "Compiler.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +bytes VM::go(ExtVMFace& _ext) +{ + auto module = Compiler().compile(_ext.code); + + ExecutionEngine engine; + auto exitCode = engine.run(std::move(module), m_gas, &_ext); + + switch (exitCode) + { + case 101: + BOOST_THROW_EXCEPTION(BadJumpDestination()); + case 102: + BOOST_THROW_EXCEPTION(OutOfGas()); + } + + return std::move(engine.returnData); +} + +} +} +} diff --git a/libevmjit/VM.h b/libevmjit/VM.h new file mode 100644 index 000000000..3e7884b10 --- /dev/null +++ b/libevmjit/VM.h @@ -0,0 +1,32 @@ + +#pragma once + +#include +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class VM +{ +public: + /// Construct VM object. + explicit VM(u256 _gas = 0): m_gas(_gas) {} + + void reset(u256 _gas = 0) { m_gas = _gas; } + + bytes go(ExtVMFace& _ext); + + u256 gas() const { return m_gas; } + +private: + u256 m_gas = 0; +}; + +} +} +} diff --git a/liblll/Assembly.cpp b/liblll/Assembly.cpp index 695c9ffab..c26a9a98e 100644 --- a/liblll/Assembly.cpp +++ b/liblll/Assembly.cpp @@ -413,8 +413,8 @@ bytes Assembly::assemble() const break; } case Tag: - tagPos[(unsigned)i.m_data] = ret.size(); ret.push_back((byte)Instruction::JUMPDEST); + tagPos[(unsigned)i.m_data] = ret.size(); break; default:; } diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index 7746613ec..cb50cc36e 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -6,15 +6,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE lll) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} evmface) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index ab852fc57..9e20fd99f 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -6,17 +6,16 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE p2p) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) +target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} secp256k1) if(MINIUPNPC_LS) diff --git a/libp2p/Capability.cpp b/libp2p/Capability.cpp index 2dbfd76a8..dfa1ab546 100644 --- a/libp2p/Capability.cpp +++ b/libp2p/Capability.cpp @@ -53,14 +53,14 @@ void Capability::sealAndSend(RLPStream& _s) m_session->sealAndSend(_s); } -void Capability::sendDestroy(bytes& _msg) +void Capability::send(bytesConstRef _msg) { - m_session->sendDestroy(_msg); + m_session->send(_msg); } -void Capability::send(bytesConstRef _msg) +void Capability::send(bytes&& _msg) { - m_session->send(_msg); + m_session->send(move(_msg)); } void Capability::addRating(unsigned _r) diff --git a/libp2p/Capability.h b/libp2p/Capability.h index bd2ab7a95..04b116aa8 100644 --- a/libp2p/Capability.h +++ b/libp2p/Capability.h @@ -52,7 +52,7 @@ protected: RLPStream& prep(RLPStream& _s, unsigned _id, unsigned _args = 0); void sealAndSend(RLPStream& _s); - void sendDestroy(bytes& _msg); + void send(bytes&& _msg); void send(bytesConstRef _msg); void addRating(unsigned _r); diff --git a/libp2p/Common.cpp b/libp2p/Common.cpp index 540f285c1..8a3b27ef0 100644 --- a/libp2p/Common.cpp +++ b/libp2p/Common.cpp @@ -64,7 +64,12 @@ std::string p2p::reasonOf(DisconnectReason _r) case TooManyPeers: return "Peer had too many connections."; case DuplicatePeer: return "Peer was already connected."; case IncompatibleProtocol: return "Peer protocol versions are incompatible."; + case NullIdentity: return "Null identity given."; case ClientQuit: return "Peer is exiting."; + case UnexpectedIdentity: return "Unexpected identity given."; + case LocalIdentity: return "Connected to ourselves."; + case UserReason: return "Subprotocol reason."; + case NoDisconnect: return "(No disconnect has happened.)"; default: return "Unknown reason."; } } diff --git a/libp2p/Common.h b/libp2p/Common.h index 895b76404..7c2c61156 100644 --- a/libp2p/Common.h +++ b/libp2p/Common.h @@ -44,6 +44,8 @@ class RLPStream; namespace p2p { +using NodeId = h512; + bool isPrivateAddress(bi::address const& _addressToCheck); class UPnP; @@ -82,11 +84,30 @@ enum DisconnectReason TooManyPeers, DuplicatePeer, IncompatibleProtocol, - InvalidIdentity, + NullIdentity, ClientQuit, - UserReason = 0x10 + UnexpectedIdentity, + LocalIdentity, + PingTimeout, + UserReason = 0x10, + NoDisconnect = 0xffff }; +inline bool isPermanentProblem(DisconnectReason _r) +{ + switch (_r) + { + case DuplicatePeer: + case IncompatibleProtocol: + case NullIdentity: + case UnexpectedIdentity: + case LocalIdentity: + return true; + default: + return false; + } +} + /// @returns the string form of the given disconnection reason. std::string reasonOf(DisconnectReason _r); @@ -96,6 +117,7 @@ typedef std::vector CapDescs; struct PeerInfo { + NodeId id; std::string clientVersion; std::string host; unsigned short port; diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 05fa81f4c..ea89b5613 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -63,11 +63,10 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool m_netPrefs(_n), m_acceptor(m_ioService), m_socket(m_ioService), - m_id(h512::random()) + m_key(KeyPair::create()) { populateAddresses(); - m_lastPeersRequest = chrono::steady_clock::time_point::min(); - clog(NetNote) << "Id:" << m_id.abridged(); + clog(NetNote) << "Id:" << id().abridged(); if (_start) start(); } @@ -109,11 +108,10 @@ void Host::start() determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp); ensureAccepting(); - m_incomingPeers.clear(); - m_freePeers.clear(); + if (!m_public.address().is_unspecified() && (m_nodes.empty() || m_nodes[m_nodesList[0]]->id != id())) + noteNode(id(), m_public, Origin::Perfect, false); - m_lastPeersRequest = chrono::steady_clock::time_point::min(); - clog(NetNote) << "Id:" << m_id.abridged(); + clog(NetNote) << "Id:" << id().abridged(); for (auto const& h: m_capabilities) h.second->onStarting(); @@ -144,14 +142,20 @@ void Host::stop() unsigned Host::protocolVersion() const { - return 1; + return 2; } void Host::registerPeer(std::shared_ptr _s, CapDescs const& _caps) { + if (!_s->m_node || !_s->m_node->id) { - Guard l(x_peers); - m_peers[_s->m_id] = _s; + cwarn << "Attempting to register a peer without node information!"; + return; + } + + { + RecursiveGuard l(x_peers); + m_peers[_s->m_node->id] = _s; } unsigned o = (unsigned)UserPacket; for (auto const& i: _caps) @@ -167,7 +171,7 @@ void Host::disconnectPeers() for (unsigned n = 0;; n = 0) { { - Guard l(x_peers); + RecursiveGuard l(x_peers); for (auto i: m_peers) if (auto p = i.second.lock()) { @@ -182,6 +186,7 @@ void Host::disconnectPeers() } delete m_upnp; + m_upnp = nullptr; } void Host::seal(bytes& _b) @@ -210,7 +215,10 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp) if (m_upnp && m_upnp->isValid() && m_peerAddresses.size()) { clog(NetNote) << "External addr:" << m_upnp->externalIP(); - int p = m_upnp->addRedirect(m_peerAddresses[0].to_string().c_str(), m_listenPort); + int p; + for (auto const& addr : m_peerAddresses) + if ((p = m_upnp->addRedirect(addr.to_string().c_str(), m_listenPort))) + break; if (p) clog(NetNote) << "Punched through NAT and mapped local port" << m_listenPort << "onto external port" << p << "."; else @@ -226,7 +234,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp) else { m_public = bi::tcp::endpoint(bi::address::from_string(_publicAddress.empty() ? eip : _publicAddress), (unsigned short)p); - m_addresses.push_back(m_public.address().to_v4()); + m_addresses.push_back(m_public.address()); } } else @@ -235,7 +243,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp) m_public = bi::tcp::endpoint(_publicAddress.size() ? bi::address::from_string(_publicAddress) : m_peerAddresses.size() ? m_peerAddresses[0] : bi::address(), m_listenPort); - m_addresses.push_back(m_public.address().to_v4()); + m_addresses.push_back(m_public.address()); } } @@ -308,33 +316,107 @@ void Host::populateAddresses() clog(NetNote) << "Couldn't resolve: " << host; } } + else if (ifa->ifa_addr->sa_family == AF_INET6) + { + char host[NI_MAXHOST]; + if (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) + continue; + try + { + auto it = r.resolve({host, "30303"}); + bi::tcp::endpoint ep = it->endpoint(); + bi::address ad = ep.address(); + m_addresses.push_back(ad.to_v6()); + bool isLocal = std::find(c_rejectAddresses.begin(), c_rejectAddresses.end(), ad) != c_rejectAddresses.end(); + if (!isLocal) + m_peerAddresses.push_back(ad); + clog(NetNote) << "Address: " << host << " = " << m_addresses.back() << (isLocal ? " [LOCAL]" : " [PEER]"); + } + catch (...) + { + clog(NetNote) << "Couldn't resolve: " << host; + } + } } freeifaddrs(ifaddr); #endif } -std::map Host::potentialPeers() +shared_ptr Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId) { - std::map ret; - if (!m_public.address().is_unspecified()) - ret.insert(make_pair(m_id, m_public)); - Guard l(x_peers); - for (auto i: m_peers) - if (auto j = i.second.lock()) - { - auto ep = j->endpoint(); -// cnote << "Checking potential peer" << j->m_listenPort << j->endpoint() << isPrivateAddress(ep.address()) << ep.port() << j->m_id.abridged(); - // Skip peers with a listen port of zero or are on a private network - bool peerOnNet = (j->m_listenPort != 0 && (!isPrivateAddress(ep.address()) || m_netPrefs.localNetworking)); - if (!peerOnNet && m_incomingPeers.count(j->m_id)) + RecursiveGuard l(x_peers); + if (_a.port() < 30300 && _a.port() > 30303) + cwarn << "Wierd port being recorded!"; + + if (_a.port() >= 49152) + { + cwarn << "Private port being recorded - setting to 0"; + _a = bi::tcp::endpoint(_a.address(), 0); + } + + cnote << "Node:" << _id.abridged() << _a << (_ready ? "ready" : "used") << _oldId.abridged() << (m_nodes.count(_id) ? "[have]" : "[NEW]"); + + // First check for another node with the same connection credentials, and put it in oldId if found. + if (!_oldId) + for (pair> const& n: m_nodes) + if (n.second->address == _a && n.second->id != _id) { - ep = m_incomingPeers.at(j->m_id).first; - peerOnNet = (j->m_listenPort != 0 && (!isPrivateAddress(ep.address()) || m_netPrefs.localNetworking)); + _oldId = n.second->id; + break; } - if (peerOnNet && ep.port() && j->m_id) - ret.insert(make_pair(i.first, ep)); + + unsigned i; + if (!m_nodes.count(_id)) + { + if (m_nodes.count(_oldId)) + { + i = m_nodes[_oldId]->index; + m_nodes.erase(_oldId); + m_nodesList[i] = _id; + } + else + { + i = m_nodesList.size(); + m_nodesList.push_back(_id); } + m_nodes[_id] = make_shared(); + m_nodes[_id]->id = _id; + m_nodes[_id]->index = i; + m_nodes[_id]->idOrigin = _o; + } + else + { + i = m_nodes[_id]->index; + m_nodes[_id]->idOrigin = max(m_nodes[_id]->idOrigin, _o); + } + m_nodes[_id]->address = _a; + m_ready.extendAll(i); + m_private.extendAll(i); + if (_ready) + m_ready += i; + else + m_ready -= i; + if (!_a.port() || (isPrivateAddress(_a.address()) && !m_netPrefs.localNetworking)) + m_private += i; + else + m_private -= i; + + cnote << m_nodes[_id]->index << ":" << m_ready; + + m_hadNewNodes = true; + + return m_nodes[_id]; +} + +Nodes Host::potentialPeers(RangeMask const& _known) +{ + RecursiveGuard l(x_peers); + Nodes ret; + + auto ns = (m_netPrefs.localNetworking ? _known : (m_private + _known)).inverted(); + for (auto i: ns) + ret.push_back(*m_nodes[m_nodesList[i]]); return ret; } @@ -355,7 +437,7 @@ void Host::ensureAccepting() } catch (...){} bi::address remoteAddress = m_socket.remote_endpoint().address(); // Port defaults to 0 - we let the hello tell us which port the peer listens to - auto p = std::make_shared(this, std::move(m_socket), remoteAddress); + auto p = std::make_shared(this, std::move(m_socket), bi::tcp::endpoint(remoteAddress, 0)); p->start(); } catch (Exception const& _e) @@ -411,26 +493,15 @@ void Host::connect(std::string const& _addr, unsigned short _port) noexcept void Host::connect(bi::tcp::endpoint const& _ep) { - clog(NetConnect) << "Attempting connection to " << _ep; + clog(NetConnect) << "Attempting single-shot connection to " << _ep; bi::tcp::socket* s = new bi::tcp::socket(m_ioService); s->async_connect(_ep, [=](boost::system::error_code const& ec) { if (ec) - { clog(NetConnect) << "Connection refused to " << _ep << " (" << ec.message() << ")"; - for (auto i = m_incomingPeers.begin(); i != m_incomingPeers.end(); ++i) - if (i->second.first == _ep && i->second.second < 3) - { - m_freePeers.push_back(i->first); - goto OK; - } - // for-else - clog(NetConnect) << "Giving up."; - OK:; - } else { - auto p = make_shared(this, std::move(*s), _ep.address(), _ep.port()); + auto p = make_shared(this, std::move(*s), _ep); clog(NetConnect) << "Connected to " << _ep; p->start(); } @@ -438,9 +509,36 @@ void Host::connect(bi::tcp::endpoint const& _ep) }); } -bool Host::havePeer(h512 _id) const +void Node::connect(Host* _h) +{ + clog(NetConnect) << "Attempting connection to node" << id.abridged() << "@" << address << "from" << _h->id().abridged(); + lastAttempted = std::chrono::system_clock::now(); + failedAttempts++; + _h->m_ready -= index; + bi::tcp::socket* s = new bi::tcp::socket(_h->m_ioService); + s->async_connect(address, [=](boost::system::error_code const& ec) + { + if (ec) + { + clog(NetConnect) << "Connection refused to node" << id.abridged() << "@" << address << "(" << ec.message() << ")"; + lastDisconnect = TCPError; + lastAttempted = std::chrono::system_clock::now(); + _h->m_ready += index; + } + else + { + clog(NetConnect) << "Connected to" << id.abridged() << "@" << address; + lastConnected = std::chrono::system_clock::now(); + auto p = make_shared(_h, std::move(*s), _h->node(id), true); // true because we don't care about ids matched for now. Once we have permenant IDs this will matter a lot more and we can institute a safer mechanism. + p->start(); + } + delete s; + }); +} + +bool Host::havePeer(NodeId _id) const { - Guard l(x_peers); + RecursiveGuard l(x_peers); // Remove dead peers from list. for (auto i = m_peers.begin(); i != m_peers.end();) @@ -452,43 +550,67 @@ bool Host::havePeer(h512 _id) const return !!m_peers.count(_id); } +unsigned Node::fallbackSeconds() const +{ + switch (lastDisconnect) + { + case BadProtocol: + return 30 * (failedAttempts + 1); + case UselessPeer: + case TooManyPeers: + case ClientQuit: + return 15 * (failedAttempts + 1); + case NoDisconnect: + return 0; + default: + if (failedAttempts < 5) + return failedAttempts * 5; + else if (failedAttempts < 15) + return 25 + (failedAttempts - 5) * 10; + else + return 25 + 100 + (failedAttempts - 15) * 20; + } +} + +bool Node::shouldReconnect() const +{ + return chrono::system_clock::now() > lastAttempted + chrono::seconds(fallbackSeconds()); +} + void Host::growPeers() { - Guard l(x_peers); - while (m_peers.size() < m_idealPeerCount) + RecursiveGuard l(x_peers); + int morePeers = (int)m_idealPeerCount - m_peers.size(); + if (morePeers > 0) { - if (m_freePeers.empty()) - { - if (chrono::steady_clock::now() > m_lastPeersRequest + chrono::seconds(10)) + auto toTry = m_ready; + if (!m_netPrefs.localNetworking) + toTry -= m_private; + set ns; + for (auto i: toTry) + if (m_nodes[m_nodesList[i]]->shouldReconnect()) + ns.insert(*m_nodes[m_nodesList[i]]); + + if (ns.size()) + for (Node const& i: ns) { - RLPStream s; - bytes b; - Session::prep(s, GetPeersPacket).swapOut(b); - seal(b); - for (auto const& i: m_peers) - if (auto p = i.second.lock()) - if (p->isOpen()) - p->send(&b); - m_lastPeersRequest = chrono::steady_clock::now(); + m_nodes[i.id]->connect(this); + if (!--morePeers) + return; } - - if (!m_accepting) - ensureAccepting(); - - break; + else + { + ensureAccepting(); + for (auto const& i: m_peers) + if (auto p = i.second.lock()) + p->ensureNodesRequested(); } - - auto x = time(0) % m_freePeers.size(); - m_incomingPeers[m_freePeers[x]].second++; - if (!m_peers.count(m_freePeers[x])) - connect(m_incomingPeers[m_freePeers[x]].first); - m_freePeers.erase(m_freePeers.begin() + x); } } void Host::prunePeers() { - Guard l(x_peers); + RecursiveGuard l(x_peers); // We'll keep at most twice as many as is ideal, halfing what counts as "too young to kill" until we get there. for (unsigned old = 15000; m_peers.size() > m_idealPeerCount * 2 && old > 100; old /= 2) while (m_peers.size() > m_idealPeerCount) @@ -502,7 +624,7 @@ void Host::prunePeers() if (/*(m_mode != NodeMode::Host || p->m_caps != 0x01) &&*/ chrono::steady_clock::now() > p->m_connect + chrono::milliseconds(old)) // don't throw off new peers; peer-servers should never kick off other peer-servers. { ++agedPeers; - if ((!worst || p->m_rating < worst->m_rating || (p->m_rating == worst->m_rating && p->m_connect > worst->m_connect))) // kill older ones + if ((!worst || p->rating() < worst->rating() || (p->rating() == worst->rating() && p->m_connect > worst->m_connect))) // kill older ones worst = p; } if (!worst || agedPeers <= m_idealPeerCount) @@ -520,10 +642,12 @@ void Host::prunePeers() std::vector Host::peers(bool _updatePing) const { - Guard l(x_peers); + RecursiveGuard l(x_peers); if (_updatePing) + { const_cast(this)->pingAll(); - this_thread::sleep_for(chrono::milliseconds(200)); + this_thread::sleep_for(chrono::milliseconds(200)); + } std::vector ret; for (auto& i: m_peers) if (auto j = i.second.lock()) @@ -536,41 +660,116 @@ void Host::doWork() { growPeers(); prunePeers(); + + if (m_hadNewNodes) + { + for (auto p: m_peers) + if (auto pp = p.second.lock()) + pp->serviceNodesRequest(); + + m_hadNewNodes = false; + } + + if (chrono::steady_clock::now() - m_lastPing > chrono::seconds(30)) // ping every 30s. + { + for (auto p: m_peers) + if (auto pp = p.second.lock()) + if (chrono::steady_clock::now() - pp->m_lastReceived > chrono::seconds(60)) + pp->disconnect(PingTimeout); + pingAll(); + } + m_ioService.poll(); } void Host::pingAll() { - Guard l(x_peers); + RecursiveGuard l(x_peers); for (auto& i: m_peers) if (auto j = i.second.lock()) j->ping(); + m_lastPing = chrono::steady_clock::now(); } -bytes Host::savePeers() const +bytes Host::saveNodes() const { - Guard l(x_peers); - RLPStream ret; - int n = 0; - for (auto& i: m_peers) - if (auto p = i.second.lock()) - if (p->m_socket.is_open() && p->endpoint().port()) + RLPStream nodes; + int count = 0; + { + RecursiveGuard l(x_peers); + for (auto const& i: m_nodes) + { + Node const& n = *(i.second); + // TODO: PoC-7: Figure out why it ever shares these ports.//n.address.port() >= 30300 && n.address.port() <= 30305 && + if (!n.dead && n.address.port() > 0 && n.address.port() < 49152 && n.id != id() && !isPrivateAddress(n.address.address())) { - ret.appendList(3) << p->endpoint().address().to_v4().to_bytes() << p->endpoint().port() << p->m_id; - n++; + nodes.appendList(10); + if (n.address.address().is_v4()) + nodes << n.address.address().to_v4().to_bytes(); + else + nodes << n.address.address().to_v6().to_bytes(); + nodes << n.address.port() << n.id << (int)n.idOrigin + << std::chrono::duration_cast(n.lastConnected.time_since_epoch()).count() + << std::chrono::duration_cast(n.lastAttempted.time_since_epoch()).count() + << n.failedAttempts << (unsigned)n.lastDisconnect << n.score << n.rating; + count++; } - return RLPStream(n).appendRaw(ret.out(), n).out(); + } + } + RLPStream ret(3); + ret << 0 << m_key.secret(); + ret.appendList(count).appendRaw(nodes.out(), count); + return ret.out(); } -void Host::restorePeers(bytesConstRef _b) +void Host::restoreNodes(bytesConstRef _b) { - for (auto i: RLP(_b)) - { - auto k = (h512)i[2]; - if (!m_incomingPeers.count(k)) + RecursiveGuard l(x_peers); + RLP r(_b); + if (r.itemCount() > 0 && r[0].isInt()) + switch (r[0].toInt()) + { + case 0: + { + auto oldId = id(); + m_key = KeyPair(r[1].toHash()); + noteNode(id(), m_public, Origin::Perfect, false, oldId); + + for (auto i: r[2]) + { + bi::tcp::endpoint ep; + if (i[0].itemCount() == 4) + ep = bi::tcp::endpoint(bi::address_v4(i[0].toArray()), i[1].toInt()); + else + ep = bi::tcp::endpoint(bi::address_v6(i[0].toArray()), i[1].toInt()); + auto id = (NodeId)i[2]; + if (!m_nodes.count(id)) + { + auto o = (Origin)i[3].toInt(); + auto n = noteNode(id, ep, o, true); + n->lastConnected = chrono::system_clock::time_point(chrono::seconds(i[4].toInt())); + n->lastAttempted = chrono::system_clock::time_point(chrono::seconds(i[5].toInt())); + n->failedAttempts = i[6].toInt(); + n->lastDisconnect = (DisconnectReason)i[7].toInt(); + n->score = (int)i[8].toInt(); + n->rating = (int)i[9].toInt(); + } + } + } + default:; + } + else + for (auto i: r) { - m_incomingPeers.insert(make_pair(k, make_pair(bi::tcp::endpoint(bi::address_v4(i[0].toArray()), i[1].toInt()), 0))); - m_freePeers.push_back(k); + auto id = (NodeId)i[2]; + if (!m_nodes.count(id)) + { + bi::tcp::endpoint ep; + if (i[0].itemCount() == 4) + ep = bi::tcp::endpoint(bi::address_v4(i[0].toArray()), i[1].toInt()); + else + ep = bi::tcp::endpoint(bi::address_v6(i[0].toArray()), i[1].toInt()); + auto n = noteNode(id, ep, Origin::Self, true); + } } - } } diff --git a/libp2p/Host.h b/libp2p/Host.h index b4ba9c2d4..c981edc29 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -28,8 +28,11 @@ #include #include #include +#include #include #include +#include +#include #include "HostCapability.h" #include "Common.h" namespace ba = boost::asio; @@ -43,6 +46,63 @@ class RLPStream; namespace p2p { +class Host; + +enum class Origin +{ + Unknown, + Self, + SelfThird, + PerfectThird, + Perfect, +}; + +struct Node +{ + NodeId id; ///< Their id/public key. + unsigned index; ///< Index into m_nodesList + bi::tcp::endpoint address; ///< As reported from the node itself. + int score = 0; ///< All time cumulative. + int rating = 0; ///< Trending. + bool dead = false; ///< If true, we believe this node is permanently dead - forget all about it. + std::chrono::system_clock::time_point lastConnected; + std::chrono::system_clock::time_point lastAttempted; + unsigned failedAttempts = 0; + DisconnectReason lastDisconnect = NoDisconnect; ///< Reason for disconnect that happened last. + + Origin idOrigin = Origin::Unknown; ///< How did we get to know this node's id? + + int secondsSinceLastConnected() const { return lastConnected == std::chrono::system_clock::time_point() ? -1 : (int)std::chrono::duration_cast(std::chrono::system_clock::now() - lastConnected).count(); } + int secondsSinceLastAttempted() const { return lastAttempted == std::chrono::system_clock::time_point() ? -1 : (int)std::chrono::duration_cast(std::chrono::system_clock::now() - lastAttempted).count(); } + + unsigned fallbackSeconds() const; + bool shouldReconnect() const; + + bool isOffline() const { return lastAttempted > lastConnected; } + bool operator<(Node const& _n) const + { + if (isOffline() != _n.isOffline()) + return isOffline(); + else if (isOffline()) + if (lastAttempted == _n.lastAttempted) + return failedAttempts < _n.failedAttempts; + else + return lastAttempted < _n.lastAttempted; + else + if (score == _n.score) + if (rating == _n.rating) + return failedAttempts < _n.failedAttempts; + else + return rating < _n.rating; + else + return score < _n.score; + } + + void connect(Host* _h); +}; + +using Nodes = std::vector; + struct NetworkPreferences { NetworkPreferences(unsigned short p = 30303, std::string i = std::string(), bool u = true, bool l = false): listenPort(p), publicIP(i), upnp(u), localNetworking(l) {} @@ -61,6 +121,7 @@ class Host: public Worker { friend class Session; friend class HostCapabilityFace; + friend struct Node; public: /// Start server, listening for connections on the given port. @@ -88,7 +149,7 @@ public: void connect(bi::tcp::endpoint const& _ep); /// @returns true iff we have the a peer of the given id. - bool havePeer(h512 _id) const; + bool havePeer(NodeId _id) const; /// Set ideal number of peers. void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; } @@ -97,7 +158,7 @@ public: std::vector peers(bool _updatePing = false) const; /// Get number of peers connected; equivalent to, but faster than, peers().size(). - size_t peerCount() const { Guard l(x_peers); return m_peers.size(); } + size_t peerCount() const { RecursiveGuard l(x_peers); return m_peers.size(); } /// Ping the peers, to update the latency information. void pingAll(); @@ -106,10 +167,12 @@ public: unsigned short listenPort() const { return m_public.port(); } /// Serialise the set of known peers. - bytes savePeers() const; + bytes saveNodes() const; /// Deserialise the data and populate the set of known peers. - void restorePeers(bytesConstRef _b); + void restoreNodes(bytesConstRef _b); + + Nodes nodes() const { RecursiveGuard l(x_peers); Nodes ret; for (auto const& i: m_nodes) ret.push_back(*i.second); return ret; } void setNetworkPreferences(NetworkPreferences const& _p) { stop(); m_netPrefs = _p; start(); } @@ -117,14 +180,13 @@ public: void stop(); bool isStarted() const { return isWorking(); } - h512 id() const { return m_id; } + NodeId id() const { return m_key.pub(); } void registerPeer(std::shared_ptr _s, CapDescs const& _caps); -private: - /// Called when the session has provided us with a new peer we can connect to. - void noteNewPeers() {} + std::shared_ptr node(NodeId _id) const { if (m_nodes.count(_id)) return m_nodes.at(_id); return std::shared_ptr(); } +private: void seal(bytes& _b); void populateAddresses(); void determinePublic(std::string const& _publicAddress, bool _upnp); @@ -138,36 +200,52 @@ private: /// This won't touch alter the blockchain. virtual void doWork(); - std::map potentialPeers(); + std::shared_ptr noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId = h256()); + Nodes potentialPeers(RangeMask const& _known); + + std::string m_clientVersion; ///< Our version string. + + NetworkPreferences m_netPrefs; ///< Network settings. + + static const int NetworkStopped = -1; ///< The value meaning we're not actually listening. + int m_listenPort = NetworkStopped; ///< What port are we listening on? + + ba::io_service m_ioService; ///< IOService for network stuff. + bi::tcp::acceptor m_acceptor; ///< Listening acceptor. + bi::tcp::socket m_socket; ///< Listening socket. + + UPnP* m_upnp = nullptr; ///< UPnP helper. + bi::tcp::endpoint m_public; ///< Our public listening endpoint. + KeyPair m_key; ///< Our unique ID. - std::string m_clientVersion; + bool m_hadNewNodes = false; - NetworkPreferences m_netPrefs; + mutable RecursiveMutex x_peers; - static const int NetworkStopped = -1; - int m_listenPort = NetworkStopped; + /// The nodes to which we are currently connected. + /// Mutable because we flush zombie entries (null-weakptrs) as regular maintenance from a const method. + mutable std::map> m_peers; - ba::io_service m_ioService; - bi::tcp::acceptor m_acceptor; - bi::tcp::socket m_socket; + /// Nodes to which we may connect (or to which we have connected). + /// TODO: does this need a lock? + std::map > m_nodes; - UPnP* m_upnp = nullptr; - bi::tcp::endpoint m_public; - h512 m_id; + /// A list of node IDs. This contains every index from m_nodes; the order is guaranteed to remain the same. + std::vector m_nodesList; - mutable std::mutex x_peers; - mutable std::map> m_peers; // mutable because we flush zombie entries (null-weakptrs) as regular maintenance from a const method. + RangeMask m_ready; ///< Indices into m_nodesList over to which nodes we are not currently connected, connecting or otherwise ignoring. + RangeMask m_private; ///< Indices into m_nodesList over to which nodes are private. - std::map> m_incomingPeers; // TODO: does this need a lock? - std::vector m_freePeers; + unsigned m_idealPeerCount = 5; ///< Ideal number of peers to be connected to. - std::chrono::steady_clock::time_point m_lastPeersRequest; - unsigned m_idealPeerCount = 5; + // Our addresses. + std::vector m_addresses; ///< Addresses for us. + std::vector m_peerAddresses; ///< Addresses that peers (can) know us by. - std::vector m_addresses; - std::vector m_peerAddresses; + // Our capabilities. + std::map> m_capabilities; ///< Each of the capabilities we support. - std::map> m_capabilities; + std::chrono::steady_clock::time_point m_lastPing; ///< Time we sent the last ping to all peers. bool m_accepting = false; }; diff --git a/libp2p/HostCapability.cpp b/libp2p/HostCapability.cpp index 2f295afd0..0728bef2c 100644 --- a/libp2p/HostCapability.cpp +++ b/libp2p/HostCapability.cpp @@ -34,7 +34,7 @@ void HostCapabilityFace::seal(bytes& _b) std::vector > HostCapabilityFace::peers() const { - Guard l(m_host->x_peers); + RecursiveGuard l(m_host->x_peers); std::vector > ret; for (auto const& i: m_host->m_peers) if (std::shared_ptr p = i.second.lock()) diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index d6a45bfc7..5a66064f8 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -36,19 +36,38 @@ using namespace dev::p2p; #endif #define clogS(X) dev::LogOutputStream(false) << "| " << std::setw(2) << m_socket.native_handle() << "] " -Session::Session(Host* _s, bi::tcp::socket _socket, bi::address _peerAddress, unsigned short _peerPort): +Session::Session(Host* _s, bi::tcp::socket _socket, bi::tcp::endpoint const& _manual): m_server(_s), m_socket(std::move(_socket)), - m_listenPort(_peerPort), - m_rating(0) + m_node(nullptr), + m_manualEndpoint(_manual) // NOTE: the port on this shouldn't be used if it's zero. { - m_disconnect = std::chrono::steady_clock::time_point::max(); - m_connect = std::chrono::steady_clock::now(); - m_info = PeerInfo({"?", _peerAddress.to_string(), m_listenPort, std::chrono::steady_clock::duration(0), CapDescSet(), 0, map()}); + m_lastReceived = m_connect = std::chrono::steady_clock::now(); + + m_info = PeerInfo({NodeId(), "?", m_manualEndpoint.address().to_string(), 0, std::chrono::steady_clock::duration(0), CapDescSet(), 0, map()}); +} + +Session::Session(Host* _s, bi::tcp::socket _socket, std::shared_ptr const& _n, bool _force): + m_server(_s), + m_socket(std::move(_socket)), + m_node(_n), + m_manualEndpoint(_n->address), + m_force(_force) +{ + m_lastReceived = m_connect = std::chrono::steady_clock::now(); + m_info = PeerInfo({m_node->id, "?", _n->address.address().to_string(), _n->address.port(), std::chrono::steady_clock::duration(0), CapDescSet(), 0, map()}); } Session::~Session() { + if (m_node) + { + if (id() && !isPermanentProblem(m_node->lastDisconnect) && !m_node->dead) + m_server->m_ready += m_node->index; + else + m_node->lastConnected = m_node->lastAttempted - chrono::seconds(1); + } + // Read-chain finished for one reason or another. for (auto& i: m_capabilities) i.second.reset(); @@ -61,21 +80,103 @@ Session::~Session() catch (...){} } +NodeId Session::id() const +{ + return m_node ? m_node->id : NodeId(); +} + +void Session::addRating(unsigned _r) +{ + if (m_node) + { + m_node->rating += _r; + m_node->score += _r; + } +} + +int Session::rating() const +{ + return m_node->rating; +} + bi::tcp::endpoint Session::endpoint() const { - if (m_socket.is_open()) + if (m_socket.is_open() && m_node) try { - return bi::tcp::endpoint(m_socket.remote_endpoint().address(), m_listenPort); + return bi::tcp::endpoint(m_socket.remote_endpoint().address(), m_node->address.port()); } - catch (...){} + catch (...) {} + + if (m_node) + return m_node->address; - return bi::tcp::endpoint(); + return m_manualEndpoint; +} + +template vector randomSelection(vector const& _t, unsigned _n) +{ + if (_t.size() <= _n) + return _t; + vector ret = _t; + while (ret.size() > _n) + { + auto i = ret.begin(); + advance(i, rand() % ret.size()); + ret.erase(i); + } + return ret; +} + +void Session::ensureNodesRequested() +{ + if (isOpen() && !m_weRequestedNodes) + { + m_weRequestedNodes = true; + RLPStream s; + sealAndSend(prep(s, GetPeersPacket)); + } +} + +void Session::serviceNodesRequest() +{ + if (!m_theyRequestedNodes) + return; + + auto peers = m_server->potentialPeers(m_knownNodes); + if (peers.empty()) + { + addNote("peers", "requested"); + return; + } + + // note this should cost them... + RLPStream s; + prep(s, PeersPacket, min(10, peers.size())); + auto rs = randomSelection(peers, 10); + for (auto const& i: rs) + { + clogS(NetTriviaDetail) << "Sending peer " << i.id.abridged() << i.address; + if (i.address.address().is_v4()) + s.appendList(3) << bytesConstRef(i.address.address().to_v4().to_bytes().data(), 4) << i.address.port() << i.id; + else// if (i.second.address().is_v6()) - assumed + s.appendList(3) << bytesConstRef(i.address.address().to_v6().to_bytes().data(), 16) << i.address.port() << i.id; + m_knownNodes.extendAll(i.index); + m_knownNodes.unionWith(i.index); + } + sealAndSend(s); + m_theyRequestedNodes = false; + addNote("peers", "done"); } bool Session::interpret(RLP const& _r) { + m_lastReceived = chrono::steady_clock::now(); + clogS(NetRight) << _r; + try // Generic try-catch block designed to capture RLP format errors - TODO: give decent diagnostics, make a bit more specific over what is caught. + { + switch ((PacketType)_r[0].toInt()) { case HelloPacket: @@ -83,8 +184,8 @@ bool Session::interpret(RLP const& _r) m_protocolVersion = _r[1].toInt(); auto clientVersion = _r[2].toString(); auto caps = _r[3].toVector(); - m_listenPort = _r[4].toInt(); - m_id = _r[5].toHash(); + auto listenPort = _r[4].toInt(); + auto id = _r[5].toHash(); // clang error (previously: ... << hex << caps ...) // "'operator<<' should be declared prior to the call site or in an associated namespace of one of its arguments" @@ -92,32 +193,62 @@ bool Session::interpret(RLP const& _r) for (auto cap: caps) capslog << "(" << hex << cap.first << "," << hex << cap.second << ")"; - clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "]" << m_id.abridged() << showbase << capslog.str() << dec << m_listenPort; + clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "]" << id.abridged() << showbase << capslog.str() << dec << listenPort; - if (m_server->havePeer(m_id)) + if (m_server->id() == id) { // Already connected. - clogS(NetWarn) << "Already have peer id" << m_id.abridged();// << "at" << l->endpoint() << "rather than" << endpoint(); + clogS(NetWarn) << "Connected to ourself under a false pretext. We were told this peer was id" << m_info.id.abridged(); + disconnect(LocalIdentity); + return true; + } + + if (m_node && m_node->id != id) + { + if (m_force || m_node->idOrigin <= Origin::SelfThird) + // SECURITY: We're forcing through the new ID, despite having been told + clogS(NetWarn) << "Connected to node, but their ID has changed since last time. This could indicate a MitM attack. Allowing anyway..."; + else + { + clogS(NetWarn) << "Connected to node, but their ID has changed since last time. This could indicate a MitM attack. Disconnecting."; + disconnect(UnexpectedIdentity); + return true; + } + + if (m_server->havePeer(id)) + { + m_node->dead = true; + disconnect(DuplicatePeer); + return true; + } + } + + if (m_server->havePeer(id)) + { + // Already connected. + clogS(NetWarn) << "Already connected to a peer with id" << id.abridged(); disconnect(DuplicatePeer); - return false; + return true; } - if (!m_id) + + if (!id) { - disconnect(InvalidIdentity); - return false; + disconnect(NullIdentity); + return true; } + + m_node = m_server->noteNode(id, bi::tcp::endpoint(m_socket.remote_endpoint().address(), listenPort), Origin::Self, false, !m_node || m_node->id == id ? NodeId() : m_node->id); + if (m_node->isOffline()) + m_node->lastConnected = chrono::system_clock::now(); + m_knownNodes.extendAll(m_node->index); + m_knownNodes.unionWith(m_node->index); + if (m_protocolVersion != m_server->protocolVersion()) { disconnect(IncompatibleProtocol); - return false; - } - try - { m_info = PeerInfo({clientVersion, m_socket.remote_endpoint().address().to_string(), m_listenPort, std::chrono::steady_clock::duration(), _r[3].toSet(), (unsigned)m_socket.native_handle(), map() }); } - catch (...) - { - disconnect(BadProtocol); - return false; + return true; } + m_info = PeerInfo({id, clientVersion, m_socket.remote_endpoint().address().to_string(), listenPort, std::chrono::steady_clock::duration(), _r[3].toSet(), (unsigned)m_socket.native_handle(), map() }); m_server->registerPeer(shared_from_this(), caps); break; @@ -125,16 +256,16 @@ bool Session::interpret(RLP const& _r) case DisconnectPacket: { string reason = "Unspecified"; - if (_r[1].isInt()) - reason = reasonOf((DisconnectReason)_r[1].toInt()); - - clogS(NetMessageSummary) << "Disconnect (reason: " << reason << ")"; - if (m_socket.is_open()) - clogS(NetNote) << "Closing " << m_socket.remote_endpoint(); + auto r = (DisconnectReason)_r[1].toInt(); + if (!_r[1].isInt()) + drop(BadProtocol); else - clogS(NetNote) << "Remote closed."; - m_socket.close(); - return false; + { + reason = reasonOf(r); + clogS(NetMessageSummary) << "Disconnect (reason: " << reason << ")"; + drop(DisconnectRequested); + } + break; } case PingPacket: { @@ -150,22 +281,13 @@ bool Session::interpret(RLP const& _r) case GetPeersPacket: { clogS(NetTriviaSummary) << "GetPeers"; - auto peers = m_server->potentialPeers(); - RLPStream s; - prep(s, PeersPacket, peers.size()); - for (auto i: peers) - { - clogS(NetTriviaDetail) << "Sending peer " << i.first.abridged() << i.second; - if (i.second.address().is_v4()) - s.appendList(3) << bytesConstRef(i.second.address().to_v4().to_bytes().data(), 4) << i.second.port() << i.first; - else// if (i.second.address().is_v6()) - assumed - s.appendList(3) << bytesConstRef(i.second.address().to_v6().to_bytes().data(), 16) << i.second.port() << i.first; - } - sealAndSend(s); + m_theyRequestedNodes = true; + serviceNodesRequest(); break; } case PeersPacket: clogS(NetTriviaSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)"; + m_weRequestedNodes = false; for (unsigned i = 1; i < _r.itemCount(); ++i) { bi::address peerAddress; @@ -175,32 +297,66 @@ bool Session::interpret(RLP const& _r) peerAddress = bi::address_v4(_r[i][0].toHash>().asArray()); else { + cwarn << "Received bad peer packet:" << _r; disconnect(BadProtocol); - return false; + return true; } auto ep = bi::tcp::endpoint(peerAddress, _r[i][1].toInt()); - h512 id = _r[i][2].toHash(); - clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")" << isPrivateAddress(peerAddress) << m_id.abridged() << isPrivateAddress(endpoint().address()) << m_server->m_incomingPeers.count(id) << (m_server->m_incomingPeers.count(id) ? isPrivateAddress(m_server->m_incomingPeers.at(id).first.address()) : -1); + NodeId id = _r[i][2].toHash(); + clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")" << isPrivateAddress(peerAddress) << this->id().abridged() << isPrivateAddress(endpoint().address()) << m_server->m_nodes.count(id) << (m_server->m_nodes.count(id) ? isPrivateAddress(m_server->m_nodes.at(id)->address.address()) : -1); if (isPrivateAddress(peerAddress) && !m_server->m_netPrefs.localNetworking) - goto CONTINUE; + goto CONTINUE; // Private address. Ignore. + + if (!id) + goto CONTINUE; // Null identity. Ignore. + + if (m_server->id() == id) + goto CONTINUE; // Just our info - we already have that. + + if (id == this->id()) + goto CONTINUE; // Just their info - we already have that. // check that it's not us or one we already know: - if (!(m_id == id && isPrivateAddress(endpoint().address()) && (!m_server->m_incomingPeers.count(id) || isPrivateAddress(m_server->m_incomingPeers.at(id).first.address()))) && (!id || m_server->m_id == id || m_server->m_incomingPeers.count(id))) + if (m_server->m_nodes.count(id)) + { + /* MEH. Far from an ideal solution. Leave alone for now. + // Already got this node. + // See if it's any better that ours or not... + // This could be the public address of a known node. + // SECURITY: remove this in beta - it's only for lazy connections and presents an easy attack vector. + if (m_server->m_nodes.count(id) && isPrivateAddress(m_server->m_nodes.at(id)->address.address()) && ep.port() != 0) + // Update address if the node if we now have a public IP for it. + m_server->m_nodes[id]->address = ep; + */ goto CONTINUE; + } - // check that we're not already connected to addr: if (!ep.port()) - goto CONTINUE; + goto CONTINUE; // Zero port? Don't think so. + + if (ep.port() >= 49152) + goto CONTINUE; // Private port according to IANA. + + // TODO: PoC-7: + // Technically fine, but ignore for now to avoid peers passing on incoming ports until we can be sure that doesn't happen any more. +// if (ep.port() < 30300 || ep.port() > 30305) +// goto CONTINUE; // Wierd port. + + // Avoid our random other addresses that they might end up giving us. for (auto i: m_server->m_addresses) if (ep.address() == i && ep.port() == m_server->listenPort()) goto CONTINUE; - for (auto i: m_server->m_incomingPeers) - if (i.second.first == ep) - goto CONTINUE; - m_server->m_incomingPeers[id] = make_pair(ep, 0); - m_server->m_freePeers.push_back(id); - m_server->noteNewPeers(); + + // Check that we don't already know about this addr:port combination. If we are, assume the original is best. + // SECURITY: Not a valid assumption in general. Should compare ID origins and pick the best or note uncertainty and weight each equally. + for (auto const& i: m_server->m_nodes) + if (i.second->address == ep) + goto CONTINUE; // Same address but a different node. + + // OK passed all our checks. Assume it's good. + addRating(1000); + m_server->noteNode(id, ep, m_node->idOrigin == Origin::Perfect ? Origin::PerfectThird : Origin::SelfThird, true); clogS(NetTriviaDetail) << "New peer: " << ep << "(" << id .abridged()<< ")"; CONTINUE:; } @@ -214,6 +370,13 @@ bool Session::interpret(RLP const& _r) return false; } } + } + catch (std::exception const& _e) + { + clogS(NetWarn) << "Peer causing an exception:" << _e.what() << _r; + disconnect(BadProtocol); + return true; + } return true; } @@ -224,12 +387,6 @@ void Session::ping() m_ping = std::chrono::steady_clock::now(); } -void Session::getPeers() -{ - RLPStream s; - sealAndSend(prep(s, GetPeersPacket)); -} - RLPStream& Session::prep(RLPStream& _s, PacketType _id, unsigned _args) { return prep(_s).appendList(_args + 1).append((unsigned)_id); @@ -245,7 +402,7 @@ void Session::sealAndSend(RLPStream& _s) bytes b; _s.swapOut(b); m_server->seal(b); - sendDestroy(b); + send(move(b)); } bool Session::checkPacket(bytesConstRef _msg) @@ -263,42 +420,26 @@ bool Session::checkPacket(bytesConstRef _msg) return true; } -void Session::sendDestroy(bytes& _msg) +void Session::send(bytesConstRef _msg) { - clogS(NetLeft) << RLP(bytesConstRef(&_msg).cropped(8)); - - if (!checkPacket(bytesConstRef(&_msg))) - { - clogS(NetWarn) << "INVALID PACKET CONSTRUCTED!"; - } - - bytes buffer = bytes(std::move(_msg)); - writeImpl(buffer); + send(_msg.toBytes()); } -void Session::send(bytesConstRef _msg) +void Session::send(bytes&& _msg) { - clogS(NetLeft) << RLP(_msg.cropped(8)); - - if (!checkPacket(_msg)) - { - clogS(NetWarn) << "INVALID PACKET CONSTRUCTED!"; - } + clogS(NetLeft) << RLP(bytesConstRef(&_msg).cropped(8)); - bytes buffer = bytes(_msg.toBytes()); - writeImpl(buffer); -} + if (!checkPacket(bytesConstRef(&_msg))) + clogS(NetWarn) << "INVALID PACKET CONSTRUCTED!"; -void Session::writeImpl(bytes& _buffer) -{ // cerr << (void*)this << " writeImpl" << endl; if (!m_socket.is_open()) return; bool doWrite = false; { - lock_guard l(m_writeLock); - m_writeQueue.push_back(_buffer); + Guard l(x_writeQueue); + m_writeQueue.push_back(_msg); doWrite = (m_writeQueue.size() == 1); } @@ -312,18 +453,16 @@ void Session::write() auto self(shared_from_this()); ba::async_write(m_socket, ba::buffer(bytes), [this, self](boost::system::error_code ec, std::size_t /*length*/) { -// cerr << (void*)this << " write.callback" << endl; - // must check queue, as write callback can occur following dropped() if (ec) { clogS(NetWarn) << "Error sending: " << ec.message(); - dropped(); + drop(TCPError); return; } else { - lock_guard l(m_writeLock); + Guard l(x_writeQueue); m_writeQueue.pop_front(); if (m_writeQueue.empty()) return; @@ -332,33 +471,43 @@ void Session::write() }); } -void Session::dropped() +void Session::drop(DisconnectReason _reason) { -// cerr << (void*)this << " dropped" << endl; + if (m_dropped) + return; + cerr << (void*)this << " dropped" << endl; if (m_socket.is_open()) try { - clogS(NetConnect) << "Closing " << m_socket.remote_endpoint(); + clogS(NetConnect) << "Closing " << m_socket.remote_endpoint() << "(" << reasonOf(_reason) << ")"; m_socket.close(); } catch (...) {} + + if (m_node) + { + if (_reason != m_node->lastDisconnect || _reason == NoDisconnect || _reason == ClientQuit || _reason == DisconnectRequested) + m_node->failedAttempts = 0; + m_node->lastDisconnect = _reason; + if (_reason == BadProtocol) + { + m_node->rating /= 2; + m_node->score /= 2; + } + } + m_dropped = true; } -void Session::disconnect(int _reason) +void Session::disconnect(DisconnectReason _reason) { - clogS(NetConnect) << "Disconnecting (reason:" << reasonOf((DisconnectReason)_reason) << ")"; + clogS(NetConnect) << "Disconnecting (our reason:" << reasonOf(_reason) << ")"; if (m_socket.is_open()) { - if (m_disconnect == chrono::steady_clock::time_point::max()) - { - RLPStream s; - prep(s, DisconnectPacket, 1) << _reason; - sealAndSend(s); - m_disconnect = chrono::steady_clock::now(); - } - else - dropped(); + RLPStream s; + prep(s, DisconnectPacket, 1) << (int)_reason; + sealAndSend(s); } + drop(_reason); } void Session::start() @@ -369,18 +518,16 @@ void Session::start() << m_server->m_clientVersion << m_server->caps() << m_server->m_public.port() - << m_server->m_id; + << m_server->id(); sealAndSend(s); ping(); - getPeers(); - doRead(); } void Session::doRead() { // ignore packets received while waiting to disconnect - if (chrono::steady_clock::now() - m_disconnect > chrono::seconds(0)) + if (m_dropped) return; auto self(shared_from_this()); @@ -391,7 +538,7 @@ void Session::doRead() { // got here with length of 1241... clogS(NetWarn) << "Error reading: " << ec.message(); - dropped(); + drop(TCPError); } else if (ec && length == 0) { @@ -432,8 +579,9 @@ void Session::doRead() RLP r(data.cropped(8)); if (!interpret(r)) { - // error - dropped(); + // error - bad protocol + clogS(NetWarn) << "Couldn't interpret packet." << RLP(r); + // Just wasting our bandwidth - perhaps reduce rating? return; } } @@ -446,12 +594,12 @@ void Session::doRead() catch (Exception const& _e) { clogS(NetWarn) << "ERROR: " << diagnostic_information(_e); - dropped(); + drop(BadProtocol); } catch (std::exception const& _e) { clogS(NetWarn) << "ERROR: " << _e.what(); - dropped(); + drop(BadProtocol); } } }); diff --git a/libp2p/Session.h b/libp2p/Session.h index 1a0ae8730..e8de1c398 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "Common.h" namespace dev @@ -37,6 +39,8 @@ namespace dev namespace p2p { +struct Node; + /** * @brief The Session class * @todo Document fully. @@ -47,17 +51,18 @@ class Session: public std::enable_shared_from_this friend class HostCapabilityFace; public: - Session(Host* _server, bi::tcp::socket _socket, bi::address _peerAddress, unsigned short _peerPort = 0); + Session(Host* _server, bi::tcp::socket _socket, std::shared_ptr const& _n, bool _force = false); + Session(Host* _server, bi::tcp::socket _socket, bi::tcp::endpoint const& _manual); virtual ~Session(); void start(); - void disconnect(int _reason); + void disconnect(DisconnectReason _reason); void ping(); bool isOpen() const { return m_socket.is_open(); } - h512 id() const { return m_id; } + NodeId id() const; unsigned socketId() const { return m_socket.native_handle(); } bi::tcp::endpoint endpoint() const; ///< for other peers to connect to. @@ -68,52 +73,60 @@ public: static RLPStream& prep(RLPStream& _s, PacketType _t, unsigned _args = 0); static RLPStream& prep(RLPStream& _s); void sealAndSend(RLPStream& _s); - void sendDestroy(bytes& _msg); + void send(bytes&& _msg); void send(bytesConstRef _msg); - void addRating(unsigned _r) { m_rating += _r; } + int rating() const; + void addRating(unsigned _r); void addNote(std::string const& _k, std::string const& _v) { m_info.notes[_k] = _v; } PeerInfo const& info() const { return m_info; } + void ensureNodesRequested(); + void serviceNodesRequest(); + private: - void dropped(); + /// Drop the connection for the reason @a _r. + void drop(DisconnectReason _r); + + /// Perform a read on the socket. void doRead(); - void doWrite(std::size_t length); - void writeImpl(bytes& _buffer); + + /// Perform a single round of the write operation. This could end up calling itself asynchronously. void write(); - void getPeers(); + /// Interpret an incoming message. bool interpret(RLP const& _r); /// @returns true iff the _msg forms a valid message for sending or receiving on the network. static bool checkPacket(bytesConstRef _msg); - Host* m_server; - - std::mutex m_writeLock; - std::deque m_writeQueue; + Host* m_server; ///< The host that owns us. Never null. - mutable bi::tcp::socket m_socket; ///< Mutable to ask for native_handle(). - std::array m_data; - PeerInfo m_info; - h512 m_id; + mutable bi::tcp::socket m_socket; ///< Socket for the peer's connection. Mutable to ask for native_handle(). + Mutex x_writeQueue; ///< Mutex for the write queue. + std::deque m_writeQueue; ///< The write queue. + std::array m_data; ///< Data buffer for the write queue. + bytes m_incoming; ///< The incoming read queue of bytes. - bytes m_incoming; - unsigned m_protocolVersion; - unsigned short m_listenPort; ///< Port that the remote client is listening on for connections. Useful for giving to peers. + PeerInfo m_info; ///< Dyanamic information about this peer. - std::chrono::steady_clock::time_point m_ping; - std::chrono::steady_clock::time_point m_connect; - std::chrono::steady_clock::time_point m_disconnect; + unsigned m_protocolVersion = 0; ///< The protocol version of the peer. + std::shared_ptr m_node; ///< The Node object. Might be null if we constructed using a bare address/port. + bi::tcp::endpoint m_manualEndpoint; ///< The endpoint as specified by the constructor. + bool m_force = false; ///< If true, ignore IDs being different. This could open you up to MitM attacks. + bool m_dropped = false; ///< If true, we've already divested ourselves of this peer. We're just waiting for the reads & writes to fail before the shared_ptr goes OOS and the destructor kicks in. - unsigned m_rating; + bool m_theyRequestedNodes = false; ///< Has the peer requested nodes from us without receiveing an answer from us? + bool m_weRequestedNodes = false; ///< Have we requested nodes from the peer and not received an answer yet? - std::map> m_capabilities; - std::set m_knownPeers; + std::chrono::steady_clock::time_point m_connect; ///< Time point of connection. + std::chrono::steady_clock::time_point m_ping; ///< Time point of last ping. + std::chrono::steady_clock::time_point m_lastReceived; ///< Time point of last message. - bool m_willBeDeleted = false; ///< True if we already posted a deleter on the strand. + std::map> m_capabilities; ///< The peer's capability set. + RangeMask m_knownNodes; ///< Nodes we already know about as indices into Host's nodesList. These shouldn't be resent to peer. }; } diff --git a/libp2p/UPnP.cpp b/libp2p/UPnP.cpp index 211b185bb..42868d67a 100644 --- a/libp2p/UPnP.cpp +++ b/libp2p/UPnP.cpp @@ -123,16 +123,18 @@ int UPnP::addRedirect(char const* _addr, int _port) // Try direct mapping first (port external, port internal). char port_str[16]; + char ext_port_str[16]; sprintf(port_str, "%d", _port); if (!UPNP_AddPortMapping(m_urls->controlURL, m_data->first.servicetype, port_str, port_str, _addr, "ethereum", "TCP", NULL, NULL)) return _port; // Failed - now try (random external, port internal) and cycle up to 10 times. + srand(time(NULL)); for (unsigned i = 0; i < 10; ++i) { - _port = rand() % 65535 - 1024 + 1024; - sprintf(port_str, "%d", _port); - if (!UPNP_AddPortMapping(m_urls->controlURL, m_data->first.servicetype, NULL, port_str, _addr, "ethereum", "TCP", NULL, NULL)) + _port = rand() % (65535 - 1024) + 1024; + sprintf(ext_port_str, "%d", _port); + if (!UPNP_AddPortMapping(m_urls->controlURL, m_data->first.servicetype, ext_port_str, port_str, _addr, "ethereum", "TCP", NULL, NULL)) return _port; } diff --git a/libqethereum/CMakeLists.txt b/libqethereum/CMakeLists.txt index 68ee1bb9d..4fb7d1a21 100644 --- a/libqethereum/CMakeLists.txt +++ b/libqethereum/CMakeLists.txt @@ -51,10 +51,11 @@ if (APPLE) include(BundleUtilities) endif () +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${RESOURCE_ADDED} ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${RESOURCE_ADDED} ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS}) endif() include_directories(/) diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index a244b9c9b..e85d381f8 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -396,7 +395,7 @@ static QString toJson(dev::eth::Transaction const& _bi) v["from"] = toQJS(_bi.sender()); v["gas"] = (int)_bi.gas; v["gasPrice"] = toQJS(_bi.gasPrice); - v["nonce"] = toQJS(_bi.nonce); + v["nonce"] = (int)_bi.nonce; v["value"] = toQJS(_bi.value); return QString::fromUtf8(QJsonDocument(v).toJson()); diff --git a/libqethereum/QmlEthereum.cpp b/libqethereum/QmlEthereum.cpp index 89578a29a..a7ed3df4d 100644 --- a/libqethereum/QmlEthereum.cpp +++ b/libqethereum/QmlEthereum.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index 0d66393b2..0090b5dc3 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -6,15 +6,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE serpent) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} lll) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index d3332d8b0..cc1b290f5 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -6,15 +6,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE webthree) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} ethereum) diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index 46725de1a..1515a8707 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -68,14 +68,14 @@ void WebThreeDirect::setIdealPeerCount(size_t _n) return m_net.setIdealPeerCount(_n); } -bytes WebThreeDirect::savePeers() +bytes WebThreeDirect::saveNodes() { - return m_net.savePeers(); + return m_net.saveNodes(); } -void WebThreeDirect::restorePeers(bytesConstRef _saved) +void WebThreeDirect::restoreNodes(bytesConstRef _saved) { - return m_net.restorePeers(_saved); + return m_net.restoreNodes(_saved); } void WebThreeDirect::connect(std::string const& _seedHost, unsigned short _port) diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index d4f23ca26..32bbe0b31 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -96,10 +96,10 @@ public: bool haveNetwork() { return peerCount() != 0; } /// Save peers - dev::bytes savePeers(); + dev::bytes saveNodes(); /// Restore peers - void restorePeers(bytesConstRef _saved); + void restoreNodes(bytesConstRef _saved); /// Sets the ideal number of peers. void setIdealPeerCount(size_t _n); @@ -108,6 +108,11 @@ public: void setNetworkPreferences(p2p::NetworkPreferences const& _n) { auto had = haveNetwork(); if (had) stopNetwork(); m_net.setNetworkPreferences(_n); if (had) startNetwork(); } + p2p::NodeId id() const { return m_net.id(); } + + /// Gets the nodes. + p2p::Nodes nodes() const { return m_net.nodes(); } + /// Start the network subsystem. void startNetwork() { m_net.start(); } diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 49857d16a..364d9759a 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -6,15 +6,13 @@ aux_source_directory(. SRC_LIST) set(EXECUTABLE whisper) -# set(CMAKE_INSTALL_PREFIX ../lib) +file(GLOB HEADERS "*.h") if(ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST}) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST}) + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) endif() -file(GLOB HEADERS "*.h") - include_directories(..) target_link_libraries(${EXECUTABLE} ethcore) diff --git a/libwhisper/Common.h b/libwhisper/Common.h index 251a089b7..26e8b9da8 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -35,7 +35,6 @@ namespace shh /* this makes these symbols ambiguous on VS2013 using h256 = dev::h256; -using h512 = dev::h512; using h256s = dev::h256s; using bytes = dev::bytes; using RLPStream = dev::RLPStream; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6936addb3..2e5366079 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,7 +6,8 @@ include_directories(..) link_directories(../libethcore) link_directories(../libethereum) -add_executable(testeth ${SRC_LIST}) +file(GLOB HEADERS "*.h") +add_executable(testeth ${SRC_LIST} ${HEADERS}) target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) diff --git a/test/TestHelperCrypto.h b/test/TestHelperCrypto.h new file mode 100644 index 000000000..6feeeb97f --- /dev/null +++ b/test/TestHelperCrypto.h @@ -0,0 +1,56 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file TestHelperCrypto.h + * @author Alex Leverington + * @date 2014 + */ + +#pragma once + +//#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace CryptoPP; + +void SavePrivateKey(const PrivateKey& key, const string& file = "ecies.private.key") +{ + FileSink sink(file.c_str()); + key.Save(sink); +} + +void SavePublicKey(const PublicKey& key, const string& file = "ecies.public.key") +{ + FileSink sink(file.c_str()); + key.Save(sink); +} + +void LoadPrivateKey(PrivateKey& key, const string& file = "ecies.private.key") +{ + FileSource source(file.c_str(), true); + key.Load(source); +} + +void LoadPublicKey(PublicKey& key, const string& file = "ecies.public.key") +{ + FileSource source(file.c_str(), true); + key.Load(source); +} diff --git a/test/crypto.cpp b/test/crypto.cpp index 55feb1a54..25106a77f 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -27,13 +27,170 @@ #include #include #include +#include "TestHelperCrypto.h" using namespace std; using namespace dev; -using namespace dev::eth; +namespace dev +{ +namespace crypto +{ + +inline CryptoPP::AutoSeededRandomPool& PRNG() { + static CryptoPP::AutoSeededRandomPool prng; + return prng; +} + +} +} + +using namespace CryptoPP; + +BOOST_AUTO_TEST_SUITE(crypto) + +BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) +{ + cnote << "Testing cryptopp_ecies_message..."; + + string const message("Now is the time for all good men to come to the aide of humanity."); + + AutoSeededRandomPool prng; + + ECIES::Decryptor localDecryptor(prng, ASN1::secp256r1()); + SavePrivateKey(localDecryptor.GetPrivateKey()); + + ECIES::Encryptor localEncryptor(localDecryptor); + SavePublicKey(localEncryptor.GetPublicKey()); -BOOST_AUTO_TEST_CASE(crypto_tests) + ECIES::Decryptor futureDecryptor; + LoadPrivateKey(futureDecryptor.AccessPrivateKey()); + futureDecryptor.GetPrivateKey().ThrowIfInvalid(prng, 3); + + ECIES::Encryptor futureEncryptor; + LoadPublicKey(futureEncryptor.AccessPublicKey()); + futureEncryptor.GetPublicKey().ThrowIfInvalid(prng, 3); + + // encrypt/decrypt with local + string cipherLocal; + StringSource ss1 (message, true, new PK_EncryptorFilter(prng, localEncryptor, new StringSink(cipherLocal) ) ); + string plainLocal; + StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(prng, localDecryptor, new StringSink(plainLocal) ) ); + + // encrypt/decrypt with future + string cipherFuture; + StringSource ss3 (message, true, new PK_EncryptorFilter(prng, futureEncryptor, new StringSink(cipherFuture) ) ); + string plainFuture; + StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(prng, futureDecryptor, new StringSink(plainFuture) ) ); + + // decrypt local w/future + string plainFutureFromLocal; + StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(prng, futureDecryptor, new StringSink(plainFutureFromLocal) ) ); + + // decrypt future w/local + string plainLocalFromFuture; + StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(prng, localDecryptor, new StringSink(plainLocalFromFuture) ) ); + + + assert(plainLocal == message); + assert(plainFuture == plainLocal); + assert(plainFutureFromLocal == plainLocal); + assert(plainLocalFromFuture == plainLocal); +} + +BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime) +{ + cnote << "Testing cryptopp_ecdh_prime..."; + + using namespace CryptoPP; + OID curve = ASN1::secp256r1(); + + ECDH::Domain dhLocal(curve); + SecByteBlock privLocal(dhLocal.PrivateKeyLength()); + SecByteBlock pubLocal(dhLocal.PublicKeyLength()); + dhLocal.GenerateKeyPair(dev::crypto::PRNG(), privLocal, pubLocal); + + ECDH::Domain dhRemote(curve); + SecByteBlock privRemote(dhRemote.PrivateKeyLength()); + SecByteBlock pubRemote(dhRemote.PublicKeyLength()); + dhRemote.GenerateKeyPair(dev::crypto::PRNG(), privRemote, pubRemote); + + assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength()); + + // local: send public to remote; remote: send public to local + + // Local + SecByteBlock sharedLocal(dhLocal.AgreedValueLength()); + assert(dhLocal.Agree(sharedLocal, privLocal, pubRemote)); + + // Remote + SecByteBlock sharedRemote(dhRemote.AgreedValueLength()); + assert(dhRemote.Agree(sharedRemote, privRemote, pubLocal)); + + // Test + Integer ssLocal, ssRemote; + ssLocal.Decode(sharedLocal.BytePtr(), sharedLocal.SizeInBytes()); + ssRemote.Decode(sharedRemote.BytePtr(), sharedRemote.SizeInBytes()); + + assert(ssLocal != 0); + assert(ssLocal == ssRemote); +} + +BOOST_AUTO_TEST_CASE(cryptopp_ecdh_aes128_cbc_noauth) +{ + // ECDH gives 256-bit shared while aes uses 128-bits + // Use first 128-bits of shared secret as symmetric key + // IV is 0 + // New connections require new ECDH keypairs + + +} + +BOOST_AUTO_TEST_CASE(cryptopp_eth_fbba) +{ + // Initial Authentication: + // + // New/Known Peer: + // pubkeyL = knownR? ? myKnown : myECDH + // pubkeyR = knownR? ? theirKnown : theirECDH + // + // Initial message = hmac(k=sha3(shared-secret[128..255]), address(pubkeyL)) || ECIES encrypt(pubkeyR, pubkeyL) + // + // Key Exchange (this could occur after handshake messages): + // If peers do not know each other they will need to exchange public keys. + // + // Drop ECDH (this could occur after handshake messages): + // After authentication and/or key exchange, both sides generate shared key + // from their 'known' keys and use this to encrypt all future messages. + // + // v2: If one side doesn't trust the other then a single-use key maybe sent. + // This will need to be tracked for future connections; when non-trusting peer + // wants to trust the other, it can request that it's old, 'new', public key be + // accepted. And, if the peer *really* doesn't trust the other side, it can request + // that a new, 'new', public key be accepted. + // + // Handshake (all or nothing, padded): + // All Peers (except blacklisted): + // + // + // New Peer: + // + // + // Known Untrusted Peer: + // + // + // Known Trusted Peer: + // + // + // Blacklisted Peeer: + // Already dropped by now. + // + // + // MAC: + // ... +} + +BOOST_AUTO_TEST_CASE(eth_keypairs) { cnote << "Testing Crypto..."; secp256k1_start(); @@ -42,7 +199,7 @@ BOOST_AUTO_TEST_CASE(crypto_tests) BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); { - Transaction t; + eth::Transaction t; t.nonce = 0; t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); t.value = 1000; @@ -70,7 +227,7 @@ int cryptoTest() assert(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); assert(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); { - Transaction t; + eth::Transaction t; t.nonce = 0; t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); t.value = 1000; @@ -156,3 +313,5 @@ int cryptoTest() return 0; } +BOOST_AUTO_TEST_SUITE_END() + diff --git a/test/dagger.cpp b/test/dagger.cpp index 555c5d776..9422b6a96 100644 --- a/test/dagger.cpp +++ b/test/dagger.cpp @@ -17,12 +17,12 @@ /** @file dagger.cpp * @author Gav Wood * @date 2014 - * Dagger test functions. + * ProofOfWork test functions. */ #include #include -#include +#include using namespace std; using namespace std::chrono; using namespace dev; @@ -30,20 +30,20 @@ using namespace dev::eth; int daggerTest() { - cnote << "Testing Dagger..."; + cnote << "Testing ProofOfWork..."; // Test dagger { auto s = steady_clock::now(); - cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)0); + cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)0); cout << " " << dec << duration_cast(steady_clock::now() - s).count() << " ms" << endl; - cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)1); + cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)1); cout << " " << dec << duration_cast(steady_clock::now() - s).count() << " ms" << endl; } { auto s = steady_clock::now(); - cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)0); + cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)0); cout << " " << dec << duration_cast(steady_clock::now() - s).count() << " ms" << endl; - cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)1); + cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)1); cout << " " << dec << duration_cast(steady_clock::now() - s).count() << " ms" << endl; } return 0; diff --git a/test/rlp.cpp b/test/rlp.cpp index 95d40ada7..69360ad66 100644 --- a/test/rlp.cpp +++ b/test/rlp.cpp @@ -79,7 +79,7 @@ namespace dev if ( v.type() == js::str_type ) { const std::string& expectedText = v.get_str(); - if ( expectedText.front() == '#' ) + if ( !expectedText.empty() && expectedText.front() == '#' ) { // Deal with bigint instead of a raw string std::string bigIntStr = expectedText.substr(1,expectedText.length()-1); diff --git a/test/vm.cpp b/test/vm.cpp index a90b122e2..d65b5d3d5 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -22,8 +22,9 @@ #include "vm.h" #include +#include -#define FILL_TESTS +//#define FILL_TESTS using namespace std; using namespace json_spirit; @@ -31,8 +32,8 @@ using namespace dev; using namespace dev::eth; using namespace dev::test; -FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock): - ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytesConstRef(), _previousBlock, _currentBlock) {} +FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth): /// TODO: XXX: remove the default argument & fix. + ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytesConstRef(), _previousBlock, _currentBlock, _depth) {} h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc) { @@ -41,7 +42,6 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun t.gasPrice = gasPrice; t.gas = *_gas; t.data = _init.toBytes(); - callcreates.push_back(t); m_s.noteSending(myAddress); m_ms.internal.resize(m_ms.internal.size() + 1); @@ -56,57 +56,103 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun get<3>(addresses[ret]) = m_s.code(ret); } + t.receiveAddress = ret; + callcreates.push_back(t); return ret; } -bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc, Address, Address) +bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc, Address _myAddressOverride = Address(), Address _codeAddressOverride = Address()) { + + u256 contractgas = 0xffff; + Transaction t; t.value = _value; t.gasPrice = gasPrice; t.gas = *_gas; t.data = _data.toVector(); t.receiveAddress = _receiveAddress; + callcreates.push_back(t); - string codeOf_receiveAddress = toHex(get<3>(addresses[_receiveAddress]) ); - string sizeOfCode = toHex(toCompactBigEndian((codeOf_receiveAddress.size()+1)/2)); + string codeOf_CodeAddress = _codeAddressOverride ? toHex(get<3>(addresses[_codeAddressOverride])) : toHex(get<3>(addresses[_receiveAddress]) ); + string sizeOfCode = toHex(toCompactBigEndian((codeOf_CodeAddress.size()+1)/2)); - if (codeOf_receiveAddress.size()) + string codeOf_SenderAddress = toHex(get<3>(addresses[myAddress]) ); + string sizeOfSenderCode = toHex(toCompactBigEndian((codeOf_SenderAddress.size()+1)/2)); + + if (codeOf_SenderAddress.size()) + { + // create init code that returns given contract code + string initStringHex = "{ (CODECOPY 0 (- (CODESIZE) 0x" + sizeOfSenderCode + " ) 0x" + sizeOfSenderCode + ") (RETURN 0 0x" + sizeOfSenderCode +")}"; + bytes initBytes = compileLLL(initStringHex, true, NULL); + initBytes += fromHex(codeOf_SenderAddress); + bytesConstRef init(&initBytes); + + if (!m_s.addresses().count(myAddress)) + { + m_ms.internal.resize(m_ms.internal.size() + 1); + auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); + if (!m_ms.internal.back().from) + m_ms.internal.pop_back(); + if (na != myAddress) + { + cnote << "not able to call to : " << myAddress << "\n"; + cnote << "in FakeExtVM you can only make a call to " << na << "\n"; + BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(myAddress)); + return false; + } + } + } + + if (codeOf_CodeAddress.size()) { // create init code that returns given contract code string initStringHex = "{ (CODECOPY 0 (- (CODESIZE) 0x" + sizeOfCode + " ) 0x" + sizeOfCode + ") (RETURN 0 0x" + sizeOfCode +")}"; bytes initBytes = compileLLL(initStringHex, true, NULL); - initBytes += fromHex(codeOf_receiveAddress); + initBytes += fromHex(codeOf_CodeAddress); bytesConstRef init(&initBytes); - if (!m_s.addresses().count(_receiveAddress)) + if (!m_s.addresses().count(_codeAddressOverride ? _codeAddressOverride : _receiveAddress)) { m_s.noteSending(myAddress); m_ms.internal.resize(m_ms.internal.size() + 1); - auto na = m_s.create(myAddress, 0, gasPrice, _gas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); + auto na = m_s.createNewAddress(_codeAddressOverride ? _codeAddressOverride : _receiveAddress, myAddress, balance(_codeAddressOverride ? _codeAddressOverride : _receiveAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); if (!m_ms.internal.back().from) m_ms.internal.pop_back(); - if (!m_s.addresses().count(_receiveAddress)) + + if (na != (_codeAddressOverride ? _codeAddressOverride : _receiveAddress)) { - cnote << "not able to call to : " << _receiveAddress << "\n"; + cnote << "not able to call to : " << (_codeAddressOverride ? _codeAddressOverride : _receiveAddress) << "\n"; cnote << "in FakeExtVM you can only make a call to " << na << "\n"; - BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(_receiveAddress)); + BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(_codeAddressOverride ? _codeAddressOverride : _receiveAddress)); return false; } } m_ms.internal.resize(m_ms.internal.size() + 1); - auto ret = m_s.call(_receiveAddress, Address() ? Address() : _receiveAddress, Address() ? Address() : myAddress, _value, gasPrice, _data, _gas, _out, origin, &suicides, &(m_ms.internal.back()), OnOpFunc(), 1); + + auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &suicides, &(m_ms.internal.back()), OnOpFunc(), 1); + if (!m_ms.internal.back().from) m_ms.internal.pop_back(); + + // get correct balances, (also for sucicides in the call function) + for (auto const& f: addresses) + { + if (m_s.addressInUse(f.first)) + get<0>(addresses[f.first]) = m_s.balance(f.first); + } + if (!ret) return false; - if (get<0>(addresses[myAddress]) >= _value) - { - get<1>(addresses[myAddress])++; - get<0>(addresses[_receiveAddress]) += _value; + // do suicides + for (auto const& f: suicides) + addresses.erase(f); + // get storage + if ((get<0>(addresses[myAddress]) >= _value) && (suicides.find(_receiveAddress) == suicides.end())) + { for (auto const& j: m_s.storage(_receiveAddress)) { u256 adr(j.first); @@ -114,13 +160,10 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, get<2>(addresses[_receiveAddress])[adr] = j.second; } } - } else addresses.erase(_receiveAddress); // for the sake of comparison - callcreates.push_back(t); - return true; } @@ -235,30 +278,8 @@ mObject FakeExtVM::exportState() { mObject store; - string curKey; - u256 li = 0; - bool isOutOfRange = false; - mArray curVal; for (auto const& s: get<2>(a.second)) - { - if (!li || s.first > li + 8) - { - if (li || isOutOfRange) - store[curKey] = curVal; - li = s.first; - curKey = "0x"+toHex(toCompactBigEndian(li)); - curVal = mArray(); - } - else - for (; li != s.first; ++li) - curVal.push_back(0); - curVal.push_back("0x"+toHex(toCompactBigEndian(s.second))); - if ( toHex(toCompactBigEndian(li)) == "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") - isOutOfRange = true; - ++li; - } - if (li || isOutOfRange) - store[curKey] = curVal; + store["0x"+toHex(toCompactBigEndian(s.first))] = "0x"+toHex(toCompactBigEndian(s.second)); o["storage"] = store; } o["code"] = "0x" + toHex(get<3>(a.second)); @@ -282,15 +303,7 @@ void FakeExtVM::importState(mObject& _object) get<0>(a) = toInt(o["balance"]); get<1>(a) = toInt(o["nonce"]); for (auto const& j: o["storage"].get_obj()) - { - u256 adr(j.first); - for (auto const& k: j.second.get_array()) - { - if ((toInt(k) != 0) || (j.second.get_array().size() == 1)) - get<2>(a)[adr] = toInt(k); - adr++; - } - } + get<2>(a)[toInt(j.first)] = toInt(j.second); if (o["code"].type() == str_type) if (o["code"].get_str().find_first_of("0x") != 0) @@ -402,6 +415,71 @@ void FakeExtVM::importCallCreates(mArray& _callcreates) } } +h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, std::set
* o_suicides, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level) +{ + if (!_origin) + _origin = _sender; + + if (o_ms) + { + o_ms->from = _sender; + o_ms->to = Address(); + o_ms->value = _endowment; + o_ms->input = _code.toBytes(); + } + + // Set up new account... + m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256()); + + // Execute init code. + VM vm(*_gas); + ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); + bool revert = false; + bytesConstRef out; + + try + { + out = vm.go(evm, _onOp); + if (o_ms) + o_ms->output = out.toBytes(); + if (o_suicides) + for (auto i: evm.suicides) + o_suicides->insert(i); + } + catch (OutOfGas const& /*_e*/) + { + clog(StateChat) << "Out of Gas! Reverting."; + revert = true; + } + catch (VMException const& _e) + { + clog(StateChat) << "VM Exception: " << diagnostic_information(_e); + } + catch (Exception const& _e) + { + clog(StateChat) << "Exception in VM: " << diagnostic_information(_e); + } + catch (std::exception const& _e) + { + clog(StateChat) << "std::exception in VM: " << _e.what(); + } + + // TODO: CHECK: IS THIS CORRECT?! (esp. given account created prior to revertion init.) + + // Write state out only in the case of a non-out-of-gas transaction. + if (revert) + evm.revert(); + + // Set code. + if (addressInUse(_newAddress)) + m_cache[_newAddress].setCode(out); + + *_gas = vm.gas(); + + return _newAddress; +} + + namespace dev { namespace test { @@ -416,7 +494,6 @@ void doTests(json_spirit::mValue& v, bool _fillin) BOOST_REQUIRE(o.count("pre") > 0); BOOST_REQUIRE(o.count("exec") > 0); - VM vm; dev::test::FakeExtVM fev; fev.importEnv(o["env"].get_obj()); fev.importState(o["pre"].get_obj()); @@ -431,11 +508,26 @@ void doTests(json_spirit::mValue& v, bool _fillin) fev.code = &fev.thisTxCode; } - vm.reset(fev.gas); bytes output; + u256 gas; try { - output = vm.go(fev).toBytes(); + auto argc = boost::unit_test::framework::master_test_suite().argc; + auto argv = boost::unit_test::framework::master_test_suite().argv; + + auto useJit = argc >= 2 && std::string(argv[1]) == "--jit"; + if (useJit) + { + jit::VM vm(fev.gas); + output = vm.go(fev); + gas = vm.gas(); + } + else + { + VM vm(fev.gas); + output = vm.go(fev).toVector(); + gas = vm.gas(); // Get the remaining gas + } } catch (Exception const& _e) { @@ -472,7 +564,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) o["post"] = mValue(fev.exportState()); o["callcreates"] = fev.exportCallCreates(); o["out"] = "0x" + toHex(output); - fev.push(o, "gas", vm.gas()); + fev.push(o, "gas", gas); } else { @@ -496,7 +588,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) else BOOST_CHECK(output == fromHex(o["out"].get_str())); - BOOST_CHECK(test.toInt(o["gas"]) == vm.gas()); + BOOST_CHECK(test.toInt(o["gas"]) == gas); BOOST_CHECK(test.addresses == fev.addresses); BOOST_CHECK(test.callcreates == fev.callcreates); } @@ -542,7 +634,7 @@ void executeTests(const string& _name) BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + "Filler.json is empty."); json_spirit::read_string(s, v); dev::test::doTests(v, true); - writeFile("../../../tests/" + _name + ".json", asBytes(json_spirit::write_string(v, true))); + writeFile("../../../tests/vmtests/" + _name + ".json", asBytes(json_spirit::write_string(v, true))); } catch (Exception const& _e) { @@ -558,7 +650,7 @@ void executeTests(const string& _name) { cnote << "Testing VM..." << _name; json_spirit::mValue v; - string s = asString(contents("../../../tests/" + _name + ".json")); + string s = asString(contents("../../../tests/vmtests/" + _name + ".json")); BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + ".json is empty. Have you cloned the 'tests' repo branch develop?"); json_spirit::read_string(s, v); dev::test::doTests(v, false); @@ -620,3 +712,4 @@ BOOST_AUTO_TEST_CASE(vmSystemOperationsTest) { dev::test::executeTests("vmSystemOperationsTest"); } + diff --git a/test/vm.h b/test/vm.h index 5bad9d7d4..34e0e855a 100644 --- a/test/vm.h +++ b/test/vm.h @@ -40,11 +40,18 @@ namespace dev { namespace test { struct FakeExtVMFailure : virtual Exception {}; +class FakeState: public eth::State +{ +public: + /// Execute a contract-creation transaction. + h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = Address(), std::set
* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = eth::OnOpFunc(), unsigned _level = 0); +}; + class FakeExtVM: public eth::ExtVMFace { public: FakeExtVM() {} - FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock); + FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth = 0); u256 store(u256 _n) { return std::get<2>(addresses[myAddress])[_n]; } void setStore(u256 _n, u256 _v) { std::get<2>(addresses[myAddress])[_n] = _v; } @@ -63,6 +70,7 @@ public: byte toByte(json_spirit::mValue const& _v); void push(json_spirit::mObject& o, std::string const& _n, u256 _v); void push(json_spirit::mArray& a, u256 _v); + u256 doPosts(); json_spirit::mObject exportEnv(); void importEnv(json_spirit::mObject& _o); json_spirit::mObject exportState(); @@ -79,7 +87,7 @@ public: u256 gas; private: - eth::State m_s; + FakeState m_s; eth::Manifest m_ms; }; diff --git a/test/vmSystemOperationsTestFiller.json b/test/vmSystemOperationsTestFiller.json index 34235e040..de8a3ad1a 100644 --- a/test/vmSystemOperationsTestFiller.json +++ b/test/vmSystemOperationsTestFiller.json @@ -48,7 +48,7 @@ "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000", + "value" : "100", "data" : "", "gasPrice" : "100000000000000", "gas" : "10000" @@ -76,7 +76,7 @@ "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000", + "value" : "100", "data" : "", "gasPrice" : "100000000000000", "gas" : "10000" @@ -104,7 +104,7 @@ "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", - "value" : "1000000000000000000", + "value" : "100", "data" : "", "gasPrice" : "100000000000000", "gas" : "10000" @@ -638,7 +638,7 @@ "address" : "cd1722f3947def4cf144679da39c4c32bdc35681", "origin" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "value" : "100000", + "value" : "23", "data" : "0xaa", "gasPrice" : "100000000000000", "gas" : "1000" @@ -668,7 +668,7 @@ "address" : "cd1722f3947def4cf144679da39c4c32bdc35681", "origin" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "value" : "100000", + "value" : "23", "data" : "0xaa", "gasPrice" : "100000000000000", "gas" : "1000" @@ -698,7 +698,7 @@ "address" : "cd1722f3947def4cf144679da39c4c32bdc35681", "origin" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", "caller" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "value" : "100000", + "value" : "23", "data" : "0xaa", "gasPrice" : "100000000000000", "gas" : "1000" @@ -777,9 +777,6 @@ } }, - - - "TestNameRegistrator": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -806,9 +803,149 @@ "gasPrice" : "100000000000000", "gas" : "10000" } - } + }, + "ABAcalls0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ (PC) ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 24 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : " { [[ (PC) ]] (ADD 1 (CALL 500 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 23 0 0 0 0)) } ", + "nonce" : "0", + "storage" : { + } + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000000000000" + } + }, + "ABAcalls0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ (PC) ]] (CALL (- (GAS) 1000) 0x945304eb96065b2a98b57a48a06ae28d285a71b5 24 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : " { [[ (PC) ]] (ADD 1 (CALL (- (GAS) 1000) 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 23 0 0 0 0)) } ", + "nonce" : "0", + "storage" : { + } + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000000000000" + } + }, + + + "ABAcallsSuicide0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ (PC) ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 24 0 0 0 0) (SUICIDE 0x945304eb96065b2a98b57a48a06ae28d285a71b5) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "{ [[ (PC) ]] (ADD 1 (CALL 500 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 23 0 0 0 0)) } ", + "nonce" : "0", + "storage" : { + } + } + + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000000000000" + } + }, + + "ABAcallsSuicide1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : 0, + "code" : "{ [[ (PC) ]] (CALL 1000 0x945304eb96065b2a98b57a48a06ae28d285a71b5 24 0 0 0 0) }", + "storage": {} + }, + "945304eb96065b2a98b57a48a06ae28d285a71b5" : { + "balance" : "23", + "code" : "{ [[ (PC) ]] (ADD 1 (CALL 500 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 23 0 0 0 0)) (SUICIDE 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6) } ", + "nonce" : "0", + "storage" : { + } + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "100000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "10000000000000" + } + } } diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 77b2bb496..9221ad045 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -25,6 +25,7 @@ find_package(Qt5WebKitWidgets REQUIRED) qt5_wrap_ui(ui_Main.h Main.ui) # Set name of binary and add_executable() +file(GLOB HEADERS "*.h") if (APPLE) set(EXECUTEABLE Third) set(BIN_INSTALL_DIR ".") @@ -41,14 +42,14 @@ if (APPLE) set(MACOSX_BUNDLE_ICON_FILE third) include(BundleUtilities) - add_executable(${EXECUTEABLE} MACOSX_BUNDLE third.icns Main.ui ${SRC_LIST}) + add_executable(${EXECUTEABLE} MACOSX_BUNDLE third.icns Main.ui ${SRC_LIST} ${HEADERS}) set_target_properties(${EXECUTEABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") SET_SOURCE_FILES_PROPERTIES(${EXECUTEABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) SET_SOURCE_FILES_PROPERTIES(${MACOSX_BUNDLE_ICON_FILE}.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") else () set(EXECUTEABLE third) - add_executable(${EXECUTEABLE} Main.ui ${SRC_LIST}) + add_executable(${EXECUTEABLE} Main.ui ${SRC_LIST} ${HEADERS}) endif () qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets) diff --git a/third/MainWin.cpp b/third/MainWin.cpp index f86dc0434..d21077f86 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -365,10 +364,10 @@ void Main::writeSettings() s.setValue("address", b); s.setValue("url", ui->urlEdit->text()); - bytes d = m_web3->savePeers(); + bytes d = m_web3->saveNodes(); if (d.size()) - m_peers = QByteArray((char*)d.data(), (int)d.size()); - s.setValue("peers", m_peers); + m_nodes = QByteArray((char*)d.data(), (int)d.size()); + s.setValue("peers", m_nodes); s.setValue("geometry", saveGeometry()); s.setValue("windowState", saveState()); @@ -397,7 +396,7 @@ void Main::readSettings(bool _skipGeometry) } } ethereum()->setAddress(m_myKeys.back().address()); - m_peers = s.value("peers").toByteArray(); + m_nodes = s.value("peers").toByteArray(); ui->urlEdit->setText(s.value("url", "about:blank").toString()); //http://gavwood.com/gavcoin.html on_urlEdit_returnPressed(); } @@ -571,8 +570,8 @@ void Main::ensureNetwork() else if (!m_web3->peerCount()) m_web3->connect(defPeer); - if (m_peers.size()) - m_web3->restorePeers(bytesConstRef((byte*)m_peers.data(), m_peers.size())); + if (m_nodes.size()) + m_web3->restoreNodes(bytesConstRef((byte*)m_nodes.data(), m_nodes.size())); } void Main::on_connect_triggered() diff --git a/third/MainWin.h b/third/MainWin.h index 0afab773f..fcb7ab304 100644 --- a/third/MainWin.h +++ b/third/MainWin.h @@ -127,7 +127,7 @@ private: unsigned m_currenciesFilter = (unsigned)-1; unsigned m_balancesFilter = (unsigned)-1; - QByteArray m_peers; + QByteArray m_nodes; QStringList m_servers; QNetworkAccessManager m_webCtrl; diff --git a/windows/Ethereum.sln b/windows/Ethereum.sln index c894b8a79..33167a23b 100644 --- a/windows/Ethereum.sln +++ b/windows/Ethereum.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.21005.1 +VisualStudioVersion = 12.0.30723.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libs", "Libs", "{988F2383-FA1D-408B-BCF6-C0EE7AB0A560}" EndProject @@ -16,6 +16,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSecp256k1", "TestSecp256k1.vcxproj", "{3BF049F8-AF7E-4E1C-9627-3E94C887AF24}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestEthereum", "TestEthereum.vcxproj", "{3F3E389B-88DE-41D5-A73B-4F6036E18B36}" + ProjectSection(ProjectDependencies) = postProject + {9C816740-5C11-4377-A3A7-46BE12F35FA0} = {9C816740-5C11-4377-A3A7-46BE12F35FA0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCryptoPP", "LibCryptoPP.vcxproj", "{1CC213A4-3482-4211-B47B-172E90DAC7DE}" EndProject @@ -38,141 +41,221 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lllc", "Lllc.vcxproj", "{255BDC68-B8DB-465F-8220-981E77684189}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evmcc", "evmcc.vcxproj", "{D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}" + ProjectSection(ProjectDependencies) = postProject + {9C816740-5C11-4377-A3A7-46BE12F35FA0} = {9C816740-5C11-4377-A3A7-46BE12F35FA0} + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} = {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibEvmJit", "LibEvmJit.vcxproj", "{9C816740-5C11-4377-A3A7-46BE12F35FA0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.ActiveCfg = Debug|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|Win32.Build.0 = Debug|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.ActiveCfg = Debug|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Debug|x64.Build.0 = Debug|x64 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Mixed Platforms.Build.0 = Release|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.ActiveCfg = Release|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|Win32.Build.0 = Release|Win32 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.ActiveCfg = Release|x64 {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F}.Release|x64.Build.0 = Release|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.ActiveCfg = Debug|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|Win32.Build.0 = Debug|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.ActiveCfg = Debug|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Debug|x64.Build.0 = Debug|x64 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {27014763-955D-486B-9BA7-69872192E6F4}.Release|Mixed Platforms.Build.0 = Release|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.ActiveCfg = Release|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Release|Win32.Build.0 = Release|Win32 {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.ActiveCfg = Release|x64 {27014763-955D-486B-9BA7-69872192E6F4}.Release|x64.Build.0 = Release|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.ActiveCfg = Debug|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|Win32.Build.0 = Debug|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.ActiveCfg = Debug|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Debug|x64.Build.0 = Debug|x64 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Mixed Platforms.Build.0 = Release|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.ActiveCfg = Release|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|Win32.Build.0 = Release|Win32 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.ActiveCfg = Release|x64 {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA}.Release|x64.Build.0 = Release|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.ActiveCfg = Debug|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|Win32.Build.0 = Debug|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.ActiveCfg = Debug|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Debug|x64.Build.0 = Debug|x64 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Mixed Platforms.Build.0 = Release|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.ActiveCfg = Release|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|Win32.Build.0 = Release|Win32 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.ActiveCfg = Release|x64 {3BF049F8-AF7E-4E1C-9627-3E94C887AF24}.Release|x64.Build.0 = Release|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.ActiveCfg = Debug|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|Win32.Build.0 = Debug|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.ActiveCfg = Debug|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Debug|x64.Build.0 = Debug|x64 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Mixed Platforms.Build.0 = Release|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.ActiveCfg = Release|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|Win32.Build.0 = Release|Win32 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.ActiveCfg = Release|x64 {3F3E389B-88DE-41D5-A73B-4F6036E18B36}.Release|x64.Build.0 = Release|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.ActiveCfg = Debug|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|Win32.Build.0 = Debug|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.ActiveCfg = Debug|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Debug|x64.Build.0 = Debug|x64 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Mixed Platforms.Build.0 = Release|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.ActiveCfg = Release|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|Win32.Build.0 = Release|Win32 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.ActiveCfg = Release|x64 {1CC213A4-3482-4211-B47B-172E90DAC7DE}.Release|x64.Build.0 = Release|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.ActiveCfg = Debug|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|Win32.Build.0 = Debug|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.ActiveCfg = Debug|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Debug|x64.Build.0 = Debug|x64 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Mixed Platforms.Build.0 = Release|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.ActiveCfg = Release|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|Win32.Build.0 = Release|Win32 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.ActiveCfg = Release|x64 {1B1CA20E-39C3-4D9B-AC37-3783048E6672}.Release|x64.Build.0 = Release|x64 + {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Win32.ActiveCfg = Debug|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|Win32.Build.0 = Debug|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|x64.ActiveCfg = Debug|x64 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Debug|x64.Build.0 = Debug|x64 + {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Win32.ActiveCfg = Release|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|Win32.Build.0 = Release|Win32 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|x64.ActiveCfg = Release|x64 {BFCFFC46-78A3-4350-9938-0EA3A2B1CCCD}.Release|x64.Build.0 = Release|x64 + {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Win32.ActiveCfg = Debug|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|Win32.Build.0 = Debug|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|x64.ActiveCfg = Debug|x64 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Debug|x64.Build.0 = Debug|x64 + {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Win32.ActiveCfg = Release|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|Win32.Build.0 = Release|Win32 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.ActiveCfg = Release|x64 {DF3C5B07-A1A2-4F16-B37F-A27333622CDD}.Release|x64.Build.0 = Release|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.ActiveCfg = Debug|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|Win32.Build.0 = Debug|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.ActiveCfg = Debug|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Debug|x64.Build.0 = Debug|x64 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Mixed Platforms.Build.0 = Release|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.ActiveCfg = Release|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|Win32.Build.0 = Release|Win32 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.ActiveCfg = Release|x64 {C60C065C-2135-4B2B-AFD4-35FD7AC56B40}.Release|x64.Build.0 = Release|x64 + {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Win32.ActiveCfg = Debug|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|Win32.Build.0 = Debug|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|x64.ActiveCfg = Debug|x64 {90C70663-7181-4E99-9079-54188CEB8954}.Debug|x64.Build.0 = Debug|x64 + {90C70663-7181-4E99-9079-54188CEB8954}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {90C70663-7181-4E99-9079-54188CEB8954}.Release|Mixed Platforms.Build.0 = Release|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Release|Win32.ActiveCfg = Release|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Release|Win32.Build.0 = Release|Win32 {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.ActiveCfg = Release|x64 {90C70663-7181-4E99-9079-54188CEB8954}.Release|x64.Build.0 = Release|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.ActiveCfg = Debug|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|Win32.Build.0 = Debug|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.ActiveCfg = Debug|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Debug|x64.Build.0 = Debug|x64 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Mixed Platforms.Build.0 = Release|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.ActiveCfg = Release|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|Win32.Build.0 = Release|Win32 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.ActiveCfg = Release|x64 {F174E81A-2A66-4693-B917-11BB42D3658C}.Release|x64.Build.0 = Release|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.ActiveCfg = Debug|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|Win32.Build.0 = Debug|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.ActiveCfg = Debug|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Debug|x64.Build.0 = Debug|x64 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Mixed Platforms.Build.0 = Release|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.ActiveCfg = Release|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|Win32.Build.0 = Release|Win32 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.ActiveCfg = Release|x64 {9AA5CF66-1150-4A02-B40E-3B89740DADB8}.Release|x64.Build.0 = Release|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.ActiveCfg = Debug|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|Win32.Build.0 = Debug|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.ActiveCfg = Debug|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Debug|x64.Build.0 = Debug|x64 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Mixed Platforms.Build.0 = Release|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.ActiveCfg = Release|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|Win32.Build.0 = Release|Win32 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.ActiveCfg = Release|x64 {90068D1B-070E-4C41-88B0-1E243E1E5BFF}.Release|x64.Build.0 = Release|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.ActiveCfg = Debug|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|Win32.Build.0 = Debug|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.ActiveCfg = Debug|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Debug|x64.Build.0 = Debug|x64 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {255BDC68-B8DB-465F-8220-981E77684189}.Release|Mixed Platforms.Build.0 = Release|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.ActiveCfg = Release|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Release|Win32.Build.0 = Release|Win32 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.ActiveCfg = Release|x64 {255BDC68-B8DB-465F-8220-981E77684189}.Release|x64.Build.0 = Release|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.ActiveCfg = Debug|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|Win32.Build.0 = Debug|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Debug|x64.ActiveCfg = Debug|x64 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Mixed Platforms.Build.0 = Release|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.ActiveCfg = Release|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|Win32.Build.0 = Release|Win32 {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D}.Release|x64.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.ActiveCfg = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|Win32.Build.0 = Debug|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.ActiveCfg = Debug|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Debug|x64.Build.0 = Debug|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Mixed Platforms.Build.0 = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.ActiveCfg = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|Win32.Build.0 = Release|Win32 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.ActiveCfg = Release|x64 + {9C816740-5C11-4377-A3A7-46BE12F35FA0}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -181,11 +264,12 @@ Global {826E68CB-D3EE-4A8A-B540-59A8C3F38D4F} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {27014763-955D-486B-9BA7-69872192E6F4} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {1E1175BB-C4A9-41D8-B2D1-9022F71D3CEA} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} + {3BF049F8-AF7E-4E1C-9627-3E94C887AF24} = {6838FA95-01BF-4FF7-914C-FC209B81406E} + {3F3E389B-88DE-41D5-A73B-4F6036E18B36} = {6838FA95-01BF-4FF7-914C-FC209B81406E} {1CC213A4-3482-4211-B47B-172E90DAC7DE} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {1B1CA20E-39C3-4D9B-AC37-3783048E6672} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {DF3C5B07-A1A2-4F16-B37F-A27333622CDD} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} {F174E81A-2A66-4693-B917-11BB42D3658C} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} - {3BF049F8-AF7E-4E1C-9627-3E94C887AF24} = {6838FA95-01BF-4FF7-914C-FC209B81406E} - {3F3E389B-88DE-41D5-A73B-4F6036E18B36} = {6838FA95-01BF-4FF7-914C-FC209B81406E} + {9C816740-5C11-4377-A3A7-46BE12F35FA0} = {988F2383-FA1D-408B-BCF6-C0EE7AB0A560} EndGlobalSection EndGlobal diff --git a/windows/LLVM.props b/windows/LLVM.props new file mode 100644 index 000000000..708ff3085 --- /dev/null +++ b/windows/LLVM.props @@ -0,0 +1,23 @@ + + + + + ..\..\builds\llvm3.5 + ..\..\llvm-3.5.0\include;$(LLVMBuildDir)\include + + + + + $(LLVMIncludeDir);%(AdditionalIncludeDirectories) + 4800;%(DisableSpecificWarnings) + + + + + $(LLVMBuildDir) + + + $(LLVMIncludeDir) + + + \ No newline at end of file diff --git a/windows/LibEthereum.props b/windows/LibEthereum.props index 136a8edab..8c0bcac90 100644 --- a/windows/LibEthereum.props +++ b/windows/LibEthereum.props @@ -15,7 +15,7 @@ true false include/$(ProjectName);$(IntDir);../../cryptopp;..;../libethcore;../libethereum;../libethsupport;$(BoostDir);../../leveldb/include;../secp256k1;../../miniupnp - ETH_BUILD_PLATFORM=Windows/VS2013;ETH_BUILD_TYPE=$(Configuration)-$(Platform);STATICLIB;LEVELDB_PLATFORM_WINDOWS;USE_NUM_BOOST;USE_FIELD_10X26;USE_FIELD_INV_BUILTIN;_WIN32_WINNT=0x0501;WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ETH_BUILD_PLATFORM=Windows/VS2013;ETH_BUILD_TYPE=$(Configuration)-$(Platform);ETH_MINIUPNPC=1;STATICLIB;LEVELDB_PLATFORM_WINDOWS;USE_NUM_BOOST;USE_FIELD_10X26;USE_FIELD_INV_BUILTIN;_WIN32_WINNT=0x0501;WIN32;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true true Level3 diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj new file mode 100644 index 000000000..1c71bb082 --- /dev/null +++ b/windows/LibEvmJit.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {9C816740-5C11-4377-A3A7-46BE12F35FA0} + LibEvmJit + + + + StaticLibrary + true + v120 + + + StaticLibrary + true + v120 + + + StaticLibrary + false + v120 + true + + + StaticLibrary + false + v120 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters new file mode 100644 index 000000000..a2008f971 --- /dev/null +++ b/windows/LibEvmJit.vcxproj.filters @@ -0,0 +1,78 @@ + + + + + {9bb7d84d-6d6c-48af-a954-60049208b2f1} + + + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + libevmjit + + + \ No newline at end of file diff --git a/windows/LibMiniUPnPc.vcxproj b/windows/LibMiniUPnPc.vcxproj index 7e5e44412..07489d0e8 100644 --- a/windows/LibMiniUPnPc.vcxproj +++ b/windows/LibMiniUPnPc.vcxproj @@ -106,7 +106,7 @@ Disabled MultiThreadedDebugDLL - _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) 4100;4244;4245;4267;4389;%(DisableSpecificWarnings) @@ -123,7 +123,7 @@ Disabled MultiThreadedDebugDLL - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) 4100;4244;4245;4267;4389;%(DisableSpecificWarnings) @@ -142,7 +142,7 @@ true true MultiThreadedDLL - _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;MINIUPNP_STATICLIB;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) 4100;4244;4245;4267;4389;%(DisableSpecificWarnings) @@ -163,7 +163,7 @@ true true MultiThreadedDLL - _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) 4100;4244;4245;4267;4389;%(DisableSpecificWarnings) diff --git a/windows/TestEthereum.vcxproj b/windows/TestEthereum.vcxproj index 172e6be86..b07124581 100644 --- a/windows/TestEthereum.vcxproj +++ b/windows/TestEthereum.vcxproj @@ -55,6 +55,7 @@ + @@ -107,6 +108,8 @@ Console true + LibEthereum.lib;LibEvmJit.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index efa7a6f20..6c1b72143 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -19,29 +19,7 @@ - - - - - - - - - - - - - - - - - - - - - - {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} @@ -132,8 +110,8 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -152,8 +130,8 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibEvmJit.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -173,8 +151,8 @@ true true true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) @@ -196,8 +174,8 @@ true true true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEvmJit/x64_Debug;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index adfcfaf60..6be5386a1 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -2,27 +2,5 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file