Browse Source

Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc

cl-refactor
artur-zawlocki 10 years ago
parent
commit
e27f48572a
  1. 353
      CMakeLists.txt
  2. 6
      README.md
  3. 5
      alethzero/CMakeLists.txt
  4. 2
      alethzero/DownloadView.cpp
  5. 34
      alethzero/Main.ui
  6. 71
      alethzero/MainWin.cpp
  7. 1
      alethzero/MainWin.h
  8. 59
      cmake/EthCompilerSettings.cmake
  9. 208
      cmake/EthDependenciesDeprecated.cmake
  10. 3
      eth/CMakeLists.txt
  11. 100
      eth/main.cpp
  12. 1
      evmcc/bytecode/if1.evm
  13. 12
      evmcc/evmcc.cpp
  14. 21
      evmcc/lll/if1.asm
  15. 5
      evmcc/lll/if1.lll
  16. 0
      evmcc/test/arith/arith1.evm
  17. 0
      evmcc/test/arith/arith1.lll
  18. 0
      evmcc/test/arith/fib1.evm
  19. 0
      evmcc/test/arith/fib1.lll
  20. 0
      evmcc/test/ext/ext_test.evm
  21. 0
      evmcc/test/ext/ext_test.lll
  22. 0
      evmcc/test/ext/store_test.evm
  23. 0
      evmcc/test/ext/store_test.lll
  24. 0
      evmcc/test/jump/for1.evm
  25. 0
      evmcc/test/jump/for1.lll
  26. 0
      evmcc/test/jump/for2.evm
  27. 0
      evmcc/test/jump/for2.lll
  28. 0
      evmcc/test/jump/when1.asm
  29. 0
      evmcc/test/jump/when1.evm
  30. 0
      evmcc/test/jump/when1.lll
  31. 0
      evmcc/test/kv.evm
  32. 0
      evmcc/test/kv.lll
  33. 0
      evmcc/test/mem/byte.evm
  34. 0
      evmcc/test/mem/byte.lll
  35. 0
      evmcc/test/mem/mem2.evm
  36. 0
      evmcc/test/mem/mem2.lll
  37. 0
      evmcc/test/mem/memtest1.evm
  38. 0
      evmcc/test/mem/memtest1.lll
  39. 0
      evmcc/test/ret/return1.evm
  40. 0
      evmcc/test/ret/return1.lll
  41. 0
      evmcc/test/ret/return2.evm
  42. 0
      evmcc/test/ret/return2.lll
  43. 0
      evmcc/test/ret/return_test.evm
  44. 0
      evmcc/test/ret/return_test.lll
  45. 0
      evmcc/test/stack/push_test.evm
  46. 0
      evmcc/test/stack/push_test.lll
  47. 0
      evmcc/test/stack/stack_test.evm
  48. 0
      evmcc/test/stack/stack_test.lll
  49. 0
      evmcc/test/stack/stackjump.evm
  50. 0
      evmcc/test/stack/stackjump.lll
  51. 7
      libdevcore/CMakeLists.txt
  52. 2
      libdevcore/Common.cpp
  53. 42
      libdevcore/Common.h
  54. 27
      libdevcore/RangeMask.h
  55. 121
      libdevcore/debugbreak.h
  56. 8
      libdevcrypto/CMakeLists.txt
  57. 3
      libdevcrypto/Common.cpp
  58. 2
      libdevcrypto/MemoryDB.h
  59. 4
      libdevcrypto/TrieDB.h
  60. 2
      libethcore/All.h
  61. 4
      libethcore/BlockInfo.cpp
  62. 8
      libethcore/CMakeLists.txt
  63. 4
      libethcore/CommonEth.cpp
  64. 84
      libethcore/Dagger.h
  65. 17
      libethcore/Exceptions.cpp
  66. 2
      libethcore/Exceptions.h
  67. 97
      libethcore/ProofOfWork.cpp
  68. 117
      libethcore/ProofOfWork.h
  69. 2
      libethcore/_libethcore.cpp
  70. 23
      libethereum/BlockChain.cpp
  71. 8
      libethereum/CMakeLists.txt
  72. 37
      libethereum/Client.cpp
  73. 1
      libethereum/Client.h
  74. 30
      libethereum/EthereumHost.cpp
  75. 6
      libethereum/EthereumHost.h
  76. 18
      libethereum/EthereumPeer.cpp
  77. 16
      libethereum/Executive.cpp
  78. 11
      libethereum/ExtVM.h
  79. 2
      libethereum/Interface.h
  80. 14
      libethereum/State.cpp
  81. 10
      libethereum/State.h
  82. 8
      libevm/CMakeLists.txt
  83. 5
      libevm/ExtVMFace.cpp
  84. 3
      libevm/ExtVMFace.h
  85. 174
      libevm/FeeStructure.cpp
  86. 34
      libevm/FeeStructure.h
  87. 44
      libevm/VM.h
  88. 8
      libevmface/CMakeLists.txt
  89. 0
      libevmjit/BasicBlock.cpp
  90. 0
      libevmjit/BasicBlock.h
  91. 47
      libevmjit/Compiler.cpp
  92. 8
      libevmjit/Compiler.h
  93. 0
      libevmjit/CompilerHelper.cpp
  94. 0
      libevmjit/CompilerHelper.h
  95. 44
      libevmjit/ExecutionEngine.cpp
  96. 5
      libevmjit/ExecutionEngine.h
  97. 2
      libevmjit/Ext.cpp
  98. 0
      libevmjit/Ext.h
  99. 32
      libevmjit/GasMeter.cpp
  100. 0
      libevmjit/GasMeter.h

353
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)

6
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

5
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)

2
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);

34
alethzero/Main.ui

@ -1480,6 +1480,40 @@ font-size: 14pt</string>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_13">
<property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set>
</property>
<property name="windowTitle">
<string>Nodes</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_13">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="nodes">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="quit">
<property name="text">
<string>&amp;Quit</string>

71
alethzero/MainWin.cpp

@ -33,7 +33,6 @@
#include <libserpent/funcs.h>
#include <libserpent/util.h>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Dagger.h>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#include <libevm/VM.h>
@ -207,6 +206,12 @@ unsigned Main::installWatch(dev::h256 _tf, std::function<void()> 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<chrono::milliseconds>(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<h512, QString> 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<chrono::milliseconds>(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 << "<br/>Bloom: <b>" << details.bloom << "</b>";
s << "<br/>Transactions: <b>" << block[1].itemCount() << "</b> @<b>" << info.transactionsRoot << "</b>";
s << "<br/>Uncles: <b>" << block[2].itemCount() << "</b> @<b>" << info.sha3Uncles << "</b>";
s << "<br/>Pre: <b>" << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << "</b>";
if (info.parentHash)
s << "<br/>Pre: <b>" << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << "</b>";
else
s << "<br/>Pre: <i>Nothing is before the Gensesis</i>";
for (auto const& i: block[1])
s << "<br/>" << sha3(i[0].data()).abridged() << ": <b>" << i[1].toHash<h256>() << "</b> [<b>" << i[2].toInt<u256>() << "</b> used]";
s << "<br/>Post: <b>" << info.stateRoot << "</b>";
@ -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);

1
alethzero/MainWin.h

@ -183,6 +183,7 @@ private:
unsigned installWatch(dev::eth::MessageFilter const& _tf, std::function<void()> const& _f);
unsigned installWatch(dev::h256 _tf, std::function<void()> const& _f);
void uninstallWatch(unsigned _w);
void keysChanged();

59
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()

208
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()

3
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)

100
eth/main.cpp

@ -24,6 +24,7 @@
#include <chrono>
#include <fstream>
#include <iostream>
#include <signal.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp>
#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;
}

1
evmcc/bytecode/if1.evm

@ -1 +0,0 @@
600160805460006080530b6016596003608054601b586002608054

12
evmcc/evmcc.cpp

@ -12,9 +12,8 @@
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <libevmface/Instruction.h>
#include "Compiler.h"
#include "ExecutionEngine.h"
#include <libevmjit/Compiler.h>
#include <libevmjit/ExecutionEngine.h>
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;
}

21
evmcc/lll/if1.asm

@ -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:

5
evmcc/lll/if1.lll

@ -1,5 +0,0 @@
{
[i] 1
( if (> @i 0) [i] 2 [i] 3 )
}

0
evmcc/bytecode/arithmetic_test.evm → evmcc/test/arith/arith1.evm

0
evmcc/lll/arithmetic_test.lll → evmcc/test/arith/arith1.lll

0
evmcc/bytecode/fib1.evm → evmcc/test/arith/fib1.evm

0
evmcc/lll/fib1.lll → evmcc/test/arith/fib1.lll

0
evmcc/bytecode/ext_test.evm → evmcc/test/ext/ext_test.evm

0
evmcc/lll/ext_test.lll → evmcc/test/ext/ext_test.lll

0
evmcc/bytecode/store_test.evm → evmcc/test/ext/store_test.evm

0
evmcc/lll/store_test.lll → evmcc/test/ext/store_test.lll

0
evmcc/bytecode/for1.evm → evmcc/test/jump/for1.evm

0
evmcc/lll/for1.lll → evmcc/test/jump/for1.lll

0
evmcc/bytecode/for2.evm → evmcc/test/jump/for2.evm

0
evmcc/lll/for2.lll → evmcc/test/jump/for2.lll

0
evmcc/lll/when1.asm → evmcc/test/jump/when1.asm

0
evmcc/bytecode/when1.evm → evmcc/test/jump/when1.evm

0
evmcc/lll/when1.lll → evmcc/test/jump/when1.lll

0
evmcc/bytecode/kv.evm → evmcc/test/kv.evm

0
evmcc/lll/kv.lll → evmcc/test/kv.lll

0
evmcc/bytecode/byte.evm → evmcc/test/mem/byte.evm

0
evmcc/lll/byte.lll → evmcc/test/mem/byte.lll

0
evmcc/bytecode/mem2.evm → evmcc/test/mem/mem2.evm

0
evmcc/lll/mem2.lll → evmcc/test/mem/mem2.lll

0
evmcc/bytecode/memtest1.evm → evmcc/test/mem/memtest1.evm

0
evmcc/lll/memtest1.lll → evmcc/test/mem/memtest1.lll

0
evmcc/bytecode/return1.evm → evmcc/test/ret/return1.evm

0
evmcc/lll/return1.lll → evmcc/test/ret/return1.lll

0
evmcc/bytecode/return2.evm → evmcc/test/ret/return2.evm

0
evmcc/lll/return2.lll → evmcc/test/ret/return2.lll

0
evmcc/bytecode/return_test.evm → evmcc/test/ret/return_test.evm

0
evmcc/lll/return_test.lll → evmcc/test/ret/return_test.lll

0
evmcc/bytecode/push_test.evm → evmcc/test/stack/push_test.evm

0
evmcc/lll/push_test.lll → evmcc/test/stack/push_test.lll

0
evmcc/bytecode/stack_test.evm → evmcc/test/stack/stack_test.evm

0
evmcc/lll/stack_test.lll → evmcc/test/stack/stack_test.lll

0
evmcc/bytecode/stackjump.evm → evmcc/test/stack/stackjump.evm

0
evmcc/lll/stackjump.lll → evmcc/test/stack/stackjump.lll

7
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(..)

2
libdevcore/Common.cpp

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

42
libdevcore/Common.h

@ -38,6 +38,7 @@
#include <set>
#include <boost/multiprecision/cpp_int.hpp>
#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<class A, class B>
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;
}
}

27
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 <class S> RangeMask operator-(S const& _m) const { auto ret = *this; return ret -= _m; }
template <class S> 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<T, T> 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
{

121
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 <signal.h>
#include <unistd.h>
#include <sys/syscall.h>
#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

8
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)

3
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);

2
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)

4
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 <class DB> void GenericTrieDB<DB>::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)

2
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"

4
libethcore/BlockInfo.cpp

@ -24,7 +24,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#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)

8
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)

4
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<pair<u256, string>> g_units =
{

84
libethcore/Dagger.h

@ -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 <http://www.gnu.org/licenses/>.
*/
/** @file Dagger.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*
* Dagger algorithm. Or not.
*/
#pragma once
#include <libdevcrypto/SHA3.h>
#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
}
}

17
libethcore/Exceptions.cpp

@ -22,14 +22,17 @@
#include "Exceptions.h"
#include <libdevcore/CommonIO.h>
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) + ")"); }

2
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; };

97
libethcore/Dagger.cpp → 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 <http://www.gnu.org/licenses/>.
*/
/** @file Dagger.cpp
/** @file ProofOfWork.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
@ -28,7 +28,7 @@
#include <thread>
#include <libethcore/CryptoHeaders.h>
#include <libdevcore/Common.h>
#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<double>(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 <class _T>
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 <class _T>
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 <class _T>
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

117
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 <http://www.gnu.org/licenses/>.
*/
/** @file ProofOfWork.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*
* ProofOfWork algorithm. Or not.
*/
#pragma once
#include <chrono>
#include <thread>
#include <cstdint>
#include <libdevcrypto/SHA3.h>
#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 Evaluator>
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<SHA3Evaluator>;
using ProofOfWork = SHA3ProofOfWork;
template <class Evaluator>
MineInfo ProofOfWorkEngine<Evaluator>::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<double>(ret.best, log2((double)e));
if (e <= d)
{
ret.completed = true;
break;
}
}
if (ret.completed)
assert(verify(_root, o_solution, _difficulty));
return ret;
}
}
}

2
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

23
libethereum/BlockChain.cpp

@ -26,7 +26,7 @@
#include <libdevcore/RLP.h>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Exceptions.h>
#include <libethcore/Dagger.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h>
#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;

8
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)

37
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;
}

1
libethereum/Client.h

@ -31,7 +31,6 @@
#include <libdevcore/Guards.h>
#include <libdevcore/Worker.h>
#include <libevm/FeeStructure.h>
#include <libethcore/Dagger.h>
#include <libp2p/Common.h>
#include "BlockChain.h"
#include "TransactionQueue.h"

30
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<EthereumPeer>())
@ -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<EthereumPeer>();
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))

6
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<h512> m_banned;
std::set<p2p::NodeId> m_banned;
};
}

18
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;
}

16
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<VMTraceChannel, false>(true) << o.str();
dev::LogOutputStream<VMTraceChannel, false>(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<VMTraceChannel, false>(false) << " | " << dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << dec << vm.gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32" << " ]";
};
}

11
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<Address, AddressState> m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution.

2
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;

14
libethereum/State.cpp

@ -28,7 +28,6 @@
#include <libdevcore/CommonIO.h>
#include <libevmface/Instruction.h>
#include <libethcore/Exceptions.h>
#include <libethcore/Dagger.h>
#include <libevm/VM.h>
#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<int>(12, _out.size()));
if (_out.size() > 12)
memcpy(_out.data() + 12, &ret, min(_out.size() - 12, sizeof(ret)));
}
const std::map<unsigned, PrecompiledAddress> 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<h256>() != 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<u256, u256> mem;
std::set<u256> back;

10
libethereum/State.h

@ -29,7 +29,7 @@
#include <libdevcrypto/TrieDB.h>
#include <libethcore/Exceptions.h>
#include <libethcore/BlockInfo.h>
#include <libethcore/Dagger.h>
#include <libethcore/ProofOfWork.h>
#include <libevm/FeeStructure.h>
#include <libevm/ExtVMFace.h>
#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;

8
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)

5
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)
{}

3
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<Address> suicides; ///< Any accounts that have suicided.
unsigned depth; ///< Depth of the present call.
};
}

174
libevm/FeeStructure.cpp

@ -16,22 +16,168 @@
*/
/** @file FeeStructure.cpp
* @author Gav Wood <i@gavwood.com>
* @author Pawel Bylica <chfast@gmail.com>
* @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 <libevmface/Instruction.h>
#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;
}
}
}
}

34
libevm/FeeStructure.h

@ -16,28 +16,40 @@
*/
/** @file FeeStructure.h
* @author Gav Wood <i@gavwood.com>
* @author Pawel Bylica <chfast@gmail.com>
* @date 2014
*/
#pragma once
#include <libdevcore/Common.h>
#include <cstdint>
#include <boost/config.hpp>
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);
};
}
}

44
libevm/VM.h

@ -101,30 +101,17 @@ template <class Ext> 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 <class Ext> 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 <class Ext> 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 <class Ext> 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 <class Ext> 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 <class Ext> 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 <class Ext> 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 <class Ext> 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 <class Ext> 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)

8
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)

0
evmcc/BasicBlock.cpp → libevmjit/BasicBlock.cpp

0
evmcc/BasicBlock.h → libevmjit/BasicBlock.h

47
evmcc/Compiler.cpp → 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<ProgramCounter> 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<ProgramCounter> 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<Instruction>(*curr);
@ -51,7 +51,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
{
auto numBytes = static_cast<size_t>(inst) - static_cast<size_t>(Instruction::PUSH1) + 1;
auto next = curr + numBytes + 1;
if (next >= bytecode.cend())
if (next >= bytecode.end())
break;
auto nextInst = static_cast<Instruction>(*next);
@ -67,12 +67,10 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
}
// Create a block for the JUMP target.
ProgramCounter targetPC = val.convert_to<ProgramCounter>();
if (targetPC > bytecode.size())
targetPC = bytecode.size();
ProgramCounter targetPC = val < bytecode.size() ? val.convert_to<ProgramCounter>() : 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<llvm::Module> Compiler::compile(const bytes& bytecode)
std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef bytecode)
{
auto module = std::make_unique<llvm::Module>("main", m_builder.getContext());
@ -214,7 +219,7 @@ std::unique_ptr<llvm::Module> 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)

8
evmcc/Compiler.h → libevmjit/Compiler.h

@ -22,16 +22,16 @@ public:
Compiler();
std::unique_ptr<llvm::Module> compile(const bytes& bytecode);
std::unique_ptr<llvm::Module> 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<ProgramCounter, BasicBlock*> m_directJumpTargets;
std::map<ProgramCounter, llvm::BasicBlock*> m_directJumpTargets;
/**
* A list of possible blocks to which there may be indirect jumps.

0
evmcc/CompilerHelper.cpp → libevmjit/CompilerHelper.cpp

0
evmcc/CompilerHelper.h → libevmjit/CompilerHelper.h

44
evmcc/ExecutionEngine.cpp → libevmjit/ExecutionEngine.cpp

@ -36,7 +36,7 @@ ExecutionEngine::ExecutionEngine()
extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; }
int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
int ExecutionEngine::run(std::unique_ptr<llvm::Module> _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<llvm::Module> _module)
exec->finalizeObject();
// Create fake ExtVM interface
auto ext = std::make_unique<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);
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<llvm::Module> _module)
else
returnCode = static_cast<ReturnCode>(r);
gas = static_cast<decltype(gas)>(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)

5
evmcc/ExecutionEngine.h → libevmjit/ExecutionEngine.h

@ -4,6 +4,7 @@
#include <llvm/IR/Module.h>
#include <libdevcore/Common.h>
#include <libevm/ExtVMFace.h>
namespace dev
{
@ -17,7 +18,9 @@ class ExecutionEngine
public:
ExecutionEngine();
int run(std::unique_ptr<llvm::Module> module);
int run(std::unique_ptr<llvm::Module> module, u256& _gas, ExtVMFace* _ext = nullptr);
bytes returnData;
};
}

2
evmcc/Ext.cpp → 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;

0
evmcc/Ext.h → libevmjit/Ext.h

32
evmcc/GasMeter.cpp → 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<uint64_t>(c_sstoreGas);
return static_cast<uint64_t>(FeeStructure::c_sstoreGas);
case Instruction::SLOAD:
return static_cast<uint64_t>(c_sloadGas);
return static_cast<uint64_t>(FeeStructure::c_sloadGas);
case Instruction::SHA3:
return static_cast<uint64_t>(c_sha3Gas);
return static_cast<uint64_t>(FeeStructure::c_sha3Gas);
case Instruction::BALANCE:
return static_cast<uint64_t>(c_sha3Gas);
return static_cast<uint64_t>(FeeStructure::c_sha3Gas);
case Instruction::CALL:
case Instruction::CALLCODE:
return static_cast<uint64_t>(c_callGas);
return static_cast<uint64_t>(FeeStructure::c_callGas);
case Instruction::CREATE:
return static_cast<uint64_t>(c_createGas);
return static_cast<uint64_t>(FeeStructure::c_createGas);
default: // Assumes instruction code is valid
return static_cast<uint64_t>(c_stepGas);
return static_cast<uint64_t>(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<uint64_t>(c_sstoreGas);
static const auto sstoreCost = static_cast<uint64_t>(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<uint64_t>(c_memoryGas)), "memcost");
auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast<uint64_t>(FeeStructure::c_memoryGas)), "memcost");
_builder.CreateCall(m_gasCheckFunc, cost);
}

0
evmcc/GasMeter.h → libevmjit/GasMeter.h

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

Loading…
Cancel
Save