Browse Source

Merge branch 'develop' into rlpx

Conflicts:
	libp2p/Session.cpp
cl-refactor
subtly 10 years ago
parent
commit
273d5a66ce
  1. 19
      CMakeLists.txt
  2. 2
      abi/CMakeLists.txt
  3. 2
      alethzero/DappLoader.cpp
  4. 7
      alethzero/NatspecHandler.h
  5. 15
      alethzero/Transact.cpp
  6. 3
      alethzero/Transact.h
  7. 173
      alethzero/Transact.ui
  8. 1
      cmake/EthCompilerSettings.cmake
  9. 6
      cmake/EthDependencies.cmake
  10. 49
      cmake/FindRocksDB.cmake
  11. 95
      eth/main.cpp
  12. 31
      ethconsole/CMakeLists.txt
  13. 41
      ethconsole/main.cpp
  14. 11
      ethkey/KeyAux.h
  15. 20
      ethminer/MinerAux.h
  16. 2
      ethvm/CMakeLists.txt
  17. 2
      ethvm/main.cpp
  18. 23
      evmjit/CMakeLists.txt
  19. 15
      evmjit/libevmjit/Arith256.cpp
  20. 20
      evmjit/libevmjit/Array.cpp
  21. 17
      evmjit/libevmjit/Cache.cpp
  22. 6
      evmjit/libevmjit/Cache.h
  23. 10
      evmjit/libevmjit/Compiler.cpp
  24. 5
      evmjit/libevmjit/Endianness.cpp
  25. 28
      evmjit/libevmjit/ExecutionEngine.cpp
  26. 22
      evmjit/libevmjit/GasMeter.cpp
  27. 8
      evmjit/libevmjit/Optimizer.cpp
  28. 12
      evmjit/libevmjit/RuntimeManager.cpp
  29. 5
      evmjit/libevmjit/Type.h
  30. 2
      exp/CMakeLists.txt
  31. 4
      exp/main.cpp
  32. 2
      libdevcore/CMakeLists.txt
  33. 6
      libdevcore/Common.cpp
  34. 25
      libdevcore/Common.h
  35. 4
      libdevcore/CommonData.h
  36. 8
      libdevcore/CommonIO.cpp
  37. 3
      libdevcore/FixedHash.h
  38. 4
      libdevcore/RLP.cpp
  39. 20
      libdevcore/RLP.h
  40. 2
      libdevcore/TrieCommon.cpp
  41. 15
      libdevcore/TrieDB.h
  42. 8
      libdevcore/Worker.cpp
  43. 36
      libdevcore/db.h
  44. 8
      libdevcore/vector_ref.h
  45. 4
      libdevcrypto/CMakeLists.txt
  46. 3
      libdevcrypto/OverlayDB.cpp
  47. 7
      libdevcrypto/OverlayDB.h
  48. 93
      libethash-cl/ethash_cl_miner.cpp
  49. 29
      libethash-cl/ethash_cl_miner.h
  50. 4
      libethcore/BlockInfo.cpp
  51. 6
      libethcore/Common.h
  52. 60
      libethcore/Ethash.cpp
  53. 15
      libethcore/EthashAux.cpp
  54. 2
      libethcore/EthashAux.h
  55. 1
      libethcore/Exceptions.h
  56. 2
      libethcore/Farm.h
  57. 16
      libethcore/ICAP.cpp
  58. 4
      libethcore/Miner.h
  59. 40
      libethereum/BlockChain.cpp
  60. 15
      libethereum/BlockChain.h
  61. 143
      libethereum/BlockChainSync.cpp
  62. 66
      libethereum/BlockChainSync.h
  63. 7
      libethereum/BlockDetails.h
  64. 11
      libethereum/BlockQueue.cpp
  65. 1
      libethereum/BlockQueue.h
  66. 3
      libethereum/CMakeLists.txt
  67. 6
      libethereum/CanonBlockChain.h
  68. 57
      libethereum/Client.cpp
  69. 9
      libethereum/Client.h
  70. 13
      libethereum/ClientBase.cpp
  71. 1
      libethereum/ClientBase.h
  72. 56
      libethereum/EthereumHost.cpp
  73. 19
      libethereum/EthereumHost.h
  74. 65
      libethereum/EthereumPeer.cpp
  75. 5
      libethereum/EthereumPeer.h
  76. 2
      libethereum/Executive.cpp
  77. 38
      libethereum/State.cpp
  78. 4
      libethereum/State.h
  79. 7
      libethereum/Transaction.cpp
  80. 1
      libethereum/Transaction.h
  81. 29
      libethereum/TransactionQueue.cpp
  82. 3
      libethereum/TransactionQueue.h
  83. 6
      libevmasm/Assembly.cpp
  84. 4
      libevmasm/AssemblyItem.cpp
  85. 8
      libjsconsole/CMakeLists.txt
  86. 66
      libjsconsole/CURLRequest.cpp
  87. 58
      libjsconsole/CURLRequest.h
  88. 62
      libjsconsole/JSConsole.cpp
  89. 64
      libjsconsole/JSConsole.h
  90. 34
      libjsconsole/JSLocalConsole.cpp
  91. 50
      libjsconsole/JSLocalConsole.h
  92. 23
      libjsconsole/JSRemoteConsole.cpp
  93. 48
      libjsconsole/JSRemoteConsole.h
  94. 2
      libjsconsole/JSV8Connector.h
  95. 20
      libjsconsole/JSV8RemoteConnector.cpp
  96. 32
      libjsconsole/JSV8RemoteConnector.h
  97. 3
      libjsengine/JSResources.cmake
  98. 2
      libjsengine/JSV8Engine.cpp
  99. 3
      libjsengine/JSV8Engine.h
  100. 120
      libjsqrc/admin.js

19
CMakeLists.txt

@ -30,7 +30,7 @@ option(JSONRPC "Build with jsonprc. default on" ON)
option(FATDB "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents." OFF)
option(USENPM "Use npm to recompile ethereum.js if it was changed" OFF)
option(PROFILING "Build in support for profiling" OFF)
option(ROCKSDB "Use rocksdb rather than leveldb" OFF)
set(BUNDLE "none" CACHE STRING "Predefined bundle of software to build (none, full, user, tests, minimal).")
option(MINER "Build the CLI miner component" ON)
@ -84,7 +84,10 @@ function(configureProject)
add_definitions(-DETH_CURL)
endif()
add_definitions(-DNOBOOST)
if (NOBOOST)
add_definitions(-DNOBOOST)
endif()
add_definitions(-DETH_TRUE)
endfunction()
@ -196,6 +199,7 @@ eth_format_option(MINER)
eth_format_option(USENPM)
eth_format_option(PROFILING)
eth_format_option(SOLIDITY)
eth_format_option(ROCKSDB)
eth_format_option(GUI)
eth_format_option(TESTS)
eth_format_option(NOBOOST)
@ -311,6 +315,7 @@ message("-- PROFILING Profiling support ${PROFILIN
message("-- FATDB Full database exploring ${FATDB}")
message("-- JSONRPC JSON-RPC support ${JSONRPC}")
message("-- USENPM Javascript source building ${USENPM}")
message("-- ROCKSDB Prefer rocksdb to leveldb ${ROCKSDB}")
message("------------------------------------------------------------- components")
message("-- MINER Build miner ${MINER}")
message("-- ETHKEY Build wallet tools ${ETHKEY}")
@ -337,6 +342,15 @@ include(EthExecutableHelper)
createBuildInfo()
if (ROCKSDB AND ROCKSDB_FOUND)
set(DB_INCLUDE_DIRS ${ROCKSDB_INCLUDE_DIRS})
set(DB_LIBRARIES ${ROCKSDB_LIBRARIES})
add_definitions(-DETH_ROCKSDB)
else()
set(DB_INCLUDE_DIRS ${LEVELDB_INCLUDE_DIRS})
set(DB_LIBRARIES ${LEVELDB_LIBRARIES})
endif()
if (EVMJIT)
set(EVMJIT_CPP TRUE) # include CPP-JIT connector
add_subdirectory(evmjit)
@ -380,6 +394,7 @@ endif ()
if (JSCONSOLE)
add_subdirectory(libjsengine)
add_subdirectory(libjsconsole)
add_subdirectory(ethconsole)
endif ()
add_subdirectory(secp256k1)

2
abi/CMakeLists.txt

@ -4,7 +4,7 @@ set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${DB_INCLUDE_DIRS})
set(EXECUTABLE abi)

2
alethzero/DappLoader.cpp

@ -193,6 +193,8 @@ QByteArray const& DappLoader::web3Content()
code += "\n";
code += contentsOfQResource(":/js/setup.js");
code += "\n";
code += contentsOfQResource(":/js/admin.js");
code += "\n";
m_web3Js = code.toLatin1();
}
return m_web3Js;

7
alethzero/NatspecHandler.h

@ -22,16 +22,11 @@
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#include <leveldb/db.h>
#pragma warning(pop)
#include <libdevcore/db.h>
#include <json/json.h>
#include <libdevcore/FixedHash.h>
#include "Context.h"
namespace ldb = leveldb;
class NatspecHandler: public NatSpecFace
{
public:

15
alethzero/Transact.cpp

@ -139,7 +139,7 @@ void Transact::updateDestination()
void Transact::updateFee()
{
ui->fee->setText(QString("(gas sub-total: %1)").arg(formatBalance(fee()).c_str()));
// ui->fee->setText(QString("(gas sub-total: %1)").arg(formatBalance(fee()).c_str()));
auto totalReq = total();
ui->total->setText(QString("Total: %1").arg(formatBalance(totalReq).c_str()));
@ -435,9 +435,18 @@ Address Transact::fromAccount()
return *it;
}
void Transact::updateNonce()
{
u256 n = ethereum()->countAt(fromAccount(), PendingBlock);
ui->nonce->setMaximum((unsigned)n);
ui->nonce->setMinimum(0);
ui->nonce->setValue((unsigned)n);
}
void Transact::on_send_clicked()
{
// Secret s = findSecret(value() + fee());
u256 nonce = ui->autoNonce->isChecked() ? ethereum()->countAt(fromAccount(), PendingBlock) : ui->nonce->value();
auto a = fromAccount();
auto b = ethereum()->balanceAt(a, PendingBlock);
@ -455,7 +464,7 @@ void Transact::on_send_clicked()
{
// If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB
ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice());
ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice(), nonce);
#if ETH_SOLIDITY
string src = ui->data->toPlainText().toStdString();
if (sourceIsSolidity(src))
@ -474,7 +483,7 @@ void Transact::on_send_clicked()
}
else
// TODO: cache like m_data.
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, ui->gas->value(), gasPrice());
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, ui->gas->value(), gasPrice(), nonce);
close();
}

3
alethzero/Transact.h

@ -45,7 +45,7 @@ public:
void setEnvironment(dev::AddressHash const& _accounts, dev::eth::Client* _eth, NatSpecFace* _natSpecDB);
private slots:
void on_from_currentIndexChanged(int) { rejigData(); rejigData(); }
void on_from_currentIndexChanged(int) { updateNonce(); rejigData(); }
void on_destination_currentTextChanged(QString);
void on_value_valueChanged(int) { updateFee(); rejigData(); }
void on_gas_valueChanged(int) { updateFee(); rejigData(); }
@ -61,6 +61,7 @@ private slots:
private:
dev::eth::Client* ethereum() const { return m_ethereum; }
void rejigData();
void updateNonce();
dev::Address fromAccount();
void updateDestination();

173
alethzero/Transact.ui

@ -14,35 +14,6 @@
<string>Transact</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>D&amp;ata</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>data</cstring>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QCheckBox" name="optimize">
<property name="text">
<string>&amp;Optimise</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="gas">
<property name="suffix">
@ -92,6 +63,9 @@
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QComboBox" name="gasPriceUnits"/>
</item>
<item row="7" column="0" colspan="4">
<widget class="QLabel" name="total">
<property name="sizePolicy">
@ -105,22 +79,6 @@
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QComboBox" name="gasPriceUnits"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label5_2">
<property name="text">
@ -166,6 +124,54 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>D&amp;ata</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>data</cstring>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="6" column="0" colspan="4">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
@ -205,53 +211,68 @@
</property>
</widget>
</item>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;From</string>
</property>
<property name="placeholderText">
<string/>
<property name="buddy">
<cstring>from</cstring>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QComboBox" name="valueUnits"/>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="from"/>
</item>
<item row="5" column="1" colspan="2">
<widget class="QLabel" name="fee">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item row="5" column="1">
<widget class="QCheckBox" name="optimize">
<property name="text">
<string/>
<string>&amp;Optimise</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<item row="5" column="3">
<widget class="QSpinBox" name="nonce">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="autoNonce">
<property name="text">
<string>&amp;From</string>
<string>Auto Nonce</string>
</property>
<property name="buddy">
<cstring>from</cstring>
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="from"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
<connections>
<connection>
<sender>autoNonce</sender>
<signal>toggled(bool)</signal>
<receiver>nonce</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>374</x>
<y>196</y>
</hint>
<hint type="destinationlabel">
<x>451</x>
<y>190</y>
</hint>
</hints>
</connection>
</connections>
</ui>

1
cmake/EthCompilerSettings.cmake

@ -19,6 +19,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -DSHAREDLIB -fPIC")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_DEBUGSAN "-O1 -g -fsanitize=address,integer,undefined -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/sanitizer-blacklist.txt -fno-omit-frame-pointer -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE")

6
cmake/EthDependencies.cmake

@ -49,6 +49,12 @@ find_package (LevelDB REQUIRED)
message(" - LevelDB header: ${LEVELDB_INCLUDE_DIRS}")
message(" - LevelDB lib: ${LEVELDB_LIBRARIES}")
find_package (RocksDB)
if (ROCKSDB_FOUND)
message(" - RocksDB header: ${ROCKSDB_INCLUDE_DIRS}")
message(" - RocksDB lib: ${ROCKSDB_LIBRARIES}")
endif()
if (JSCONSOLE)
find_package (v8 REQUIRED)
message(" - v8 header: ${V8_INCLUDE_DIRS}")

49
cmake/FindRocksDB.cmake

@ -0,0 +1,49 @@
# Find rocksdb
#
# Find the rocksdb includes and library
#
# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH
#
# This module defines
# ROCKSDB_INCLUDE_DIRS, where to find header, etc.
# ROCKSDB_LIBRARIES, the libraries needed to use rocksdb.
# ROCKSDB_FOUND, If false, do not try to use rocksdb.
# only look in default directories
find_path(
ROCKSDB_INCLUDE_DIR
NAMES rocksdb/db.h
DOC "rocksdb include dir"
)
find_library(
ROCKSDB_LIBRARY
NAMES rocksdb
DOC "rocksdb library"
)
set(ROCKSDB_INCLUDE_DIRS ${ROCKSDB_INCLUDE_DIR})
set(ROCKSDB_LIBRARIES ${ROCKSDB_LIBRARY})
# debug library on windows
# same naming convention as in qt (appending debug library with d)
# boost is using the same "hack" as us with "optimized" and "debug"
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
find_library(
ROCKSDB_LIBRARY_DEBUG
NAMES rocksdbd
DOC "rocksdb debug library"
)
set(ROCKSDB_LIBRARIES optimized ${ROCKSDB_LIBRARIES} debug ${ROCKSDB_LIBRARY_DEBUG})
endif()
# handle the QUIETLY and REQUIRED arguments and set ROCKSDB_FOUND to TRUE
# if all listed variables are TRUE, hide their existence from configuration view
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(rocksdb DEFAULT_MSG
ROCKSDB_INCLUDE_DIR ROCKSDB_LIBRARY)
mark_as_advanced (ROCKSDB_INCLUDE_DIR ROCKSDB_LIBRARY)

95
eth/main.cpp

@ -41,7 +41,7 @@
#include <libwebthree/WebThree.h>
#if ETH_JSCONSOLE || !ETH_TRUE
#include <libjsconsole/JSConsole.h>
#include <libjsconsole/JSLocalConsole.h>
#endif
#if ETH_READLINE || !ETH_TRUE
#include <readline/readline.h>
@ -141,6 +141,7 @@ void help()
<< " --master <password> Give the master password for the key store." << endl
<< " --password <password> Give a password for a private key." << endl
<< " --sentinel <server> Set the sentinel for reporting bad blocks or chain issues." << endl
<< " --prime <n> Specify n as the 6 digit prime number to start Frontier." << endl
<< endl
<< "Client transacting:" << endl
/*<< " -B,--block-fees <n> Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl
@ -187,6 +188,7 @@ void help()
<< " --from <n> Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --to <n> Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl
<< " --only <n> Equivalent to --export-from n --export-to n." << endl
<< " --dont-check Avoids checking some of the aspects of blocks. Faster importing, but only do if you know the data is valid." << endl
<< endl
<< "General Options:" << endl
<< " -d,--db-path <path> Load database from path (default: " << getDataDir() << ")" << endl
@ -240,6 +242,16 @@ string pretty(h160 _a, dev::eth::State const& _st)
bool g_exit = false;
inline bool isPrime(unsigned _number)
{
if (((!(_number & 1)) && _number != 2 ) || (_number < 2) || (_number % 3 == 0 && _number != 3))
return false;
for(unsigned k = 1; 36 * k * k - 12 * k < _number; ++k)
if ((_number % (6 * k + 1) == 0) || (_number % (6 * k - 1) == 0))
return false;
return true;
}
void sighandler(int)
{
g_exit = true;
@ -280,9 +292,12 @@ int main(int argc, char** argv)
/// Operating mode.
OperationMode mode = OperationMode::Node;
string dbPath;
unsigned prime = 0;
bool yesIReallyKnowWhatImDoing = false;
/// File name for import/export.
string filename;
bool safeImport = false;
/// Hashes/numbers for export range.
string exportFrom = "1";
@ -395,11 +410,25 @@ int main(int argc, char** argv)
mode = OperationMode::Import;
filename = argv[++i];
}
else if (arg == "--dont-check")
safeImport = true;
else if ((arg == "-E" || arg == "--export") && i + 1 < argc)
{
mode = OperationMode::Export;
filename = argv[++i];
}
else if (arg == "--prime" && i + 1 < argc)
try
{
prime = stoi(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--yes-i-really-know-what-im-doing")
yesIReallyKnowWhatImDoing = true;
else if (arg == "--sentinel" && i + 1 < argc)
sentinel = argv[++i];
else if (arg == "--mine-on-wrong-chain")
@ -753,13 +782,18 @@ int main(int argc, char** argv)
unsigned futureTime = 0;
unsigned unknownParent = 0;
unsigned bad = 0;
chrono::steady_clock::time_point t = chrono::steady_clock::now();
double last = 0;
unsigned lastImported = 0;
unsigned imported = 0;
while (in.peek() != -1)
{
bytes block(8);
in.read((char*)block.data(), 8);
block.resize(RLP(block, RLP::LaisezFaire).actualSize());
in.read((char*)block.data() + 8, block.size() - 8);
switch (web3.ethereum()->injectBlock(block))
switch (web3.ethereum()->queueBlock(block, safeImport))
{
case ImportResult::Success: good++; break;
case ImportResult::AlreadyKnown: alreadyHave++; break;
@ -768,11 +802,52 @@ int main(int argc, char** argv)
case ImportResult::FutureTimeKnown: futureTime++; break;
default: bad++; break;
}
// sync chain with queue
tuple<ImportRoute, bool, unsigned> r = web3.ethereum()->syncQueue(10);
imported += get<2>(r);
double e = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - t).count() / 1000.0;
if ((unsigned)e >= last + 10)
{
auto i = imported - lastImported;
auto d = e - last;
cout << i << " more imported at " << (round(i * 10 / d) / 10) << " blocks/s. " << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl;
last = (unsigned)e;
lastImported = imported;
}
}
cout << (good + bad + futureTime + unknownParent + alreadyHave) << " total: " << good << " ok, " << alreadyHave << " got, " << futureTime << " future, " << unknownParent << " unknown parent, " << bad << " malformed." << endl;
while (web3.ethereum()->blockQueue().items().first + web3.ethereum()->blockQueue().items().second > 0)
{
sleep(1);
web3.ethereum()->syncQueue(100000);
}
double e = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - t).count() / 1000.0;
cout << imported << " imported in " << e << " seconds at " << (round(imported * 10 / e) / 10) << " blocks/s (#" << web3.ethereum()->number() << ")" << endl;
return 0;
}
if (c_network == eth::Network::Frontier && !yesIReallyKnowWhatImDoing)
{
auto pd = contents(getDataDir() + "primes");
unordered_set<unsigned> primes = RLP(pd).toUnorderedSet<unsigned>();
while (true)
{
if (!prime)
try
{
prime = stoi(getPassword("To enter the Frontier, enter a 6 digit prime that you have not entered before: "));
}
catch (...) {}
if (isPrime(prime) && !primes.count(prime))
break;
prime = 0;
}
primes.insert(prime);
writeFile(getDataDir() + "primes", rlp(primes));
}
if (keyManager.exists())
{
if (masterPassword.empty() || !keyManager.load(masterPassword))
@ -1742,12 +1817,24 @@ int main(int argc, char** argv)
if (useConsole)
{
#if ETH_JSCONSOLE
JSConsole console(web3, make_shared<SimpleAccountHolder>([&](){return web3.ethereum();}, getAccountPassword, keyManager));
JSLocalConsole console;
jsonrpcServer = shared_ptr<dev::WebThreeStubServer>(new dev::WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared<SimpleAccountHolder>([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector<KeyPair>(), keyManager, *gasPricer));
jsonrpcServer->setMiningBenefactorChanger([&](Address const& a) { beneficiary = a; });
jsonrpcServer->StartListening();
if (jsonAdmin.empty())
jsonAdmin = jsonrpcServer->newSession(SessionPermissions{{Priviledge::Admin}});
else
jsonrpcServer->addSession(jsonAdmin, SessionPermissions{{Priviledge::Admin}});
cout << "JSONRPC Admin Session Key: " << jsonAdmin << endl;
while (!g_exit)
{
console.readExpression();
stopMiningAfterXBlocks(c, n, mining);
}
jsonrpcServer->StopListening();
#endif
}
else

31
ethconsole/CMakeLists.txt

@ -0,0 +1,31 @@
cmake_policy(SET CMP0015 NEW)
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${CURL_INCLUDE_DIRS})
include_directories(${V8_INCLUDE_DIRS})
set(EXECUTABLE ethconsole)
file(GLOB HEADERS "*.h")
add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES})
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls(${EXECUTABLE} CURL_DLLS)
endif()
target_link_libraries(${EXECUTABLE} jsconsole)
if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

41
ethconsole/main.cpp

@ -0,0 +1,41 @@
/*
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 main.cpp
* @author Marek
* @date 2014
*/
#include <string>
#include <libjsconsole/JSRemoteConsole.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
int main(int argc, char** argv)
{
string remote;
if (argc == 1)
remote = "http://localhost:8545";
else if (argc == 2)
remote = argv[1];
JSRemoteConsole console(remote);
while (true)
console.readExpression();
return 0;
}

11
ethkey/KeyAux.h

@ -198,7 +198,16 @@ public:
if (m_masterPassword.empty())
cerr << "Aborted (empty password not allowed)." << endl;
else
wallet.create(m_masterPassword);
{
try
{
wallet.create(m_masterPassword);
}
catch (Exception const& _e)
{
cerr << "unable to create wallet" << endl << boost::diagnostic_information(_e);
}
}
}
else if (m_mode < OperationMode::CreateWallet)
{

20
ethminer/MinerAux.h

@ -107,7 +107,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--opencl-platform" && i + 1 < argc)
try {
@ -116,7 +116,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--opencl-device" && i + 1 < argc)
try {
@ -126,7 +126,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--list-devices")
m_shouldListDevices = true;
@ -144,7 +144,7 @@ public:
else
{
cerr << "Bad " << arg << " option: " << m << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else if (arg == "--benchmark-warmup" && i + 1 < argc)
@ -154,7 +154,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--benchmark-trial" && i + 1 < argc)
try {
@ -163,7 +163,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "--benchmark-trials" && i + 1 < argc)
try {
@ -172,7 +172,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
else if (arg == "-C" || arg == "--cpu")
m_minerType = MinerType::CPU;
@ -195,7 +195,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc)
@ -232,7 +232,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << m << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else if (arg == "-M" || arg == "--benchmark")
@ -245,7 +245,7 @@ public:
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
BOOST_THROW_EXCEPTION(BadArgument());
}
}
else

2
ethvm/CMakeLists.txt

@ -4,7 +4,7 @@ set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${DB_INCLUDE_DIRS})
set(EXECUTABLE ethvm)

2
ethvm/main.cpp

@ -165,7 +165,7 @@ int main(int argc, char** argv)
executive.initialize(t);
executive.create(sender, value, gasPrice, gas, &data, origin);
boost::timer timer;
Timer timer;
executive.go(onOp);
double execTime = timer.elapsed();
executive.finalize();

23
evmjit/CMakeLists.txt

@ -10,28 +10,17 @@ else()
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra -Wconversion -Wno-sign-conversion -Wno-unknown-pragmas ${CMAKE_CXX_FLAGS}")
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT ${CMAKE_BUILD_TYPE} STREQUAL "DebugSan")
# Do not allow unresovled symbols in shared library (default on linux)
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined")
endif()
# LLVM
if(LLVM_DIR OR APPLE) # local LLVM build
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
add_definitions(${LLVM_DEFINITIONS})
# TODO: bitwriter is needed only for evmcc
llvm_map_components_to_libnames(LLVM_LIBS core support mcjit x86asmparser x86codegen bitwriter ipo)
else()
# Workaround for Ubuntu broken LLVM package
message(STATUS "Using llvm-3.5-dev package from Ubuntu. If does not work, build LLVM and set -DLLVM_DIR=llvm-build/share/llvm/cmake")
execute_process(COMMAND llvm-config-3.5 --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS)
message(STATUS "LLVM include dirs: ${LLVM_INCLUDE_DIRS}")
set(LLVM_LIBS "-lLLVMBitWriter -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMTransformUtils -lLLVMipa -lLLVMAnalysis -lLLVMX86AsmParser -lLLVMX86Desc -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMTarget -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMExecutionEngine -lLLVMMC -lLLVMCore -lLLVMSupport -lz -lpthread -lffi -ltinfo -ldl -lm")
add_definitions(-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS)
link_directories(/usr/lib/llvm-3.5/lib)
endif()
find_package(LLVM 3.7 REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
add_definitions(${LLVM_DEFINITIONS})
llvm_map_components_to_libnames(LLVM_LIBS core support mcjit x86asmparser x86codegen ipo)
get_filename_component(EVMJIT_INCLUDE_DIR include ABSOLUTE)

15
evmjit/libevmjit/Arith256.cpp

@ -167,21 +167,10 @@ llvm::Function* Arith256::getDivFunc(llvm::Type* _type)
m_builder.SetInsertPoint(mainBB);
auto ctlzIntr = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::ctlz, _type);
// both y and r are non-zero
auto yLz = m_builder.CreateCall2(ctlzIntr, yArg, m_builder.getInt1(true), "y.lz");
auto rLz = m_builder.CreateCall2(ctlzIntr, r0, m_builder.getInt1(true), "r.lz");
auto yLz = m_builder.CreateCall(ctlzIntr, {yArg, m_builder.getInt1(true)}, "y.lz");
auto rLz = m_builder.CreateCall(ctlzIntr, {r0, m_builder.getInt1(true)}, "r.lz");
auto i0 = m_builder.CreateNUWSub(yLz, rLz, "i0");
auto shlBy0 = m_builder.CreateICmpEQ(i0, zero);
auto y0 = m_builder.CreateShl(yArg, i0);
if (_type == m_builder.getIntNTy(512)) // Workaround for shl bug for long shifts
{
const auto treshold = m_builder.getIntN(512, 128);
auto highShift = m_builder.CreateICmpUGT(i0, treshold);
auto s = m_builder.CreateNUWSub(i0, treshold);
auto yhs = m_builder.CreateShl(yArg, treshold);
yhs = m_builder.CreateShl(yhs, s);
y0 = m_builder.CreateSelect(highShift, yhs, y0);
}
y0 = m_builder.CreateSelect(shlBy0, yArg, y0, "y0"); // Workaround for LLVM bug: shl by 0 produces wrong result
m_builder.CreateBr(loopBB);
m_builder.SetInsertPoint(loopBB);

20
evmjit/libevmjit/Array.cpp

@ -45,9 +45,9 @@ llvm::Function* Array::createArrayPushFunc()
auto pushBB = llvm::BasicBlock::Create(m_builder.getContext(), "Push", func);
m_builder.SetInsertPoint(entryBB);
auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr");
auto sizePtr = m_builder.CreateStructGEP(arrayPtr, 1, "sizePtr");
auto capPtr = m_builder.CreateStructGEP(arrayPtr, 2, "capPtr");
auto dataPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 0, "dataPtr");
auto sizePtr = m_builder.CreateStructGEP(getType(), arrayPtr, 1, "sizePtr");
auto capPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 2, "capPtr");
auto data = m_builder.CreateLoad(dataPtr, "data");
auto size = m_builder.CreateLoad(sizePtr, "size");
auto cap = m_builder.CreateLoad(capPtr, "cap");
@ -94,7 +94,7 @@ llvm::Function* Array::createArraySetFunc()
InsertPointGuard guard{m_builder};
m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr");
auto dataPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 0, "dataPtr");
auto data = m_builder.CreateLoad(dataPtr, "data");
auto valuePtr = m_builder.CreateGEP(data, index, "valuePtr");
m_builder.CreateStore(value, valuePtr);
@ -116,7 +116,7 @@ llvm::Function* Array::createArrayGetFunc()
InsertPointGuard guard{m_builder};
m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr");
auto dataPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 0, "dataPtr");
auto data = m_builder.CreateLoad(dataPtr, "data");
auto valuePtr = m_builder.CreateGEP(data, index, "valuePtr");
auto value = m_builder.CreateLoad(valuePtr, "value");
@ -161,7 +161,7 @@ llvm::Function* Array::createFreeFunc()
InsertPointGuard guard{m_builder};
m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr");
auto dataPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 0, "dataPtr");
auto data = m_builder.CreateLoad(dataPtr, "data");
auto mem = m_builder.CreateBitCast(data, Type::BytePtr, "mem");
m_builder.CreateCall(freeFunc, mem);
@ -197,8 +197,8 @@ llvm::Function* Array::createExtendFunc()
InsertPointGuard guard{m_builder};
m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func));
auto dataPtr = m_builder.CreateBitCast(arrayPtr, Type::BytePtr->getPointerTo(), "dataPtr");// TODO: Use byte* in Array
auto sizePtr = m_builder.CreateStructGEP(arrayPtr, 1, "sizePtr");
auto capPtr = m_builder.CreateStructGEP(arrayPtr, 2, "capPtr");
auto sizePtr = m_builder.CreateStructGEP(getType(), arrayPtr, 1, "sizePtr");
auto capPtr = m_builder.CreateStructGEP(getType(), arrayPtr, 2, "capPtr");
auto data = m_builder.CreateLoad(dataPtr, "data");
auto size = m_builder.CreateLoad(sizePtr, "size");
auto extSize = m_builder.CreateNUWSub(newSize, size, "extSize");
@ -244,7 +244,7 @@ Array::Array(llvm::IRBuilder<>& _builder, llvm::Value* _array) :
void Array::pop(llvm::Value* _count)
{
auto sizePtr = m_builder.CreateStructGEP(m_array, 1, "sizePtr");
auto sizePtr = m_builder.CreateStructGEP(getType(), m_array, 1, "sizePtr");
auto size = m_builder.CreateLoad(sizePtr, "size");
auto newSize = m_builder.CreateNUWSub(size, _count, "newSize");
m_builder.CreateStore(newSize, sizePtr);
@ -252,7 +252,7 @@ void Array::pop(llvm::Value* _count)
llvm::Value* Array::size(llvm::Value* _array)
{
auto sizePtr = m_builder.CreateStructGEP(_array ? _array : m_array, 1, "sizePtr");
auto sizePtr = m_builder.CreateStructGEP(getType(), _array ? _array : m_array, 1, "sizePtr");
return m_builder.CreateLoad(sizePtr, "array.size");
}

17
evmjit/libevmjit/Cache.cpp

@ -28,7 +28,7 @@ namespace
using Guard = std::lock_guard<std::mutex>;
std::mutex x_cacheMutex;
CacheMode g_mode;
llvm::MemoryBuffer* g_lastObject;
std::unique_ptr<llvm::MemoryBuffer> g_lastObject;
ExecutionEngineListener* g_listener;
static const size_t c_versionStampLength = 32;
@ -90,8 +90,7 @@ void Cache::preload(llvm::ExecutionEngine& _ee, std::unordered_map<std::string,
if (auto module = getObject(name))
{
DLOG(cache) << "Preload: " << name << "\n";
_ee.addModule(module.get());
module.release();
_ee.addModule(std::move(module));
auto addr = _ee.getFunctionAddress(name);
assert(addr);
_funcCache[std::move(name)] = addr;
@ -148,7 +147,7 @@ std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
}
void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBuffer const* _object)
void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBufferRef _object)
{
Guard g{x_cacheMutex};
@ -171,19 +170,17 @@ void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::Memory
llvm::sys::path::append(cachePath, id);
DLOG(cache) << id << ": write\n";
std::string error;
std::error_code error;
llvm::raw_fd_ostream cacheFile(cachePath.c_str(), error, llvm::sys::fs::F_None);
cacheFile << _object->getBuffer() << getLibVersionStamp();
cacheFile << _object.getBuffer() << getLibVersionStamp();
}
llvm::MemoryBuffer* ObjectCache::getObject(llvm::Module const* _module)
std::unique_ptr<llvm::MemoryBuffer> ObjectCache::getObject(llvm::Module const* _module)
{
Guard g{x_cacheMutex};
DLOG(cache) << _module->getModuleIdentifier() << ": use\n";
auto o = g_lastObject;
g_lastObject = nullptr;
return o;
return std::move(g_lastObject);
}
}

6
evmjit/libevmjit/Cache.h

@ -3,7 +3,9 @@
#include <memory>
#include <unordered_map>
#include "preprocessor/llvm_includes_start.h"
#include <llvm/ExecutionEngine/ObjectCache.h>
#include "preprocessor/llvm_includes_end.h"
namespace llvm
{
@ -32,13 +34,13 @@ class ObjectCache : public llvm::ObjectCache
{
public:
/// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
virtual void notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBuffer const* _object) final override;
virtual void notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBufferRef _object) final override;
/// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that
/// contains the object which corresponds with Module M, or 0 if an object is
/// not available. The caller owns both the MemoryBuffer returned by this
/// and the memory it references.
virtual llvm::MemoryBuffer* getObject(llvm::Module const* _module) final override;
virtual std::unique_ptr<llvm::MemoryBuffer> getObject(llvm::Module const* _module) final override;
};

10
evmjit/libevmjit/Compiler.cpp

@ -148,7 +148,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(code_iterator _begin, code_itera
auto fp = m_builder.CreateCall(frameaddress, m_builder.getInt32(0), "fp");
m_builder.CreateStore(fp, jmpBufWords);
auto stacksave = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::stacksave);
auto sp = m_builder.CreateCall(stacksave, "sp");
auto sp = m_builder.CreateCall(stacksave, {}, "sp");
auto jmpBufSp = m_builder.CreateConstInBoundsGEP1_64(jmpBufWords, 2, "jmpBuf.sp");
m_builder.CreateStore(sp, jmpBufSp);
auto setjmp = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::eh_sjlj_setjmp);
@ -464,12 +464,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti
// test for word >> (k * 8 + 7)
auto bitpos = m_builder.CreateAdd(k32x8, m_builder.getInt64(7), "bitpos");
auto bitposEx = m_builder.CreateZExt(bitpos, Type::Word);
auto bittester = m_builder.CreateShl(Constant::get(1), bitposEx);
auto bitresult = m_builder.CreateAnd(word, bittester);
auto bittest = m_builder.CreateICmpUGT(bitresult, Constant::get(0));
// FIXME: The following does not work - LLVM bug, report!
//auto bitval = m_builder.CreateLShr(word, bitpos, "bitval");
//auto bittest = m_builder.CreateTrunc(bitval, Type::Bool, "bittest");
auto bitval = m_builder.CreateLShr(word, bitposEx, "bitval");
auto bittest = m_builder.CreateTrunc(bitval, Type::Bool, "bittest");
auto mask_ = m_builder.CreateShl(Constant::get(1), bitposEx);
auto mask = m_builder.CreateSub(mask_, Constant::get(1), "mask");

5
evmjit/libevmjit/Endianness.cpp

@ -18,9 +18,8 @@ llvm::Value* Endianness::bswapIfLE(llvm::IRBuilder<>& _builder, llvm::Value* _wo
{
if (llvm::sys::IsLittleEndianHost)
{
// FIXME: Disabled because of problems with BYTE
//if (auto constant = llvm::dyn_cast<llvm::ConstantInt>(_word))
// return _builder.getInt(constant->getValue().byteSwap());
if (auto constant = llvm::dyn_cast<llvm::ConstantInt>(_word))
return _builder.getInt(constant->getValue().byteSwap());
// OPT: Cache func declaration?
auto bswapFunc = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::Word);

28
evmjit/libevmjit/ExecutionEngine.cpp

@ -87,20 +87,7 @@ void parseOptions()
{
static llvm::llvm_shutdown_obj shutdownObj{};
cl::AddExtraVersionPrinter(printVersion);
//cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
// FIXME: LLVM workaround:
// Manually select instruction scheduler. Confirmed bad schedulers: source, list-burr, list-hybrid.
// "source" scheduler has a bug: http://llvm.org/bugs/show_bug.cgi?id=22304
auto envLine = std::getenv("EVMJIT");
auto commandLine = std::string{"evmjit "} + (envLine ? envLine : "") + " -pre-RA-sched=list-ilp\0";
static const auto c_maxArgs = 20;
char const* argv[c_maxArgs] = {nullptr, };
auto arg = std::strtok(&*commandLine.begin(), " ");
auto i = 0;
for (; i < c_maxArgs && arg; ++i, arg = std::strtok(nullptr, " "))
argv[i] = arg;
cl::ParseCommandLineOptions(i, argv, "Ethereum EVM JIT Compiler");
cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
}
}
@ -131,20 +118,20 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
llvm::InitializeNativeTargetAsmPrinter();
auto module = std::unique_ptr<llvm::Module>(new llvm::Module({}, llvm::getGlobalContext()));
llvm::EngineBuilder builder(module.get());
builder.setEngineKind(llvm::EngineKind::JIT);
builder.setUseMCJIT(true);
builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);
// FIXME: LLVM 3.7: test on Windows
auto triple = llvm::Triple(llvm::sys::getProcessTriple());
if (triple.getOS() == llvm::Triple::OSType::Win32)
triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format
module->setTargetTriple(triple.str());
llvm::EngineBuilder builder(std::move(module));
builder.setEngineKind(llvm::EngineKind::JIT);
builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);
ee.reset(builder.create());
if (!CHECK(ee))
return ReturnCode::LLVMConfigError;
module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
ee->setObjectCache(objectCache);
// FIXME: Disabled during API changes
@ -177,8 +164,7 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
if (g_dump)
module->dump();
ee->addModule(module.get());
module.release();
ee->addModule(std::move(module));
listener->stateChanged(ExecState::CodeGen);
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
if (!CHECK(entryFuncPtr))

22
evmjit/libevmjit/GasMeter.cpp

@ -216,22 +216,12 @@ void GasMeter::countExp(llvm::Value* _exponent)
// cost = ((256 - lz) + 7) / 8
// OPT: Can gas update be done in exp algorithm?
auto t = llvm::APInt{256, 1};
auto c = m_builder.CreateSelect(m_builder.CreateICmpUGE(_exponent, Constant::get(t)), m_builder.getInt64(1), m_builder.getInt64(0));
for (auto i = 2; i <= 32; ++i)
{
t <<= 8;
c = m_builder.CreateSelect(m_builder.CreateICmpUGE(_exponent, Constant::get(t)), m_builder.getInt64(i), c);
}
// FIXME: Does not work because of LLVM bug: https://llvm.org/bugs/show_bug.cgi?id=22304
// auto ctlz = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::ctlz, Type::Word);
// auto lz256 = m_builder.CreateCall2(ctlz, _exponent, m_builder.getInt1(false));
// auto lz = m_builder.CreateTrunc(lz256, Type::Gas, "lz");
// auto sigBits = m_builder.CreateSub(m_builder.getInt64(256), lz, "sigBits");
// auto sigBytes = m_builder.CreateUDiv(m_builder.CreateAdd(sigBits, m_builder.getInt64(7)), m_builder.getInt64(8));
count(m_builder.CreateNUWMul(c, m_builder.getInt64(c_expByteGas)));
auto ctlz = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::ctlz, Type::Word);
auto lz256 = m_builder.CreateCall(ctlz, {_exponent, m_builder.getInt1(false)});
auto lz = m_builder.CreateTrunc(lz256, Type::Gas, "lz");
auto sigBits = m_builder.CreateSub(m_builder.getInt64(256), lz, "sigBits");
auto sigBytes = m_builder.CreateUDiv(m_builder.CreateAdd(sigBits, m_builder.getInt64(7)), m_builder.getInt64(8));
count(m_builder.CreateNUWMul(sigBytes, m_builder.getInt64(c_expByteGas)));
}
void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValue)

8
evmjit/libevmjit/Optimizer.cpp

@ -1,7 +1,7 @@
#include "Optimizer.h"
#include "preprocessor/llvm_includes_start.h"
#include <llvm/PassManager.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/IPO.h>
#include "preprocessor/llvm_includes_end.h"
@ -15,10 +15,10 @@ namespace jit
bool optimize(llvm::Module& _module)
{
auto pm = llvm::PassManager{};
//pm.add(llvm::createFunctionInliningPass(2, 2)); // Produces invalid IR
auto pm = llvm::legacy::PassManager{};
//pm.add(llvm::createFunctionInliningPass(2, 2)); // Problem with APInt value bigger than 64bit
pm.add(llvm::createCFGSimplificationPass());
//pm.add(llvm::createInstructionCombiningPass()); // Produces invalid runtime results
pm.add(llvm::createInstructionCombiningPass());
pm.add(llvm::createAggressiveDCEPass());
pm.add(llvm::createLowerSwitchPass());
return pm.run(_module);

12
evmjit/libevmjit/RuntimeManager.cpp

@ -93,13 +93,13 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB
// Unpack data
auto rtPtr = getRuntimePtr();
m_dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 0), "data");
m_dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 0), "data");
assert(m_dataPtr->getType() == Type::RuntimeDataPtr);
m_gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0, "gas");
m_gasPtr = m_builder.CreateStructGEP(getRuntimeDataType(), m_dataPtr, 0, "gas");
assert(m_gasPtr->getType() == Type::Gas->getPointerTo());
m_memPtr = m_builder.CreateStructGEP(rtPtr, 2, "mem");
m_memPtr = m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 2, "mem");
assert(m_memPtr->getType() == Array::getType()->getPointerTo());
m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 1), "env");
m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 1), "env");
assert(m_envPtr->getType() == Type::EnvPtr);
m_stackSize = m_builder.CreateAlloca(Type::Size, nullptr, "stackSize");
@ -160,7 +160,7 @@ llvm::Value* RuntimeManager::getDataPtr()
return m_dataPtr;
auto rtPtr = getRuntimePtr();
auto dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 0), "data");
auto dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(getRuntimeType(), rtPtr, 0), "data");
assert(dataPtr->getType() == getRuntimeDataType()->getPointerTo());
return dataPtr;
}
@ -173,7 +173,7 @@ llvm::Value* RuntimeManager::getEnvPtr()
llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index)
{
auto ptr = getBuilder().CreateStructGEP(getDataPtr(), _index);
auto ptr = getBuilder().CreateStructGEP(getRuntimeDataType(), getDataPtr(), _index);
assert(getRuntimeDataType()->getElementType(_index)->getPointerTo() == ptr->getType());
return ptr;
}

5
evmjit/libevmjit/Type.h

@ -2,8 +2,9 @@
#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Type.h>
#include <llvm/IR/Constants.h>
#include "preprocessor/llvm_includes_end.h"
#include <llvm/IR/Constants.h>
#include <llvm/IR/Metadata.h>
#include "preprocessor/llvm_includes_end.h" // FIXME: LLVM 3.7: check if needed
#include "Common.h"

2
exp/CMakeLists.txt

@ -5,7 +5,7 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..)
include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${DB_INCLUDE_DIRS})
set(EXECUTABLE exp)

4
exp/main.cpp

@ -88,7 +88,7 @@ int main()
data.push_back(rlp(i));
h256 ret;
DEV_TIMED(triedb)
DEV_TIMED("triedb")
{
MemoryDB mdb;
GenericTrieDB<MemoryDB> t(&mdb);
@ -99,7 +99,7 @@ int main()
ret = t.root();
}
cdebug << ret;
DEV_TIMED(hash256)
DEV_TIMED("hash256")
ret = orderedTrieRoot(data);
cdebug << ret;
}

2
libdevcore/CMakeLists.txt

@ -15,6 +15,7 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${DB_INCLUDE_DIRS})
set(EXECUTABLE devcore)
@ -26,6 +27,7 @@ target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${DB_LIBRARIES})
# transitive dependencies for windows executables
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")

6
libdevcore/Common.cpp

@ -48,9 +48,9 @@ const char* TimerChannel::name() { return EthRed " ⚡ "; }
TimerHelper::~TimerHelper()
{
auto e = m_t.elapsed();
if (!m_ms || e * 1000 > m_ms)
clog(TimerChannel) << m_id << e << "s";
auto e = std::chrono::high_resolution_clock::now() - m_t;
if (!m_ms || e > chrono::milliseconds(m_ms))
clog(TimerChannel) << m_id << chrono::duration_cast<chrono::milliseconds>(e).count() << "ms";
}
}

25
libdevcore/Common.h

@ -40,7 +40,7 @@
#include <unordered_set>
#include <functional>
#include <string>
#include <boost/timer.hpp>
#include <chrono>
#include <boost/functional/hash.hpp>
#pragma warning(push)
#pragma GCC diagnostic push
@ -193,16 +193,29 @@ private:
class TimerHelper
{
public:
TimerHelper(char const* _id, unsigned _msReportWhenGreater = 0): m_id(_id), m_ms(_msReportWhenGreater) {}
TimerHelper(std::string const& _id, unsigned _msReportWhenGreater = 0): m_t(std::chrono::high_resolution_clock::now()), m_id(_id), m_ms(_msReportWhenGreater) {}
~TimerHelper();
private:
boost::timer m_t;
char const* m_id;
std::chrono::high_resolution_clock::time_point m_t;
std::string m_id;
unsigned m_ms;
};
#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(#S, true); __eth_t.second; __eth_t.second = false)
class Timer
{
public:
Timer() { restart(); }
std::chrono::high_resolution_clock::duration duration() const { return std::chrono::high_resolution_clock::now() - m_t; }
double elapsed() const { return std::chrono::duration_cast<std::chrono::microseconds>(duration()).count() / 1000000.0; }
void restart() { m_t = std::chrono::high_resolution_clock::now(); }
private:
std::chrono::high_resolution_clock::time_point m_t;
};
#define DEV_TIMED(S) for (::std::pair<::dev::TimerHelper, bool> __eth_t(S, true); __eth_t.second; __eth_t.second = false)
#define DEV_TIMED_SCOPE(S) ::dev::TimerHelper __eth_t(S)
#if WIN32
#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__FUNCSIG__)
@ -210,7 +223,7 @@ private:
#define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__PRETTY_FUNCTION__)
#endif
#define DEV_TIMED_ABOVE(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(#S, MS), true); __eth_t.second; __eth_t.second = false)
#define DEV_TIMED_ABOVE(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(S, MS), true); __eth_t.second; __eth_t.second = false)
#define DEV_TIMED_SCOPE_ABOVE(S, MS) ::dev::TimerHelper __eth_t(S, MS)
#if WIN32
#define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__FUNCSIG__, MS)

4
libdevcore/CommonData.h

@ -104,10 +104,10 @@ bytes asNibbles(bytesConstRef const& _s);
template <class _T, class _Out>
inline void toBigEndian(_T _val, _Out& o_out)
{
for (auto i = o_out.size(); i-- != 0; _val >>= 8)
for (auto i = o_out.size(); i != 0; _val >>= 8, i--)
{
_T v = _val & (_T)0xff;
o_out[i] = (typename _Out::value_type)(uint8_t)v;
o_out[i - 1] = (typename _Out::value_type)(uint8_t)v;
}
}

8
libdevcore/CommonIO.cpp

@ -98,9 +98,9 @@ string dev::contentsString(string const& _file)
void dev::writeFile(std::string const& _file, bytesConstRef _data, bool _writeDeleteRename)
{
namespace fs = boost::filesystem;
if (_writeDeleteRename)
{
namespace fs = boost::filesystem;
fs::path tempPath = fs::unique_path(_file + "-%%%%%%");
writeFile(tempPath.string(), _data, false);
// will delete _file if it exists
@ -108,10 +108,14 @@ void dev::writeFile(std::string const& _file, bytesConstRef _data, bool _writeDe
}
else
{
// create directory if not existent
fs::path p(_file);
fs::create_directories(p.parent_path());
ofstream s(_file, ios::trunc | ios::binary);
s.write(reinterpret_cast<char const*>(_data.data()), _data.size());
if (!s)
BOOST_THROW_EXCEPTION(FileError());
BOOST_THROW_EXCEPTION(FileError() << errinfo_comment("Could not write to file: " + _file));
}
}

3
libdevcore/FixedHash.h

@ -113,6 +113,9 @@ public:
/// @returns an abridged version of the hash as a user-readable hex string.
std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; }
/// @returns a version of the hash as a user-readable hex string that leaves out the middle part.
std::string abridgedMiddle() const { return toHex(ref().cropped(0, 4)) + "\342\200\246" + toHex(ref().cropped(N - 4)); }
/// @returns the hash as a user-readable hex string.
std::string hex() const { return toHex(ref()); }

4
libdevcore/RLP.cpp

@ -202,9 +202,7 @@ unsigned RLP::items() const
RLPStream& RLPStream::appendRaw(bytesConstRef _s, unsigned _itemCount)
{
unsigned os = m_out.size();
m_out.resize(os + _s.size());
memcpy(m_out.data() + os, _s.data(), _s.size());
m_out.insert(m_out.end(), _s.begin(), _s.end());
noteAppended(_itemCount);
return *this;
}

20
libdevcore/RLP.h

@ -204,9 +204,7 @@ public:
{
ret.reserve(itemCount());
for (auto const& i: *this)
{
ret.push_back((T)i);
}
}
return ret;
}
@ -216,15 +214,21 @@ public:
{
std::set<T> ret;
if (isList())
{
for (auto const& i: *this)
{
ret.insert((T)i);
}
}
return ret;
}
template <class T>
std::unordered_set<T> toUnorderedSet() const
{
std::unordered_set<T> ret;
if (isList())
for (auto const& i: *this)
ret.insert((T)i);
return ret;
}
template <class T, class U>
std::pair<T, U> toPair() const
{
@ -292,7 +296,7 @@ public:
RLPs toList() const;
/// @returns the data payload. Valid for all types.
bytesConstRef payload() const { auto l = length(); if (l > m_data.size()) throw BadRLP(); return m_data.cropped(payloadOffset(), l); }
bytesConstRef payload() const { auto l = length(); if (l > m_data.size()) BOOST_THROW_EXCEPTION(BadRLP()); return m_data.cropped(payloadOffset(), l); }
/// @returns the theoretical size of this item.
/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.

2
libdevcore/TrieCommon.cpp

@ -60,7 +60,7 @@ std::string hexPrefixEncode(bytes const& _hexVector, bool _leaf, int _begin, int
std::string hexPrefixEncode(bytesConstRef _data, bool _leaf, int _beginNibble, int _endNibble, unsigned _offset)
{
unsigned begin = _beginNibble + _offset;
unsigned end = (_endNibble < 0 ? (_data.size() * 2 - _offset) + 1 + _endNibble : _endNibble) + _offset;
unsigned end = (_endNibble < 0 ? ((int)(_data.size() * 2 - _offset) + 1) + _endNibble : _endNibble) + _offset;
bool odd = (end - begin) & 1;
std::string ret(1, ((_leaf ? 2 : 0) | (odd ? 1 : 0)) * 16);

15
libdevcore/TrieDB.h

@ -21,19 +21,14 @@
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#include <leveldb/db.h>
#pragma warning(pop)
#include <memory>
#include <libdevcore/Common.h>
#include <libdevcore/Log.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/SHA3.h>
#include "db.h"
#include "Common.h"
#include "Log.h"
#include "Exceptions.h"
#include "SHA3.h"
#include "MemoryDB.h"
#include "TrieCommon.h"
namespace ldb = leveldb;
namespace dev
{

8
libdevcore/Worker.cpp

@ -65,14 +65,14 @@ void Worker::startWorking()
m_state.exchange(ex);
// cnote << "Waiting until not Stopped...";
DEV_TIMED_ABOVE(Worker stopping, 100)
DEV_TIMED_ABOVE("Worker stopping", 100)
while (m_state == WorkerState::Stopped)
this_thread::sleep_for(chrono::milliseconds(20));
}
}));
// cnote << "Spawning" << m_name;
}
DEV_TIMED_ABOVE(Start worker, 100)
DEV_TIMED_ABOVE("Start worker", 100)
while (m_state == WorkerState::Starting)
this_thread::sleep_for(chrono::microseconds(20));
}
@ -85,7 +85,7 @@ void Worker::stopWorking()
WorkerState ex = WorkerState::Started;
m_state.compare_exchange_strong(ex, WorkerState::Stopping);
DEV_TIMED_ABOVE(Stop worker, 100)
DEV_TIMED_ABOVE("Stop worker", 100)
while (m_state != WorkerState::Stopped)
this_thread::sleep_for(chrono::microseconds(20));
}
@ -99,7 +99,7 @@ void Worker::terminate()
{
m_state.exchange(WorkerState::Killing);
DEV_TIMED_ABOVE(Terminate worker, 100)
DEV_TIMED_ABOVE("Terminate worker", 100)
m_work->join();
m_work.reset();

36
libdevcore/db.h

@ -0,0 +1,36 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file DB.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#if ETH_ROCKSDB || !ETH_TRUE
#include <rocksdb/db.h>
#include <rocksdb/write_batch.h>
namespace ldb = rocksdb;
#else
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
namespace ldb = leveldb;
#endif
#pragma warning(pop)
#define DEV_LDB 1

8
libdevcore/vector_ref.h

@ -31,8 +31,8 @@ public:
vector_ref(typename std::conditional<std::is_const<_T>::value, std::vector<typename std::remove_const<_T>::type> const*, std::vector<_T>*>::type _data): m_data(_data->data()), m_count(_data->size()) {}
/// Creates a new vector_ref pointing to the data part of a string (given as reference).
vector_ref(typename std::conditional<std::is_const<_T>::value, std::string const&, std::string&>::type _data): m_data(reinterpret_cast<_T*>(_data.data())), m_count(_data.size() / sizeof(_T)) {}
#ifdef STORAGE_LEVELDB_INCLUDE_DB_H_
vector_ref(leveldb::Slice const& _s): m_data(reinterpret_cast<_T*>(_s.data())), m_count(_s.size() / sizeof(_T)) {}
#if DEV_LDB
vector_ref(ldb::Slice const& _s): m_data(reinterpret_cast<_T*>(_s.data())), m_count(_s.size() / sizeof(_T)) {}
#endif
explicit operator bool() const { return m_data && m_count; }
@ -77,8 +77,8 @@ public:
bool operator==(vector_ref<_T> const& _cmp) const { return m_data == _cmp.m_data && m_count == _cmp.m_count; }
bool operator!=(vector_ref<_T> const& _cmp) const { return !operator==(_cmp); }
#ifdef STORAGE_LEVELDB_INCLUDE_DB_H_
operator leveldb::Slice() const { return leveldb::Slice((char const*)m_data, m_count * sizeof(_T)); }
#if DEV_LDB
operator ldb::Slice() const { return ldb::Slice((char const*)m_data, m_count * sizeof(_T)); }
#endif
void reset() { m_data = nullptr; m_count = 0; }

4
libdevcrypto/CMakeLists.txt

@ -12,7 +12,7 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${CRYPTOPP_INCLUDE_DIRS})
include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${DB_INCLUDE_DIRS})
set(EXECUTABLE devcrypto)
@ -20,7 +20,7 @@ file(GLOB HEADERS "*.h")
add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${DB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} scrypt)
target_link_libraries(${EXECUTABLE} devcore)

3
libdevcrypto/OverlayDB.cpp

@ -20,8 +20,7 @@
*/
#include <thread>
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
#include <libdevcore/db.h>
#include <libdevcore/Common.h>
#include "OverlayDB.h"
using namespace std;

7
libdevcrypto/OverlayDB.h

@ -21,16 +21,11 @@
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#include <leveldb/db.h>
#pragma warning(pop)
#include <memory>
#include <libdevcore/db.h>
#include <libdevcore/Common.h>
#include <libdevcore/Log.h>
#include <libdevcore/MemoryDB.h>
namespace ldb = leveldb;
namespace dev
{

93
libethash-cl/ethash_cl_miner.cpp

@ -30,6 +30,7 @@
#include <queue>
#include <random>
#include <vector>
#include <boost/timer.hpp>
#include <libethash/util.h>
#include <libethash/ethash.h>
#include <libethash/internal.h>
@ -64,7 +65,7 @@ static void addDefinition(string& _source, char const* _id, unsigned _value)
ethash_cl_miner::search_hook::~search_hook() {}
ethash_cl_miner::ethash_cl_miner()
: m_opencl_1_1()
: m_openclOnePointOne()
{
}
@ -252,7 +253,7 @@ void ethash_cl_miner::finish()
bool ethash_cl_miner::init(
uint8_t const* _dag,
uint64_t _dagSize,
unsigned workgroup_size,
unsigned _workgroupSize,
unsigned _platformId,
unsigned _deviceId
)
@ -291,23 +292,23 @@ bool ethash_cl_miner::init(
return false;
}
if (strncmp("OpenCL 1.1", device_version.c_str(), 10) == 0)
m_opencl_1_1 = true;
m_openclOnePointOne = true;
// create context
m_context = cl::Context(vector<cl::Device>(&device, &device + 1));
m_queue = cl::CommandQueue(m_context, device);
// use requested workgroup size, but we require multiple of 8
m_workgroup_size = ((workgroup_size + 7) / 8) * 8;
m_workgroupSize = ((_workgroupSize + 7) / 8) * 8;
// patch source code
// note: ETHASH_CL_MINER_KERNEL is simply ethash_cl_miner_kernel.cl compiled
// into a byte array by bin2h.cmake. There is no need to load the file by hand in runtime
string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE);
addDefinition(code, "GROUP_SIZE", m_workgroup_size);
addDefinition(code, "GROUP_SIZE", m_workgroupSize);
addDefinition(code, "DAG_SIZE", (unsigned)(_dagSize / ETHASH_MIX_BYTES));
addDefinition(code, "ACCESSES", ETHASH_ACCESSES);
addDefinition(code, "MAX_OUTPUTS", c_max_search_results);
addDefinition(code, "MAX_OUTPUTS", c_maxSearchResults);
//debugf("%s", code.c_str());
// create miner OpenCL program
@ -330,7 +331,7 @@ bool ethash_cl_miner::init(
// create buffer for dag
try
{
m_dagChunksNum = 1;
m_dagChunksCount = 1;
m_dagChunks.push_back(cl::Buffer(m_context, CL_MEM_READ_ONLY, _dagSize));
ETHCL_LOG("Created one big buffer for the DAG");
}
@ -346,8 +347,8 @@ bool ethash_cl_miner::init(
<< result << ". Trying to allocate 4 chunks."
);
// The OpenCL kernel has a hard coded number of 4 chunks at the moment
m_dagChunksNum = 4;
for (unsigned i = 0; i < m_dagChunksNum; i++)
m_dagChunksCount = 4;
for (unsigned i = 0; i < m_dagChunksCount; i++)
{
// TODO Note: If we ever change to _dagChunksNum other than 4, then the size would need recalculation
ETHCL_LOG("Creating buffer for chunk " << i);
@ -359,24 +360,24 @@ bool ethash_cl_miner::init(
}
}
if (m_dagChunksNum == 1)
if (m_dagChunksCount == 1)
{
ETHCL_LOG("Loading single big chunk kernels");
m_hash_kernel = cl::Kernel(program, "ethash_hash");
m_search_kernel = cl::Kernel(program, "ethash_search");
m_hashKernel = cl::Kernel(program, "ethash_hash");
m_searchKernel = cl::Kernel(program, "ethash_search");
}
else
{
ETHCL_LOG("Loading chunk kernels");
m_hash_kernel = cl::Kernel(program, "ethash_hash_chunks");
m_search_kernel = cl::Kernel(program, "ethash_search_chunks");
m_hashKernel = cl::Kernel(program, "ethash_hash_chunks");
m_searchKernel = cl::Kernel(program, "ethash_search_chunks");
}
// create buffer for header
ETHCL_LOG("Creating buffer for header.");
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32);
if (m_dagChunksNum == 1)
if (m_dagChunksCount == 1)
{
ETHCL_LOG("Mapping one big chunk.");
m_queue.enqueueWriteBuffer(m_dagChunks[0], CL_TRUE, 0, _dagSize, _dag);
@ -385,12 +386,12 @@ bool ethash_cl_miner::init(
{
// TODO Note: If we ever change to _dagChunksNum other than 4, then the size would need recalculation
void* dag_ptr[4];
for (unsigned i = 0; i < m_dagChunksNum; i++)
for (unsigned i = 0; i < m_dagChunksCount; i++)
{
ETHCL_LOG("Mapping chunk " << i);
dag_ptr[i] = m_queue.enqueueMapBuffer(m_dagChunks[i], true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, (i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7);
dag_ptr[i] = m_queue.enqueueMapBuffer(m_dagChunks[i], true, m_openclOnePointOne ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, (i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7);
}
for (unsigned i = 0; i < m_dagChunksNum; i++)
for (unsigned i = 0; i < m_dagChunksCount; i++)
{
memcpy(dag_ptr[i], (char *)_dag + i*((_dagSize >> 9) << 7), (i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7);
m_queue.enqueueUnmapMemObject(m_dagChunks[i], dag_ptr[i]);
@ -398,11 +399,11 @@ bool ethash_cl_miner::init(
}
// create mining buffers
for (unsigned i = 0; i != c_num_buffers; ++i)
for (unsigned i = 0; i != c_bufferCount; ++i)
{
ETHCL_LOG("Creating mining buffer " << i);
m_hash_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY | (!m_opencl_1_1 ? CL_MEM_HOST_READ_ONLY : 0), 32 * c_hash_batch_size);
m_search_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY, (c_max_search_results + 1) * sizeof(uint32_t));
m_hashBuffer[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY | (!m_openclOnePointOne ? CL_MEM_HOST_READ_ONLY : 0), 32 * c_hashBatchSize);
m_searchBuffer[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY, (c_maxSearchResults + 1) * sizeof(uint32_t));
}
}
catch (cl::Error const& err)
@ -413,7 +414,7 @@ bool ethash_cl_miner::init(
return true;
}
void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook)
void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook, unsigned _msPerBatch)
{
try
{
@ -429,8 +430,8 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
// update header constant buffer
m_queue.enqueueWriteBuffer(m_header, false, 0, 32, header);
for (unsigned i = 0; i != c_num_buffers; ++i)
m_queue.enqueueWriteBuffer(m_search_buf[i], false, 0, 4, &c_zero);
for (unsigned i = 0; i != c_bufferCount; ++i)
m_queue.enqueueWriteBuffer(m_searchBuffer[i], false, 0, 4, &c_zero);
#if CL_VERSION_1_2 && 0
cl::Event pre_return_event;
@ -441,53 +442,59 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
m_queue.finish();
unsigned argPos = 2;
m_search_kernel.setArg(1, m_header);
for (unsigned i = 0; i < m_dagChunksNum; ++i, ++argPos)
m_search_kernel.setArg(argPos, m_dagChunks[i]);
m_searchKernel.setArg(1, m_header);
for (unsigned i = 0; i < m_dagChunksCount; ++i, ++argPos)
m_searchKernel.setArg(argPos, m_dagChunks[i]);
// pass these to stop the compiler unrolling the loops
m_search_kernel.setArg(argPos + 1, target);
m_search_kernel.setArg(argPos + 2, ~0u);
m_searchKernel.setArg(argPos + 1, target);
m_searchKernel.setArg(argPos + 2, ~0u);
unsigned buf = 0;
random_device engine;
uint64_t start_nonce = uniform_int_distribution<uint64_t>()(engine);
for (;; start_nonce += c_search_batch_size)
for (;; start_nonce += m_batchSize)
{
// supply output buffer to kernel
m_search_kernel.setArg(0, m_search_buf[buf]);
if (m_dagChunksNum == 1)
m_search_kernel.setArg(3, start_nonce);
m_searchKernel.setArg(0, m_searchBuffer[buf]);
if (m_dagChunksCount == 1)
m_searchKernel.setArg(3, start_nonce);
else
m_search_kernel.setArg(6, start_nonce);
m_searchKernel.setArg(6, start_nonce);
// execute it!
m_queue.enqueueNDRangeKernel(m_search_kernel, cl::NullRange, c_search_batch_size, m_workgroup_size);
boost::timer t;
m_queue.enqueueNDRangeKernel(m_searchKernel, cl::NullRange, m_batchSize, m_workgroupSize);
unsigned ms = t.elapsed() * 1000;
if (ms > _msPerBatch * 1.1)
m_batchSize = max<unsigned>(128, m_batchSize * 9 / 10);
else if (ms < _msPerBatch * 0.9)
m_batchSize = m_batchSize * 10 / 9;
pending.push({ start_nonce, buf });
buf = (buf + 1) % c_num_buffers;
buf = (buf + 1) % c_bufferCount;
// read results
if (pending.size() == c_num_buffers)
if (pending.size() == c_bufferCount)
{
pending_batch const& batch = pending.front();
// could use pinned host pointer instead
uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_search_buf[batch.buf], true, CL_MAP_READ, 0, (1 + c_max_search_results) * sizeof(uint32_t));
unsigned num_found = min<unsigned>(results[0], c_max_search_results);
uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_searchBuffer[batch.buf], true, CL_MAP_READ, 0, (1 + c_maxSearchResults) * sizeof(uint32_t));
unsigned num_found = min<unsigned>(results[0], c_maxSearchResults);
uint64_t nonces[c_max_search_results];
uint64_t nonces[c_maxSearchResults];
for (unsigned i = 0; i != num_found; ++i)
nonces[i] = batch.start_nonce + results[i + 1];
m_queue.enqueueUnmapMemObject(m_search_buf[batch.buf], results);
m_queue.enqueueUnmapMemObject(m_searchBuffer[batch.buf], results);
bool exit = num_found && hook.found(nonces, num_found);
exit |= hook.searched(batch.start_nonce, c_search_batch_size); // always report searched before exit
exit |= hook.searched(batch.start_nonce, m_batchSize); // always report searched before exit
if (exit)
break;
// reset search buffer if we're still going
if (num_found)
m_queue.enqueueWriteBuffer(m_search_buf[batch.buf], true, 0, 4, &c_zero);
m_queue.enqueueWriteBuffer(m_searchBuffer[batch.buf], true, 0, 4, &c_zero);
pending.pop();
}

29
libethash-cl/ethash_cl_miner.h

@ -19,6 +19,9 @@
class ethash_cl_miner
{
private:
enum { c_maxSearchResults = 63, c_bufferCount = 2, c_hashBatchSize = 1024, c_searchBatchSize = 1024 * 16 };
public:
struct search_hook
{
@ -29,7 +32,6 @@ public:
virtual bool searched(uint64_t start_nonce, uint32_t count) = 0;
};
public:
ethash_cl_miner();
~ethash_cl_miner();
@ -50,33 +52,32 @@ public:
bool init(
uint8_t const* _dag,
uint64_t _dagSize,
unsigned workgroup_size = 64,
unsigned _workgroupSize = 64,
unsigned _platformId = 0,
unsigned _deviceId = 0
);
void finish();
void search(uint8_t const* header, uint64_t target, search_hook& hook);
void search(uint8_t const* _header, uint64_t _target, search_hook& _hook, unsigned _msPerBatch = 100);
void hash_chunk(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count);
void search_chunk(uint8_t const* header, uint64_t target, search_hook& hook);
void hash_chunk(uint8_t* _ret, uint8_t const* _header, uint64_t _nonce, unsigned _count);
void search_chunk(uint8_t const*_header, uint64_t _target, search_hook& _hook);
private:
static std::vector<cl::Device> getDevices(std::vector<cl::Platform> const& _platforms, unsigned _platformId);
enum { c_max_search_results = 63, c_num_buffers = 2, c_hash_batch_size = 1024, c_search_batch_size = 1024*256 };
cl::Context m_context;
cl::CommandQueue m_queue;
cl::Kernel m_hash_kernel;
cl::Kernel m_search_kernel;
unsigned int m_dagChunksNum;
cl::Kernel m_hashKernel;
cl::Kernel m_searchKernel;
unsigned int m_dagChunksCount;
std::vector<cl::Buffer> m_dagChunks;
cl::Buffer m_header;
cl::Buffer m_hash_buf[c_num_buffers];
cl::Buffer m_search_buf[c_num_buffers];
unsigned m_workgroup_size;
bool m_opencl_1_1;
cl::Buffer m_hashBuffer[c_bufferCount];
cl::Buffer m_searchBuffer[c_bufferCount];
unsigned m_workgroupSize;
unsigned m_batchSize = c_searchBatchSize;
bool m_openclOnePointOne;
/// Allow CPU to appear as an OpenCL device or not. Default is false
static bool s_allowCPU;

4
libethcore/BlockInfo.cpp

@ -122,7 +122,7 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const
try
{
if (_header.itemCount() != 15)
throw InvalidBlockHeaderItemCount();
BOOST_THROW_EXCEPTION(InvalidBlockHeaderItemCount());
parentHash = _header[field = 0].toHash<h256>(RLP::VeryStrict);
sha3Uncles = _header[field = 1].toHash<h256>(RLP::VeryStrict);
coinbaseAddress = _header[field = 2].toHash<Address>(RLP::VeryStrict);
@ -146,7 +146,7 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const
}
if (number > ~(unsigned)0)
throw InvalidNumber();
BOOST_THROW_EXCEPTION(InvalidNumber());
// check it hashes according to proof of work or that it's the genesis block.
if (_s == CheckEverything && parentHash && !ProofOfWork::verify(*this))

6
libethcore/Common.h

@ -97,6 +97,12 @@ enum class RelativeBlock: BlockNumber
Pending = PendingBlock
};
struct ImportRoute
{
h256s deadBlocks;
h256s liveBlocks;
};
enum class ImportResult
{
Success = 0,

60
libethcore/Ethash.cpp

@ -225,26 +225,58 @@ std::string Ethash::CPUMiner::platformInfo()
#if ETH_ETHASHCL || !ETH_TRUE
using UniqueGuard = std::unique_lock<std::mutex>;
template <class N>
class Notified
{
public:
Notified() {}
Notified(N const& _v): m_value(_v) {}
Notified(Notified const&) = delete;
Notified& operator=(N const& _v) { UniqueGuard l(m_mutex); m_value = _v; m_cv.notify_all(); return *this; }
operator N() const { UniqueGuard l(m_mutex); return m_value; }
void wait() const { UniqueGuard l(m_mutex); m_cv.wait(l); }
void wait(N const& _v) const { UniqueGuard l(m_mutex); m_cv.wait(l, [&](){return m_value == _v;}); }
template <class F> void wait(F const& _f) const { UniqueGuard l(m_mutex); m_cv.wait(l, _f); }
private:
mutable Mutex m_mutex;
mutable std::condition_variable m_cv;
N m_value;
};
class EthashCLHook: public ethash_cl_miner::search_hook
{
public:
EthashCLHook(Ethash::GPUMiner* _owner): m_owner(_owner) {}
EthashCLHook(EthashCLHook const&) = delete;
void abort()
{
Guard l(x_all);
if (m_aborted)
return;
{
UniqueGuard l(x_all);
if (m_aborted)
return;
// cdebug << "Attempting to abort";
m_abort = true;
for (unsigned timeout = 0; timeout < 100 && !m_aborted; ++timeout)
std::this_thread::sleep_for(chrono::milliseconds(30));
m_abort = true;
}
// m_abort is true so now searched()/found() will return true to abort the search.
// we hang around on this thread waiting for them to point out that they have aborted since
// otherwise we may end up deleting this object prior to searched()/found() being called.
m_aborted.wait(true);
// for (unsigned timeout = 0; timeout < 100 && !m_aborted; ++timeout)
// std::this_thread::sleep_for(chrono::milliseconds(30));
// if (!m_aborted)
// cwarn << "Couldn't abort. Abandoning OpenCL process.";
}
void reset()
{
UniqueGuard l(x_all);
m_aborted = m_abort = false;
}
@ -253,27 +285,19 @@ protected:
{
// dev::operator <<(std::cerr << "Found nonces: ", vector<uint64_t>(_nonces, _nonces + _count)) << std::endl;
for (uint32_t i = 0; i < _count; ++i)
{
if (m_owner->report(_nonces[i]))
{
m_aborted = true;
return true;
}
}
return (m_aborted = true);
return m_owner->shouldStop();
}
virtual bool searched(uint64_t _startNonce, uint32_t _count) override
{
Guard l(x_all);
UniqueGuard l(x_all);
// std::cerr << "Searched " << _count << " from " << _startNonce << std::endl;
m_owner->accumulateHashes(_count);
m_last = _startNonce + _count;
if (m_abort || m_owner->shouldStop())
{
m_aborted = true;
return true;
}
return (m_aborted = true);
return false;
}
@ -281,7 +305,7 @@ private:
Mutex x_all;
uint64_t m_last;
bool m_abort = false;
bool m_aborted = true;
Notified<bool> m_aborted = {true};
Ethash::GPUMiner* m_owner = nullptr;
};

15
libethcore/EthashAux.cpp

@ -49,6 +49,13 @@ EthashAux::~EthashAux()
{
}
EthashAux* EthashAux::get()
{
static std::once_flag flag;
std::call_once(flag, []{s_this = new EthashAux();});
return s_this;
}
uint64_t EthashAux::cacheSize(BlockInfo const& _header)
{
return ethash_get_cachesize((uint64_t)_header.number);
@ -112,9 +119,11 @@ void EthashAux::killCache(h256 const& _s)
EthashAux::LightType EthashAux::light(h256 const& _seedHash)
{
ReadGuard l(get()->x_lights);
LightType ret = get()->m_lights[_seedHash];
return ret ? ret : (get()->m_lights[_seedHash] = make_shared<LightAllocation>(_seedHash));
UpgradableGuard l(get()->x_lights);
if (get()->m_lights.count(_seedHash))
return get()->m_lights.at(_seedHash);
UpgradeGuard l2(l);
return (get()->m_lights[_seedHash] = make_shared<LightAllocation>(_seedHash));
}
EthashAux::LightAllocation::LightAllocation(h256 const& _seedHash)

2
libethcore/EthashAux.h

@ -38,7 +38,7 @@ class EthashAux
public:
~EthashAux();
static EthashAux* get() { if (!s_this) s_this = new EthashAux(); return s_this; }
static EthashAux* get();
struct LightAllocation
{

1
libethcore/Exceptions.h

@ -51,6 +51,7 @@ DEV_SIMPLE_EXCEPTION(FeeTooSmall);
DEV_SIMPLE_EXCEPTION(TooMuchGasUsed);
DEV_SIMPLE_EXCEPTION(ExtraDataTooBig);
DEV_SIMPLE_EXCEPTION(InvalidSignature);
DEV_SIMPLE_EXCEPTION(InvalidTransactionFormat);
DEV_SIMPLE_EXCEPTION(InvalidBlockFormat);
DEV_SIMPLE_EXCEPTION(InvalidUnclesHash);
DEV_SIMPLE_EXCEPTION(TooManyUncles);

2
libethcore/Farm.h

@ -68,6 +68,7 @@ public:
void setWork(WorkPackage const& _wp)
{
WriteGuard l(x_minerWork);
cdebug << "Farm::setWork()";
if (_wp.headerHash == m_work.headerHash)
return;
m_work = _wp;
@ -175,6 +176,7 @@ private:
bool start()
{
WriteGuard l(x_minerWork);
cdebug << "start()";
if (!m_miners.empty() && !!std::dynamic_pointer_cast<MinerType>(m_miners[0]))
return true;
m_miners.clear();

16
libethcore/ICAP.cpp

@ -71,7 +71,7 @@ ICAP ICAP::decoded(std::string const& _encoded)
std::string data;
std::tie(country, data) = fromIBAN(_encoded);
if (country != "XE")
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
if (data.size() == 30)
{
ret.m_type = Direct;
@ -88,10 +88,10 @@ ICAP ICAP::decoded(std::string const& _encoded)
ret.m_client = data.substr(7);
}
else
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
}
else
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
return ret;
}
@ -101,7 +101,7 @@ std::string ICAP::encoded() const
if (m_type == Direct)
{
if (!!m_direct[0])
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
std::string d = toBase36<Address::size>(m_direct);
while (d.size() < 30)
d = "0" + d;
@ -118,11 +118,11 @@ std::string ICAP::encoded() const
m_institution.size() != 4 ||
m_client.size() != 9
)
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
return iban("XE", m_asset + m_institution + m_client);
}
else
throw InvalidICAP();
BOOST_THROW_EXCEPTION(InvalidICAP());
}
pair<Address, bytes> ICAP::lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const
@ -149,9 +149,9 @@ pair<Address, bytes> ICAP::lookup(std::function<bytes(Address, bytes)> const& _c
else if (m_institution[0] != 'X')
return make_pair(resolve(m_institution + "/" + m_client), bytes());
else
throw InterfaceNotSupported("ICAP::lookup(), bad institution");
BOOST_THROW_EXCEPTION(InterfaceNotSupported("ICAP::lookup(), bad institution"));
}
throw InterfaceNotSupported("ICAP::lookup(), bad asset");
BOOST_THROW_EXCEPTION(InterfaceNotSupported("ICAP::lookup(), bad asset"));
}
}

4
libethcore/Miner.h

@ -107,9 +107,9 @@ public:
}
if (!!_work)
{
DEV_TIMED_ABOVE(pause, 250)
DEV_TIMED_ABOVE("pause", 250)
pause();
DEV_TIMED_ABOVE(kickOff, 250)
DEV_TIMED_ABOVE("kickOff", 250)
kickOff();
}
else if (!_work && !!old)

40
libethereum/BlockChain.cpp

@ -24,8 +24,6 @@
#if ETH_PROFILING_GPERF
#include <gperftools/profiler.h>
#endif
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
#include <boost/timer.hpp>
#include <boost/filesystem.hpp>
#include <test/JsonSpiritHeaders.h>
@ -151,6 +149,7 @@ void BlockChain::open(std::string const& _path, WithExisting _we)
ldb::Options o;
o.create_if_missing = true;
o.max_open_files = 256;
ldb::DB::Open(o, path + "/blocks", &m_blocksDB);
ldb::DB::Open(o, path + "/details", &m_extrasDB);
if (!m_blocksDB || !m_extrasDB)
@ -241,7 +240,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
m_extrasDB->Put(m_writeOptions, toSlice(m_lastBlockHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[m_lastBlockHash].rlp()));
h256 lastHash = m_lastBlockHash;
boost::timer t;
Timer t;
for (unsigned d = 1; d < originalNumber; ++d)
{
if (!(d % 1000))
@ -305,7 +304,7 @@ LastHashes BlockChain::lastHashes(unsigned _n) const
return m_lastLastHashes;
}
tuple<ImportRoute, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max)
tuple<ImportRoute, bool, unsigned> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max)
{
// _bq.tick(*this);
@ -315,6 +314,7 @@ tuple<ImportRoute, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _sta
h256s fresh;
h256s dead;
h256s badBlocks;
unsigned count = 0;
for (VerifiedBlock const& block: blocks)
if (!badBlocks.empty())
badBlocks.push_back(block.verified.info.hash());
@ -324,10 +324,11 @@ tuple<ImportRoute, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _sta
{
// Nonce & uncle nonces already verified in verification thread at this point.
ImportRoute r;
DEV_TIMED_ABOVE(Block import, 500)
DEV_TIMED_ABOVE("Block import", 500)
r = import(block.verified, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles);
fresh += r.liveBlocks;
dead += r.deadBlocks;
++count;
}
catch (dev::eth::UnknownParent)
{
@ -353,7 +354,7 @@ tuple<ImportRoute, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _sta
badBlocks.push_back(block.verified.info.hash());
}
}
return make_tuple(ImportRoute{dead, fresh}, _bq.doneDrain(badBlocks));
return make_tuple(ImportRoute{dead, fresh}, _bq.doneDrain(badBlocks), count);
}
pair<ImportResult, ImportRoute> BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir) noexcept
@ -391,12 +392,13 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
try
#endif
{
block = verifyBlock(_block, m_onBad);
block = verifyBlock(_block, m_onBad, _ir);
}
#if ETH_CATCH
catch (Exception& ex)
{
// clog(BlockChainNote) << " Malformed block: " << diagnostic_information(ex);
ex << errinfo_phase(2);
ex << errinfo_now(time(0));
ex << errinfo_block(_block);
throw;
@ -411,13 +413,13 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
//@tidy This is a behemoth of a method - could do to be split into a few smaller ones.
#if ETH_TIMED_IMPORTS
boost::timer total;
Timer total;
double preliminaryChecks;
double enactment;
double collation;
double writing;
double checkBest;
boost::timer t;
Timer t;
#endif
// Check block doesn't already exist first!
@ -469,6 +471,9 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
h256 newLastBlockHash = currentHash();
unsigned newLastBlockNumber = number();
BlockLogBlooms blb;
BlockReceipts br;
u256 td;
#if ETH_CATCH
try
@ -479,8 +484,6 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
State s(_db);
auto tdIncrease = s.enactOn(_block, *this, _ir);
BlockLogBlooms blb;
BlockReceipts br;
for (unsigned i = 0; i < s.pending().size(); ++i)
{
blb.blooms.push_back(s.receipt(i).bloom());
@ -674,15 +677,17 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
#if ETH_TIMED_IMPORTS
checkBest = t.elapsed();
if (total.elapsed() > 1.0)
if (total.elapsed() > 0.5)
{
cnote << "SLOW IMPORT:" << _block.info.hash();
cnote << "SLOW IMPORT:" << _block.info.hash() << " #" << _block.info.number;
cnote << " Import took:" << total.elapsed();
cnote << " preliminaryChecks:" << preliminaryChecks;
cnote << " enactment:" << enactment;
cnote << " collation:" << collation;
cnote << " writing:" << writing;
cnote << " checkBest:" << checkBest;
cnote << " " << _block.transactions.size() << " transactions";
cnote << " " << _block.info.gasUsed << " gas used";
}
#endif
@ -1080,6 +1085,7 @@ VerifiedBlockRef BlockChain::verifyBlock(bytes const& _block, function<void(Exce
}
catch (Exception& ex)
{
ex << errinfo_phase(1);
ex << errinfo_now(time(0));
ex << errinfo_block(_block);
if (_onBad)
@ -1097,6 +1103,7 @@ VerifiedBlockRef BlockChain::verifyBlock(bytes const& _block, function<void(Exce
}
catch (Exception& ex)
{
ex << errinfo_phase(1);
ex << errinfo_uncleIndex(i);
ex << errinfo_now(time(0));
ex << errinfo_block(_block);
@ -1107,15 +1114,18 @@ VerifiedBlockRef BlockChain::verifyBlock(bytes const& _block, function<void(Exce
++i;
}
i = 0;
for (auto const& tr: r[1])
for (RLP const& tr: r[1])
{
bytesConstRef d = tr.data();
try
{
res.transactions.push_back(Transaction(tr.data(), CheckTransaction::Everything));
res.transactions.push_back(Transaction(d, CheckTransaction::Everything));
}
catch (Exception& ex)
{
ex << errinfo_phase(1);
ex << errinfo_transactionIndex(i);
ex << errinfo_transaction(d.toBytes());
ex << errinfo_block(_block);
throw;
}

15
libethereum/BlockChain.h

@ -21,15 +21,11 @@
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#include <leveldb/db.h>
#pragma warning(pop)
#include <deque>
#include <chrono>
#include <unordered_map>
#include <unordered_set>
#include <libdevcore/db.h>
#include <libdevcore/Log.h>
#include <libdevcore/Exceptions.h>
#include <libdevcore/Guards.h>
@ -41,7 +37,6 @@
#include "Transaction.h"
#include "BlockQueue.h"
#include "VerifiedBlock.h"
namespace ldb = leveldb;
namespace std
{
@ -81,12 +76,6 @@ using BlocksHash = std::unordered_map<h256, bytes>;
using TransactionHashes = h256s;
using UncleHashes = h256s;
struct ImportRoute
{
h256s deadBlocks;
h256s liveBlocks;
};
enum {
ExtraDetails = 0,
ExtraBlockHash,
@ -117,7 +106,7 @@ public:
/// Sync the chain with any incoming blocks. All blocks should, if processed in order.
/// @returns fresh blocks, dead blocks and true iff there are additional blocks to be processed waiting.
std::tuple<ImportRoute, bool> sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max);
std::tuple<ImportRoute, bool, unsigned> sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max);
/// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB.
/// @returns the block hashes of any blocks that came into/went out of the canonical block chain.

143
libethereum/BlockChainSync.cpp

@ -68,13 +68,10 @@ DownloadMan& BlockChainSync::downloadMan()
void BlockChainSync::abortSync()
{
DEV_INVARIANT_CHECK;
host().foreachPeer([this](EthereumPeer* _p) { onPeerAborting(_p); return true; });
downloadMan().resetToChain(h256s());
DEV_INVARIANT_CHECK;
}
void BlockChainSync::onPeerStatus(EthereumPeer* _peer)
void BlockChainSync::onPeerStatus(std::shared_ptr<EthereumPeer> _peer)
{
RecursiveGuard l(x_sync);
DEV_INVARIANT_CHECK;
@ -111,7 +108,7 @@ unsigned BlockChainSync::estimatedHashes() const
return blockCount;
}
void BlockChainSync::requestBlocks(EthereumPeer* _peer)
void BlockChainSync::requestBlocks(std::shared_ptr<EthereumPeer> _peer)
{
if (host().bq().knownFull())
{
@ -130,7 +127,14 @@ void BlockChainSync::requestBlocks(EthereumPeer* _peer)
}
}
void BlockChainSync::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
void BlockChainSync::logNewBlock(h256 const& _h)
{
if (m_state == SyncState::NewBlocks)
clog(NetNote) << "NewBlock: " << _h;
m_knownNewHashes.erase(_h);
}
void BlockChainSync::onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{
RecursiveGuard l(x_sync);
DEV_INVARIANT_CHECK;
@ -138,7 +142,7 @@ void BlockChainSync::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
clog(NetMessageSummary) << "Blocks (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreBlocks");
_peer->setIdle();
if (m_state != SyncState::Blocks && m_state != SyncState::NewBlocks)
if (m_state != SyncState::Blocks && m_state != SyncState::NewBlocks && m_state != SyncState::Waiting)
clog(NetWarn) << "Unexpected Blocks received!";
if (m_state == SyncState::Waiting)
{
@ -173,14 +177,17 @@ void BlockChainSync::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
{
case ImportResult::Success:
success++;
logNewBlock(h);
break;
case ImportResult::Malformed:
case ImportResult::BadChain:
logNewBlock(h);
_peer->disable("Malformed block received.");
return;
case ImportResult::FutureTimeKnown:
logNewBlock(h);
future++;
break;
case ImportResult::AlreadyInChain:
@ -194,6 +201,7 @@ void BlockChainSync::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
case ImportResult::UnknownParent:
{
unknown++;
logNewBlock(h);
if (m_state == SyncState::NewBlocks)
{
BlockInfo bi;
@ -241,12 +249,11 @@ void BlockChainSync::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
DEV_INVARIANT_CHECK;
}
void BlockChainSync::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
void BlockChainSync::onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{
DEV_INVARIANT_CHECK;
RecursiveGuard l(x_sync);
auto h = BlockInfo::headerHash(_r[0].data());
clog(NetMessageSummary) << "NewBlock: " << h;
if (_r.itemCount() != 2)
_peer->disable("NewBlock without 2 data fields.");
@ -256,6 +263,7 @@ void BlockChainSync::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
{
case ImportResult::Success:
_peer->addRating(100);
logNewBlock(h);
break;
case ImportResult::FutureTimeKnown:
//TODO: Rating dependent on how far in future it is.
@ -263,6 +271,7 @@ void BlockChainSync::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
case ImportResult::Malformed:
case ImportResult::BadChain:
logNewBlock(h);
_peer->disable("Malformed block received.");
return;
@ -272,6 +281,7 @@ void BlockChainSync::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
case ImportResult::FutureTimeUnknown:
case ImportResult::UnknownParent:
logNewBlock(h);
clog(NetMessageSummary) << "Received block with no known parent. Resyncing...";
resetSyncFor(_peer, h, _r[1].toInt<u256>());
break;
@ -309,17 +319,17 @@ SyncStatus PV60Sync::status() const
return res;
}
void PV60Sync::setState(EthereumPeer* _peer, SyncState _s, bool _isSyncing, bool _needHelp)
void PV60Sync::setState(std::shared_ptr<EthereumPeer> _peer, SyncState _s, bool _isSyncing, bool _needHelp)
{
bool changedState = (m_state != _s);
m_state = _s;
if (_isSyncing != (m_syncer == _peer) || (_isSyncing && changedState))
if (_isSyncing != (m_syncer.lock() == _peer) || (_isSyncing && changedState))
changeSyncer(_isSyncing ? _peer : nullptr, _needHelp);
else if (_s == SyncState::Idle)
changeSyncer(nullptr, _needHelp);
assert(!!m_syncer || _s == SyncState::Idle);
assert(isSyncing() || _s == SyncState::Idle);
}
void PV60Sync::resetSync()
@ -335,32 +345,33 @@ void PV60Sync::restartSync()
resetSync();
host().bq().clear();
if (isSyncing())
transition(m_syncer, SyncState::Idle);
transition(m_syncer.lock(), SyncState::Idle);
}
void PV60Sync::completeSync()
{
if (isSyncing())
transition(m_syncer, SyncState::Idle);
transition(m_syncer.lock(), SyncState::Idle);
}
void PV60Sync::pauseSync()
{
if (isSyncing())
setState(m_syncer, SyncState::Waiting, true);
setState(m_syncer.lock(), SyncState::Waiting, true);
}
void PV60Sync::continueSync()
{
transition(m_syncer, SyncState::Blocks);
if (isSyncing())
transition(m_syncer.lock(), SyncState::Blocks);
}
void PV60Sync::onNewPeer(EthereumPeer* _peer)
void PV60Sync::onNewPeer(std::shared_ptr<EthereumPeer> _peer)
{
setNeedsSyncing(_peer, _peer->m_latestHash, _peer->m_totalDifficulty);
}
void PV60Sync::transition(EthereumPeer* _peer, SyncState _s, bool _force, bool _needHelp)
void PV60Sync::transition(std::shared_ptr<EthereumPeer> _peer, SyncState _s, bool _force, bool _needHelp)
{
clog(NetMessageSummary) << "Transition!" << EthereumHost::stateName(_s) << "from" << EthereumHost::stateName(m_state) << ", " << (isSyncing(_peer) ? "syncing" : "holding") << (needsSyncing(_peer) ? "& needed" : "");
@ -404,13 +415,13 @@ void PV60Sync::transition(EthereumPeer* _peer, SyncState _s, bool _force, bool _
}
if (shouldGrabBlocks(_peer))
{
clog(NetNote) << "Difficulty of hashchain HIGHER. Grabbing" << m_syncingNeededBlocks.size() << "blocks [latest now" << m_syncingLatestHash << ", was" << host().latestBlockSent() << "]";
clog(NetMessageDetail) << "Difficulty of hashchain HIGHER. Grabbing" << m_syncingNeededBlocks.size() << "blocks [latest now" << m_syncingLatestHash << ", was" << host().latestBlockSent() << "]";
downloadMan().resetToChain(m_syncingNeededBlocks);
resetSync();
}
else
{
clog(NetNote) << "Difficulty of hashchain not HIGHER. Ignoring.";
clog(NetMessageDetail) << "Difficulty of hashchain not HIGHER. Ignoring.";
resetSync();
setState(_peer, SyncState::Idle, false);
return;
@ -451,10 +462,10 @@ void PV60Sync::transition(EthereumPeer* _peer, SyncState _s, bool _force, bool _
}
else if (_s == SyncState::Idle)
{
host().foreachPeer([this](EthereumPeer* _p) { _p->setIdle(); return true; });
host().foreachPeer([this](std::shared_ptr<EthereumPeer> _p) { _p->setIdle(); return true; });
if (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks)
{
clog(NetNote) << "Finishing blocks fetch...";
clog(NetMessageDetail) << "Finishing blocks fetch...";
// a bit overkill given that the other nodes may yet have the needed blocks, but better to be safe than sorry.
if (isSyncing(_peer))
@ -467,7 +478,7 @@ void PV60Sync::transition(EthereumPeer* _peer, SyncState _s, bool _force, bool _
}
else if (m_state == SyncState::Hashes)
{
clog(NetNote) << "Finishing hashes fetch...";
clog(NetMessageDetail) << "Finishing hashes fetch...";
setState(_peer, SyncState::Idle, false);
}
// Otherwise it's fine. We don't care if it's Nothing->Nothing.
@ -478,12 +489,12 @@ void PV60Sync::transition(EthereumPeer* _peer, SyncState _s, bool _force, bool _
clog(NetWarn) << "Invalid state transition:" << EthereumHost::stateName(_s) << "from" << EthereumHost::stateName(m_state) << ", " << (isSyncing(_peer) ? "syncing" : "holding") << (needsSyncing(_peer) ? "& needed" : "");
}
void PV60Sync::resetSyncFor(EthereumPeer* _peer, h256 const& _latestHash, u256 const& _td)
void PV60Sync::resetSyncFor(std::shared_ptr<EthereumPeer> _peer, h256 const& _latestHash, u256 const& _td)
{
setNeedsSyncing(_peer, _latestHash, _td);
}
void PV60Sync::setNeedsSyncing(EthereumPeer* _peer, h256 const& _latestHash, u256 const& _td)
void PV60Sync::setNeedsSyncing(std::shared_ptr<EthereumPeer> _peer, h256 const& _latestHash, u256 const& _td)
{
_peer->m_latestHash = _latestHash;
_peer->m_totalDifficulty = _td;
@ -494,17 +505,17 @@ void PV60Sync::setNeedsSyncing(EthereumPeer* _peer, h256 const& _latestHash, u25
_peer->session()->addNote("sync", string(isSyncing(_peer) ? "ongoing" : "holding") + (needsSyncing(_peer) ? " & needed" : ""));
}
bool PV60Sync::needsSyncing(EthereumPeer* _peer) const
bool PV60Sync::needsSyncing(std::shared_ptr<EthereumPeer> _peer) const
{
return !!_peer->m_latestHash;
}
bool PV60Sync::isSyncing(EthereumPeer* _peer) const
bool PV60Sync::isSyncing(std::shared_ptr<EthereumPeer> _peer) const
{
return m_syncer == _peer;
return m_syncer.lock() == _peer;
}
bool PV60Sync::shouldGrabBlocks(EthereumPeer* _peer) const
bool PV60Sync::shouldGrabBlocks(std::shared_ptr<EthereumPeer> _peer) const
{
auto td = _peer->m_totalDifficulty;
auto lh = _peer->m_latestHash;
@ -513,7 +524,7 @@ bool PV60Sync::shouldGrabBlocks(EthereumPeer* _peer) const
if (m_syncingNeededBlocks.empty())
return false;
clog(NetNote) << "Should grab blocks? " << td << "vs" << ctd << ";" << m_syncingNeededBlocks.size() << " blocks, ends" << m_syncingNeededBlocks.back();
clog(NetMessageDetail) << "Should grab blocks? " << td << "vs" << ctd << ";" << m_syncingNeededBlocks.size() << " blocks, ends" << m_syncingNeededBlocks.back();
if (td < ctd || (td == ctd && host().chain().currentHash() == lh))
return false;
@ -521,7 +532,7 @@ bool PV60Sync::shouldGrabBlocks(EthereumPeer* _peer) const
return true;
}
void PV60Sync::attemptSync(EthereumPeer* _peer)
void PV60Sync::attemptSync(std::shared_ptr<EthereumPeer> _peer)
{
if (m_state != SyncState::Idle)
{
@ -556,7 +567,7 @@ void PV60Sync::attemptSync(EthereumPeer* _peer)
}
}
void PV60Sync::noteNeedsSyncing(EthereumPeer* _peer)
void PV60Sync::noteNeedsSyncing(std::shared_ptr<EthereumPeer> _peer)
{
// if already downloading hash-chain, ignore.
if (isSyncing())
@ -570,7 +581,7 @@ void PV60Sync::noteNeedsSyncing(EthereumPeer* _peer)
attemptSync(_peer);
}
void PV60Sync::changeSyncer(EthereumPeer* _syncer, bool _needHelp)
void PV60Sync::changeSyncer(std::shared_ptr<EthereumPeer> _syncer, bool _needHelp)
{
if (_syncer)
clog(NetAllDetail) << "Changing syncer to" << _syncer->session()->socketId();
@ -581,9 +592,9 @@ void PV60Sync::changeSyncer(EthereumPeer* _syncer, bool _needHelp)
if (isSyncing())
{
if (_needHelp && (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks))
host().foreachPeer([&](EthereumPeer* _p)
host().foreachPeer([&](std::shared_ptr<EthereumPeer> _p)
{
clog(NetNote) << "Getting help with downloading blocks";
clog(NetMessageDetail) << "Getting help with downloading blocks";
if (_p != _syncer && _p->m_asking == Asking::Nothing)
transition(_p, m_state);
return true;
@ -592,7 +603,7 @@ void PV60Sync::changeSyncer(EthereumPeer* _syncer, bool _needHelp)
else
{
// start grabbing next hash chain if there is one.
host().foreachPeer([this](EthereumPeer* _p)
host().foreachPeer([this](std::shared_ptr<EthereumPeer> _p)
{
attemptSync(_p);
return !isSyncing();
@ -601,24 +612,24 @@ void PV60Sync::changeSyncer(EthereumPeer* _syncer, bool _needHelp)
{
if (m_state != SyncState::Idle)
setState(_syncer, SyncState::Idle);
clog(NetNote) << "No more peers to sync with.";
clog(NetMessageDetail) << "No more peers to sync with.";
}
}
assert(!!m_syncer || m_state == SyncState::Idle);
assert(isSyncing() || m_state == SyncState::Idle);
}
void PV60Sync::peerDoneBlocks(EthereumPeer* _peer)
void PV60Sync::peerDoneBlocks(std::shared_ptr<EthereumPeer> _peer)
{
noteDoneBlocks(_peer, false);
}
void PV60Sync::noteDoneBlocks(EthereumPeer* _peer, bool _clemency)
void PV60Sync::noteDoneBlocks(std::shared_ptr<EthereumPeer> _peer, bool _clemency)
{
resetNeedsSyncing(_peer);
if (downloadMan().isComplete())
{
// Done our chain-get.
clog(NetNote) << "Chain download complete.";
clog(NetMessageDetail) << "Chain download complete.";
// 1/100th for each useful block hash.
_peer->addRating(downloadMan().chainSize() / 100);
downloadMan().reset();
@ -643,7 +654,7 @@ void PV60Sync::noteDoneBlocks(EthereumPeer* _peer, bool _clemency)
_peer->m_sub.doneFetch();
}
void PV60Sync::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes)
void PV60Sync::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes)
{
RecursiveGuard l(x_sync);
DEV_INVARIANT_CHECK;
@ -698,11 +709,11 @@ void PV60Sync::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes)
DEV_INVARIANT_CHECK;
}
void PV60Sync::onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes)
void PV60Sync::onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes)
{
RecursiveGuard l(x_sync);
DEV_INVARIANT_CHECK;
if (isSyncing())
if (isSyncing() && (m_state != SyncState::NewBlocks || isSyncing(_peer)))
{
clog(NetMessageSummary) << "Ignoring since we're already downloading.";
return;
@ -734,43 +745,55 @@ void PV60Sync::onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes)
clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns";
if (unknowns > 0)
{
clog(NetNote) << "Not syncing and new block hash discovered: syncing without help.";
downloadMan().resetToChain(m_syncingNeededBlocks);
if (m_state == SyncState::NewBlocks)
{
clog(NetMessageDetail) << "Downloading new blocks and seeing new hashes. Trying grabbing blocks";
_peer->requestBlocks(m_syncingNeededBlocks);
}
else
{
clog(NetMessageDetail) << "Not syncing and new block hash discovered: syncing without help.";
downloadMan().resetToChain(m_syncingNeededBlocks);
transition(_peer, SyncState::NewBlocks, false, false);
}
for (auto const& h: m_syncingNeededBlocks)
if (!m_knownNewHashes.count(h))
{
m_knownNewHashes.insert(h);
clog(NetNote) << "NewHash: " << h;
}
resetSync();
transition(_peer, SyncState::NewBlocks, false, false);
}
DEV_INVARIANT_CHECK;
}
void PV60Sync::abortSync(EthereumPeer* _peer)
void PV60Sync::abortSync()
{
// Can't check invariants here since the peers is already removed from the list and the state is not updated yet.
if (isSyncing(_peer))
{
host().foreachPeer([this](EthereumPeer* _p) { _p->setIdle(); return true; });
transition(_peer, SyncState::Idle, true);
}
host().foreachPeer([this](std::shared_ptr<EthereumPeer> _p) { _p->setIdle(); return true; });
setState(std::shared_ptr<EthereumPeer>(), SyncState::Idle, false, true);
DEV_INVARIANT_CHECK;
}
void PV60Sync::onPeerAborting(EthereumPeer* _peer)
void PV60Sync::onPeerAborting()
{
RecursiveGuard l(x_sync);
// Can't check invariants here since the peers is already removed from the list and the state is not updated yet.
abortSync(_peer);
if (m_syncer.expired())
abortSync();
DEV_INVARIANT_CHECK;
}
bool PV60Sync::invariants() const
{
if (m_state == SyncState::Idle && !!m_syncer)
if (m_state == SyncState::Idle && isSyncing())
return false;
if (m_state != SyncState::Idle && !m_syncer)
if (m_state != SyncState::Idle && !isSyncing())
return false;
if (m_state == SyncState::Hashes)
{
bool hashes = false;
host().foreachPeer([&](EthereumPeer* _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; });
host().foreachPeer([&](std::shared_ptr<EthereumPeer> _p) { if (_p->m_asking == Asking::Hashes) hashes = true; return !hashes; });
if (!hashes)
return false;
if (!m_syncingLatestHash)
@ -781,7 +804,7 @@ bool PV60Sync::invariants() const
if (m_state == SyncState::Blocks || m_state == SyncState::NewBlocks)
{
bool blocks = false;
host().foreachPeer([&](EthereumPeer* _p) { if (_p->m_asking == Asking::Blocks) blocks = true; return !blocks; });
host().foreachPeer([&](std::shared_ptr<EthereumPeer> _p) { if (_p->m_asking == Asking::Blocks) blocks = true; return !blocks; });
if (!blocks)
return false;
if (downloadMan().isComplete())
@ -790,7 +813,7 @@ bool PV60Sync::invariants() const
if (m_state == SyncState::Idle)
{
bool busy = false;
host().foreachPeer([&](EthereumPeer* _p) { if (_p->m_asking != Asking::Nothing && _p->m_asking != Asking::State) busy = true; return !busy; });
host().foreachPeer([&](std::shared_ptr<EthereumPeer> _p) { if (_p->m_asking != Asking::Nothing && _p->m_asking != Asking::State) busy = true; return !busy; });
if (busy)
return false;
}

66
libethereum/BlockChainSync.h

@ -60,22 +60,22 @@ public:
virtual bool isSyncing() const = 0;
/// Called by peer to report status
virtual void onPeerStatus(EthereumPeer* _peer);
virtual void onPeerStatus(std::shared_ptr<EthereumPeer> _peer);
/// Called by peer once it has new blocks during syn
virtual void onPeerBlocks(EthereumPeer* _peer, RLP const& _r);
virtual void onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const& _r);
/// Called by peer once it has new blocks
virtual void onPeerNewBlock(EthereumPeer* _peer, RLP const& _r);
virtual void onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP const& _r);
/// Called by peer once it has new hashes
virtual void onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes) = 0;
virtual void onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes) = 0;
/// Called by peer once it has another sequential block of hashes during sync
virtual void onPeerHashes(EthereumPeer* _peer, h256s const& _hashes) = 0;
virtual void onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes) = 0;
/// Called by peer when it is disconnecting
virtual void onPeerAborting(EthereumPeer* _peer) = 0;
virtual void onPeerAborting() = 0;
/// @returns Synchonization status
virtual SyncStatus status() const = 0;
@ -85,10 +85,10 @@ public:
protected:
//To be implemented in derived classes:
/// New valid peer appears
virtual void onNewPeer(EthereumPeer* _peer) = 0;
virtual void onNewPeer(std::shared_ptr<EthereumPeer> _peer) = 0;
/// Peer done downloading blocks
virtual void peerDoneBlocks(EthereumPeer* _peer) = 0;
virtual void peerDoneBlocks(std::shared_ptr<EthereumPeer> _peer) = 0;
/// Resume downloading after witing state
virtual void continueSync() = 0;
@ -103,7 +103,7 @@ protected:
virtual void pauseSync() = 0;
/// Restart sync for given peer
virtual void resetSyncFor(EthereumPeer* _peer, h256 const& _latestHash, u256 const& _td) = 0;
virtual void resetSyncFor(std::shared_ptr<EthereumPeer> _peer, h256 const& _latestHash, u256 const& _td) = 0;
EthereumHost& host() { return m_host; }
EthereumHost const& host() const { return m_host; }
@ -112,17 +112,20 @@ protected:
unsigned estimatedHashes() const;
/// Request blocks from peer if needed
void requestBlocks(EthereumPeer* _peer);
void requestBlocks(std::shared_ptr<EthereumPeer> _peer);
protected:
Handler m_bqRoomAvailable; ///< Triggered once block queue
mutable RecursiveMutex x_sync;
SyncState m_state = SyncState::Idle; ///< Current sync state
unsigned m_estimatedHashes = 0; ///< Number of estimated hashes for the last peer over PV60. Used for status reporting only.
h256Hash m_knownNewHashes; ///< New hashes we know about use for logging only
private:
static char const* const s_stateNames[static_cast<int>(SyncState::Size)];
bool invariants() const override = 0;
void logNewBlock(h256 const& _h);
EthereumHost& m_host;
HashDownloadMan m_hashMan;
};
@ -202,65 +205,65 @@ public:
PV60Sync(EthereumHost& _host);
/// @returns true is Sync is in progress
bool isSyncing() const override { return !!m_syncer; }
bool isSyncing() const override { return !!m_syncer.lock(); }
/// Called by peer once it has new hashes
void onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes) override;
void onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes) override;
/// Called by peer once it has another sequential block of hashes during sync
void onPeerHashes(EthereumPeer* _peer, h256s const& _hashes) override;
void onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes) override;
/// Called by peer when it is disconnecting
void onPeerAborting(EthereumPeer* _peer) override;
void onPeerAborting() override;
/// @returns Sync status
SyncStatus status() const override;
protected:
void onNewPeer(EthereumPeer* _peer) override;
void onNewPeer(std::shared_ptr<EthereumPeer> _peer) override;
void continueSync() override;
void peerDoneBlocks(EthereumPeer* _peer) override;
void peerDoneBlocks(std::shared_ptr<EthereumPeer> _peer) override;
void restartSync() override;
void completeSync() override;
void pauseSync() override;
void resetSyncFor(EthereumPeer* _peer, h256 const& _latestHash, u256 const& _td) override;
void resetSyncFor(std::shared_ptr<EthereumPeer> _peer, h256 const& _latestHash, u256 const& _td) override;
private:
/// Transition sync state in a particular direction. @param _peer Peer that is responsible for state tranfer
void transition(EthereumPeer* _peer, SyncState _s, bool _force = false, bool _needHelp = true);
void transition(std::shared_ptr<EthereumPeer> _peer, SyncState _s, bool _force = false, bool _needHelp = true);
/// Reset peer syncing requirements state.
void resetNeedsSyncing(EthereumPeer* _peer) { setNeedsSyncing(_peer, h256(), 0); }
void resetNeedsSyncing(std::shared_ptr<EthereumPeer> _peer) { setNeedsSyncing(_peer, h256(), 0); }
/// Update peer syncing requirements state.
void setNeedsSyncing(EthereumPeer* _peer, h256 const& _latestHash, u256 const& _td);
void setNeedsSyncing(std::shared_ptr<EthereumPeer> _peer, h256 const& _latestHash, u256 const& _td);
/// Do we presently need syncing with this peer?
bool needsSyncing(EthereumPeer* _peer) const;
bool needsSyncing(std::shared_ptr<EthereumPeer> _peer) const;
/// Check whether the session should bother grabbing blocks from a peer.
bool shouldGrabBlocks(EthereumPeer* _peer) const;
bool shouldGrabBlocks(std::shared_ptr<EthereumPeer> _peer) const;
/// Attempt to begin syncing with the peer; first check the peer has a more difficlult chain to download, then start asking for hashes, then move to blocks
void attemptSync(EthereumPeer* _peer);
void attemptSync(std::shared_ptr<EthereumPeer> _peer);
/// Update our syncing state
void setState(EthereumPeer* _peer, SyncState _s, bool _isSyncing = false, bool _needHelp = false);
void setState(std::shared_ptr<EthereumPeer> _peer, SyncState _s, bool _isSyncing = false, bool _needHelp = false);
/// Check if peer is main syncer
bool isSyncing(EthereumPeer* _peer) const;
bool isSyncing(std::shared_ptr<EthereumPeer> _peer) const;
/// Check if we need (re-)syncing with the peer.
void noteNeedsSyncing(EthereumPeer* _who);
void noteNeedsSyncing(std::shared_ptr<EthereumPeer> _who);
/// Set main syncing peer
void changeSyncer(EthereumPeer* _syncer, bool _needHelp);
void changeSyncer(std::shared_ptr<EthereumPeer> _syncer, bool _needHelp);
/// Called when peer done downloading blocks
void noteDoneBlocks(EthereumPeer* _who, bool _clemency);
void noteDoneBlocks(std::shared_ptr<EthereumPeer> _who, bool _clemency);
/// Abort syncing for peer
void abortSync(EthereumPeer* _peer);
/// Abort syncing
void abortSync();
/// Reset hash chain syncing
void resetSync();
@ -271,8 +274,7 @@ private:
h256 m_syncingLastReceivedHash; ///< Hash most recently received from peer.
h256 m_syncingLatestHash; ///< Latest block's hash of the peer we are syncing to, as of the current sync.
u256 m_syncingTotalDifficulty; ///< Latest block's total difficulty of the peer we aresyncing to, as of the current sync.
// TODO: switch to weak_ptr
EthereumPeer* m_syncer = nullptr; ///< Peer we are currently syncing with
std::weak_ptr<EthereumPeer> m_syncer; ///< Peer we are currently syncing with
};
}
}

7
libethereum/BlockDetails.h

@ -22,15 +22,10 @@
#pragma once
#include <unordered_map>
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#include <leveldb/db.h>
#pragma warning(pop)
#include <libdevcore/db.h>
#include <libdevcore/Log.h>
#include <libdevcore/RLP.h>
#include "TransactionReceipt.h"
namespace ldb = leveldb;
namespace dev
{

11
libethereum/BlockQueue.cpp

@ -36,6 +36,7 @@ const char* BlockQueueChannel::name() { return EthOrange "[]>"; }
#else
const char* BlockQueueChannel::name() { return EthOrange "▣┅▶"; }
#endif
const char* BlockQueueTraceChannel::name() { return EthOrange "▣ ▶"; }
size_t const c_maxKnownCount = 100000;
size_t const c_maxKnownSize = 128 * 1024 * 1024;
@ -183,14 +184,14 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
// Check if we already know this block.
h256 h = BlockInfo::headerHash(_block);
cblockq << "Queuing block" << h << "for import...";
clog(BlockQueueTraceChannel) << "Queuing block" << h << "for import...";
UpgradableGuard l(m_lock);
if (m_readySet.count(h) || m_drainingSet.count(h) || m_unknownSet.count(h) || m_knownBad.count(h))
{
// Already know about this one.
cblockq << "Already known.";
clog(BlockQueueTraceChannel) << "Already known.";
return ImportResult::AlreadyKnown;
}
@ -228,7 +229,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
time_t bit = (unsigned)bi.timestamp;
if (strftime(buf, 24, "%X", localtime(&bit)) == 0)
buf[0] = '\0'; // empty if case strftime fails
cblockq << "OK - queued for future [" << bi.timestamp << "vs" << time(0) << "] - will wait until" << buf;
clog(BlockQueueTraceChannel) << "OK - queued for future [" << bi.timestamp << "vs" << time(0) << "] - will wait until" << buf;
m_unknownSize += _block.size();
m_unknownCount++;
m_difficulty += bi.difficulty;
@ -248,7 +249,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
else if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash))
{
// We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on.
cblockq << "OK - queued as unknown parent:" << bi.parentHash;
clog(BlockQueueTraceChannel) << "OK - queued as unknown parent:" << bi.parentHash;
m_unknown.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes())));
m_unknownSet.insert(h);
m_unknownSize += _block.size();
@ -260,7 +261,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
else
{
// If valid, append to blocks.
cblockq << "OK - ready for chain insertion.";
clog(BlockQueueTraceChannel) << "OK - ready for chain insertion.";
DEV_GUARDED(m_verification)
m_unverified.push_back(UnverifiedBlock { h, bi.parentHash, _block.toBytes() });
m_moreToVerify.notify_one();

1
libethereum/BlockQueue.h

@ -42,6 +42,7 @@ namespace eth
class BlockChain;
struct BlockQueueChannel: public LogChannel { static const char* name(); static const int verbosity = 4; };
struct BlockQueueTraceChannel: public LogChannel { static const char* name(); static const int verbosity = 7; };
#define cblockq dev::LogOutputStream<dev::eth::BlockQueueChannel, true>()
struct BlockQueueStatus

3
libethereum/CMakeLists.txt

@ -12,7 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB")
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${DB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
if (JSONRPC)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
@ -31,7 +31,6 @@ target_link_libraries(${EXECUTABLE} whisper)
target_link_libraries(${EXECUTABLE} p2p)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
target_link_libraries(${EXECUTABLE} secp256k1)
if (JSONRPC)

6
libethereum/CanonBlockChain.h

@ -21,11 +21,6 @@
#pragma once
#pragma warning(push)
#pragma warning(disable: 4100 4267)
#include <leveldb/db.h>
#pragma warning(pop)
#include <mutex>
#include <libdevcore/Log.h>
#include <libdevcore/Exceptions.h>
@ -35,7 +30,6 @@
#include "BlockDetails.h"
#include "Account.h"
#include "BlockChain.h"
namespace ldb = leveldb;
namespace dev
{

57
libethereum/Client.cpp

@ -87,6 +87,18 @@ void VersionChecker::setOk()
}
}
ImportResult Client::queueBlock(bytes const& _block, bool _isSafe)
{
if (m_bq.status().verified + m_bq.status().verifying + m_bq.status().unverified > 30000)
this_thread::sleep_for(std::chrono::milliseconds(500));
return m_bq.import(&_block, bc(), _isSafe);
}
tuple<ImportRoute, bool, unsigned> Client::syncQueue(unsigned _max)
{
return m_bc.sync(m_bq, m_stateDB, _max);
}
void Client::onBadBlock(Exception& _ex) const
{
// BAD BLOCK!!!
@ -159,7 +171,9 @@ void Client::onBadBlock(Exception& _ex) const
DEV_HINT_ERRINFO(max);
DEV_HINT_ERRINFO(name);
DEV_HINT_ERRINFO(field);
DEV_HINT_ERRINFO(transaction);
DEV_HINT_ERRINFO(data);
DEV_HINT_ERRINFO(phase);
DEV_HINT_ERRINFO_HASH(nonce);
DEV_HINT_ERRINFO(difficulty);
DEV_HINT_ERRINFO(target);
@ -355,11 +369,19 @@ bool Client::isSyncing() const
return false;
}
bool Client::isMajorSyncing() const
{
// TODO: only return true if it is actually doing a proper chain sync.
if (auto h = m_host.lock())
return h->isSyncing();
return false;
}
void Client::startedWorking()
{
// Synchronise the state according to the head of the block chain.
// TODO: currently it contains keys for *all* blocks. Make it remove old ones.
cdebug << "startedWorking()";
clog(ClientTrace) << "startedWorking()";
DEV_WRITE_GUARDED(x_preMine)
m_preMine.sync(m_bc);
@ -555,7 +577,7 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256
try
{
State temp;
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
// clog(ClientTrace) << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
DEV_READ_GUARDED(x_postMine)
temp = m_postMine;
temp.addBalance(_from, _value + _gasPrice * _gas);
@ -612,22 +634,24 @@ bool Client::submitWork(ProofOfWork::Solution const& _solution)
}
unsigned static const c_syncMin = 1;
unsigned static const c_syncMax = 100;
unsigned static const c_syncMax = 1000;
double static const c_targetDuration = 1;
void Client::syncBlockQueue()
{
ImportRoute ir;
cwork << "BQ ==> CHAIN ==> STATE";
boost::timer t;
tie(ir, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, m_syncAmount);
ImportRoute ir;
unsigned count;
Timer t;
tie(ir, m_syncBlockQueue, count) = m_bc.sync(m_bq, m_stateDB, m_syncAmount);
double elapsed = t.elapsed();
cnote << m_syncAmount << "blocks imported in" << unsigned(elapsed * 1000) << "ms (" << (m_syncAmount / elapsed) << "blocks/s)";
if (count)
clog(ClientNote) << count << "blocks imported in" << unsigned(elapsed * 1000) << "ms (" << (count / elapsed) << "blocks/s)";
if (elapsed > c_targetDuration * 1.1 && m_syncAmount > c_syncMin)
m_syncAmount = max(c_syncMin, m_syncAmount * 9 / 10);
else if (elapsed < c_targetDuration * 0.9 && m_syncAmount < c_syncMax)
if (elapsed > c_targetDuration * 1.1 && count > c_syncMin)
m_syncAmount = max(c_syncMin, count * 9 / 10);
else if (count == m_syncAmount && elapsed < c_targetDuration * 0.9 && m_syncAmount < c_syncMax)
m_syncAmount = min(c_syncMax, m_syncAmount * 11 / 10 + 1);
if (ir.liveBlocks.empty())
return;
@ -656,7 +680,6 @@ void Client::syncTransactionQueue()
for (size_t i = 0; i < newPendingReceipts.size(); i++)
appendFromNewPending(newPendingReceipts[i], changeds, m_postMine.pending()[i].sha3());
// Tell farm about new transaction (i.e. restartProofOfWork mining).
onPostStateChanged();
@ -701,7 +724,7 @@ void Client::onChainChanged(ImportRoute const& _ir)
// RESTART MINING
if (!m_bq.items().first)
if (!isMajorSyncing())
{
bool preChanged = false;
State newPreMine;
@ -714,7 +737,7 @@ void Client::onChainChanged(ImportRoute const& _ir)
if (preChanged || m_postMine.address() != m_preMine.address())
{
if (isMining())
cnote << "New block on chain.";
clog(ClientTrace) << "New block on chain.";
DEV_WRITE_GUARDED(x_preMine)
m_preMine = newPreMine;
@ -751,7 +774,7 @@ bool Client::remoteActive() const
void Client::onPostStateChanged()
{
cnote << "Post state changed.";
clog(ClientTrace) << "Post state changed.";
rejigMining();
m_remoteWorking = false;
}
@ -764,9 +787,9 @@ void Client::startMining()
void Client::rejigMining()
{
if ((wouldMine() || remoteActive()) && !m_bq.items().first && (!isChainBad() || mineOnBadChain()) /*&& (forceMining() || transactionsWaiting())*/)
if ((wouldMine() || remoteActive()) && !isMajorSyncing() && (!isChainBad() || mineOnBadChain()) /*&& (forceMining() || transactionsWaiting())*/)
{
cnote << "Rejigging mining...";
clog(ClientTrace) << "Rejigging mining...";
DEV_WRITE_GUARDED(x_working)
m_working.commitToMine(m_bc);
DEV_READ_GUARDED(x_working)
@ -863,7 +886,7 @@ void Client::checkWatchGarbage()
if (m_watches[key].lastPoll != chrono::system_clock::time_point::max() && chrono::system_clock::now() - m_watches[key].lastPoll > chrono::seconds(20))
{
toUninstall.push_back(key);
cnote << "GC: Uninstall" << key << "(" << chrono::duration_cast<chrono::seconds>(chrono::system_clock::now() - m_watches[key].lastPoll).count() << "s old)";
clog(ClientTrace) << "GC: Uninstall" << key << "(" << chrono::duration_cast<chrono::seconds>(chrono::system_clock::now() - m_watches[key].lastPoll).count() << "s old)";
}
for (auto i: toUninstall)
uninstallWatch(i);

9
libethereum/Client.h

@ -138,6 +138,9 @@ public:
/// Blocks until all pending transactions have been processed.
virtual void flushTransactions() override;
/// Queues a block for import.
ImportResult queueBlock(bytes const& _block, bool _isSafe = false);
using Interface::call; // to remove warning about hiding virtual function
/// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH.
ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether, Address const& _from = Address());
@ -160,6 +163,11 @@ public:
SyncStatus syncStatus() const;
/// Get the block queue.
BlockQueue const& blockQueue() const { return m_bq; }
/// Get the block queue.
OverlayDB const& stateDB() const { return m_stateDB; }
/// Freeze worker thread and sync some of the block queue.
std::tuple<ImportRoute, bool, unsigned> syncQueue(unsigned _max = 1);
// Mining stuff:
@ -219,6 +227,7 @@ public:
DownloadMan const* downloadMan() const;
bool isSyncing() const;
bool isMajorSyncing() const;
/// Sets the network id.
void setNetworkId(u256 _n);
/// Clears pending transactions. Just for debug use.

13
libethereum/ClientBase.cpp

@ -56,6 +56,19 @@ void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, b
cnote << "New transaction " << t;
}
Address ClientBase::submitTransaction(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce)
{
prepareForTransaction();
Transaction t(_value, _gasPrice, _gas, _data, _nonce, _secret);
m_tq.import(t.rlp());
StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged());
cnote << "New transaction " << t;
return right160(sha3(rlpList(t.sender(), t.nonce())));
}
void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
{
auto a = toAddress(_secret);

1
libethereum/ClientBase.h

@ -81,6 +81,7 @@ public:
/// Submits a new contract-creation transaction.
/// @returns the new contract's address (assuming it all goes through).
virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, u256 _nonce);
virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override;
using Interface::submitTransaction;

56
libethereum/EthereumHost.cpp

@ -41,7 +41,6 @@ using namespace dev::eth;
using namespace p2p;
unsigned const EthereumHost::c_oldProtocolVersion = 60; //TODO: remove this once v61+ is common
unsigned const c_chainReorgSize = 30000;
char const* const EthereumHost::s_stateNames[static_cast<int>(SyncState::Size)] = {"Idle", "Waiting", "Hashes", "Blocks", "NewBlocks" };
@ -105,7 +104,7 @@ void EthereumHost::doWork()
}
}
foreachPeer([](EthereumPeer* _p) { _p->tick(); return true; });
foreachPeer([](std::shared_ptr<EthereumPeer> _p) { _p->tick(); return true; });
// return netChange;
// TODO: Figure out what to do with netChange.
@ -126,7 +125,7 @@ void EthereumHost::maintainTransactions()
}
for (auto const& t: ts)
m_transactionsSent.insert(t.first);
foreachPeerPtr([&](shared_ptr<EthereumPeer> _p)
foreachPeer([&](shared_ptr<EthereumPeer> _p)
{
bytes b;
unsigned n = 0;
@ -151,17 +150,7 @@ void EthereumHost::maintainTransactions()
});
}
void EthereumHost::foreachPeer(std::function<bool(EthereumPeer*)> const& _f) const
{
foreachPeerPtr([&](std::shared_ptr<EthereumPeer> _p)
{
if (_p)
return _f(_p.get());
return true;
});
}
void EthereumHost::foreachPeerPtr(std::function<bool(std::shared_ptr<EthereumPeer>)> const& _f) const
void EthereumHost::foreachPeer(std::function<bool(std::shared_ptr<EthereumPeer>)> const& _f) const
{
for (auto s: peerSessions())
if (!_f(s.first->cap<EthereumPeer>()))
@ -177,20 +166,21 @@ tuple<vector<shared_ptr<EthereumPeer>>, vector<shared_ptr<EthereumPeer>>, vector
vector<shared_ptr<EthereumPeer>> allowed;
vector<shared_ptr<Session>> sessions;
auto const& ps = peerSessions();
allowed.reserve(ps.size());
for (auto const& j: ps)
size_t peerCount = 0;
foreachPeer([&](std::shared_ptr<EthereumPeer> _p)
{
auto pp = j.first->cap<EthereumPeer>();
if (_allow(pp.get()))
if (_allow(_p.get()))
{
allowed.push_back(move(pp));
sessions.push_back(move(j.first));
allowed.push_back(_p);
sessions.push_back(_p->session());
}
}
++peerCount;
return true;
});
chosen.reserve((ps.size() * _percent + 99) / 100);
for (unsigned i = (ps.size() * _percent + 99) / 100; i-- && allowed.size();)
size_t chosenSize = (peerCount * _percent + 99) / 100;
chosen.reserve(chosenSize);
for (unsigned i = chosenSize; i && allowed.size(); i--)
{
unsigned n = rand() % allowed.size();
chosen.push_back(std::move(allowed[n]));
@ -246,7 +236,7 @@ BlockChainSync& EthereumHost::sync()
return *m_sync; // We only chose sync strategy once
bool pv61 = false;
foreachPeer([&](EthereumPeer* _p)
foreachPeer([&](std::shared_ptr<EthereumPeer> _p)
{
if (_p->m_protocolVersion == protocolVersion())
pv61 = true;
@ -256,37 +246,37 @@ BlockChainSync& EthereumHost::sync()
return *m_sync;
}
void EthereumHost::onPeerStatus(EthereumPeer* _peer)
void EthereumHost::onPeerStatus(std::shared_ptr<EthereumPeer> _peer)
{
Guard l(x_sync);
sync().onPeerStatus(_peer);
}
void EthereumHost::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes)
void EthereumHost::onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes)
{
Guard l(x_sync);
sync().onPeerHashes(_peer, _hashes);
}
void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
void EthereumHost::onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{
Guard l(x_sync);
sync().onPeerBlocks(_peer, _r);
}
void EthereumHost::onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes)
void EthereumHost::onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes)
{
Guard l(x_sync);
sync().onPeerNewHashes(_peer, _hashes);
}
void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
void EthereumHost::onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{
Guard l(x_sync);
sync().onPeerNewBlock(_peer, _r);
}
void EthereumHost::onPeerTransactions(EthereumPeer* _peer, RLP const& _r)
void EthereumHost::onPeerTransactions(std::shared_ptr<EthereumPeer> _peer, RLP const& _r)
{
if (_peer->isCriticalSyncing())
{
@ -319,11 +309,11 @@ void EthereumHost::onPeerTransactions(EthereumPeer* _peer, RLP const& _r)
}
}
void EthereumHost::onPeerAborting(EthereumPeer* _peer)
void EthereumHost::onPeerAborting()
{
Guard l(x_sync);
if (m_sync)
m_sync->onPeerAborting(_peer);
m_sync->onPeerAborting();
}
bool EthereumHost::isSyncing() const

19
libethereum/EthereumHost.h

@ -86,16 +86,15 @@ public:
static char const* stateName(SyncState _s) { return s_stateNames[static_cast<int>(_s)]; }
static unsigned const c_oldProtocolVersion;
void foreachPeerPtr(std::function<bool(std::shared_ptr<EthereumPeer>)> const& _f) const;
void foreachPeer(std::function<bool(EthereumPeer*)> const& _f) const;
void onPeerStatus(EthereumPeer* _peer);
void onPeerHashes(EthereumPeer* _peer, h256s const& _hashes);
void onPeerBlocks(EthereumPeer* _peer, RLP const& _r);
void onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes);
void onPeerNewBlock(EthereumPeer* _peer, RLP const& _r);
void onPeerTransactions(EthereumPeer* _peer, RLP const& _r);
void onPeerAborting(EthereumPeer* _peer);
void foreachPeer(std::function<bool(std::shared_ptr<EthereumPeer>)> const& _f) const;
void onPeerStatus(std::shared_ptr<EthereumPeer> _peer);
void onPeerHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes);
void onPeerBlocks(std::shared_ptr<EthereumPeer> _peer, RLP const& _r);
void onPeerNewHashes(std::shared_ptr<EthereumPeer> _peer, h256s const& _hashes);
void onPeerNewBlock(std::shared_ptr<EthereumPeer> _peer, RLP const& _r);
void onPeerTransactions(std::shared_ptr<EthereumPeer> _peer, RLP const& _r);
void onPeerAborting();
private:
static char const* const s_stateNames[static_cast<int>(SyncState::Size)];

65
libethereum/EthereumPeer.cpp

@ -49,7 +49,7 @@ string toString(Asking _a)
return "?";
}
EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h, unsigned _i, CapDesc const& _cap):
EthereumPeer::EthereumPeer(std::shared_ptr<Session> _s, HostCapabilityFace* _h, unsigned _i, CapDesc const& _cap):
Capability(_s, _h, _i),
m_sub(host()->downloadMan()),
m_peerCapabilityVersion(_cap.second)
@ -71,27 +71,39 @@ EthereumPeer::~EthereumPeer()
bool EthereumPeer::isRude() const
{
return repMan().isRude(*session(), name());
auto s = session();
if (s)
return repMan().isRude(*s, name());
return false;
}
unsigned EthereumPeer::askOverride() const
{
bytes const& d = repMan().data(*session(), name());
std::string static const badGeth = "Geth/v0.9.27";
auto s = session();
if (!s)
return c_maxBlocksAsk;
if (s->info().clientVersion.substr(0, badGeth.size()) == badGeth)
return 1;
bytes const& d = repMan().data(*s, name());
return d.empty() ? c_maxBlocksAsk : RLP(d).toInt<unsigned>(RLP::LaisezFaire);
}
void EthereumPeer::setRude()
{
auto s = session();
if (!s)
return;
auto old = askOverride();
repMan().setData(*session(), name(), rlp(askOverride() / 2 + 1));
repMan().setData(*s, name(), rlp(askOverride() / 2 + 1));
cnote << "Rude behaviour; askOverride now" << askOverride() << ", was" << old;
repMan().noteRude(*session(), name());
repMan().noteRude(*s, name());
session()->addNote("manners", "RUDE");
}
void EthereumPeer::abortSync()
{
host()->onPeerAborting(this);
host()->onPeerAborting();
}
EthereumHost* EthereumPeer::host() const
@ -150,6 +162,21 @@ void EthereumPeer::requestHashes(h256 const& _lastHash)
sealAndSend(s);
}
void EthereumPeer::requestBlocks(h256s const& _blocks)
{
setAsking(Asking::Blocks);
if (_blocks.size())
{
RLPStream s;
prep(s, GetBlocksPacket, _blocks.size());
for (auto const& i: _blocks)
s << i;
sealAndSend(s);
}
else
setIdle();
}
void EthereumPeer::requestBlocks()
{
setAsking(Asking::Blocks);
@ -164,7 +191,6 @@ void EthereumPeer::requestBlocks()
}
else
setIdle();
return;
}
void EthereumPeer::setAsking(Asking _a)
@ -172,15 +198,20 @@ void EthereumPeer::setAsking(Asking _a)
m_asking = _a;
m_lastAsk = chrono::system_clock::now();
session()->addNote("ask", _a == Asking::Nothing ? "nothing" : _a == Asking::State ? "state" : _a == Asking::Hashes ? "hashes" : _a == Asking::Blocks ? "blocks" : "?");
session()->addNote("sync", string(isCriticalSyncing() ? "ONGOING" : "holding") + (needsSyncing() ? " & needed" : ""));
auto s = session();
if (s)
{
s->addNote("ask", _a == Asking::Nothing ? "nothing" : _a == Asking::State ? "state" : _a == Asking::Hashes ? "hashes" : _a == Asking::Blocks ? "blocks" : "?");
s->addNote("sync", string(isCriticalSyncing() ? "ONGOING" : "holding") + (needsSyncing() ? " & needed" : ""));
}
}
void EthereumPeer::tick()
{
if (chrono::system_clock::now() - m_lastAsk > chrono::seconds(10) && m_asking != Asking::Nothing)
auto s = session();
if (s && (chrono::system_clock::now() - m_lastAsk > chrono::seconds(10) && m_asking != Asking::Nothing))
// timeout
session()->disconnect(PingTimeout);
s->disconnect(PingTimeout);
}
bool EthereumPeer::isConversing() const
@ -222,12 +253,12 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
clog(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << m_genesisHash << "/" << m_latestBlockNumber << ", TD:" << m_totalDifficulty << "=" << m_latestHash;
setAsking(Asking::Nothing);
host()->onPeerStatus(this);
host()->onPeerStatus(dynamic_pointer_cast<EthereumPeer>(dynamic_pointer_cast<EthereumPeer>(shared_from_this())));
break;
}
case TransactionsPacket:
{
host()->onPeerTransactions(this, _r);
host()->onPeerTransactions(dynamic_pointer_cast<EthereumPeer>(dynamic_pointer_cast<EthereumPeer>(shared_from_this())), _r);
break;
}
case GetBlockHashesPacket:
@ -282,7 +313,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
for (unsigned i = 0; i < itemCount; ++i)
hashes[i] = _r[i].toHash<h256>();
host()->onPeerHashes(this, hashes);
host()->onPeerHashes(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), hashes);
break;
}
case GetBlocksPacket:
@ -324,12 +355,12 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
if (m_asking != Asking::Blocks)
clog(NetImpolite) << "Peer giving us blocks when we didn't ask for them.";
else
host()->onPeerBlocks(this, _r);
host()->onPeerBlocks(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
break;
}
case NewBlockPacket:
{
host()->onPeerNewBlock(this, _r);
host()->onPeerNewBlock(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), _r);
break;
}
case NewBlockHashesPacket:
@ -341,7 +372,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
for (unsigned i = 0; i < itemCount; ++i)
hashes[i] = _r[i].toHash<h256>();
host()->onPeerNewHashes(this, hashes);
host()->onPeerNewHashes(dynamic_pointer_cast<EthereumPeer>(shared_from_this()), hashes);
break;
}
default:

5
libethereum/EthereumPeer.h

@ -56,7 +56,7 @@ class EthereumPeer: public p2p::Capability
public:
/// Basic constructor.
EthereumPeer(p2p::Session* _s, p2p::HostCapabilityFace* _h, unsigned _i, p2p::CapDesc const& _cap);
EthereumPeer(std::shared_ptr<p2p::Session> _s, p2p::HostCapabilityFace* _h, unsigned _i, p2p::CapDesc const& _cap);
/// Basic destructor.
virtual ~EthereumPeer();
@ -85,6 +85,9 @@ public:
/// Request blocks. Uses block download manager.
void requestBlocks();
/// Request specified blocks from peer.
void requestBlocks(h256s const& _blocks);
/// Check if this node is rude.
bool isRude() const;

2
libethereum/Executive.cpp

@ -316,7 +316,7 @@ bool Executive::go(OnOpFunc const& _onOp)
if (m_ext)
{
#if ETH_TIMED_EXECUTIONS
boost::timer t;
Timer t;
#endif
try
{

38
libethereum/State.cpp

@ -139,7 +139,7 @@ PopulationStatistics State::populateFromChain(BlockChain const& _bc, h256 const&
// 2. Enact the block's transactions onto this state.
m_ourAddress = bi.coinbaseAddress;
boost::timer t;
Timer t;
auto vb = BlockChain::verifyBlock(b);
ret.verify = t.elapsed();
t.restart();
@ -401,7 +401,7 @@ bool State::sync(BlockChain const& _bc, h256 _block, BlockInfo const& _bi, Impor
u256 State::enactOn(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportRequirements::value _ir)
{
#if ETH_TIMED_ENACTMENTS
boost::timer t;
Timer t;
double populateVerify;
double populateGrand;
double syncReset;
@ -456,7 +456,7 @@ unordered_map<Address, u256> State::addresses() const
ret[i.first] = RLP(i.second)[1].toInt<u256>();
return ret;
#else
throw InterfaceNotSupported("State::addresses()");
BOOST_THROW_EXCEPTION(InterfaceNotSupported("State::addresses()"));
#endif
}
@ -507,7 +507,7 @@ pair<TransactionReceipts, bool> State::sync(BlockChain const& _bc, TransactionQu
{
if (i.second.gasPrice() >= _gp.ask(*this))
{
// boost::timer t;
// Timer t;
if (lh.empty())
lh = _bc.lastHashes();
execute(lh, i.second);
@ -531,8 +531,20 @@ pair<TransactionReceipts, bool> State::sync(BlockChain const& _bc, TransactionQu
if (req > got)
{
// too old
cnote << i.first << "Dropping old transaction (nonce too low)";
_tq.drop(i.first);
for (Transaction const& t: m_transactions)
if (t.from() == i.second.from())
{
if (t.nonce() < i.second.nonce())
{
cnote << i.first << "Dropping old transaction (nonce too low)";
_tq.drop(i.first);
}
else if (t.nonce() == i.second.nonce() && t.gasPrice() <= i.second.gasPrice())
{
cnote << i.first << "Dropping old transaction (gas price lower)";
_tq.drop(i.first);
}
}
}
else if (got > req + _tq.waiting(i.second.sender()))
{
@ -634,7 +646,7 @@ u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportR
// cnote << m_state;
LastHashes lh;
DEV_TIMED_ABOVE(lastHashes, 500)
DEV_TIMED_ABOVE("lastHashes", 500)
lh = _bc.lastHashes((unsigned)m_previousBlock.number);
RLP rlp(_block.block);
@ -643,7 +655,7 @@ u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportR
// All ok with the block generally. Play back the transactions now...
unsigned i = 0;
DEV_TIMED_ABOVE(txEcec, 500)
DEV_TIMED_ABOVE("txExec", 500)
for (auto const& tr: _block.transactions)
{
try
@ -664,7 +676,7 @@ u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportR
}
h256 receiptsRoot;
DEV_TIMED_ABOVE(receiptsRoot, 500)
DEV_TIMED_ABOVE("receiptsRoot", 500)
receiptsRoot = orderedTrieRoot(receipts);
if (receiptsRoot != m_currentBlock.receiptsRoot)
@ -698,12 +710,12 @@ u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportR
vector<BlockInfo> rewarded;
h256Hash excluded;
DEV_TIMED_ABOVE(allKin, 500)
DEV_TIMED_ABOVE("allKin", 500)
excluded = _bc.allKinFrom(m_currentBlock.parentHash, 6);
excluded.insert(m_currentBlock.hash());
unsigned ii = 0;
DEV_TIMED_ABOVE(uncleCheck, 500)
DEV_TIMED_ABOVE("uncleCheck", 500)
for (auto const& i: rlp[2])
{
try
@ -752,11 +764,11 @@ u256 State::enact(VerifiedBlockRef const& _block, BlockChain const& _bc, ImportR
}
}
DEV_TIMED_ABOVE(applyRewards, 500)
DEV_TIMED_ABOVE("applyRewards", 500)
applyRewards(rewarded);
// Commit all cached state changes to the state trie.
DEV_TIMED_ABOVE(commit, 500)
DEV_TIMED_ABOVE("commit", 500)
commit();
// Hash the state trie and check against the state_root hash in m_currentBlock.

4
libethereum/State.h

@ -58,6 +58,8 @@ using errinfo_transactionIndex = boost::error_info<struct tag_transactionIndex,
using errinfo_vmtrace = boost::error_info<struct tag_vmtrace, std::string>;
using errinfo_receipts = boost::error_info<struct tag_receipts, std::vector<bytes>>;
using errinfo_transaction = boost::error_info<struct tag_transaction, bytes>;
using errinfo_phase = boost::error_info<struct tag_phase, unsigned>;
using errinfo_required_LogBloom = boost::error_info<struct tag_required_LogBloom, LogBloom>;
using errinfo_got_LogBloom = boost::error_info<struct tag_get_LogBloom, LogBloom>;
using LogBloomRequirementError = boost::tuple<errinfo_required_LogBloom, errinfo_got_LogBloom>;
@ -206,6 +208,8 @@ public:
return false;
PoW::assignResult(_result, m_currentBlock);
if (!PoW::verify(m_currentBlock))
return false;
cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce) << m_currentBlock.nonce << m_currentBlock.difficulty << PoW::verify(m_currentBlock);

7
libethereum/Transaction.cpp

@ -77,6 +77,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, TransactionException cons
{
case TransactionException::None: _out << "None"; break;
case TransactionException::BadRLP: _out << "BadRLP"; break;
case TransactionException::InvalidFormat: _out << "InvalidFormat"; break;
case TransactionException::OutOfGasIntrinsic: _out << "OutOfGasIntrinsic"; break;
case TransactionException::InvalidSignature: _out << "InvalidSignature"; break;
case TransactionException::InvalidNonce: _out << "InvalidNonce"; break;
@ -100,7 +101,7 @@ Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig)
try
{
if (!rlp.isList())
BOOST_THROW_EXCEPTION(BadRLP() << errinfo_comment("transaction RLP must be a list"));
BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("transaction RLP must be a list"));
m_nonce = rlp[field = 0].toInt<u256>();
m_gasPrice = rlp[field = 1].toInt<u256>();
@ -110,7 +111,7 @@ Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig)
m_value = rlp[field = 4].toInt<u256>();
if (!rlp[field = 5].isData())
BOOST_THROW_EXCEPTION(BadRLP() << errinfo_comment("transaction data RLP must be an array"));
BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("transaction data RLP must be an array"));
m_data = rlp[field = 5].toBytes();
byte v = rlp[field = 6].toInt<byte>() - 27;
@ -118,7 +119,7 @@ Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig)
h256 s = rlp[field = 8].toInt<u256>();
if (rlp.itemCount() > 9)
BOOST_THROW_EXCEPTION(BadRLP() << errinfo_comment("to many fields in the transaction RLP"));
BOOST_THROW_EXCEPTION(InvalidTransactionFormat() << errinfo_comment("to many fields in the transaction RLP"));
m_vrs = SignatureStruct{ r, s, v };
if (_checkSig >= CheckTransaction::Cheap && !m_vrs.isValid())

1
libethereum/Transaction.h

@ -50,6 +50,7 @@ enum class TransactionException
None = 0,
Unknown,
BadRLP,
InvalidFormat,
OutOfGasIntrinsic, ///< Too little gas to pay for the base transaction cost.
InvalidSignature,
InvalidNonce,

29
libethereum/TransactionQueue.cpp

@ -29,6 +29,7 @@ using namespace dev;
using namespace dev::eth;
const char* TransactionQueueChannel::name() { return EthCyan "┉┅▶"; }
const char* TransactionQueueTraceChannel::name() { return EthCyan " ┅▶"; }
ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallback const& _cb, IfDropped _ik)
{
@ -38,20 +39,22 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb
Transaction t;
ImportResult ir;
{
UpgradableGuard l(m_lock);
UpgradableGuard l(m_lock);
ir = check_WITH_LOCK(h, _ik);
if (ir != ImportResult::Success)
return ir;
ir = check_WITH_LOCK(h, _ik);
if (ir != ImportResult::Success)
return ir;
try {
t = Transaction(_transactionRLP, CheckTransaction::Everything);
UpgradeGuard ul(l);
ir = manageImport_WITH_LOCK(h, t, _cb);
}
catch (...) {
return ImportResult::Malformed;
}
try
{
t = Transaction(_transactionRLP, CheckTransaction::Everything);
UpgradeGuard ul(l);
ir = manageImport_WITH_LOCK(h, t, _cb);
}
catch (...)
{
return ImportResult::Malformed;
}
}
// cdebug << "import-END: Nonce of" << t.sender() << "now" << maxNonce(t.sender());
return ir;
@ -115,7 +118,7 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio
m_known.insert(_h);
if (_cb)
m_callbacks[_h] = _cb;
ctxq << "Queued vaguely legit-looking transaction" << _h;
clog(TransactionQueueTraceChannel) << "Queued vaguely legit-looking transaction" << _h;
m_onReady();
}
catch (Exception const& _e)

3
libethereum/TransactionQueue.h

@ -36,7 +36,8 @@ namespace eth
class BlockChain;
struct TransactionQueueChannel: public LogChannel { static const char* name(); static const int verbosity = 4; };
#define ctxq dev::LogOutputStream<dev::eth::TransactionQueueChannel, true>()
struct TransactionQueueTraceChannel: public LogChannel { static const char* name(); static const int verbosity = 7; };
#define ctxq dev::LogOutputStream<dev::eth::TransactionQueueTraceChannel, true>()
enum class IfDropped { Ignore, Retry };

6
libevmasm/Assembly.cpp

@ -41,7 +41,7 @@ void Assembly::append(Assembly const& _a)
if (i.type() == Tag || i.type() == PushTag)
i.setData(i.data() + m_usedTags);
else if (i.type() == PushSub || i.type() == PushSubSize)
i.setData(i.data() + m_usedTags);
i.setData(i.data() + m_subs.size());
append(i);
}
m_deposit = newDeposit;
@ -136,10 +136,10 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
_out << " PUSH [tag" << dec << i.data() << "]";
break;
case PushSub:
_out << " PUSH [$" << h256(i.data()).abridged() << "]";
_out << " PUSH [$" << h256(i.data()).abridgedMiddle() << "]";
break;
case PushSubSize:
_out << " PUSH #[$" << h256(i.data()).abridged() << "]";
_out << " PUSH #[$" << h256(i.data()).abridgedMiddle() << "]";
break;
case PushProgramSize:
_out << " PUSHSIZE";

4
libevmasm/AssemblyItem.cpp

@ -110,10 +110,10 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item)
_out << " PushData " << hex << (unsigned)_item.data();
break;
case PushSub:
_out << " PushSub " << hex << h256(_item.data()).abridged();
_out << " PushSub " << hex << h256(_item.data()).abridgedMiddle();
break;
case PushSubSize:
_out << " PushSubSize " << hex << h256(_item.data()).abridged();
_out << " PushSubSize " << hex << h256(_item.data()).abridgedMiddle();
break;
case PushProgramSize:
_out << " PushProgramSize";

8
libjsconsole/CMakeLists.txt

@ -14,6 +14,7 @@ include_directories(BEFORE ${V8_INCLUDE_DIRS})
include_directories(BEFORE ..)
include_directories(${READLINE_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
include_directories(${CURL_INCLUDE_DIRS})
set(EXECUTABLE jsconsole)
@ -24,7 +25,12 @@ add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
target_link_libraries(${EXECUTABLE} jsengine)
target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES})
target_link_libraries(${EXECUTABLE} web3jsonrpc)
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_SERVER_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES})
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls(${EXECUTABLE} CURL_DLLS)
endif()
install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

66
libjsconsole/CURLRequest.cpp

@ -0,0 +1,66 @@
/*
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 CURLRequest.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
* Ethereum client.
*/
#include "CURLRequest.h"
using namespace std;
static size_t write_data(void *buffer, size_t elementSize, size_t numberOfElements, void *userp)
{
static_cast<stringstream *>(userp)->write((const char *)buffer, elementSize * numberOfElements);
return elementSize * numberOfElements;
}
void CURLRequest::commonCURLPreparation()
{
m_resultBuffer.str("");
curl_easy_setopt(m_curl, CURLOPT_URL, (m_url + "?").c_str());
curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &m_resultBuffer);
}
std::tuple<long, string> CURLRequest::commonCURLPerform()
{
CURLcode res = curl_easy_perform(m_curl);
if (res != CURLE_OK) {
throw runtime_error(curl_easy_strerror(res));
}
long httpCode = 0;
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &httpCode);
return make_tuple(httpCode, m_resultBuffer.str());
}
std::tuple<long, string> CURLRequest::post()
{
commonCURLPreparation();
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, m_body.c_str());
struct curl_slist *headerList = NULL;
headerList = curl_slist_append(headerList, "Content-Type: application/json");
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headerList);
auto result = commonCURLPerform();
curl_slist_free_all(headerList);
return result;
}

58
libjsconsole/CURLRequest.h

@ -0,0 +1,58 @@
/*
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 CURLRequest.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
* Ethereum client.
*/
// based on http://stackoverflow.com/questions/1011339/how-do-you-make-a-http-request-with-c/27026683#27026683
#pragma once
#include <stdio.h>
#include <sstream>
#include <unordered_map>
#include <curl/curl.h>
class CURLRequest
{
public:
CURLRequest(): m_curl(curl_easy_init()) {}
~CURLRequest()
{
if (m_curl)
curl_easy_cleanup(m_curl);
}
void setUrl(std::string _url) { m_url = _url; }
void setBody(std::string _body) { m_body = _body; }
std::tuple<long, std::string> post();
private:
std::string m_url;
std::string m_body;
CURL* m_curl;
std::stringstream m_resultBuffer;
void commonCURLPreparation();
std::tuple<long, std::string> commonCURLPerform();
};

62
libjsconsole/JSConsole.cpp

@ -20,65 +20,5 @@
* Ethereum client.
*/
#include <iostream>
#include <libdevcore/Log.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include "JSConsole.h"
#include "JSV8Connector.h"
// TODO! make readline optional!
#include <readline/readline.h>
#include <readline/history.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
JSConsole::JSConsole(WebThreeDirect& _web3, shared_ptr<AccountHolder> const& _accounts):
m_engine(),
m_printer(m_engine)
{
m_jsonrpcConnector.reset(new JSV8Connector(m_engine));
(void)_web3; (void)_accounts;
// m_jsonrpcServer.reset(new WebThreeStubServer(*m_jsonrpcConnector.get(), _web3, _accounts, vector<KeyPair>()));
}
void JSConsole::readExpression() const
{
string cmd = "";
g_logPost = [](std::string const& a, char const*) { cout << "\r \r" << a << endl << flush; rl_forced_update_display(); };
bool isEmpty = true;
int openBrackets = 0;
do {
char* buff = readline(promptForIndentionLevel(openBrackets).c_str());
isEmpty = !(buff && *buff);
if (!isEmpty)
{
cmd += string(buff);
cmd += " ";
free(buff);
int open = count(cmd.begin(), cmd.end(), '{');
open += count(cmd.begin(), cmd.end(), '(');
int closed = count(cmd.begin(), cmd.end(), '}');
closed += count(cmd.begin(), cmd.end(), ')');
openBrackets = open - closed;
}
} while (openBrackets > 0);
if (!isEmpty)
{
add_history(cmd.c_str());
auto value = m_engine.eval(cmd.c_str());
string result = m_printer.prettyPrint(value).cstr();
cout << result << endl;
}
}
std::string JSConsole::promptForIndentionLevel(int _i) const
{
if (_i == 0)
return "> ";
return string((_i + 1) * 2, ' ');
}
#include "JSConsole.h"

64
libjsconsole/JSConsole.h

@ -22,32 +22,66 @@
#pragma once
#include <libjsengine/JSV8Engine.h>
#include <libjsengine/JSV8Printer.h>
namespace dev { class WebThreeStubServer; }
namespace jsonrpc { class AbstractServerConnector; }
#include <libdevcore/Log.h>
// TODO! make readline optional!
#include <readline/readline.h>
#include <readline/history.h>
namespace dev
{
namespace eth
{
class AccountHolder;
template<typename Engine, typename Printer>
class JSConsole
{
public:
JSConsole(WebThreeDirect& _web3, std::shared_ptr<AccountHolder> const& _accounts);
void readExpression() const;
JSConsole(): m_engine(Engine()), m_printer(Printer(m_engine)) {}
~JSConsole() {}
void readExpression() const
{
std::string cmd = "";
g_logPost = [](std::string const& a, char const*) { std::cout << "\r \r" << a << std::endl << std::flush; rl_forced_update_display(); };
bool isEmpty = true;
int openBrackets = 0;
do {
char* buff = readline(promptForIndentionLevel(openBrackets).c_str());
isEmpty = !(buff && *buff);
if (!isEmpty)
{
cmd += std::string(buff);
cmd += " ";
free(buff);
int open = std::count(cmd.begin(), cmd.end(), '{');
open += std::count(cmd.begin(), cmd.end(), '(');
int closed = std::count(cmd.begin(), cmd.end(), '}');
closed += std::count(cmd.begin(), cmd.end(), ')');
openBrackets = open - closed;
}
} while (openBrackets > 0);
if (!isEmpty)
{
add_history(cmd.c_str());
auto value = m_engine.eval(cmd.c_str());
std::string result = m_printer.prettyPrint(value).cstr();
std::cout << result << std::endl;
}
}
protected:
Engine m_engine;
Printer m_printer;
private:
std::string promptForIndentionLevel(int _i) const;
virtual std::string promptForIndentionLevel(int _i) const
{
if (_i == 0)
return "> ";
JSV8Engine m_engine;
JSV8Printer m_printer;
std::unique_ptr<dev::WebThreeStubServer> m_jsonrpcServer;
std::unique_ptr<jsonrpc::AbstractServerConnector> m_jsonrpcConnector;
return std::string((_i + 1) * 2, ' ');
}
};
}

34
libjsconsole/JSLocalConsole.cpp

@ -0,0 +1,34 @@
/*
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 JSLocalConsole.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
* Ethereum client.
*/
#include <iostream>
#include "JSLocalConsole.h"
#include "JSV8Connector.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
JSLocalConsole::JSLocalConsole()
{
m_jsonrpcConnector.reset(new JSV8Connector(m_engine));
}

50
libjsconsole/JSLocalConsole.h

@ -0,0 +1,50 @@
/*
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 JSLocalConsole.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
* Ethereum client.
*/
#pragma once
#include <libjsengine/JSV8Engine.h>
#include <libjsengine/JSV8Printer.h>
#include "JSConsole.h"
class WebThreeStubServer;
namespace jsonrpc { class AbstractServerConnector; }
namespace dev
{
namespace eth
{
class JSLocalConsole: public JSConsole<JSV8Engine, JSV8Printer>
{
public:
JSLocalConsole();
virtual ~JSLocalConsole() {}
jsonrpc::AbstractServerConnector* connector() { return m_jsonrpcConnector.get(); }
private:
std::unique_ptr<jsonrpc::AbstractServerConnector> m_jsonrpcConnector;
};
}
}

23
libjsconsole/JSRemoteConsole.cpp

@ -0,0 +1,23 @@
/*
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 JSRemoteConsole.cpp
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
* Ethereum client.
*/
#include "JSRemoteConsole.h"

48
libjsconsole/JSRemoteConsole.h

@ -0,0 +1,48 @@
/*
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 JSRemoteConsole.h
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2015
* Ethereum client.
*/
#pragma once
#include <libjsengine/JSV8Engine.h>
#include <libjsengine/JSV8Printer.h>
#include "JSV8RemoteConnector.h"
#include "JSConsole.h"
namespace dev
{
namespace eth
{
class JSRemoteConsole: public JSConsole<JSV8Engine, JSV8Printer>
{
public:
JSRemoteConsole(std::string _url): m_connector(m_engine, _url) {}
virtual ~JSRemoteConsole() {}
private:
JSV8RemoteConnector m_connector;
};
}
}

2
libjsconsole/JSV8Connector.h

@ -43,7 +43,7 @@ public:
bool SendResponse(std::string const& _response, void* _addInfo = nullptr);
// implement JSV8RPC interface
void onSend(char const* payload);
void onSend(char const* _payload);
};
}

20
libjsconsole/JSV8RemoteConnector.cpp

@ -0,0 +1,20 @@
//
// Created by Marek Kotewicz on 15/06/15.
//
#include "JSV8RemoteConnector.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
void JSV8RemoteConnector::onSend(char const* _payload)
{
m_request.setUrl(m_url);
m_request.setBody(_payload);
long code;
string response;
tie(code, response) = m_request.post();
(void)code;
m_lastResponse = response.c_str();
}

32
libjsconsole/JSV8RemoteConnector.h

@ -0,0 +1,32 @@
//
// Created by Marek Kotewicz on 15/06/15.
//
#pragma once
#include <string>
#include <libjsengine/JSV8RPC.h>
#include "CURLRequest.h"
namespace dev
{
namespace eth
{
class JSV8RemoteConnector : public JSV8RPC
{
public:
JSV8RemoteConnector(JSV8Engine const& _engine, std::string _url): JSV8RPC(_engine), m_url(_url) {}
virtual ~JSV8RemoteConnector() {}
// implement JSV8RPC interface
void onSend(char const* _payload);
private:
std::string m_url;
CURLRequest m_request;
};
}
}

3
libjsengine/JSResources.cmake

@ -1,8 +1,9 @@
set(web3 "${CMAKE_CURRENT_LIST_DIR}/../libjsqrc/ethereumjs/dist/web3.js")
set(admin "${CMAKE_CURRENT_LIST_DIR}/../libjsqrc/admin.js")
set(pretty_print "${CMAKE_CURRENT_LIST_DIR}/PrettyPrint.js")
set(common "${CMAKE_CURRENT_LIST_DIR}/Common.js")
set(ETH_RESOURCE_NAME "JSEngineResources")
set(ETH_RESOURCE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}")
set(ETH_RESOURCES "web3" "pretty_print" "common")
set(ETH_RESOURCES "web3" "pretty_print" "common" "admin")

2
libjsengine/JSV8Engine.cpp

@ -143,9 +143,11 @@ JSV8Engine::JSV8Engine(): m_scope(new JSV8Scope())
JSEngineResources resources;
string common = resources.loadResourceAsString("common");
string web3 = resources.loadResourceAsString("web3");
string admin = resources.loadResourceAsString("admin");
eval(common.c_str());
eval(web3.c_str());
eval("web3 = require('web3');");
eval(admin.c_str());
}
JSV8Engine::~JSV8Engine()

3
libjsengine/JSV8Engine.h

@ -22,7 +22,10 @@
#pragma once
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#include <v8.h>
#pragma clang diagnostic pop
#include "JSEngine.h"
namespace dev

120
libjsqrc/admin.js

@ -0,0 +1,120 @@
web3.admin = {};
web3.admin.setSessionKey = function(s) { web3.admin.sessionKey = s; };
var getSessionKey = function () { return web3.admin.sessionKey; };
web3._extend({
property: 'admin',
methods: [new web3._extend.Method({
name: 'web3.setVerbosity',
call: 'admin_web3_setVerbosity',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'net.start',
call: 'admin_net_start',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'net.stop',
call: 'admin_net_stop',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'net.connect',
call: 'admin_net_connect',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'net.peers',
call: 'admin_net_peers',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.blockQueueStatus',
call: 'admin_eth_blockQueueStatus',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.setAskPrice',
call: 'admin_eth_setAskPrice',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setBidPrice',
call: 'admin_eth_setBidPrice',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setReferencePrice',
call: 'admin_eth_setReferencePrice',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setPriority',
call: 'admin_eth_setPriority',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setMining',
call: 'admin_eth_setMining',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.findBlock',
call: 'admin_eth_findBlock',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.blockQueueFirstUnknown',
call: 'admin_eth_blockQueueFirstUnknown',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.blockQueueRetryUnknown',
call: 'admin_eth_blockQueueRetryUnknown',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.allAccounts',
call: 'admin_eth_allAccounts',
inputFormatter: [getSessionKey],
params: 1
}), new web3._extend.Method({
name: 'eth.newAccount',
call: 'admin_eth_newAccount',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setSigningKey',
call: 'admin_eth_setSigningKey',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.setMiningBenefactor',
call: 'admin_eth_setMiningBenefactor',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.inspect',
call: 'admin_eth_inspect',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.reprocess',
call: 'admin_eth_reprocess',
inputFormatter: [null, getSessionKey],
params: 2
}), new web3._extend.Method({
name: 'eth.vmTrace',
call: 'admin_eth_vmTrace',
inputFormatter: [null, null, getSessionKey],
params: 3
}), new web3._extend.Method({
name: 'eth.getReceiptByHashAndIndex',
call: 'admin_eth_getReceiptByHashAndIndex',
inputFormatter: [null, null, getSessionKey],
params: 3
})]
});

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

Loading…
Cancel
Save