Browse Source

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

cl-refactor
arkpar 10 years ago
parent
commit
12bb49d79b
  1. 5
      cmake/EthCompilerSettings.cmake
  2. 99
      eth/main.cpp
  3. 114
      ethminer/MinerAux.h
  4. 2
      libdevcore/FixedHash.h
  5. 3
      libdevcore/vector_ref.h
  6. 61
      libethash-cl/ethash_cl_miner.cpp
  7. 11
      libethash-cl/ethash_cl_miner.h
  8. 2
      libethash-cl/ethash_cl_miner_kernel.cl
  9. 12
      libethcore/Ethash.cpp
  10. 15
      libethcore/Ethash.h
  11. 5
      libethcore/EthashAux.cpp
  12. 1
      libethcore/EthashAux.h
  13. 9
      libethereum/Client.cpp
  14. 15
      libethereum/ClientBase.cpp
  15. 1
      libethereum/ClientBase.h
  16. 3
      libethereum/EthereumHost.cpp
  17. 3
      libethereum/Precompiled.cpp
  18. 7
      libethereum/State.cpp
  19. 2
      test/TestHelper.cpp
  20. 13
      test/libevm/vm.cpp

5
cmake/EthCompilerSettings.cmake

@ -55,6 +55,11 @@ else ()
message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.")
endif () endif ()
# Set stack memory limits
if (APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-stack_size,1000000")
endif()
if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))) if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")))
set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}")
set(CMAKE_C_FLAGS "-g ${CMAKE_C_FLAGS}") set(CMAKE_C_FLAGS "-g ${CMAKE_C_FLAGS}")

99
eth/main.cpp

@ -93,6 +93,7 @@ void interactiveHelp()
<< " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl << " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl
<< " newaccount <name> Creates a new account with the given name." << endl << " newaccount <name> Creates a new account with the given name." << endl
<< " transact Execute a given transaction." << endl << " transact Execute a given transaction." << endl
<< " transactnonce Execute a given transaction with a specified nonce." << endl
<< " txcreate Execute a given contract creation transaction." << endl << " txcreate Execute a given contract creation transaction." << endl
<< " send Execute a given transaction with current secret." << endl << " send Execute a given transaction with current secret." << endl
<< " contract Create a new contract with current secret." << endl << " contract Create a new contract with current secret." << endl
@ -108,6 +109,7 @@ void interactiveHelp()
<< " exportconfig <path> Export the config (.RLP) to the path provided." << endl << " exportconfig <path> Export the config (.RLP) to the path provided." << endl
<< " importconfig <path> Import the config (.RLP) from the path provided." << endl << " importconfig <path> Import the config (.RLP) from the path provided." << endl
<< " inspect <contract> Dumps a contract to <APPDATA>/<contract>.evm." << endl << " inspect <contract> Dumps a contract to <APPDATA>/<contract>.evm." << endl
<< " reprocess <block> Reprocess a given block." << endl
<< " dumptrace <block> <index> <filename> <format> Dumps a transaction trace" << endl << "to <filename>. <format> should be one of pretty, standard, standard+." << endl << " dumptrace <block> <index> <filename> <format> Dumps a transaction trace" << endl << "to <filename>. <format> should be one of pretty, standard, standard+." << endl
<< " dumpreceipt <block> <index> Dumps a transation receipt." << endl << " dumpreceipt <block> <index> Dumps a transation receipt." << endl
<< " exit Exits the application." << endl; << " exit Exits the application." << endl;
@ -806,13 +808,19 @@ int main(int argc, char** argv)
cout << "Transaction Signer: " << signingKey << endl; cout << "Transaction Signer: " << signingKey << endl;
cout << "Mining Benefactor: " << beneficiary << endl; cout << "Mining Benefactor: " << beneficiary << endl;
web3.startNetwork();
cout << "Node ID: " << web3.enode() << endl; if (bootstrap || !remoteHost.empty())
{
web3.startNetwork();
cout << "Node ID: " << web3.enode() << endl;
}
else
cout << "Networking disabled. To start, use netstart or pass -b or a remote host." << endl;
if (bootstrap) if (bootstrap)
for (auto const& i: Host::pocHosts()) for (auto const& i: Host::pocHosts())
web3.requirePeer(i.first, i.second); web3.requirePeer(i.first, i.second);
if (remoteHost.size()) if (!remoteHost.empty())
web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort));
#if ETH_JSONRPC || !ETH_TRUE #if ETH_JSONRPC || !ETH_TRUE
@ -1175,6 +1183,75 @@ int main(int argc, char** argv)
else else
cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA"; cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA";
} }
else if (c && cmd == "transactnonce")
{
auto const& bc =c->blockChain();
auto h = bc.currentHash();
auto blockData = bc.block(h);
BlockInfo info(blockData);
if (iss.peek() != -1)
{
string hexAddr;
u256 amount;
u256 gasPrice;
u256 gas;
string sechex;
string sdata;
u256 nonce;
iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata >> nonce;
if (!gasPrice)
gasPrice = gasPricer->bid(priority);
cnote << "Data:";
cnote << sdata;
bytes data = dev::eth::parseData(sdata);
cnote << "Bytes:";
string sbd = asString(data);
bytes bbd = asBytes(sbd);
stringstream ssbd;
ssbd << bbd;
cnote << ssbd.str();
int ssize = sechex.length();
int size = hexAddr.length();
u256 minGas = (u256)Transaction::gasRequired(data, 0);
if (size < 40)
{
if (size > 0)
cwarn << "Invalid address length:" << size;
}
else if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas;
else if (ssize < 40)
{
if (ssize > 0)
cwarn << "Invalid secret length:" << ssize;
}
else
{
try
{
Secret secret = h256(fromHex(sechex));
Address dest = h160(fromHex(hexAddr));
c->submitTransaction(secret, amount, dest, data, gas, gasPrice, nonce);
}
catch (BadHexCharacter& _e)
{
cwarn << "invalid hex character, transaction rejected";
cwarn << boost::diagnostic_information(_e);
}
catch (...)
{
cwarn << "transaction rejected";
}
}
}
else
cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA NONCE";
}
else if (c && cmd == "txcreate") else if (c && cmd == "txcreate")
{ {
auto const& bc =c->blockChain(); auto const& bc =c->blockChain();
@ -1403,6 +1480,22 @@ int main(int argc, char** argv)
cout << "Hex: " << toHex(rb) << endl; cout << "Hex: " << toHex(rb) << endl;
cout << r << endl; cout << r << endl;
} }
else if (c && cmd == "reprocess")
{
string block;
iss >> block;
h256 blockHash;
try
{
if (block.size() == 64 || block.size() == 66)
blockHash = h256(block);
else
blockHash = c->blockChain().numberHash(stoi(block));
c->state(blockHash);
}
catch (...)
{}
}
else if (c && cmd == "dumptrace") else if (c && cmd == "dumptrace")
{ {
unsigned block; unsigned block;

114
ethminer/MinerAux.h

@ -30,6 +30,7 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp> #include <boost/algorithm/string/trim_all.hpp>
#include <boost/optional.hpp>
#include <libdevcore/FileSystem.h> #include <libdevcore/FileSystem.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
@ -97,11 +98,11 @@ public:
if ((arg == "-F" || arg == "--farm") && i + 1 < argc) if ((arg == "-F" || arg == "--farm") && i + 1 < argc)
{ {
mode = OperationMode::Farm; mode = OperationMode::Farm;
farmURL = argv[++i]; m_farmURL = argv[++i];
} }
else if (arg == "--farm-recheck" && i + 1 < argc) else if (arg == "--farm-recheck" && i + 1 < argc)
try { try {
farmRecheckPeriod = stol(argv[++i]); m_farmRecheckPeriod = stol(argv[++i]);
} }
catch (...) catch (...)
{ {
@ -110,7 +111,7 @@ public:
} }
else if (arg == "--opencl-platform" && i + 1 < argc) else if (arg == "--opencl-platform" && i + 1 < argc)
try { try {
openclPlatform = stol(argv[++i]); m_openclPlatform = stol(argv[++i]);
} }
catch (...) catch (...)
{ {
@ -119,8 +120,8 @@ public:
} }
else if (arg == "--opencl-device" && i + 1 < argc) else if (arg == "--opencl-device" && i + 1 < argc)
try { try {
openclDevice = stol(argv[++i]); m_openclDevice = stol(argv[++i]);
miningThreads = 1; m_miningThreads = 1;
} }
catch (...) catch (...)
{ {
@ -128,17 +129,18 @@ public:
throw BadArgument(); throw BadArgument();
} }
else if (arg == "--list-devices") else if (arg == "--list-devices")
{ m_shouldListDevices = true;
ProofOfWork::GPUMiner::listDevices(); else if (arg == "--allow-opencl-cpu")
exit(0); m_clAllowCPU = true;
} else if (arg == "--cl-extragpu-mem" && i + 1 < argc)
m_extraGPUMemory = 1000000 * stol(argv[++i]);
else if (arg == "--phone-home" && i + 1 < argc) else if (arg == "--phone-home" && i + 1 < argc)
{ {
string m = argv[++i]; string m = argv[++i];
if (isTrue(m)) if (isTrue(m))
phoneHome = true; m_phoneHome = true;
else if (isFalse(m)) else if (isFalse(m))
phoneHome = false; m_phoneHome = false;
else else
{ {
cerr << "Bad " << arg << " option: " << m << endl; cerr << "Bad " << arg << " option: " << m << endl;
@ -147,7 +149,7 @@ public:
} }
else if (arg == "--benchmark-warmup" && i + 1 < argc) else if (arg == "--benchmark-warmup" && i + 1 < argc)
try { try {
benchmarkWarmup = stol(argv[++i]); m_benchmarkWarmup = stol(argv[++i]);
} }
catch (...) catch (...)
{ {
@ -156,7 +158,7 @@ public:
} }
else if (arg == "--benchmark-trial" && i + 1 < argc) else if (arg == "--benchmark-trial" && i + 1 < argc)
try { try {
benchmarkTrial = stol(argv[++i]); m_benchmarkTrial = stol(argv[++i]);
} }
catch (...) catch (...)
{ {
@ -165,7 +167,7 @@ public:
} }
else if (arg == "--benchmark-trials" && i + 1 < argc) else if (arg == "--benchmark-trials" && i + 1 < argc)
try { try {
benchmarkTrials = stol(argv[++i]); m_benchmarkTrials = stol(argv[++i]);
} }
catch (...) catch (...)
{ {
@ -175,21 +177,12 @@ public:
else if (arg == "-C" || arg == "--cpu") else if (arg == "-C" || arg == "--cpu")
m_minerType = MinerType::CPU; m_minerType = MinerType::CPU;
else if (arg == "-G" || arg == "--opencl") else if (arg == "-G" || arg == "--opencl")
{ m_minerType = MinerType::GPU;
if (!ProofOfWork::GPUMiner::configureGPU()) else if (arg == "--current-block" && i + 1 < argc)
{ m_currentBlock = stol(argv[++i]);
cout << "No GPU device with sufficient memory was found. Defaulting to CPU" << endl;
m_minerType = MinerType::CPU;
}
else
{
m_minerType = MinerType::GPU;
miningThreads = 1;
}
}
else if (arg == "--no-precompute") else if (arg == "--no-precompute")
{ {
precompute = false; m_precompute = false;
} }
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc)
{ {
@ -197,7 +190,7 @@ public:
mode = OperationMode::DAGInit; mode = OperationMode::DAGInit;
try try
{ {
initDAG = stol(m); m_initDAG = stol(m);
} }
catch (...) catch (...)
{ {
@ -247,7 +240,7 @@ public:
else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc)
{ {
try { try {
miningThreads = stol(argv[++i]); m_miningThreads = stol(argv[++i]);
} }
catch (...) catch (...)
{ {
@ -262,20 +255,35 @@ public:
void execute() void execute()
{ {
if (m_shouldListDevices)
{
ProofOfWork::GPUMiner::listDevices();
exit(0);
}
if (m_minerType == MinerType::CPU) if (m_minerType == MinerType::CPU)
ProofOfWork::CPUMiner::setNumInstances(miningThreads); ProofOfWork::CPUMiner::setNumInstances(m_miningThreads);
else if (m_minerType == MinerType::GPU) else if (m_minerType == MinerType::GPU)
{ {
ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); ProofOfWork::GPUMiner::setNumInstances(m_miningThreads);
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); if (!ProofOfWork::GPUMiner::configureGPU(
ProofOfWork::GPUMiner::setNumInstances(miningThreads); m_openclPlatform,
m_openclDevice,
m_clAllowCPU,
m_extraGPUMemory,
m_currentBlock
))
{
cout << "No GPU device with sufficient memory was found. Can't GPU mine. Remove the -G argument" << endl;
exit(1);
}
} }
if (mode == OperationMode::DAGInit) if (mode == OperationMode::DAGInit)
doInitDAG(initDAG); doInitDAG(m_initDAG);
else if (mode == OperationMode::Benchmark) else if (mode == OperationMode::Benchmark)
doBenchmark(m_minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); doBenchmark(m_minerType, m_phoneHome, m_benchmarkWarmup, m_benchmarkTrial, m_benchmarkTrials);
else if (mode == OperationMode::Farm) else if (mode == OperationMode::Farm)
doFarm(m_minerType, farmURL, farmRecheckPeriod); doFarm(m_minerType, m_farmURL, m_farmRecheckPeriod);
} }
static void streamHelp(ostream& _out) static void streamHelp(ostream& _out)
@ -306,6 +314,10 @@ public:
<< " --opencl-platform <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl << " --opencl-platform <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl
<< " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl << " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl
<< " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl << " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl
<< " --allow-opencl-cpu Allows CPU to be considered as an OpenCL device if the OpenCL platform supports it." << endl
<< " --list-devices List the detected OpenCL devices and exit." <<endl
<< " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." <<endl
<< " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." <<endl
; ;
} }
@ -441,7 +453,7 @@ private:
cnote << "Grabbing DAG for" << newSeedHash; cnote << "Grabbing DAG for" << newSeedHash;
if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; })))
BOOST_THROW_EXCEPTION(DAGCreationFailure()); BOOST_THROW_EXCEPTION(DAGCreationFailure());
if (precompute) if (m_precompute)
EthashAux::computeFull(sha3(newSeedHash), true); EthashAux::computeFull(sha3(newSeedHash), true);
if (hh != current.headerHash) if (hh != current.headerHash)
{ {
@ -490,22 +502,26 @@ private:
/// Mining options /// Mining options
MinerType m_minerType = MinerType::CPU; MinerType m_minerType = MinerType::CPU;
unsigned openclPlatform = 0; unsigned m_openclPlatform = 0;
unsigned openclDevice = 0; unsigned m_openclDevice = 0;
unsigned miningThreads = UINT_MAX; unsigned m_miningThreads = UINT_MAX;
unsigned dagChunks = 1; bool m_shouldListDevices = false;
bool m_clAllowCPU = false;
boost::optional<uint64_t> m_currentBlock;
// default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.)
unsigned m_extraGPUMemory = 350000000;
/// DAG initialisation param. /// DAG initialisation param.
unsigned initDAG = 0; unsigned m_initDAG = 0;
/// Benchmarking params /// Benchmarking params
bool phoneHome = true; bool m_phoneHome = true;
unsigned benchmarkWarmup = 3; unsigned m_benchmarkWarmup = 3;
unsigned benchmarkTrial = 3; unsigned m_benchmarkTrial = 3;
unsigned benchmarkTrials = 5; unsigned m_benchmarkTrials = 5;
/// Farm params /// Farm params
string farmURL = "http://127.0.0.1:8545"; string m_farmURL = "http://127.0.0.1:8545";
unsigned farmRecheckPeriod = 500; unsigned m_farmRecheckPeriod = 500;
bool precompute = true; bool m_precompute = true;
}; };

2
libdevcore/FixedHash.h

@ -100,7 +100,7 @@ public:
FixedHash operator|(FixedHash const& _c) const { return FixedHash(*this) |= _c; } FixedHash operator|(FixedHash const& _c) const { return FixedHash(*this) |= _c; }
FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; } FixedHash& operator&=(FixedHash const& _c) { for (unsigned i = 0; i < N; ++i) m_data[i] &= _c.m_data[i]; return *this; }
FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; } FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; }
FixedHash& operator~() { for (unsigned i = 0; i < N; ++i) m_data[i] = ~m_data[i]; return *this; } FixedHash operator~() const { FixedHash ret; for (unsigned i = 0; i < N; ++i) ret[i] = ~m_data[i]; return ret; }
/// @returns true if all bytes in @a _c are set in this object. /// @returns true if all bytes in @a _c are set in this object.
bool contains(FixedHash const& _c) const { return (*this & _c) == _c; } bool contains(FixedHash const& _c) const { return (*this & _c) == _c; }

3
libdevcore/vector_ref.h

@ -43,7 +43,8 @@ public:
vector_ref<_T> cropped(size_t _begin) const { if (m_data && _begin <= m_count) return vector_ref<_T>(m_data + _begin, m_count - _begin); else return vector_ref<_T>(); } vector_ref<_T> cropped(size_t _begin) const { if (m_data && _begin <= m_count) return vector_ref<_T>(m_data + _begin, m_count - _begin); else return vector_ref<_T>(); }
void retarget(_T* _d, size_t _s) { m_data = _d; m_count = _s; } void retarget(_T* _d, size_t _s) { m_data = _d; m_count = _s; }
void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); } void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); }
void copyTo(vector_ref<typename std::remove_const<_T>::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); } template <class T> bool overlapsWith(vector_ref<T> _t) const { void const* f1 = data(); void const* t1 = data() + size(); void const* f2 = _t.data(); void const* t2 = _t.data() + _t.size(); return f1 < t2 && t1 > f2; }
void copyTo(vector_ref<typename std::remove_const<_T>::type> _t) const { if (overlapsWith(_t)) memmove(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); else memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); }
void populate(vector_ref<typename std::remove_const<_T>::type> _t) const { copyTo(_t); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); } void populate(vector_ref<typename std::remove_const<_T>::type> _t) const { copyTo(_t); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); }
_T* begin() { return m_data; } _T* begin() { return m_data; }

61
libethash-cl/ethash_cl_miner.cpp

@ -32,11 +32,11 @@
#include <vector> #include <vector>
#include <libethash/util.h> #include <libethash/util.h>
#include <libethash/ethash.h> #include <libethash/ethash.h>
#include <libethash/internal.h>
#include "ethash_cl_miner.h" #include "ethash_cl_miner.h"
#include "ethash_cl_miner_kernel.h" #include "ethash_cl_miner_kernel.h"
#define ETHASH_BYTES 32 #define ETHASH_BYTES 32
#define ETHASH_CL_MINIMUM_MEMORY 2000000000
// workaround lame platforms // workaround lame platforms
#if !CL_VERSION_1_2 #if !CL_VERSION_1_2
@ -51,6 +51,8 @@ using namespace std;
// TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel // TODO: If at any point we can use libdevcore in here then we should switch to using a LogChannel
#define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl #define ETHCL_LOG(_contents) cout << "[OPENCL]:" << _contents << endl
// Types of OpenCL devices we are interested in
#define ETHCL_QUERIED_DEVICE_TYPES (CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_ACCELERATOR)
static void addDefinition(string& _source, char const* _id, unsigned _value) static void addDefinition(string& _source, char const* _id, unsigned _value)
{ {
@ -82,9 +84,8 @@ string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId)
} }
// get GPU device of the selected platform // get GPU device of the selected platform
vector<cl::Device> devices;
unsigned platform_num = min<unsigned>(_platformId, platforms.size() - 1); unsigned platform_num = min<unsigned>(_platformId, platforms.size() - 1);
platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices); vector<cl::Device> devices = getDevices(platforms, _platformId);
if (devices.empty()) if (devices.empty())
{ {
ETHCL_LOG("No OpenCL devices found."); ETHCL_LOG("No OpenCL devices found.");
@ -99,6 +100,17 @@ string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId)
return "{ \"platform\": \"" + platforms[platform_num].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }"; return "{ \"platform\": \"" + platforms[platform_num].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }";
} }
std::vector<cl::Device> ethash_cl_miner::getDevices(std::vector<cl::Platform> const& _platforms, unsigned _platformId)
{
vector<cl::Device> devices;
unsigned platform_num = min<unsigned>(_platformId, _platforms.size() - 1);
_platforms[platform_num].getDevices(
s_allowCPU ? CL_DEVICE_TYPE_ALL : ETHCL_QUERIED_DEVICE_TYPES,
&devices
);
return devices;
}
unsigned ethash_cl_miner::getNumPlatforms() unsigned ethash_cl_miner::getNumPlatforms()
{ {
vector<cl::Platform> platforms; vector<cl::Platform> platforms;
@ -116,9 +128,7 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId)
return 0; return 0;
} }
vector<cl::Device> devices; vector<cl::Device> devices = getDevices(platforms, _platformId);
unsigned platform_num = min<unsigned>(_platformId, platforms.size() - 1);
platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices);
if (devices.empty()) if (devices.empty())
{ {
ETHCL_LOG("No OpenCL devices found."); ETHCL_LOG("No OpenCL devices found.");
@ -127,13 +137,18 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId)
return devices.size(); return devices.size();
} }
bool ethash_cl_miner::configureGPU() bool ethash_cl_miner::configureGPU(bool _allowCPU, unsigned _extraGPUMemory, boost::optional<uint64_t> _currentBlock)
{ {
return searchForAllDevices([](cl::Device const _device) -> bool s_allowCPU = _allowCPU;
s_extraRequiredGPUMem = _extraGPUMemory;
// by default let's only consider the DAG of the first epoch
uint64_t dagSize = _currentBlock ? ethash_get_datasize(*_currentBlock) : 1073739904U;
uint64_t requiredSize = dagSize + _extraGPUMemory;
return searchForAllDevices([&requiredSize](cl::Device const _device) -> bool
{ {
cl_ulong result; cl_ulong result;
_device.getInfo(CL_DEVICE_GLOBAL_MEM_SIZE, &result); _device.getInfo(CL_DEVICE_GLOBAL_MEM_SIZE, &result);
if (result >= ETHASH_CL_MINIMUM_MEMORY) if (result >= requiredSize)
{ {
ETHCL_LOG( ETHCL_LOG(
"Found suitable OpenCL device [" << _device.getInfo<CL_DEVICE_NAME>() "Found suitable OpenCL device [" << _device.getInfo<CL_DEVICE_NAME>()
@ -145,13 +160,16 @@ bool ethash_cl_miner::configureGPU()
ETHCL_LOG( ETHCL_LOG(
"OpenCL device " << _device.getInfo<CL_DEVICE_NAME>() "OpenCL device " << _device.getInfo<CL_DEVICE_NAME>()
<< " has insufficient GPU memory." << result << << " has insufficient GPU memory." << result <<
" bytes of memory found < " << ETHASH_CL_MINIMUM_MEMORY << " bytes of memory required" " bytes of memory found < " << requiredSize << " bytes of memory required"
); );
return false; return false;
} }
); );
} }
bool ethash_cl_miner::s_allowCPU = false;
unsigned ethash_cl_miner::s_extraRequiredGPUMem;
bool ethash_cl_miner::searchForAllDevices(function<bool(cl::Device const&)> _callback) bool ethash_cl_miner::searchForAllDevices(function<bool(cl::Device const&)> _callback)
{ {
vector<cl::Platform> platforms; vector<cl::Platform> platforms;
@ -175,8 +193,7 @@ bool ethash_cl_miner::searchForAllDevices(unsigned _platformId, function<bool(cl
if (_platformId >= platforms.size()) if (_platformId >= platforms.size())
return false; return false;
vector<cl::Device> devices; vector<cl::Device> devices = getDevices(platforms, _platformId);
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices);
for (cl::Device const& device: devices) for (cl::Device const& device: devices)
if (_callback(device)) if (_callback(device))
return true; return true;
@ -204,8 +221,7 @@ void ethash_cl_miner::doForAllDevices(unsigned _platformId, function<void(cl::De
if (_platformId >= platforms.size()) if (_platformId >= platforms.size())
return; return;
vector<cl::Device> devices; vector<cl::Device> devices = getDevices(platforms, _platformId);
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices);
for (cl::Device const& device: devices) for (cl::Device const& device: devices)
_callback(device); _callback(device);
} }
@ -253,8 +269,7 @@ bool ethash_cl_miner::init(
ETHCL_LOG("Using platform: " << platforms[_platformId].getInfo<CL_PLATFORM_NAME>().c_str()); ETHCL_LOG("Using platform: " << platforms[_platformId].getInfo<CL_PLATFORM_NAME>().c_str());
// get GPU device of the default platform // get GPU device of the default platform
vector<cl::Device> devices; vector<cl::Device> devices = getDevices(platforms, _platformId);
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices);
if (devices.empty()) if (devices.empty())
{ {
ETHCL_LOG("No OpenCL devices found."); ETHCL_LOG("No OpenCL devices found.");
@ -267,9 +282,19 @@ bool ethash_cl_miner::init(
ETHCL_LOG("Using device: " << device.getInfo<CL_DEVICE_NAME>().c_str() << "(" << device_version.c_str() << ")"); ETHCL_LOG("Using device: " << device.getInfo<CL_DEVICE_NAME>().c_str() << "(" << device_version.c_str() << ")");
// configure chunk number depending on max allocateable memory // configure chunk number depending on max allocateable memory
cl_ulong result; cl_ulong result;
device.getInfo(CL_DEVICE_MAX_MEM_ALLOC_SIZE, &result); device.getInfo(CL_DEVICE_MAX_MEM_ALLOC_SIZE, &result);
m_dagChunksNum = result >= ETHASH_CL_MINIMUM_MEMORY ? 4 : 1; if (result >= _dagSize)
{
m_dagChunksNum = 1;
ETHCL_LOG("Using 1 big chunk. Max OpenCL allocateable memory is" << result);
}
else
{
m_dagChunksNum = 4;
ETHCL_LOG("Using 4 chunks. Max OpenCL allocateable memory is" << result);
}
if (strncmp("OpenCL 1.0", device_version.c_str(), 10) == 0) if (strncmp("OpenCL 1.0", device_version.c_str(), 10) == 0)
{ {
ETHCL_LOG("OpenCL 1.0 is not supported."); ETHCL_LOG("OpenCL 1.0 is not supported.");

11
libethash-cl/ethash_cl_miner.h

@ -12,6 +12,7 @@
#include "cl.hpp" #include "cl.hpp"
#endif #endif
#include <boost/optional.hpp>
#include <time.h> #include <time.h>
#include <functional> #include <functional>
#include <libethash/ethash.h> #include <libethash/ethash.h>
@ -40,7 +41,7 @@ public:
static unsigned getNumDevices(unsigned _platformId = 0); static unsigned getNumDevices(unsigned _platformId = 0);
static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0); static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0);
static void listDevices(); static void listDevices();
static bool configureGPU(); static bool configureGPU(bool _allowCPU, unsigned _extraGPUMemory, boost::optional<uint64_t> _currentBlock);
bool init( bool init(
uint8_t const* _dag, uint8_t const* _dag,
@ -56,6 +57,9 @@ public:
void search_chunk(uint8_t const* header, uint64_t target, search_hook& hook); void search_chunk(uint8_t const* header, uint64_t target, search_hook& hook);
private: 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 }; 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::Context m_context;
@ -70,4 +74,9 @@ private:
unsigned m_workgroup_size; unsigned m_workgroup_size;
bool m_opencl_1_1; bool m_opencl_1_1;
/// Allow CPU to appear as an OpenCL device or not. Default is false
static bool s_allowCPU;
/// GPU memory required for other things, like window rendering e.t.c.
/// User can set it via the --cl-extragpu-mem argument.
static unsigned s_extraRequiredGPUMem;
}; };

2
libethash-cl/ethash_cl_miner_kernel.cl

@ -585,4 +585,4 @@ __kernel void ethash_search_chunks(
uint slot = min(convert_uint(MAX_OUTPUTS), convert_uint(atomic_inc(&g_output[0]) + 1)); uint slot = min(convert_uint(MAX_OUTPUTS), convert_uint(atomic_inc(&g_output[0]) + 1));
g_output[slot] = gid; g_output[slot] = gid;
} }
} }

12
libethcore/Ethash.cpp

@ -381,9 +381,17 @@ void Ethash::GPUMiner::listDevices()
return ethash_cl_miner::listDevices(); return ethash_cl_miner::listDevices();
} }
bool Ethash::GPUMiner::configureGPU() bool Ethash::GPUMiner::configureGPU(
unsigned _platformId,
unsigned _deviceId,
bool _allowCPU,
unsigned _extraGPUMemory,
boost::optional<uint64_t> _currentBlock
)
{ {
return ethash_cl_miner::configureGPU(); s_platformId = _platformId;
s_deviceId = _deviceId;
return ethash_cl_miner::configureGPU(_allowCPU, _extraGPUMemory, _currentBlock);
} }
#endif #endif

15
libethcore/Ethash.h

@ -87,11 +87,8 @@ public:
static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); }
static std::string platformInfo(); static std::string platformInfo();
static void setDefaultPlatform(unsigned) {}
static void setDagChunks(unsigned) {}
static void setDefaultDevice(unsigned) {}
static void listDevices() {} static void listDevices() {}
static bool configureGPU() { return false; } static bool configureGPU(unsigned, unsigned, bool, unsigned, boost::optional<uint64_t>) { return false; }
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, std::thread::hardware_concurrency()); } static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, std::thread::hardware_concurrency()); }
protected: protected:
void kickOff() override void kickOff() override
@ -120,9 +117,13 @@ public:
static std::string platformInfo(); static std::string platformInfo();
static unsigned getNumDevices(); static unsigned getNumDevices();
static void listDevices(); static void listDevices();
static bool configureGPU(); static bool configureGPU(
static void setDefaultPlatform(unsigned _id) { s_platformId = _id; } unsigned _platformId,
static void setDefaultDevice(unsigned _id) { s_deviceId = _id; } unsigned _deviceId,
bool _allowCPU,
unsigned _extraGPUMemory,
boost::optional<uint64_t> _currentBlock
);
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, getNumDevices()); } static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, getNumDevices()); }
protected: protected:

5
libethcore/EthashAux.cpp

@ -54,6 +54,11 @@ uint64_t EthashAux::cacheSize(BlockInfo const& _header)
return ethash_get_cachesize((uint64_t)_header.number); return ethash_get_cachesize((uint64_t)_header.number);
} }
uint64_t EthashAux::dataSize(uint64_t _blockNumber)
{
return ethash_get_datasize(_blockNumber);
}
h256 EthashAux::seedHash(unsigned _number) h256 EthashAux::seedHash(unsigned _number)
{ {
unsigned epoch = _number / ETHASH_EPOCH_LENGTH; unsigned epoch = _number / ETHASH_EPOCH_LENGTH;

1
libethcore/EthashAux.h

@ -66,6 +66,7 @@ public:
static h256 seedHash(unsigned _number); static h256 seedHash(unsigned _number);
static uint64_t number(h256 const& _seedHash); static uint64_t number(h256 const& _seedHash);
static uint64_t cacheSize(BlockInfo const& _header); static uint64_t cacheSize(BlockInfo const& _header);
static uint64_t dataSize(uint64_t _blockNumber);
static LightType light(h256 const& _seedHash); static LightType light(h256 const& _seedHash);

9
libethereum/Client.cpp

@ -614,13 +614,10 @@ bool Client::submitWork(ProofOfWork::Solution const& _solution)
void Client::syncBlockQueue() void Client::syncBlockQueue()
{ {
ImportRoute ir; ImportRoute ir;
cwork << "BQ ==> CHAIN ==> STATE"; cwork << "BQ ==> CHAIN ==> STATE";
{ tie(ir.first, ir.second, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, rand() % 10 + 5);
tie(ir.first, ir.second, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, rand() % 90 + 10); if (ir.first.empty())
if (ir.first.empty()) return;
return;
}
onChainChanged(ir); onChainChanged(ir);
} }

15
libethereum/ClientBase.cpp

@ -45,6 +45,21 @@ State ClientBase::asOf(BlockNumber _h) const
return asOf(bc().numberHash(_h)); return asOf(bc().numberHash(_h));
} }
void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce)
{
prepareForTransaction();
auto a = toAddress(_secret);
u256 n = postMine().transactionsFrom(a);
cdebug << "submitTx: " << a << "postMine=" << n << "; tq=" << m_tq.maxNonce(a);
Transaction t(_value, _gasPrice, _gas, _dest, _data, _nonce, _secret);
m_tq.import(t.rlp());
StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged());
cnote << "New transaction " << t << "(maxNonce for sender" << a << "is" << m_tq.maxNonce(a) << ")";
}
void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
{ {
prepareForTransaction(); prepareForTransaction();

1
libethereum/ClientBase.h

@ -76,6 +76,7 @@ public:
virtual ~ClientBase() {} virtual ~ClientBase() {}
/// Submits the given message-call transaction. /// Submits the given message-call transaction.
virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, u256 _nonce);
virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; virtual void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override;
/// Submits a new contract-creation transaction. /// Submits a new contract-creation transaction.

3
libethereum/EthereumHost.cpp

@ -111,7 +111,7 @@ void EthereumHost::doWork()
bool netChange = ensureInitialised(); bool netChange = ensureInitialised();
auto h = m_chain.currentHash(); auto h = m_chain.currentHash();
// If we've finished our initial sync (including getting all the blocks into the chain so as to reduce invalid transactions), start trading transactions & blocks // If we've finished our initial sync (including getting all the blocks into the chain so as to reduce invalid transactions), start trading transactions & blocks
if (isSyncing() && m_chain.isKnown(m_latestBlockSent)) if (!isSyncing() && m_chain.isKnown(m_latestBlockSent))
{ {
if (m_newTransactions) if (m_newTransactions)
{ {
@ -171,6 +171,7 @@ void EthereumHost::maintainTransactions()
RLPStream ts; RLPStream ts;
_p->prep(ts, TransactionsPacket, n).appendRaw(b, n); _p->prep(ts, TransactionsPacket, n).appendRaw(b, n);
_p->sealAndSend(ts); _p->sealAndSend(ts);
cnote << "Sent" << n << "transactions to " << _p->session()->info().clientVersion;
} }
_p->m_requireTransactions = false; _p->m_requireTransactions = false;
}); });

3
libethereum/Precompiled.cpp

@ -81,8 +81,7 @@ void ripemd160Code(bytesConstRef _in, bytesRef _out)
void identityCode(bytesConstRef _in, bytesRef _out) void identityCode(bytesConstRef _in, bytesRef _out)
{ {
bytes b = _in.toBytes(); _in.copyTo(_out);
memcpy(_out.data(), b.data(), min(_out.size(), b.size()));
} }
} }

7
libethereum/State.cpp

@ -141,7 +141,12 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h, ImportRequire
// 2. Enact the block's transactions onto this state. // 2. Enact the block's transactions onto this state.
m_ourAddress = bi.coinbaseAddress; m_ourAddress = bi.coinbaseAddress;
enact(BlockChain::verifyBlock(b), _bc, _ir); boost::timer t;
auto vb = BlockChain::verifyBlock(b);
cnote << "verifyBlock:" << t.elapsed();
t.restart();
enact(vb, _bc, _ir);
cnote << "enact:" << t.elapsed();
} }
else else
{ {

2
test/TestHelper.cpp

@ -352,6 +352,8 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost)
BOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); BOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);
else else
BOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); BOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning);
m_TestObject.erase(m_TestObject.find("expectOut"));
} }
// export logs // export logs

13
test/libevm/vm.cpp

@ -388,6 +388,19 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
o["callcreates"] = fev.exportCallCreates(); o["callcreates"] = fev.exportCallCreates();
o["out"] = output.size() > 4096 ? "#" + toString(output.size()) : toHex(output, 2, HexPrefix::Add); o["out"] = output.size() > 4096 ? "#" + toString(output.size()) : toHex(output, 2, HexPrefix::Add);
// compare expected output with post output
if (o.count("expectOut") > 0)
{
std::string warning = "Check State: Error! Unexpected output: " + o["out"].get_str() + " Expected: " + o["expectOut"].get_str();
if (Options::get().checkState)
BOOST_CHECK_MESSAGE((o["out"].get_str() == o["expectOut"].get_str()), warning);
else
BOOST_WARN_MESSAGE((o["out"].get_str() == o["expectOut"].get_str()), warning);
o.erase(o.find("expectOut"));
}
o["gas"] = toCompactHex(fev.gas, HexPrefix::Add, 1); o["gas"] = toCompactHex(fev.gas, HexPrefix::Add, 1);
o["logs"] = exportLog(fev.sub.logs); o["logs"] = exportLog(fev.sub.logs);
} }

Loading…
Cancel
Save