From 2bb61d80c7b86090e4b07cf0dc47f0578002903e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 15 Apr 2015 00:47:23 +0200 Subject: [PATCH] RPC-mining. --- eth/Farm.h | 38 +++++++++++++++ eth/{spec.json => farm.json} | 0 eth/main.cpp | 82 +++++++++++++++++++++++++++----- libethash-cl/ethash_cl_miner.cpp | 2 +- libethereum/Farm.h | 15 +++--- 5 files changed, 117 insertions(+), 20 deletions(-) create mode 100644 eth/Farm.h rename eth/{spec.json => farm.json} (100%) diff --git a/eth/Farm.h b/eth/Farm.h new file mode 100644 index 000000000..c061449e3 --- /dev/null +++ b/eth/Farm.h @@ -0,0 +1,38 @@ +/** + * This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY! + */ + +#ifndef JSONRPC_CPP_STUB_FARM_H_ +#define JSONRPC_CPP_STUB_FARM_H_ + +#include + +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) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + p.append(param2); + 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_ diff --git a/eth/spec.json b/eth/farm.json similarity index 100% rename from eth/spec.json rename to eth/farm.json diff --git a/eth/main.cpp b/eth/main.cpp index 8eebe3395..98d98b2ab 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -48,7 +48,10 @@ #include #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; @@ -117,7 +120,7 @@ void help() << " -C,--cpu When mining, use the CPU." << endl << " -d,--db-path Load database from path (default: ~/.ethereum " << endl << " /Etherum or Library/Application Support/Ethereum)." << endl - << " --benchmark-warmup Set the duration of warmup for the benchmark tests (default: 15)." << endl + << " --benchmark-warmup Set the duration of warmup for the benchmark tests (default: 3)." << endl << " --benchmark-trial Set the duration for each trial for the benchmark tests (default: 3)." << endl << " --benchmark-trials Set the duration of warmup for the benchmark tests (default: 5)." << endl << " -D,--create-dag Create the DAG in preparation for mining on given block and exit." << endl @@ -128,9 +131,10 @@ void help() << " --only Equivalent to --export-from n --export-to n." << endl << " -f,--force-mining Mine even when there are no transactions to mine (Default: off)" << endl #if ETH_JSONRPC || !ETH_TRUE - << " -F,--farm Put into mining farm mode (default GPU with CPU as fallback)." << endl + << " -F,--farm Put into mining farm mode with the work server at URL. Use with -G/--opencl." << endl + << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl #endif - << " -G,--gpu When mining use the GPU." << endl + << " -G,--opencl When mining use the GPU via OpenCL." << endl << " -h,--help Show this help message and exit." << endl << " -i,--interactive Enter interactive mode (default: non-interactive)." << endl << " -I,--import Import file as a concatenated series of blocks and exit." << endl @@ -146,12 +150,14 @@ void help() << " --listen-ip (:) Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl << " --public-ip Force public ip to given (default: auto)." << endl << " -m,--mining Enable mining, optionally for a specified number of blocks (Default: off)" << endl - << " -M,--benchmark Benchmark for mining and exit; use with --cpu and --gpu." << endl + << " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl << " -o,--mode Start a full node or a peer node (Default: full)." << endl - << " --opencl-device When mining use OpenCL device n (default: 0)." << endl + << " --opencl-device When mining using -G/--opencl use OpenCL device n (default: 0)." << endl << " --port Connect to remote port (default: 30303)." << endl << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl +#if ETH_JSONRPC || !ETH_TRUE << " --phone-home When benchmarking, publish results (Default: on)" << endl +#endif << " -R,--rebuild First rebuild the blockchain from the existing database." << endl << " -r,--remote (:) Connect to remote host (default: none)." << endl << " -s,--secret Set the secret key for use with send command (default: auto)." << endl @@ -323,14 +329,48 @@ void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, u exit(0); } -void doFarm(MinerType _m) +void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) { (void)_m; - // TODO: Set up JSONRPC client: to implement: -// { "name": "eth_getWork", "params": [], "order": [], "returns": [, , ]}, -// { "name": "eth_submitWork", "params": [, ], "order": [], "returns": true}, + (void)_remote; + (void)_recheckPeriod; +#if ETH_JSONRPC || !ETH_TRUE + jsonrpc::HttpClient client(_remote); + Farm rpc(client); + GenericFarm f; + if (_m == MinerType::CPU) + f.startCPU(); + else if (_m == MinerType::GPU) + f.startGPU(); + + ProofOfWork::WorkPackage current; + while (true) + { + bool completed = false; + ProofOfWork::Solution solution; + f.onSolutionFound([&](ProofOfWork::Solution sol) + { + solution = sol; + return completed = true; + }); + for (unsigned i = 0; !completed; ++i) + { + 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(v[2].asString()); + f.setWork(current); + } + this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); + } + rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(solution.mixHash)); + } +#endif exit(0); } @@ -396,10 +436,14 @@ int main(int argc, char** argv) /// Benchmarking params bool phoneHome = true; - unsigned benchmarkWarmup = 15; + unsigned benchmarkWarmup = 3; unsigned benchmarkTrial = 3; unsigned benchmarkTrials = 5; + /// Farm params + string farmURL = "http://127.0.0.1:8080"; + unsigned farmRecheckPeriod = 500; + string configFile = getDataDir() + "/config.rlp"; bytes b = contents(configFile); if (b.size()) @@ -444,8 +488,20 @@ int main(int argc, char** argv) mode = OperationMode::Export; filename = argv[++i]; } - else if (arg == "-F" || arg == "--farm") + else 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-device" && i + 1 < argc) try { openclDevice = stol(argv[++i]); @@ -557,7 +613,7 @@ int main(int argc, char** argv) } else if (arg == "-C" || arg == "--cpu") minerType = MinerType::CPU; - else if (arg == "-G" || arg == "--gpu") + else if (arg == "-G" || arg == "--opencl") minerType = MinerType::GPU; else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) sigKey = KeyPair(h256(fromHex(argv[++i]))); @@ -755,7 +811,7 @@ int main(int argc, char** argv) doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); if (mode == OperationMode::Farm) - doFarm(minerType); + doFarm(minerType, farmURL, farmRecheckPeriod); if (!clientName.empty()) clientName += "/"; diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 56ac44e6b..172123439 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -81,7 +81,7 @@ std::string ethash_cl_miner::platform_info() cl::Device& device = devices[device_num]; std::string device_version = device.getInfo(); - return "{ platform: '" + platforms[0].getInfo() + "', device: '" + device.getInfo() + "', version: '" + device_version + "' }"; + return "{ \"platform\": \"" + platforms[0].getInfo() + "\", \"device\": \"" + device.getInfo() + "\", \"version\": \"" + device_version + "\" }"; } void ethash_cl_miner::finish() diff --git a/libethereum/Farm.h b/libethereum/Farm.h index 869925098..6263faf1b 100644 --- a/libethereum/Farm.h +++ b/libethereum/Farm.h @@ -59,14 +59,18 @@ public: * @brief Sets the current mining mission. * @param _bi The block (header) we wish to be mining. */ - void setWork(BlockInfo const& _bi) + void setWork(BlockInfo const& _bi) { setWork(PoW::package(_bi)); } + + /** + * @brief Sets the current mining mission. + * @param _wp The work package we wish to be mining. + */ + void setWork(WorkPackage const& _wp) { WriteGuard l(x_minerWork); - m_header = _bi; - auto p = PoW::package(m_header); - if (p.headerHash == m_work.headerHash) + if (_wp.headerHash == m_work.headerHash) return; - m_work = p; + m_work = _wp; for (auto const& m: m_miners) m->setWork(m_work); resetTimer(); @@ -190,7 +194,6 @@ private: mutable SharedMutex x_minerWork; std::vector> m_miners; WorkPackage m_work; - BlockInfo m_header; std::atomic m_isMining = {false};