Marek Kotewicz
10 years ago
42 changed files with 1132 additions and 193 deletions
@ -0,0 +1,41 @@ |
|||||
|
cmake_policy(SET CMP0015 NEW) |
||||
|
set(CMAKE_AUTOMOC OFF) |
||||
|
|
||||
|
aux_source_directory(. SRC_LIST) |
||||
|
|
||||
|
include_directories(BEFORE ..) |
||||
|
include_directories(${Boost_INCLUDE_DIRS}) |
||||
|
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) |
||||
|
|
||||
|
set(EXECUTABLE ethminer) |
||||
|
|
||||
|
file(GLOB HEADERS "*.h") |
||||
|
|
||||
|
add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) |
||||
|
|
||||
|
add_dependencies(${EXECUTABLE} BuildInfo.h) |
||||
|
|
||||
|
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES}) |
||||
|
|
||||
|
if (READLINE_FOUND) |
||||
|
target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) |
||||
|
endif() |
||||
|
|
||||
|
if (JSONRPC) |
||||
|
target_link_libraries(${EXECUTABLE} web3jsonrpc) |
||||
|
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES}) |
||||
|
target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) |
||||
|
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) |
||||
|
eth_copy_dlls(${EXECUTABLE} CURL_DLLS) |
||||
|
endif() |
||||
|
endif() |
||||
|
|
||||
|
target_link_libraries(${EXECUTABLE} webthree) |
||||
|
target_link_libraries(${EXECUTABLE} ethash) |
||||
|
|
||||
|
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) |
||||
|
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS) |
||||
|
endif() |
||||
|
|
||||
|
install( TARGETS ${EXECUTABLE} DESTINATION bin ) |
||||
|
|
@ -0,0 +1,39 @@ |
|||||
|
/**
|
||||
|
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! |
||||
|
*/ |
||||
|
|
||||
|
#ifndef JSONRPC_CPP_STUB_FARM_H_ |
||||
|
#define JSONRPC_CPP_STUB_FARM_H_ |
||||
|
|
||||
|
#include <jsonrpccpp/client.h> |
||||
|
|
||||
|
class Farm : public jsonrpc::Client |
||||
|
{ |
||||
|
public: |
||||
|
Farm(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {} |
||||
|
|
||||
|
Json::Value eth_getWork() throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p = Json::nullValue; |
||||
|
Json::Value result = this->CallMethod("eth_getWork",p); |
||||
|
if (result.isArray()) |
||||
|
return result; |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
} |
||||
|
bool eth_submitWork(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
p.append(param3); |
||||
|
Json::Value result = this->CallMethod("eth_submitWork",p); |
||||
|
if (result.isBool()) |
||||
|
return result.asBool(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#endif //JSONRPC_CPP_STUB_FARM_H_
|
@ -0,0 +1,28 @@ |
|||||
|
/**
|
||||
|
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! |
||||
|
*/ |
||||
|
|
||||
|
#ifndef JSONRPC_CPP_STUB_PHONEHOME_H_ |
||||
|
#define JSONRPC_CPP_STUB_PHONEHOME_H_ |
||||
|
|
||||
|
#include <jsonrpccpp/client.h> |
||||
|
|
||||
|
class PhoneHome : public jsonrpc::Client |
||||
|
{ |
||||
|
public: |
||||
|
PhoneHome(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {} |
||||
|
|
||||
|
int report_benchmark(const std::string& param1, int param2) throw (jsonrpc::JsonRpcException) |
||||
|
{ |
||||
|
Json::Value p; |
||||
|
p.append(param1); |
||||
|
p.append(param2); |
||||
|
Json::Value result = this->CallMethod("report_benchmark",p); |
||||
|
if (result.isInt()) |
||||
|
return result.asInt(); |
||||
|
else |
||||
|
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#endif //JSONRPC_CPP_STUB_PHONEHOME_H_
|
@ -0,0 +1,4 @@ |
|||||
|
[ |
||||
|
{ "name": "eth_getWork", "params": [], "order": [], "returns": []}, |
||||
|
{ "name": "eth_submitWork", "params": ["", "", ""], "order": [], "returns": true} |
||||
|
] |
@ -0,0 +1,483 @@ |
|||||
|
/*
|
||||
|
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 Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
* Ethereum client. |
||||
|
*/ |
||||
|
|
||||
|
#include <thread> |
||||
|
#include <chrono> |
||||
|
#include <fstream> |
||||
|
#include <iostream> |
||||
|
#include <signal.h> |
||||
|
|
||||
|
#include <boost/algorithm/string.hpp> |
||||
|
#include <boost/algorithm/string/trim_all.hpp> |
||||
|
|
||||
|
#include <libdevcrypto/FileSystem.h> |
||||
|
#include <libevmcore/Instruction.h> |
||||
|
#include <libdevcore/StructuredLogger.h> |
||||
|
#include <libethcore/ProofOfWork.h> |
||||
|
#include <libethcore/EthashAux.h> |
||||
|
#include <libevm/VM.h> |
||||
|
#include <libevm/VMFactory.h> |
||||
|
#include <libethereum/All.h> |
||||
|
#include <libwebthree/WebThree.h> |
||||
|
#if ETH_JSONRPC || !ETH_TRUE |
||||
|
#include <libweb3jsonrpc/WebThreeStubServer.h> |
||||
|
#include <jsonrpccpp/server/connectors/httpserver.h> |
||||
|
#include <jsonrpccpp/client/connectors/httpclient.h> |
||||
|
#endif |
||||
|
#include "BuildInfo.h" |
||||
|
#if ETH_JSONRPC || !ETH_TRUE |
||||
|
#include "PhoneHome.h" |
||||
|
#include "Farm.h" |
||||
|
#endif |
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::p2p; |
||||
|
using namespace dev::eth; |
||||
|
using namespace boost::algorithm; |
||||
|
using dev::eth::Instruction; |
||||
|
|
||||
|
#undef RETURN |
||||
|
|
||||
|
bool isTrue(std::string const& _m) |
||||
|
{ |
||||
|
return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; |
||||
|
} |
||||
|
|
||||
|
bool isFalse(std::string const& _m) |
||||
|
{ |
||||
|
return _m == "off" || _m == "no" || _m == "false" || _m == "0"; |
||||
|
} |
||||
|
|
||||
|
void help() |
||||
|
{ |
||||
|
cout |
||||
|
<< "Usage ethminer [OPTIONS]" << endl |
||||
|
<< "Options:" << endl << endl |
||||
|
#if ETH_JSONRPC || !ETH_TRUE |
||||
|
<< "Work farming mode:" << endl |
||||
|
<< " -F,--farm <url> Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8080)" << endl |
||||
|
<< " --farm-recheck <n> Leave n ms between checks for changed work (default: 500)." << endl |
||||
|
#endif |
||||
|
<< "Benchmarking mode:" << endl |
||||
|
<< " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl |
||||
|
<< " --benchmark-warmup <seconds> Set the duration of warmup for the benchmark tests (default: 3)." << endl |
||||
|
<< " --benchmark-trial <seconds> Set the duration for each trial for the benchmark tests (default: 3)." << endl |
||||
|
<< " --benchmark-trials <n> Set the duration of warmup for the benchmark tests (default: 5)." << endl |
||||
|
#if ETH_JSONRPC || !ETH_TRUE |
||||
|
<< " --phone-home <on/off> When benchmarking, publish results (default: on)" << endl |
||||
|
#endif |
||||
|
<< "DAG creation mode:" << endl |
||||
|
<< " -D,--create-dag <number> Create the DAG in preparation for mining on given block and exit." << endl |
||||
|
<< "General Options:" << endl |
||||
|
<< " -C,--cpu When mining, use the CPU." << endl |
||||
|
<< " -G,--opencl When mining use the GPU via OpenCL." << 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 |
||||
|
<< " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl |
||||
|
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl |
||||
|
<< " -V,--version Show the version and exit." << endl |
||||
|
<< " -h,--help Show this help message and exit." << endl |
||||
|
; |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
string credits() |
||||
|
{ |
||||
|
std::ostringstream cout; |
||||
|
cout |
||||
|
<< "Ethereum (++) " << dev::Version << endl |
||||
|
<< " Code by Gav Wood et al, (c) 2013, 2014, 2015." << endl |
||||
|
<< " Based on a design by Vitalik Buterin." << endl << endl; |
||||
|
return cout.str(); |
||||
|
} |
||||
|
|
||||
|
void version() |
||||
|
{ |
||||
|
cout << "eth version " << dev::Version << endl; |
||||
|
cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl; |
||||
|
cout << "Client database version: " << dev::eth::c_databaseVersion << endl; |
||||
|
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
void doInitDAG(unsigned _n) |
||||
|
{ |
||||
|
BlockInfo bi; |
||||
|
bi.number = _n; |
||||
|
cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl; |
||||
|
Ethash::prep(bi); |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
enum class OperationMode |
||||
|
{ |
||||
|
DAGInit, |
||||
|
Benchmark, |
||||
|
Farm |
||||
|
}; |
||||
|
|
||||
|
enum class MinerType |
||||
|
{ |
||||
|
CPU, |
||||
|
GPU |
||||
|
}; |
||||
|
|
||||
|
void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5) |
||||
|
{ |
||||
|
BlockInfo genesis = CanonBlockChain::genesis(); |
||||
|
genesis.difficulty = 1 << 18; |
||||
|
cdebug << genesis.boundary(); |
||||
|
|
||||
|
GenericFarm<Ethash> f; |
||||
|
f.onSolutionFound([&](ProofOfWork::Solution) { return false; }); |
||||
|
|
||||
|
string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : ""; |
||||
|
cout << "Benchmarking on platform: " << platformInfo << endl; |
||||
|
|
||||
|
cout << "Preparing DAG..." << endl; |
||||
|
Ethash::prep(genesis); |
||||
|
|
||||
|
genesis.difficulty = u256(1) << 63; |
||||
|
genesis.noteDirty(); |
||||
|
f.setWork(genesis); |
||||
|
if (_m == MinerType::CPU) |
||||
|
f.startCPU(); |
||||
|
else if (_m == MinerType::GPU) |
||||
|
f.startGPU(); |
||||
|
|
||||
|
map<uint64_t, MiningProgress> results; |
||||
|
uint64_t mean = 0; |
||||
|
uint64_t innerMean = 0; |
||||
|
for (unsigned i = 0; i <= _trials; ++i) |
||||
|
{ |
||||
|
if (!i) |
||||
|
cout << "Warming up..." << endl; |
||||
|
else |
||||
|
cout << "Trial " << i << "... " << flush; |
||||
|
this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration)); |
||||
|
|
||||
|
auto mp = f.miningProgress(); |
||||
|
f.resetMiningProgress(); |
||||
|
if (!i) |
||||
|
continue; |
||||
|
auto rate = mp.rate(); |
||||
|
|
||||
|
cout << rate << endl; |
||||
|
results[rate] = mp; |
||||
|
mean += rate; |
||||
|
if (i > 1 && i < 5) |
||||
|
innerMean += rate; |
||||
|
} |
||||
|
f.stop(); |
||||
|
cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl; |
||||
|
cout << "inner mean: " << (innerMean / (_trials - 2)) << " H/s" << endl; |
||||
|
|
||||
|
(void)_phoneHome; |
||||
|
#if ETH_JSONRPC || !ETH_TRUE |
||||
|
if (_phoneHome) |
||||
|
{ |
||||
|
cout << "Phoning home to find world ranking..." << endl; |
||||
|
jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark"); |
||||
|
PhoneHome rpc(client); |
||||
|
try |
||||
|
{ |
||||
|
unsigned ranking = rpc.report_benchmark(platformInfo, innerMean); |
||||
|
cout << "Ranked: " << ranking << " of all benchmarks." << endl; |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cout << "Error phoning home. ET is sad." << endl; |
||||
|
} |
||||
|
} |
||||
|
#endif |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
struct HappyChannel: public LogChannel { static const char* name() { return ":-D"; } static const int verbosity = 1; }; |
||||
|
struct SadChannel: public LogChannel { static const char* name() { return ":-("; } static const int verbosity = 1; }; |
||||
|
|
||||
|
void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) |
||||
|
{ |
||||
|
(void)_m; |
||||
|
(void)_remote; |
||||
|
(void)_recheckPeriod; |
||||
|
#if ETH_JSONRPC || !ETH_TRUE |
||||
|
jsonrpc::HttpClient client(_remote); |
||||
|
Farm rpc(client); |
||||
|
GenericFarm<Ethash> f; |
||||
|
if (_m == MinerType::CPU) |
||||
|
f.startCPU(); |
||||
|
else if (_m == MinerType::GPU) |
||||
|
f.startGPU(); |
||||
|
|
||||
|
ProofOfWork::WorkPackage current; |
||||
|
while (true) |
||||
|
try |
||||
|
{ |
||||
|
bool completed = false; |
||||
|
ProofOfWork::Solution solution; |
||||
|
f.onSolutionFound([&](ProofOfWork::Solution sol) |
||||
|
{ |
||||
|
solution = sol; |
||||
|
return completed = true; |
||||
|
}); |
||||
|
for (unsigned i = 0; !completed; ++i) |
||||
|
{ |
||||
|
if (current) |
||||
|
cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); |
||||
|
else |
||||
|
cnote << "Getting work package..."; |
||||
|
Json::Value v = rpc.eth_getWork(); |
||||
|
h256 hh(v[0].asString()); |
||||
|
if (hh != current.headerHash) |
||||
|
{ |
||||
|
current.headerHash = hh; |
||||
|
current.seedHash = h256(v[1].asString()); |
||||
|
current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); |
||||
|
cnote << "Got work package:" << current.headerHash << " < " << current.boundary; |
||||
|
f.setWork(current); |
||||
|
} |
||||
|
this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); |
||||
|
} |
||||
|
cnote << "Solution found; submitting [" << solution.nonce << "," << current.headerHash << "," << solution.mixHash << "] to" << _remote << "..."; |
||||
|
bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); |
||||
|
if (ok) |
||||
|
clog(HappyChannel) << "Submitted and accepted."; |
||||
|
else |
||||
|
clog(SadChannel) << "Not accepted."; |
||||
|
current.reset(); |
||||
|
} |
||||
|
catch (jsonrpc::JsonRpcException&) |
||||
|
{ |
||||
|
for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1))) |
||||
|
cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; |
||||
|
cerr << endl; |
||||
|
} |
||||
|
#endif |
||||
|
exit(0); |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char** argv) |
||||
|
{ |
||||
|
// Init defaults
|
||||
|
Defaults::get(); |
||||
|
|
||||
|
/// Operating mode.
|
||||
|
OperationMode mode = OperationMode::Farm; |
||||
|
|
||||
|
/// Mining options
|
||||
|
MinerType minerType = MinerType::CPU; |
||||
|
unsigned openclPlatform = 0; |
||||
|
unsigned openclDevice = 0; |
||||
|
unsigned miningThreads = UINT_MAX; |
||||
|
|
||||
|
/// DAG initialisation param.
|
||||
|
unsigned initDAG = 0; |
||||
|
|
||||
|
/// Benchmarking params
|
||||
|
bool phoneHome = true; |
||||
|
unsigned benchmarkWarmup = 3; |
||||
|
unsigned benchmarkTrial = 3; |
||||
|
unsigned benchmarkTrials = 5; |
||||
|
|
||||
|
/// Farm params
|
||||
|
string farmURL = "http://127.0.0.1:8080"; |
||||
|
unsigned farmRecheckPeriod = 500; |
||||
|
|
||||
|
for (int i = 1; i < argc; ++i) |
||||
|
{ |
||||
|
string arg = argv[i]; |
||||
|
if ((arg == "-F" || arg == "--farm") && i + 1 < argc) |
||||
|
{ |
||||
|
mode = OperationMode::Farm; |
||||
|
farmURL = argv[++i]; |
||||
|
} |
||||
|
else if (arg == "--farm-recheck" && i + 1 < argc) |
||||
|
try { |
||||
|
farmRecheckPeriod = stol(argv[++i]); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
else if (arg == "--opencl-platform" && i + 1 < argc) |
||||
|
try { |
||||
|
openclPlatform = stol(argv[++i]); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
else if (arg == "--opencl-device" && i + 1 < argc) |
||||
|
try { |
||||
|
openclDevice = stol(argv[++i]); |
||||
|
miningThreads = 1; |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
else if (arg == "--phone-home" && i + 1 < argc) |
||||
|
{ |
||||
|
string m = argv[++i]; |
||||
|
if (isTrue(m)) |
||||
|
phoneHome = true; |
||||
|
else if (isFalse(m)) |
||||
|
phoneHome = false; |
||||
|
else |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << m << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
} |
||||
|
else if (arg == "--benchmark-warmup" && i + 1 < argc) |
||||
|
try { |
||||
|
benchmarkWarmup = stol(argv[++i]); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
else if (arg == "--benchmark-trial" && i + 1 < argc) |
||||
|
try { |
||||
|
benchmarkTrial = stol(argv[++i]); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
else if (arg == "--benchmark-trials" && i + 1 < argc) |
||||
|
try { |
||||
|
benchmarkTrials = stol(argv[++i]); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
else if (arg == "-C" || arg == "--cpu") |
||||
|
minerType = MinerType::CPU; |
||||
|
else if (arg == "-G" || arg == "--opencl") |
||||
|
minerType = MinerType::GPU; |
||||
|
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) |
||||
|
{ |
||||
|
string m = boost::to_lower_copy(string(argv[++i])); |
||||
|
mode = OperationMode::DAGInit; |
||||
|
try |
||||
|
{ |
||||
|
initDAG = stol(m); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << m << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
} |
||||
|
else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc) |
||||
|
{ |
||||
|
string m; |
||||
|
try |
||||
|
{ |
||||
|
BlockInfo bi; |
||||
|
m = boost::to_lower_copy(string(argv[++i])); |
||||
|
h256 powHash(m); |
||||
|
m = boost::to_lower_copy(string(argv[++i])); |
||||
|
h256 seedHash; |
||||
|
if (m.size() == 64 || m.size() == 66) |
||||
|
seedHash = h256(m); |
||||
|
else |
||||
|
seedHash = EthashAux::seedHash(stol(m)); |
||||
|
m = boost::to_lower_copy(string(argv[++i])); |
||||
|
bi.difficulty = u256(m); |
||||
|
auto boundary = bi.boundary(); |
||||
|
m = boost::to_lower_copy(string(argv[++i])); |
||||
|
bi.nonce = h64(m); |
||||
|
auto r = EthashAux::eval(seedHash, powHash, bi.nonce); |
||||
|
bool valid = r.value < boundary; |
||||
|
cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; |
||||
|
cout << r.value << (valid ? " < " : " >= ") << boundary << endl; |
||||
|
cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl; |
||||
|
cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl; |
||||
|
cout << " with seed as " << seedHash << endl; |
||||
|
if (valid) |
||||
|
cout << "(mixHash = " << r.mixHash << ")" << endl; |
||||
|
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(seedHash)->data()) << endl; |
||||
|
exit(0); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << m << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
} |
||||
|
else if (arg == "-M" || arg == "--benchmark") |
||||
|
mode = OperationMode::Benchmark; |
||||
|
else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) |
||||
|
{ |
||||
|
try { |
||||
|
miningThreads = stol(argv[++i]); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
||||
|
return -1; |
||||
|
} |
||||
|
} |
||||
|
else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) |
||||
|
g_logVerbosity = atoi(argv[++i]); |
||||
|
else if (arg == "-h" || arg == "--help") |
||||
|
help(); |
||||
|
else if (arg == "-V" || arg == "--version") |
||||
|
version(); |
||||
|
else |
||||
|
{ |
||||
|
cerr << "Invalid argument: " << arg << endl; |
||||
|
exit(-1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (minerType == MinerType::CPU) |
||||
|
ProofOfWork::CPUMiner::setNumInstances(miningThreads); |
||||
|
else if (minerType == MinerType::GPU) |
||||
|
{ |
||||
|
ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); |
||||
|
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); |
||||
|
ProofOfWork::GPUMiner::setNumInstances(miningThreads); |
||||
|
} |
||||
|
|
||||
|
if (mode == OperationMode::DAGInit) |
||||
|
doInitDAG(initDAG); |
||||
|
|
||||
|
if (mode == OperationMode::Benchmark) |
||||
|
doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); |
||||
|
|
||||
|
if (mode == OperationMode::Farm) |
||||
|
doFarm(minerType, farmURL, farmRecheckPeriod); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
@ -0,0 +1,3 @@ |
|||||
|
[ |
||||
|
{ "name": "report_benchmark", "params": [ "", 0 ], "order": [], "returns": 0 } |
||||
|
] |
@ -0,0 +1,157 @@ |
|||||
|
/*
|
||||
|
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 ICAP.cpp
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "ICAP.h" |
||||
|
#include <boost/algorithm/string/case_conv.hpp> |
||||
|
#include <libdevcore/Base64.h> |
||||
|
#include <libdevcrypto/SHA3.h> |
||||
|
#include "Exceptions.h" |
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
string ICAP::iban(std::string _c, std::string _d) |
||||
|
{ |
||||
|
boost::to_upper(_c); |
||||
|
boost::to_upper(_d); |
||||
|
auto totStr = _d + _c + "00"; |
||||
|
bigint tot = 0; |
||||
|
for (char x: totStr) |
||||
|
if (x >= 'A') |
||||
|
tot = tot * 100 + x - 'A' + 10; |
||||
|
else |
||||
|
tot = tot * 10 + x - '0'; |
||||
|
unsigned check = (unsigned)(u256)(98 - tot % 97); |
||||
|
ostringstream out; |
||||
|
out << _c << setfill('0') << setw(2) << check << _d; |
||||
|
return out.str(); |
||||
|
} |
||||
|
|
||||
|
std::pair<string, string> ICAP::fromIBAN(std::string _iban) |
||||
|
{ |
||||
|
if (_iban.size() < 4) |
||||
|
return std::make_pair(string(), string()); |
||||
|
boost::to_upper(_iban); |
||||
|
std::string c = _iban.substr(0, 2); |
||||
|
std::string d = _iban.substr(4); |
||||
|
if (iban(c, d) != _iban) |
||||
|
return std::make_pair(string(), string()); |
||||
|
return make_pair(c, d); |
||||
|
} |
||||
|
|
||||
|
ICAP ICAP::decoded(std::string const& _encoded) |
||||
|
{ |
||||
|
ICAP ret; |
||||
|
std::string country; |
||||
|
std::string data; |
||||
|
std::tie(country, data) = fromIBAN(_encoded); |
||||
|
if (country != "XE") |
||||
|
throw InvalidICAP(); |
||||
|
if (data.size() == 30) |
||||
|
{ |
||||
|
ret.m_type = Direct; |
||||
|
// Direct ICAP
|
||||
|
ret.m_direct = fromBase36<Address::size>(data); |
||||
|
} |
||||
|
else if (data.size() == 16) |
||||
|
{ |
||||
|
ret.m_type = Indirect; |
||||
|
ret.m_asset = data.substr(0, 3); |
||||
|
if (ret.m_asset == "XET") |
||||
|
{ |
||||
|
ret.m_institution = data.substr(3, 4); |
||||
|
ret.m_client = data.substr(7); |
||||
|
} |
||||
|
else if (ret.m_asset == "ETH") |
||||
|
ret.m_client = data.substr(4); |
||||
|
else |
||||
|
throw InvalidICAP(); |
||||
|
} |
||||
|
else |
||||
|
throw InvalidICAP(); |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
std::string ICAP::encoded() const |
||||
|
{ |
||||
|
if (m_type == Direct) |
||||
|
{ |
||||
|
if (!!m_direct[0]) |
||||
|
return string(); |
||||
|
std::string d = toBase36<Address::size>(m_direct); |
||||
|
while (d.size() < 30) |
||||
|
d = "0" + d; |
||||
|
return iban("XE", d); |
||||
|
} |
||||
|
else if (m_type == Indirect) |
||||
|
{ |
||||
|
if ( |
||||
|
m_asset.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || |
||||
|
m_institution.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || |
||||
|
m_client.find_first_not_of("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != string::npos || |
||||
|
m_asset.size() != 3 |
||||
|
) |
||||
|
throw InvalidICAP(); |
||||
|
if (boost::to_upper_copy(m_asset) == "XET") |
||||
|
{ |
||||
|
if (m_institution.size() != 4 || m_client.size() != 9) |
||||
|
throw InvalidICAP(); |
||||
|
} |
||||
|
else if (boost::to_upper_copy(m_asset) == "ETH") |
||||
|
{ |
||||
|
if (m_client.size() != 13) |
||||
|
throw InvalidICAP(); |
||||
|
} |
||||
|
else |
||||
|
throw InvalidICAP(); |
||||
|
return iban("XE", m_asset + m_institution + m_client); |
||||
|
} |
||||
|
else |
||||
|
throw InvalidICAP(); |
||||
|
} |
||||
|
|
||||
|
Address ICAP::lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const |
||||
|
{ |
||||
|
(void)_call; |
||||
|
(void)_reg; |
||||
|
if (m_asset == "XET") |
||||
|
{ |
||||
|
// TODO
|
||||
|
throw InterfaceNotSupported("ICAP::lookup(), XET asset"); |
||||
|
} |
||||
|
else if (m_asset == "ETH") |
||||
|
{ |
||||
|
// TODO
|
||||
|
// return resolve(m_institution + "/" + m_client).primary();
|
||||
|
throw InterfaceNotSupported("ICAP::lookup(), ETH asset"); |
||||
|
} |
||||
|
else |
||||
|
throw InterfaceNotSupported("ICAP::lookup(), non XET asset"); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,106 @@ |
|||||
|
/*
|
||||
|
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 ICAP.h
|
||||
|
* @author Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
* |
||||
|
* Ethereum-specific data structures & algorithms. |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <string> |
||||
|
#include <functional> |
||||
|
#include <libdevcore/Common.h> |
||||
|
#include <libdevcore/Exceptions.h> |
||||
|
#include <libdevcore/FixedHash.h> |
||||
|
#include "Common.h" |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
struct InvalidICAP: virtual public dev::Exception {}; |
||||
|
|
||||
|
static const std::string EmptyString; |
||||
|
|
||||
|
/**
|
||||
|
* @brief Encapsulation of an ICAP address. |
||||
|
* Can be encoded, decoded, looked-up and inspected. |
||||
|
*/ |
||||
|
class ICAP |
||||
|
{ |
||||
|
public: |
||||
|
/// Construct null ICAP object.
|
||||
|
ICAP() = default; |
||||
|
/// Construct a direct ICAP object for given target address. Must have a zero first byte.
|
||||
|
ICAP(Address const& _target): m_direct(_target) {} |
||||
|
/// Construct an indirect ICAP object for given target name.
|
||||
|
ICAP(std::string const& _target): m_client(_target), m_asset("ETH") {} |
||||
|
/// Construct an indirect ICAP object for given client and institution names.
|
||||
|
ICAP(std::string const& _client, std::string const& _inst): m_client(_client), m_institution(_inst), m_asset("XET") {} |
||||
|
/// Construct an indirect ICAP object for given client, institution and asset names. You generally don't want to use this.
|
||||
|
ICAP(std::string const& _c, std::string const& _i, std::string const& _a): m_client(_c), m_institution(_i), m_asset(_a) {} |
||||
|
|
||||
|
/// Type of ICAP address.
|
||||
|
enum Type |
||||
|
{ |
||||
|
Invalid, |
||||
|
Direct, |
||||
|
Indirect |
||||
|
}; |
||||
|
|
||||
|
/// @returns IBAN encoding of client and data.
|
||||
|
static std::string iban(std::string _c, std::string _d); |
||||
|
/// @returns Client and data from given IBAN address.
|
||||
|
static std::pair<std::string, std::string> fromIBAN(std::string _iban); |
||||
|
|
||||
|
/// @returns the ICAP object for the ICAP address given.
|
||||
|
static ICAP decoded(std::string const& _encoded); |
||||
|
|
||||
|
/// @returns the encoded ICAP address.
|
||||
|
std::string encoded() const; |
||||
|
/// @returns type of ICAP.
|
||||
|
Type type() const { return m_type; } |
||||
|
/// @returns target address. Only valid when type() == Direct.
|
||||
|
Address const& direct() const { return m_type == Direct ? m_direct : ZeroAddress; } |
||||
|
/// @returns asset. Only valid when type() == Indirect.
|
||||
|
std::string const& asset() const { return m_type == Indirect ? m_asset : EmptyString; } |
||||
|
/// @returns target name. Only valid when type() == Indirect and asset() == "ETH".
|
||||
|
std::string const& target() const { return m_type == Indirect && m_asset == "ETH" ? m_client : EmptyString; } |
||||
|
/// @returns institution name. Only valid when type() == Indirect and asset() == "XET".
|
||||
|
std::string const& institution() const { return m_type == Indirect && m_asset == "XET" ? m_institution : EmptyString; } |
||||
|
/// @returns client name. Only valid when type() == Indirect and asset() == "XET".
|
||||
|
std::string const& client() const { return m_type == Indirect && m_asset == "XET" ? m_client : EmptyString; } |
||||
|
/// @returns target address. Always valid, but requires the Registry address and a function to make calls.
|
||||
|
Address address(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const { return m_type == Direct ? direct() : m_type == Indirect ? lookup(_call, _reg) : Address(); } |
||||
|
|
||||
|
/// @returns target address. Looks up through the given Registry and call function. Only valid when type() == Indirect.
|
||||
|
Address lookup(std::function<bytes(Address, bytes)> const& _call, Address const& _reg) const; |
||||
|
|
||||
|
private: |
||||
|
Type m_type = Invalid; |
||||
|
Address m_direct; |
||||
|
std::string m_client; |
||||
|
std::string m_institution; |
||||
|
std::string m_asset; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
Loading…
Reference in new issue