Browse Source

Merge branch 'develop' into mk_jsonrpc

cl-refactor
Marek Kotewicz 10 years ago
parent
commit
4ad6113eb4
  1. 368
      CMakeLists.txt
  2. 6
      README.md
  3. 34
      alethzero/Main.ui
  4. 40
      alethzero/MainWin.cpp
  5. 59
      cmake/EthCompilerSettings.cmake
  6. 208
      cmake/EthDependenciesDeprecated.cmake
  7. 93
      eth/main.cpp
  8. 2
      libdevcore/Common.cpp
  9. 2
      libdevcrypto/MemoryDB.h
  10. 2
      libdevcrypto/TrieDB.h
  11. 2
      libethcore/All.h
  12. 4
      libethcore/BlockInfo.cpp
  13. 4
      libethcore/CommonEth.cpp
  14. 84
      libethcore/Dagger.h
  15. 97
      libethcore/ProofOfWork.cpp
  16. 117
      libethcore/ProofOfWork.h
  17. 2
      libethcore/_libethcore.cpp
  18. 7
      libethereum/BlockChain.cpp
  19. 37
      libethereum/Client.cpp
  20. 1
      libethereum/Client.h
  21. 10
      libethereum/EthereumHost.cpp
  22. 12
      libethereum/State.cpp
  23. 4
      libethereum/State.h
  24. 112
      libevm/VM.h
  25. 8
      libp2p/Capability.cpp
  26. 2
      libp2p/Capability.h
  27. 5
      libp2p/Common.cpp
  28. 20
      libp2p/Common.h
  29. 131
      libp2p/Host.cpp
  30. 33
      libp2p/Host.h
  31. 251
      libp2p/Session.cpp
  32. 57
      libp2p/Session.h
  33. 3
      libqethereum/QEthereum.cpp
  34. 1
      libqethereum/QmlEthereum.cpp
  35. 5
      libwebthree/WebThree.h
  36. 14
      test/dagger.cpp
  37. 1
      third/MainWin.cpp

368
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)
add_definitions(-DETH_LANGUAGES)
endif ()
# propagates CMake configuration options to the compiler
function(configureProject)
if (LANGUAGES)
add_definitions(-DETH_LANGUAGES)
endif ()
if (PARANOIA)
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_definitions(-DETH_PARANOIA)
else ()
message(FATAL_ERROR "Paranoia requires debug.")
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 ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_definitions(-DETH_VMTRACE)
if (VMTRACE)
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_definitions(-DETH_VMTRACE)
else ()
message(FATAL_ERROR "VM tracing requires debug.")
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 ()
message(FATAL_ERROR "VM tracing requires debug.")
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/unknown")
endif ()
endif ()
message("LANGUAGES: ${LANGUAGES}; VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}")
# 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}")
# 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 ()
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()
include(EthDependenciesDeprecated)
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(JSONRPC_LS)
@ -377,8 +159,6 @@ if (NOT LANGUAGES)
endif()
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

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>

40
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>
@ -751,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()
@ -948,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)
@ -1712,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);

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

93
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;
@ -615,46 +630,47 @@ int main(int argc, char** argv)
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 << 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);
}
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->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);
}
}
else if (c && cmd == "inspect")
@ -764,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();
@ -772,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;
}

2
libdevcore/Common.cpp

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

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)

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

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)

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

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

7
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"
@ -429,7 +429,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)

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"

10
libethereum/EthereumHost.cpp

@ -189,20 +189,14 @@ 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)
{
// 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))

12
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"
@ -837,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();
@ -1054,14 +1053,7 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit)
Manifest ms;
Executive e(*this, &ms);
try
{
e.setup(_rlp);
}
catch (Exception const & _e)
{
cwarn << diagnostic_information(_e);
}
e.setup(_rlp);
u256 startGasUsed = gasUsed();

4
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"
@ -322,7 +322,7 @@ private:
Address m_ourAddress; ///< Our address (i.e. the address to which fees go).
Dagger m_dagger;
ProofOfWork m_pow;
u256 m_blockReward;

112
libevm/VM.h

@ -188,8 +188,116 @@ template <class Ext> dev::bytesConstRef dev::eth::VM::go(Ext& _ext, OnOpFunc con
break;
}
default:
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:
break;
default:
BOOST_THROW_EXCEPTION(BadInstruction());
}
newTempSize = (newTempSize + 31) / 32 * 32;
@ -669,8 +777,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
libp2p/Capability.cpp

@ -53,14 +53,14 @@ void Capability::sealAndSend(RLPStream& _s)
m_session->sealAndSend(_s);
}
void Capability::sendDestroy(bytes& _msg)
void Capability::send(bytesConstRef _msg)
{
m_session->sendDestroy(_msg);
m_session->send(_msg);
}
void Capability::send(bytesConstRef _msg)
void Capability::send(bytes&& _msg)
{
m_session->send(_msg);
m_session->send(move(_msg));
}
void Capability::addRating(unsigned _r)

2
libp2p/Capability.h

@ -52,7 +52,7 @@ protected:
RLPStream& prep(RLPStream& _s, unsigned _id, unsigned _args = 0);
void sealAndSend(RLPStream& _s);
void sendDestroy(bytes& _msg);
void send(bytes&& _msg);
void send(bytesConstRef _msg);
void addRating(unsigned _r);

5
libp2p/Common.cpp

@ -64,7 +64,12 @@ std::string p2p::reasonOf(DisconnectReason _r)
case TooManyPeers: return "Peer had too many connections.";
case DuplicatePeer: return "Peer was already connected.";
case IncompatibleProtocol: return "Peer protocol versions are incompatible.";
case NullIdentity: return "Null identity given.";
case ClientQuit: return "Peer is exiting.";
case UnexpectedIdentity: return "Unexpected identity given.";
case LocalIdentity: return "Connected to ourselves.";
case UserReason: return "Subprotocol reason.";
case NoDisconnect: return "(No disconnect has happened.)";
default: return "Unknown reason.";
}
}

20
libp2p/Common.h

@ -87,9 +87,27 @@ enum DisconnectReason
NullIdentity,
ClientQuit,
UnexpectedIdentity,
UserReason = 0x10
LocalIdentity,
PingTimeout,
UserReason = 0x10,
NoDisconnect = 0xffff
};
inline bool isPermanentProblem(DisconnectReason _r)
{
switch (_r)
{
case DuplicatePeer:
case IncompatibleProtocol:
case NullIdentity:
case UnexpectedIdentity:
case LocalIdentity:
return true;
default:
return false;
}
}
/// @returns the string form of the given disconnection reason.
std::string reasonOf(DisconnectReason _r);

131
libp2p/Host.cpp

@ -66,7 +66,6 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bool
m_key(KeyPair::create())
{
populateAddresses();
m_lastPeersRequest = chrono::steady_clock::time_point::min();
clog(NetNote) << "Id:" << id().abridged();
if (_start)
start();
@ -112,7 +111,6 @@ void Host::start()
if (!m_public.address().is_unspecified() && (m_nodes.empty() || m_nodes[m_nodesList[0]]->id != id()))
noteNode(id(), m_public, Origin::Perfect, false);
m_lastPeersRequest = chrono::steady_clock::time_point::min();
clog(NetNote) << "Id:" << id().abridged();
for (auto const& h: m_capabilities)
@ -144,7 +142,7 @@ void Host::stop()
unsigned Host::protocolVersion() const
{
return 1;
return 2;
}
void Host::registerPeer(std::shared_ptr<Session> _s, CapDescs const& _caps)
@ -345,31 +343,46 @@ void Host::populateAddresses()
#endif
}
shared_ptr<Node> Host::noteNode(NodeId _id, bi::tcp::endpoint const& _a, Origin _o, bool _ready, NodeId _oldId)
shared_ptr<Node> Host::noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId)
{
RecursiveGuard l(x_peers);
if (_a.port() < 30300 && _a.port() > 30303)
cwarn << "Wierd port being recorded!";
if (_a.port() >= 49152)
{
cwarn << "Private port being recorded - setting to 0";
_a = bi::tcp::endpoint(_a.address(), 0);
}
cnote << "Node:" << _id.abridged() << _a << (_ready ? "ready" : "used") << _oldId.abridged() << (m_nodes.count(_id) ? "[have]" : "[NEW]");
// First check for another node with the same connection credentials, and put it in oldId if found.
if (!_oldId)
for (pair<h512, shared_ptr<Node>> const& n: m_nodes)
if (n.second->address == _a && n.second->id != _id)
{
_oldId = n.second->id;
break;
}
unsigned i;
if (!m_nodes.count(_id))
{
shared_ptr<Node> old;
if (m_nodes.count(_oldId))
{
old = m_nodes[_oldId];
i = old->index;
i = m_nodes[_oldId]->index;
m_nodes.erase(_oldId);
m_nodesList[i] = _id;
m_nodes[id()] = make_shared<Node>();
}
else
{
i = m_nodesList.size();
m_nodesList.push_back(_id);
m_nodes[_id] = make_shared<Node>();
}
m_nodes[_id]->address = m_public;
m_nodes[_id]->index = i;
m_nodes[_id] = make_shared<Node>();
m_nodes[_id]->id = _id;
m_nodes[_id]->index = i;
m_nodes[_id]->idOrigin = _o;
}
else
@ -377,6 +390,7 @@ shared_ptr<Node> Host::noteNode(NodeId _id, bi::tcp::endpoint const& _a, Origin
i = m_nodes[_id]->index;
m_nodes[_id]->idOrigin = max(m_nodes[_id]->idOrigin, _o);
}
m_nodes[_id]->address = _a;
m_ready.extendAll(i);
m_private.extendAll(i);
if (_ready)
@ -390,6 +404,8 @@ shared_ptr<Node> Host::noteNode(NodeId _id, bi::tcp::endpoint const& _a, Origin
cnote << m_nodes[_id]->index << ":" << m_ready;
m_hadNewNodes = true;
return m_nodes[_id];
}
@ -398,7 +414,8 @@ Nodes Host::potentialPeers(RangeMask<unsigned> const& _known)
RecursiveGuard l(x_peers);
Nodes ret;
for (auto i: m_ready - (m_private + _known))
auto ns = (m_netPrefs.localNetworking ? _known : (m_private + _known)).inverted();
for (auto i: ns)
ret.push_back(*m_nodes[m_nodesList[i]]);
return ret;
}
@ -494,7 +511,9 @@ void Host::connect(bi::tcp::endpoint const& _ep)
void Node::connect(Host* _h)
{
clog(NetConnect) << "Attempting connection to node" << id.abridged() << "@" << address;
clog(NetConnect) << "Attempting connection to node" << id.abridged() << "@" << address << "from" << _h->id().abridged();
lastAttempted = std::chrono::system_clock::now();
failedAttempts++;
_h->m_ready -= index;
bi::tcp::socket* s = new bi::tcp::socket(_h->m_ioService);
s->async_connect(address, [=](boost::system::error_code const& ec)
@ -502,14 +521,13 @@ void Node::connect(Host* _h)
if (ec)
{
clog(NetConnect) << "Connection refused to node" << id.abridged() << "@" << address << "(" << ec.message() << ")";
failedAttempts++;
lastDisconnect = TCPError;
lastAttempted = std::chrono::system_clock::now();
_h->m_ready += index;
}
else
{
clog(NetConnect) << "Connected to" << id.abridged() << "@" << address;
failedAttempts = 0;
lastConnected = std::chrono::system_clock::now();
auto p = make_shared<Session>(_h, std::move(*s), _h->node(id), true); // true because we don't care about ids matched for now. Once we have permenant IDs this will matter a lot more and we can institute a safer mechanism.
p->start();
@ -532,14 +550,31 @@ bool Host::havePeer(NodeId _id) const
return !!m_peers.count(_id);
}
unsigned cumulativeFallback(unsigned _failed)
unsigned Node::fallbackSeconds() const
{
if (_failed < 5)
return _failed * 5;
else if (_failed < 15)
return 25 + (_failed - 5) * 10;
else
return 25 + 100 + (_failed - 15) * 20;
switch (lastDisconnect)
{
case BadProtocol:
return 30 * (failedAttempts + 1);
case UselessPeer:
case TooManyPeers:
case ClientQuit:
return 15 * (failedAttempts + 1);
case NoDisconnect:
return 0;
default:
if (failedAttempts < 5)
return failedAttempts * 5;
else if (failedAttempts < 15)
return 25 + (failedAttempts - 5) * 10;
else
return 25 + 100 + (failedAttempts - 15) * 20;
}
}
bool Node::shouldReconnect() const
{
return chrono::system_clock::now() > lastAttempted + chrono::seconds(fallbackSeconds());
}
void Host::growPeers()
@ -553,7 +588,7 @@ void Host::growPeers()
toTry -= m_private;
set<Node> ns;
for (auto i: toTry)
if (chrono::system_clock::now() > m_nodes[m_nodesList[i]]->lastAttempted + chrono::seconds(cumulativeFallback(m_nodes[m_nodesList[i]]->failedAttempts)))
if (m_nodes[m_nodesList[i]]->shouldReconnect())
ns.insert(*m_nodes[m_nodesList[i]]);
if (ns.size())
@ -566,25 +601,13 @@ void Host::growPeers()
else
{
ensureAccepting();
if (chrono::steady_clock::now() > m_lastPeersRequest + chrono::seconds(10))
requestPeers();
for (auto const& i: m_peers)
if (auto p = i.second.lock())
p->ensureNodesRequested();
}
}
}
void Host::requestPeers()
{
RLPStream s;
bytes b;
Session::prep(s, GetPeersPacket).swapOut(b);
seal(b);
for (auto const& i: m_peers)
if (auto p = i.second.lock())
if (p->isOpen())
p->send(&b);
m_lastPeersRequest = chrono::steady_clock::now();
}
void Host::prunePeers()
{
RecursiveGuard l(x_peers);
@ -637,6 +660,25 @@ void Host::doWork()
{
growPeers();
prunePeers();
if (m_hadNewNodes)
{
for (auto p: m_peers)
if (auto pp = p.second.lock())
pp->serviceNodesRequest();
m_hadNewNodes = false;
}
if (chrono::steady_clock::now() - m_lastPing > chrono::seconds(30)) // ping every 30s.
{
for (auto p: m_peers)
if (auto pp = p.second.lock())
if (chrono::steady_clock::now() - pp->m_lastReceived > chrono::seconds(60))
pp->disconnect(PingTimeout);
pingAll();
}
m_ioService.poll();
}
@ -646,6 +688,7 @@ void Host::pingAll()
for (auto& i: m_peers)
if (auto j = i.second.lock())
j->ping();
m_lastPing = chrono::steady_clock::now();
}
bytes Host::saveNodes() const
@ -657,7 +700,8 @@ bytes Host::saveNodes() const
for (auto const& i: m_nodes)
{
Node const& n = *(i.second);
if (n.id != id() && !isPrivateAddress(n.address.address()))
// TODO: PoC-7: Figure out why it ever shares these ports.//n.address.port() >= 30300 && n.address.port() <= 30305 &&
if (!n.dead && n.address.port() > 0 && n.address.port() < 49152 && n.id != id() && !isPrivateAddress(n.address.address()))
{
nodes.appendList(10);
if (n.address.address().is_v4())
@ -667,7 +711,7 @@ bytes Host::saveNodes() const
nodes << n.address.port() << n.id << (int)n.idOrigin
<< std::chrono::duration_cast<std::chrono::seconds>(n.lastConnected.time_since_epoch()).count()
<< std::chrono::duration_cast<std::chrono::seconds>(n.lastAttempted.time_since_epoch()).count()
<< n.failedAttempts << n.lastDisconnect << n.score << n.rating;
<< n.failedAttempts << (unsigned)n.lastDisconnect << n.score << n.rating;
count++;
}
}
@ -686,7 +730,11 @@ void Host::restoreNodes(bytesConstRef _b)
switch (r[0].toInt<int>())
{
case 0:
{
auto oldId = id();
m_key = KeyPair(r[1].toHash<Secret>());
noteNode(id(), m_public, Origin::Perfect, false, oldId);
for (auto i: r[2])
{
bi::tcp::endpoint ep;
@ -702,11 +750,12 @@ void Host::restoreNodes(bytesConstRef _b)
n->lastConnected = chrono::system_clock::time_point(chrono::seconds(i[4].toInt<unsigned>()));
n->lastAttempted = chrono::system_clock::time_point(chrono::seconds(i[5].toInt<unsigned>()));
n->failedAttempts = i[6].toInt<unsigned>();
n->lastDisconnect = (int)i[7].toInt<unsigned>();
n->lastDisconnect = (DisconnectReason)i[7].toInt<unsigned>();
n->score = (int)i[8].toInt<unsigned>();
n->rating = (int)i[9].toInt<unsigned>();
}
}
}
default:;
}
else

33
libp2p/Host.h

@ -64,19 +64,26 @@ struct Node
bi::tcp::endpoint address; ///< As reported from the node itself.
int score = 0; ///< All time cumulative.
int rating = 0; ///< Trending.
bool dead = false; ///< If true, we believe this node is permanently dead - forget all about it.
std::chrono::system_clock::time_point lastConnected;
std::chrono::system_clock::time_point lastAttempted;
unsigned failedAttempts = 0;
int lastDisconnect = -1; ///< Reason for disconnect that happened last.
DisconnectReason lastDisconnect = NoDisconnect; ///< Reason for disconnect that happened last.
Origin idOrigin = Origin::Unknown; ///< Thirdparty
Origin idOrigin = Origin::Unknown; ///< How did we get to know this node's id?
bool offline() const { return lastDisconnect == -1 || lastAttempted > lastConnected; }
int secondsSinceLastConnected() const { return lastConnected == std::chrono::system_clock::time_point() ? -1 : (int)std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - lastConnected).count(); }
int secondsSinceLastAttempted() const { return lastAttempted == std::chrono::system_clock::time_point() ? -1 : (int)std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - lastAttempted).count(); }
unsigned fallbackSeconds() const;
bool shouldReconnect() const;
bool isOffline() const { return lastAttempted > lastConnected; }
bool operator<(Node const& _n) const
{
if (offline() != _n.offline())
return offline();
else if (offline())
if (isOffline() != _n.isOffline())
return isOffline();
else if (isOffline())
if (lastAttempted == _n.lastAttempted)
return failedAttempts < _n.failedAttempts;
else
@ -114,7 +121,7 @@ class Host: public Worker
{
friend class Session;
friend class HostCapabilityFace;
friend class Node;
friend struct Node;
public:
/// Start server, listening for connections on the given port.
@ -165,6 +172,8 @@ public:
/// Deserialise the data and populate the set of known peers.
void restoreNodes(bytesConstRef _b);
Nodes nodes() const { RecursiveGuard l(x_peers); Nodes ret; for (auto const& i: m_nodes) ret.push_back(*i.second); return ret; }
void setNetworkPreferences(NetworkPreferences const& _p) { stop(); m_netPrefs = _p; start(); }
void start();
@ -191,11 +200,9 @@ private:
/// This won't touch alter the blockchain.
virtual void doWork();
std::shared_ptr<Node> noteNode(NodeId _id, bi::tcp::endpoint const& _a, Origin _o, bool _ready, NodeId _oldId = h256());
std::shared_ptr<Node> noteNode(NodeId _id, bi::tcp::endpoint _a, Origin _o, bool _ready, NodeId _oldId = h256());
Nodes potentialPeers(RangeMask<unsigned> const& _known);
void requestPeers();
std::string m_clientVersion; ///< Our version string.
NetworkPreferences m_netPrefs; ///< Network settings.
@ -211,6 +218,8 @@ private:
bi::tcp::endpoint m_public; ///< Our public listening endpoint.
KeyPair m_key; ///< Our unique ID.
bool m_hadNewNodes = false;
mutable RecursiveMutex x_peers;
/// The nodes to which we are currently connected.
@ -227,8 +236,6 @@ private:
RangeMask<unsigned> m_ready; ///< Indices into m_nodesList over to which nodes we are not currently connected, connecting or otherwise ignoring.
RangeMask<unsigned> m_private; ///< Indices into m_nodesList over to which nodes are private.
std::chrono::steady_clock::time_point m_lastPeersRequest; ///< Last time we asked for some peers - don't want to do this too often. TODO: peers should be pushed, not polled.
unsigned m_idealPeerCount = 5; ///< Ideal number of peers to be connected to.
// Our addresses.
@ -238,6 +245,8 @@ private:
// Our capabilities.
std::map<CapDesc, std::shared_ptr<HostCapabilityFace>> m_capabilities; ///< Each of the capabilities we support.
std::chrono::steady_clock::time_point m_lastPing; ///< Time we sent the last ping to all peers.
bool m_accepting = false;
};

251
libp2p/Session.cpp

@ -40,12 +40,11 @@ Session::Session(Host* _s, bi::tcp::socket _socket, bi::tcp::endpoint const& _ma
m_server(_s),
m_socket(std::move(_socket)),
m_node(nullptr),
m_manualEndpoint(_manual)
m_manualEndpoint(_manual) // NOTE: the port on this shouldn't be used if it's zero.
{
m_disconnect = std::chrono::steady_clock::time_point::max();
m_connect = std::chrono::steady_clock::now();
m_lastReceived = m_connect = std::chrono::steady_clock::now();
m_info = PeerInfo({NodeId(), "?", m_manualEndpoint.address().to_string(), m_manualEndpoint.port(), std::chrono::steady_clock::duration(0), CapDescSet(), 0, map<string, string>()});
m_info = PeerInfo({NodeId(), "?", m_manualEndpoint.address().to_string(), 0, std::chrono::steady_clock::duration(0), CapDescSet(), 0, map<string, string>()});
}
Session::Session(Host* _s, bi::tcp::socket _socket, std::shared_ptr<Node> const& _n, bool _force):
@ -55,15 +54,19 @@ Session::Session(Host* _s, bi::tcp::socket _socket, std::shared_ptr<Node> const&
m_manualEndpoint(_n->address),
m_force(_force)
{
m_disconnect = std::chrono::steady_clock::time_point::max();
m_connect = std::chrono::steady_clock::now();
m_lastReceived = m_connect = std::chrono::steady_clock::now();
m_info = PeerInfo({m_node->id, "?", _n->address.address().to_string(), _n->address.port(), std::chrono::steady_clock::duration(0), CapDescSet(), 0, map<string, string>()});
}
Session::~Session()
{
if (id())
m_server->noteNode(id(), m_manualEndpoint, Origin::Unknown, true);
if (m_node)
{
if (id() && !isPermanentProblem(m_node->lastDisconnect) && !m_node->dead)
m_server->m_ready += m_node->index;
else
m_node->lastConnected = m_node->lastAttempted - chrono::seconds(1);
}
// Read-chain finished for one reason or another.
for (auto& i: m_capabilities)
@ -125,8 +128,51 @@ template <class T> vector<T> randomSelection(vector<T> const& _t, unsigned _n)
return ret;
}
void Session::ensureNodesRequested()
{
if (isOpen() && !m_weRequestedNodes)
{
m_weRequestedNodes = true;
RLPStream s;
sealAndSend(prep(s, GetPeersPacket));
}
}
void Session::serviceNodesRequest()
{
if (!m_theyRequestedNodes)
return;
auto peers = m_server->potentialPeers(m_knownNodes);
if (peers.empty())
{
addNote("peers", "requested");
return;
}
// note this should cost them...
RLPStream s;
prep(s, PeersPacket, min<unsigned>(10, peers.size()));
auto rs = randomSelection(peers, 10);
for (auto const& i: rs)
{
clogS(NetTriviaDetail) << "Sending peer " << i.id.abridged() << i.address;
if (i.address.address().is_v4())
s.appendList(3) << bytesConstRef(i.address.address().to_v4().to_bytes().data(), 4) << i.address.port() << i.id;
else// if (i.second.address().is_v6()) - assumed
s.appendList(3) << bytesConstRef(i.address.address().to_v6().to_bytes().data(), 16) << i.address.port() << i.id;
m_knownNodes.extendAll(i.index);
m_knownNodes.unionWith(i.index);
}
sealAndSend(s);
m_theyRequestedNodes = false;
addNote("peers", "done");
}
bool Session::interpret(RLP const& _r)
{
m_lastReceived = chrono::steady_clock::now();
clogS(NetRight) << _r;
try // Generic try-catch block designed to capture RLP format errors - TODO: give decent diagnostics, make a bit more specific over what is caught.
{
@ -135,9 +181,6 @@ bool Session::interpret(RLP const& _r)
{
case HelloPacket:
{
if (m_node)
m_node->lastDisconnect = -1;
m_protocolVersion = _r[1].toInt<unsigned>();
auto clientVersion = _r[2].toString();
auto caps = _r[3].toVector<CapDesc>();
@ -152,12 +195,12 @@ bool Session::interpret(RLP const& _r)
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "]" << id.abridged() << showbase << capslog.str() << dec << listenPort;
if (m_server->havePeer(id))
if (m_server->id() == id)
{
// Already connected.
clogS(NetWarn) << "Already connected to a peer with id" << id.abridged();
disconnect(DuplicatePeer);
return false;
clogS(NetWarn) << "Connected to ourself under a false pretext. We were told this peer was id" << m_info.id.abridged();
disconnect(LocalIdentity);
return true;
}
if (m_node && m_node->id != id)
@ -169,24 +212,41 @@ bool Session::interpret(RLP const& _r)
{
clogS(NetWarn) << "Connected to node, but their ID has changed since last time. This could indicate a MitM attack. Disconnecting.";
disconnect(UnexpectedIdentity);
return false;
return true;
}
if (m_server->havePeer(id))
{
m_node->dead = true;
disconnect(DuplicatePeer);
return true;
}
}
if (m_server->havePeer(id))
{
// Already connected.
clogS(NetWarn) << "Already connected to a peer with id" << id.abridged();
disconnect(DuplicatePeer);
return true;
}
if (!id)
{
disconnect(NullIdentity);
return false;
return true;
}
m_node = m_server->noteNode(id, bi::tcp::endpoint(m_socket.remote_endpoint().address(), listenPort), Origin::Self, false, !m_node || m_node->id == id ? NodeId() : m_node->id);
if (m_node->isOffline())
m_node->lastConnected = chrono::system_clock::now();
m_knownNodes.extendAll(m_node->index);
m_knownNodes.unionWith(m_node->index);
if (m_protocolVersion != m_server->protocolVersion())
{
disconnect(IncompatibleProtocol);
return false;
return true;
}
m_info = PeerInfo({id, clientVersion, m_socket.remote_endpoint().address().to_string(), listenPort, std::chrono::steady_clock::duration(), _r[3].toSet<CapDesc>(), (unsigned)m_socket.native_handle(), map<string, string>() });
@ -196,16 +256,16 @@ bool Session::interpret(RLP const& _r)
case DisconnectPacket:
{
string reason = "Unspecified";
if (_r[1].isInt())
reason = reasonOf((DisconnectReason)_r[1].toInt<int>());
clogS(NetMessageSummary) << "Disconnect (reason: " << reason << ")";
if (m_socket.is_open())
clogS(NetNote) << "Closing " << m_socket.remote_endpoint();
auto r = (DisconnectReason)_r[1].toInt<int>();
if (!_r[1].isInt())
drop(BadProtocol);
else
clogS(NetNote) << "Remote closed.";
m_socket.close();
return false;
{
reason = reasonOf(r);
clogS(NetMessageSummary) << "Disconnect (reason: " << reason << ")";
drop(DisconnectRequested);
}
break;
}
case PingPacket:
{
@ -221,27 +281,13 @@ bool Session::interpret(RLP const& _r)
case GetPeersPacket:
{
clogS(NetTriviaSummary) << "GetPeers";
auto peers = m_server->potentialPeers(m_knownNodes);
if (peers.empty())
break;
RLPStream s;
prep(s, PeersPacket, min<unsigned>(10, peers.size()));
auto rs = randomSelection(peers, 10);
for (auto const& i: rs)
{
clogS(NetTriviaDetail) << "Sending peer " << i.id.abridged() << i.address;
if (i.address.address().is_v4())
s.appendList(3) << bytesConstRef(i.address.address().to_v4().to_bytes().data(), 4) << i.address.port() << i.id;
else// if (i.second.address().is_v6()) - assumed
s.appendList(3) << bytesConstRef(i.address.address().to_v6().to_bytes().data(), 16) << i.address.port() << i.id;
m_knownNodes.extendAll(i.index);
m_knownNodes.unionWith(i.index);
}
sealAndSend(s);
m_theyRequestedNodes = true;
serviceNodesRequest();
break;
}
case PeersPacket:
clogS(NetTriviaSummary) << "Peers (" << dec << (_r.itemCount() - 1) << " entries)";
m_weRequestedNodes = false;
for (unsigned i = 1; i < _r.itemCount(); ++i)
{
bi::address peerAddress;
@ -252,7 +298,7 @@ bool Session::interpret(RLP const& _r)
else
{
disconnect(BadProtocol);
return false;
return true;
}
auto ep = bi::tcp::endpoint(peerAddress, _r[i][1].toInt<short>());
NodeId id = _r[i][2].toHash<NodeId>();
@ -273,19 +319,29 @@ bool Session::interpret(RLP const& _r)
// check that it's not us or one we already know:
if (m_server->m_nodes.count(id))
{
/* MEH. Far from an ideal solution. Leave alone for now.
// Already got this node.
// See if it's any better that ours or not...
// This could be the public address of a known node.
// SECURITY: remove this in beta - it's only for lazy connections and presents an easy attack vector.
if (m_server->m_nodes.count(id) && isPrivateAddress(m_server->m_nodes.at(id)->address.address()))
if (m_server->m_nodes.count(id) && isPrivateAddress(m_server->m_nodes.at(id)->address.address()) && ep.port() != 0)
// Update address if the node if we now have a public IP for it.
m_server->m_nodes[id]->address = ep;
*/
goto CONTINUE;
}
if (!ep.port())
goto CONTINUE; // Zero port? Don't think so.
if (ep.port() >= 49152)
goto CONTINUE; // Private port according to IANA.
// TODO: PoC-7:
// Technically fine, but ignore for now to avoid peers passing on incoming ports until we can be sure that doesn't happen any more.
// if (ep.port() < 30300 || ep.port() > 30305)
// goto CONTINUE; // Wierd port.
// Avoid our random other addresses that they might end up giving us.
for (auto i: m_server->m_addresses)
if (ep.address() == i && ep.port() == m_server->listenPort())
@ -314,10 +370,11 @@ bool Session::interpret(RLP const& _r)
}
}
}
catch (...)
catch (std::exception const& _e)
{
clogS(NetWarn) << "Peer causing an exception:" << _e.what();
disconnect(BadProtocol);
return false;
return true;
}
return true;
}
@ -329,12 +386,6 @@ void Session::ping()
m_ping = std::chrono::steady_clock::now();
}
void Session::getPeers()
{
RLPStream s;
sealAndSend(prep(s, GetPeersPacket));
}
RLPStream& Session::prep(RLPStream& _s, PacketType _id, unsigned _args)
{
return prep(_s).appendList(_args + 1).append((unsigned)_id);
@ -350,7 +401,7 @@ void Session::sealAndSend(RLPStream& _s)
bytes b;
_s.swapOut(b);
m_server->seal(b);
sendDestroy(b);
send(move(b));
}
bool Session::checkPacket(bytesConstRef _msg)
@ -368,42 +419,26 @@ bool Session::checkPacket(bytesConstRef _msg)
return true;
}
void Session::sendDestroy(bytes& _msg)
void Session::send(bytesConstRef _msg)
{
clogS(NetLeft) << RLP(bytesConstRef(&_msg).cropped(8));
if (!checkPacket(bytesConstRef(&_msg)))
{
clogS(NetWarn) << "INVALID PACKET CONSTRUCTED!";
}
bytes buffer = bytes(std::move(_msg));
writeImpl(buffer);
send(_msg.toBytes());
}
void Session::send(bytesConstRef _msg)
void Session::send(bytes&& _msg)
{
clogS(NetLeft) << RLP(_msg.cropped(8));
clogS(NetLeft) << RLP(bytesConstRef(&_msg).cropped(8));
if (!checkPacket(_msg))
{
if (!checkPacket(bytesConstRef(&_msg)))
clogS(NetWarn) << "INVALID PACKET CONSTRUCTED!";
}
bytes buffer = bytes(_msg.toBytes());
writeImpl(buffer);
}
void Session::writeImpl(bytes& _buffer)
{
// cerr << (void*)this << " writeImpl" << endl;
if (!m_socket.is_open())
return;
bool doWrite = false;
{
lock_guard<mutex> l(m_writeLock);
m_writeQueue.push_back(_buffer);
Guard l(x_writeQueue);
m_writeQueue.push_back(_msg);
doWrite = (m_writeQueue.size() == 1);
}
@ -417,18 +452,16 @@ void Session::write()
auto self(shared_from_this());
ba::async_write(m_socket, ba::buffer(bytes), [this, self](boost::system::error_code ec, std::size_t /*length*/)
{
// cerr << (void*)this << " write.callback" << endl;
// must check queue, as write callback can occur following dropped()
if (ec)
{
clogS(NetWarn) << "Error sending: " << ec.message();
dropped();
drop(TCPError);
return;
}
else
{
lock_guard<mutex> l(m_writeLock);
Guard l(x_writeQueue);
m_writeQueue.pop_front();
if (m_writeQueue.empty())
return;
@ -437,37 +470,43 @@ void Session::write()
});
}
void Session::dropped()
void Session::drop(DisconnectReason _reason)
{
// cerr << (void*)this << " dropped" << endl;
if (m_dropped)
return;
cerr << (void*)this << " dropped" << endl;
if (m_socket.is_open())
try
{
clogS(NetConnect) << "Closing " << m_socket.remote_endpoint();
clogS(NetConnect) << "Closing " << m_socket.remote_endpoint() << "(" << reasonOf(_reason) << ")";
m_socket.close();
}
catch (...) {}
}
void Session::disconnect(int _reason)
{
clogS(NetConnect) << "Disconnecting (reason:" << reasonOf((DisconnectReason)_reason) << ")";
if (m_node)
{
if (_reason != m_node->lastDisconnect || _reason == NoDisconnect || _reason == ClientQuit || _reason == DisconnectRequested)
m_node->failedAttempts = 0;
m_node->lastDisconnect = _reason;
if (_reason == BadProtocol)
{
m_node->rating /= 2;
m_node->score /= 2;
}
}
m_dropped = true;
}
void Session::disconnect(DisconnectReason _reason)
{
clogS(NetConnect) << "Disconnecting (our reason:" << reasonOf(_reason) << ")";
if (m_socket.is_open())
{
if (m_disconnect == chrono::steady_clock::time_point::max())
{
RLPStream s;
prep(s, DisconnectPacket, 1) << _reason;
sealAndSend(s);
m_disconnect = chrono::steady_clock::now();
}
else
dropped();
RLPStream s;
prep(s, DisconnectPacket, 1) << (int)_reason;
sealAndSend(s);
}
drop(_reason);
}
void Session::start()
@ -481,15 +520,13 @@ void Session::start()
<< m_server->id();
sealAndSend(s);
ping();
getPeers();
doRead();
}
void Session::doRead()
{
// ignore packets received while waiting to disconnect
if (chrono::steady_clock::now() - m_disconnect > chrono::seconds(0))
if (m_dropped)
return;
auto self(shared_from_this());
@ -500,7 +537,7 @@ void Session::doRead()
{
// got here with length of 1241...
clogS(NetWarn) << "Error reading: " << ec.message();
dropped();
drop(TCPError);
}
else if (ec && length == 0)
{
@ -541,8 +578,8 @@ void Session::doRead()
RLP r(data.cropped(8));
if (!interpret(r))
{
// error
dropped();
// error - bad protocol
disconnect(BadProtocol);
return;
}
}
@ -555,12 +592,12 @@ void Session::doRead()
catch (Exception const& _e)
{
clogS(NetWarn) << "ERROR: " << diagnostic_information(_e);
dropped();
drop(BadProtocol);
}
catch (std::exception const& _e)
{
clogS(NetWarn) << "ERROR: " << _e.what();
dropped();
drop(BadProtocol);
}
}
});

57
libp2p/Session.h

@ -30,6 +30,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcore/RangeMask.h>
#include <libdevcore/Guards.h>
#include "Common.h"
namespace dev
@ -38,7 +39,7 @@ namespace dev
namespace p2p
{
class Node;
struct Node;
/**
* @brief The Session class
@ -55,7 +56,7 @@ public:
virtual ~Session();
void start();
void disconnect(int _reason);
void disconnect(DisconnectReason _reason);
void ping();
@ -72,7 +73,7 @@ public:
static RLPStream& prep(RLPStream& _s, PacketType _t, unsigned _args = 0);
static RLPStream& prep(RLPStream& _s);
void sealAndSend(RLPStream& _s);
void sendDestroy(bytes& _msg);
void send(bytes&& _msg);
void send(bytesConstRef _msg);
int rating() const;
@ -82,42 +83,50 @@ public:
PeerInfo const& info() const { return m_info; }
void ensureNodesRequested();
void serviceNodesRequest();
private:
void dropped();
/// Drop the connection for the reason @a _r.
void drop(DisconnectReason _r);
/// Perform a read on the socket.
void doRead();
void doWrite(std::size_t length);
void writeImpl(bytes& _buffer);
/// Perform a single round of the write operation. This could end up calling itself asynchronously.
void write();
void getPeers();
/// Interpret an incoming message.
bool interpret(RLP const& _r);
/// @returns true iff the _msg forms a valid message for sending or receiving on the network.
static bool checkPacket(bytesConstRef _msg);
Host* m_server;
Host* m_server; ///< The host that owns us. Never null.
std::mutex m_writeLock;
std::deque<bytes> m_writeQueue;
mutable bi::tcp::socket m_socket; ///< Socket for the peer's connection. Mutable to ask for native_handle().
Mutex x_writeQueue; ///< Mutex for the write queue.
std::deque<bytes> m_writeQueue; ///< The write queue.
std::array<byte, 65536> m_data; ///< Data buffer for the write queue.
bytes m_incoming; ///< The incoming read queue of bytes.
mutable bi::tcp::socket m_socket; ///< Mutable to ask for native_handle().
std::array<byte, 65536> m_data;
PeerInfo m_info;
PeerInfo m_info; ///< Dyanamic information about this peer.
bytes m_incoming;
unsigned m_protocolVersion;
std::shared_ptr<Node> m_node;
bi::tcp::endpoint m_manualEndpoint;
bool m_force = false; /// If true, ignore IDs being different. This could open you up to MitM attacks.
unsigned m_protocolVersion = 0; ///< The protocol version of the peer.
std::shared_ptr<Node> m_node; ///< The Node object. Might be null if we constructed using a bare address/port.
bi::tcp::endpoint m_manualEndpoint; ///< The endpoint as specified by the constructor.
bool m_force = false; ///< If true, ignore IDs being different. This could open you up to MitM attacks.
bool m_dropped = false; ///< If true, we've already divested ourselves of this peer. We're just waiting for the reads & writes to fail before the shared_ptr goes OOS and the destructor kicks in.
std::chrono::steady_clock::time_point m_ping;
std::chrono::steady_clock::time_point m_connect;
std::chrono::steady_clock::time_point m_disconnect;
bool m_theyRequestedNodes = false; ///< Has the peer requested nodes from us without receiveing an answer from us?
bool m_weRequestedNodes = false; ///< Have we requested nodes from the peer and not received an answer yet?
std::map<CapDesc, std::shared_ptr<Capability>> m_capabilities;
RangeMask<unsigned> m_knownNodes; ///< Nodes we already know about as indices into Host's nodesList. These shouldn't be resent to peer.
std::chrono::steady_clock::time_point m_connect; ///< Time point of connection.
std::chrono::steady_clock::time_point m_ping; ///< Time point of last ping.
std::chrono::steady_clock::time_point m_lastReceived; ///< Time point of last message.
bool m_willBeDeleted = false; ///< True if we already posted a deleter on the strand.
std::map<CapDesc, std::shared_ptr<Capability>> m_capabilities; ///< The peer's capability set.
RangeMask<unsigned> m_knownNodes; ///< Nodes we already know about as indices into Host's nodesList. These shouldn't be resent to peer.
};
}

3
libqethereum/QEthereum.cpp

@ -1,7 +1,6 @@
#include <QtCore/QtCore>
#include <QtWebKitWidgets/QWebFrame>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Dagger.h>
#include <libevmface/Instruction.h>
#include <liblll/Compiler.h>
#include <libethereum/Client.h>
@ -396,7 +395,7 @@ static QString toJson(dev::eth::Transaction const& _bi)
v["from"] = toQJS(_bi.sender());
v["gas"] = (int)_bi.gas;
v["gasPrice"] = toQJS(_bi.gasPrice);
v["nonce"] = toQJS(_bi.nonce);
v["nonce"] = (int)_bi.nonce;
v["value"] = toQJS(_bi.value);
return QString::fromUtf8(QJsonDocument(v).toJson());

1
libqethereum/QmlEthereum.cpp

@ -4,7 +4,6 @@
#include <QtCore/QtCore>
#include <QtWebKitWidgets/QWebFrame>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Dagger.h>
#include <libevmface/Instruction.h>
#include <liblll/Compiler.h>
#include <libethereum/Client.h>

5
libwebthree/WebThree.h

@ -108,6 +108,11 @@ public:
void setNetworkPreferences(p2p::NetworkPreferences const& _n) { auto had = haveNetwork(); if (had) stopNetwork(); m_net.setNetworkPreferences(_n); if (had) startNetwork(); }
p2p::NodeId id() const { return m_net.id(); }
/// Gets the nodes.
p2p::Nodes nodes() const { return m_net.nodes(); }
/// Start the network subsystem.
void startNetwork() { m_net.start(); }

14
test/dagger.cpp

@ -17,12 +17,12 @@
/** @file dagger.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Dagger test functions.
* ProofOfWork test functions.
*/
#include <chrono>
#include <libdevcore/Log.h>
#include <libethcore/Dagger.h>
#include <libethcore/ProofOfWork.h>
using namespace std;
using namespace std::chrono;
using namespace dev;
@ -30,20 +30,20 @@ using namespace dev::eth;
int daggerTest()
{
cnote << "Testing Dagger...";
cnote << "Testing ProofOfWork...";
// Test dagger
{
auto s = steady_clock::now();
cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)0);
cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)0);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)1);
cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)1);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
}
{
auto s = steady_clock::now();
cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)0);
cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)0);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)1);
cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)1);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
}
return 0;

1
third/MainWin.cpp

@ -30,7 +30,6 @@
#include <boost/algorithm/string.hpp>
#include <libserpent/funcs.h>
#include <libserpent/util.h>
#include <libethcore/Dagger.h>
#include <libdevcrypto/FileSystem.h>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>

Loading…
Cancel
Save