MinerAux.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. #pragma once
  2. /*
  3. This file is part of cpp-ethereum.
  4. cpp-ethereum is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. cpp-ethereum is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /** @file MinerAux.cpp
  16. * @author Gav Wood <i@gavwood.com>
  17. * @date 2014
  18. * CLI module for mining.
  19. */
  20. #include <boost/algorithm/string/case_conv.hpp>
  21. #include <libdevcore/CommonJS.h>
  22. #include <libethcore/BasicAuthority.h>
  23. #include <libethcore/Exceptions.h>
  24. #include <libethashseal/EthashGPUMiner.h>
  25. #include <libethashseal/EthashCPUMiner.h>
  26. #if ETH_ETHASHCL
  27. #include <libethash-cl/ethash_cl_miner.h>
  28. #endif // ETH_ETHASHCL
  29. #if ETH_JSONRPC
  30. #include <jsonrpccpp/client/connectors/httpclient.h>
  31. #include "FarmClient.h"
  32. #endif // ETH_JSONRPC
  33. #include "cpp-ethereum/BuildInfo.h"
  34. // TODO - having using derivatives in header files is very poor style, and we need to fix these up.
  35. //
  36. // http://stackoverflow.com/questions/4872373/why-is-including-using-namespace-into-a-header-file-a-bad-idea-in-c
  37. //
  38. // "However you'll virtually never see a using directive in a header file (at least not outside of scope).
  39. // The reason is that using directive eliminate the protection of that particular namespace, and the effect last
  40. // until the end of current compilation unit. If you put a using directive (outside of a scope) in a header file,
  41. // it means that this loss of "namespace protection" will occur within any file that include this header,
  42. // which often mean other header files."
  43. //
  44. // Bob has already done just that in https://github.com/bobsummerwill/cpp-ethereum/commits/cmake_fixes/ethminer,
  45. // and we should apply those changes back to 'develop'. It is probably best to defer that cleanup
  46. // until after attempting to backport the Genoil ethminer changes, because they are fairly extensive
  47. // in terms of lines of change, though all the changes are just adding explicit namespace prefixes.
  48. // So let's start with just the subset of changes which minimizes the #include dependencies.
  49. //
  50. // See https://github.com/bobsummerwill/cpp-ethereum/commit/53af845268b91bc6aa1dab53a6eac675157a072b
  51. // See https://github.com/bobsummerwill/cpp-ethereum/commit/3b9e581d7c04c637ebda18d3d86b5a24d29226f4
  52. //
  53. // More generally, the fact that nearly all of the code for ethminer is actually in the 'MinerAux.h'
  54. // header file, rather than in a source file, is also poor style and should probably be addressed.
  55. // Perhaps there is some historical reason for this which I am unaware of?
  56. using namespace std;
  57. using namespace dev;
  58. using namespace dev::eth;
  59. bool isTrue(std::string const& _m)
  60. {
  61. return _m == "on" || _m == "yes" || _m == "true" || _m == "1";
  62. }
  63. bool isFalse(std::string const& _m)
  64. {
  65. return _m == "off" || _m == "no" || _m == "false" || _m == "0";
  66. }
  67. inline std::string credits()
  68. {
  69. std::ostringstream out;
  70. out
  71. << "cpp-ethereum " << dev::Version << endl
  72. << " By cpp-ethereum contributors, (c) 2013-2016." << endl
  73. << " See the README for contributors and credits." << endl;
  74. return out.str();
  75. }
  76. class BadArgument: public Exception {};
  77. struct MiningChannel: public LogChannel
  78. {
  79. static const char* name() { return EthGreen "miner"; }
  80. static const int verbosity = 2;
  81. static const bool debug = false;
  82. };
  83. #define minelog clog(MiningChannel)
  84. class MinerCLI
  85. {
  86. public:
  87. enum class OperationMode
  88. {
  89. None,
  90. DAGInit,
  91. Benchmark,
  92. Farm
  93. };
  94. MinerCLI(OperationMode _mode = OperationMode::None): mode(_mode) {
  95. Ethash::init();
  96. NoProof::init();
  97. BasicAuthority::init();
  98. }
  99. bool interpretOption(int& i, int argc, char** argv)
  100. {
  101. string arg = argv[i];
  102. if ((arg == "-F" || arg == "--farm") && i + 1 < argc)
  103. {
  104. mode = OperationMode::Farm;
  105. m_farmURL = argv[++i];
  106. }
  107. else if (arg == "--farm-recheck" && i + 1 < argc)
  108. try {
  109. m_farmRecheckPeriod = stol(argv[++i]);
  110. }
  111. catch (...)
  112. {
  113. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  114. BOOST_THROW_EXCEPTION(BadArgument());
  115. }
  116. else if (arg == "--opencl-platform" && i + 1 < argc)
  117. try {
  118. m_openclPlatform = stol(argv[++i]);
  119. }
  120. catch (...)
  121. {
  122. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  123. BOOST_THROW_EXCEPTION(BadArgument());
  124. }
  125. else if (arg == "--opencl-device" && i + 1 < argc)
  126. try {
  127. m_openclDevice = stol(argv[++i]);
  128. m_miningThreads = 1;
  129. }
  130. catch (...)
  131. {
  132. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  133. BOOST_THROW_EXCEPTION(BadArgument());
  134. }
  135. #if ETH_ETHASHCL
  136. else if (arg == "--cl-global-work" && i + 1 < argc)
  137. try {
  138. m_globalWorkSizeMultiplier = stol(argv[++i]);
  139. }
  140. catch (...)
  141. {
  142. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  143. BOOST_THROW_EXCEPTION(BadArgument());
  144. }
  145. else if (arg == "--cl-local-work" && i + 1 < argc)
  146. try {
  147. m_localWorkSize = stol(argv[++i]);
  148. }
  149. catch (...)
  150. {
  151. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  152. BOOST_THROW_EXCEPTION(BadArgument());
  153. }
  154. else if (arg == "--cl-ms-per-batch" && i + 1 < argc)
  155. try {
  156. m_msPerBatch = stol(argv[++i]);
  157. }
  158. catch (...)
  159. {
  160. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  161. BOOST_THROW_EXCEPTION(BadArgument());
  162. }
  163. #endif // ETH_ETHASHCL
  164. else if (arg == "--list-devices")
  165. m_shouldListDevices = true;
  166. else if (arg == "--allow-opencl-cpu")
  167. m_clAllowCPU = true;
  168. else if (arg == "--cl-extragpu-mem" && i + 1 < argc)
  169. m_extraGPUMemory = 1000000 * stol(argv[++i]);
  170. else if (arg == "--benchmark-warmup" && i + 1 < argc)
  171. try {
  172. m_benchmarkWarmup = stol(argv[++i]);
  173. }
  174. catch (...)
  175. {
  176. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  177. BOOST_THROW_EXCEPTION(BadArgument());
  178. }
  179. else if (arg == "--benchmark-trial" && i + 1 < argc)
  180. try {
  181. m_benchmarkTrial = stol(argv[++i]);
  182. }
  183. catch (...)
  184. {
  185. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  186. BOOST_THROW_EXCEPTION(BadArgument());
  187. }
  188. else if (arg == "--benchmark-trials" && i + 1 < argc)
  189. try {
  190. m_benchmarkTrials = stol(argv[++i]);
  191. }
  192. catch (...)
  193. {
  194. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  195. BOOST_THROW_EXCEPTION(BadArgument());
  196. }
  197. else if (arg == "-C" || arg == "--cpu")
  198. m_minerType = "cpu";
  199. else if (arg == "-G" || arg == "--opencl")
  200. m_minerType = "opencl";
  201. else if (arg == "--current-block" && i + 1 < argc)
  202. m_currentBlock = stol(argv[++i]);
  203. else if (arg == "--no-precompute")
  204. {
  205. m_precompute = false;
  206. }
  207. else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc)
  208. {
  209. string m = boost::to_lower_copy(string(argv[++i]));
  210. mode = OperationMode::DAGInit;
  211. try
  212. {
  213. m_initDAG = stol(m);
  214. }
  215. catch (...)
  216. {
  217. cerr << "Bad " << arg << " option: " << m << endl;
  218. BOOST_THROW_EXCEPTION(BadArgument());
  219. }
  220. }
  221. else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc)
  222. {
  223. string m;
  224. try
  225. {
  226. BlockHeader bi;
  227. m = boost::to_lower_copy(string(argv[++i]));
  228. h256 powHash(m);
  229. m = boost::to_lower_copy(string(argv[++i]));
  230. h256 seedHash;
  231. if (m.size() == 64 || m.size() == 66)
  232. seedHash = h256(m);
  233. else
  234. seedHash = EthashAux::seedHash(stol(m));
  235. m = boost::to_lower_copy(string(argv[++i]));
  236. bi.setDifficulty(u256(m));
  237. auto boundary = Ethash::boundary(bi);
  238. m = boost::to_lower_copy(string(argv[++i]));
  239. Ethash::setNonce(bi, h64(m));
  240. auto r = EthashAux::eval(seedHash, powHash, h64(m));
  241. bool valid = r.value < boundary;
  242. cout << (valid ? "VALID :-)" : "INVALID :-(") << endl;
  243. cout << r.value << (valid ? " < " : " >= ") << boundary << endl;
  244. cout << " where " << boundary << " = 2^256 / " << bi.difficulty() << endl;
  245. cout << " and " << r.value << " = ethash(" << powHash << ", " << h64(m) << ")" << endl;
  246. cout << " with seed as " << seedHash << endl;
  247. if (valid)
  248. cout << "(mixHash = " << r.mixHash << ")" << endl;
  249. cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(Ethash::seedHash(bi))->data()) << endl;
  250. exit(0);
  251. }
  252. catch (...)
  253. {
  254. cerr << "Bad " << arg << " option: " << m << endl;
  255. BOOST_THROW_EXCEPTION(BadArgument());
  256. }
  257. }
  258. else if (arg == "-M" || arg == "--benchmark")
  259. mode = OperationMode::Benchmark;
  260. else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc)
  261. {
  262. try {
  263. m_miningThreads = stol(argv[++i]);
  264. }
  265. catch (...)
  266. {
  267. cerr << "Bad " << arg << " option: " << argv[i] << endl;
  268. BOOST_THROW_EXCEPTION(BadArgument());
  269. }
  270. }
  271. else if (arg == "--disable-submit-hashrate")
  272. m_submitHashrate = false;
  273. else
  274. return false;
  275. return true;
  276. }
  277. void execute()
  278. {
  279. if (m_shouldListDevices)
  280. {
  281. #if ETH_ETHASHCL
  282. EthashGPUMiner::listDevices();
  283. #endif // ETH_ETHASHCL
  284. exit(0);
  285. }
  286. if (m_minerType == "cpu")
  287. EthashCPUMiner::setNumInstances(m_miningThreads);
  288. else if (m_minerType == "opencl")
  289. {
  290. #if ETH_ETHASHCL
  291. if (!EthashGPUMiner::configureGPU(
  292. m_localWorkSize,
  293. m_globalWorkSizeMultiplier,
  294. m_msPerBatch,
  295. m_openclPlatform,
  296. m_openclDevice,
  297. m_clAllowCPU,
  298. m_extraGPUMemory,
  299. m_currentBlock
  300. ))
  301. exit(1);
  302. EthashGPUMiner::setNumInstances(m_miningThreads);
  303. #else
  304. cerr << "Selected GPU mining without having compiled with -DETHASHCL=1" << endl;
  305. exit(1);
  306. #endif // ETH_ETHASHCL
  307. }
  308. if (mode == OperationMode::DAGInit)
  309. doInitDAG(m_initDAG);
  310. else if (mode == OperationMode::Benchmark)
  311. doBenchmark(m_minerType, m_benchmarkWarmup, m_benchmarkTrial, m_benchmarkTrials);
  312. else if (mode == OperationMode::Farm)
  313. doFarm(m_minerType, m_farmURL, m_farmRecheckPeriod);
  314. }
  315. static void streamHelp(ostream& _out)
  316. {
  317. _out
  318. #if ETH_JSONRPC
  319. << "Work farming mode:" << endl
  320. << " -F,--farm <url> Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8545)" << endl
  321. << " --farm-recheck <n> Leave n ms between checks for changed work (default: 500)." << endl
  322. << " --no-precompute Don't precompute the next epoch's DAG." << endl
  323. #endif // ETH_JSONRPC
  324. << "Ethash verify mode:" << endl
  325. << " -w,--check-pow <headerHash> <seedHash> <difficulty> <nonce> Check PoW credentials for validity." << endl
  326. << endl
  327. << "Benchmarking mode:" << endl
  328. << " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl
  329. << " --benchmark-warmup <seconds> Set the duration of warmup for the benchmark tests (default: 3)." << endl
  330. << " --benchmark-trial <seconds> Set the duration for each trial for the benchmark tests (default: 3)." << endl
  331. << " --benchmark-trials <n> Set the number of trials for the benchmark tests (default: 5)." << endl
  332. #if ETH_JSONRPC
  333. << " --phone-home <on/off> When benchmarking, publish results (default: on)" << endl
  334. #endif // ETH_JSONRPC
  335. << "DAG creation mode:" << endl
  336. << " -D,--create-dag <number> Create the DAG in preparation for mining on given block and exit." << endl
  337. << "Mining configuration:" << endl
  338. << " -C,--cpu When mining, use the CPU." << endl
  339. << " -G,--opencl When mining use the GPU via OpenCL." << endl
  340. << " --opencl-platform <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl
  341. << " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl
  342. << " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl
  343. << " --allow-opencl-cpu Allows CPU to be considered as an OpenCL device if the OpenCL platform supports it." << endl
  344. << " --list-devices List the detected OpenCL devices and exit." << endl
  345. << " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." << endl
  346. << " --disable-submit-hashrate When mining, don't submit hashrate to node." << endl
  347. #if ETH_ETHASHCL
  348. << " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." << endl
  349. << " --cl-local-work Set the OpenCL local work size. Default is " << toString(ethash_cl_miner::c_defaultLocalWorkSize) << endl
  350. << " --cl-global-work Set the OpenCL global work size as a multiple of the local work size. Default is " << toString(ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier) << " * " << toString(ethash_cl_miner::c_defaultLocalWorkSize) << endl
  351. << " --cl-ms-per-batch Set the OpenCL target milliseconds per batch (global workgroup size). Default is " << toString(ethash_cl_miner::c_defaultMSPerBatch) << ". If 0 is given then no autoadjustment of global work size will happen" << endl
  352. #endif // ETH_ETHASHCL
  353. ;
  354. }
  355. enum class MinerType
  356. {
  357. CPU,
  358. GPU
  359. };
  360. std::string minerType() const { return m_minerType; }
  361. bool shouldPrecompute() const { return m_precompute; }
  362. private:
  363. void doInitDAG(unsigned _n)
  364. {
  365. h256 seedHash = EthashAux::seedHash(_n);
  366. cout << "Initializing DAG for epoch beginning #" << (_n / 30000 * 30000) << " (seedhash " << seedHash.abridged() << "). This will take a while." << endl;
  367. EthashAux::full(seedHash, true);
  368. exit(0);
  369. }
  370. void doBenchmark(std::string _m, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5)
  371. {
  372. BlockHeader genesis;
  373. genesis.setDifficulty(1 << 18);
  374. cdebug << Ethash::boundary(genesis);
  375. GenericFarm<EthashProofOfWork> f;
  376. map<string, GenericFarm<EthashProofOfWork>::SealerDescriptor> sealers;
  377. sealers["cpu"] = GenericFarm<EthashProofOfWork>::SealerDescriptor{&EthashCPUMiner::instances, [](GenericMiner<EthashProofOfWork>::ConstructionInfo ci){ return new EthashCPUMiner(ci); }};
  378. #if ETH_ETHASHCL
  379. sealers["opencl"] = GenericFarm<EthashProofOfWork>::SealerDescriptor{&EthashGPUMiner::instances, [](GenericMiner<EthashProofOfWork>::ConstructionInfo ci){ return new EthashGPUMiner(ci); }};
  380. #endif // ETH_ETHASHCL
  381. f.setSealers(sealers);
  382. f.onSolutionFound([&](EthashProofOfWork::Solution) { return false; });
  383. string platformInfo =
  384. _m == "cpu" ? EthashCPUMiner::platformInfo() :
  385. #if ETH_ETHASHCL
  386. _m == "opencl" ? EthashGPUMiner::platformInfo() :
  387. #endif // ETH_ETHASHCL
  388. "";
  389. cout << "Benchmarking on platform: " << platformInfo << endl;
  390. cout << "Preparing DAG..." << endl;
  391. Ethash::ensurePrecomputed(0);
  392. genesis.setDifficulty(u256(1) << 63);
  393. f.setWork(genesis);
  394. f.start(_m);
  395. map<u256, WorkingProgress> results;
  396. u256 mean = 0;
  397. u256 innerMean = 0;
  398. for (unsigned i = 0; i <= _trials; ++i)
  399. {
  400. if (!i)
  401. cout << "Warming up..." << endl;
  402. else
  403. cout << "Trial " << i << "... " << flush;
  404. this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration));
  405. auto mp = f.miningProgress();
  406. f.resetMiningProgress();
  407. if (!i)
  408. continue;
  409. auto rate = mp.rate();
  410. cout << rate << endl;
  411. results[rate] = mp;
  412. mean += rate;
  413. }
  414. f.stop();
  415. int j = -1;
  416. for (auto const& r: results)
  417. if (++j > 0 && j < (int)_trials - 1)
  418. innerMean += r.second.rate();
  419. innerMean /= (_trials - 2);
  420. cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl;
  421. cout << "inner mean: " << innerMean << " H/s" << endl;
  422. exit(0);
  423. }
  424. // dummy struct for special exception.
  425. struct NoWork {};
  426. void doFarm(std::string _m, string const& _remote, unsigned _recheckPeriod)
  427. {
  428. map<string, GenericFarm<EthashProofOfWork>::SealerDescriptor> sealers;
  429. sealers["cpu"] = GenericFarm<EthashProofOfWork>::SealerDescriptor{&EthashCPUMiner::instances, [](GenericMiner<EthashProofOfWork>::ConstructionInfo ci){ return new EthashCPUMiner(ci); }};
  430. #if ETH_ETHASHCL
  431. sealers["opencl"] = GenericFarm<EthashProofOfWork>::SealerDescriptor{&EthashGPUMiner::instances, [](GenericMiner<EthashProofOfWork>::ConstructionInfo ci){ return new EthashGPUMiner(ci); }};
  432. #endif // ETH_ETHASHCL
  433. (void)_m;
  434. (void)_remote;
  435. (void)_recheckPeriod;
  436. #if ETH_JSONRPC
  437. jsonrpc::HttpClient client(_remote);
  438. h256 id = h256::random();
  439. ::FarmClient rpc(client);
  440. GenericFarm<EthashProofOfWork> f;
  441. f.setSealers(sealers);
  442. f.start(_m);
  443. EthashProofOfWork::WorkPackage current;
  444. EthashAux::FullType dag;
  445. while (true)
  446. try
  447. {
  448. bool completed = false;
  449. EthashProofOfWork::Solution solution;
  450. f.onSolutionFound([&](EthashProofOfWork::Solution sol)
  451. {
  452. solution = sol;
  453. completed = true;
  454. return true;
  455. });
  456. while (!completed)
  457. {
  458. auto mp = f.miningProgress();
  459. f.resetMiningProgress();
  460. if (current)
  461. minelog << "Mining on PoWhash" << current.headerHash << ": " << mp;
  462. else
  463. minelog << "Getting work package...";
  464. if (m_submitHashrate)
  465. {
  466. auto rate = mp.rate();
  467. try
  468. {
  469. rpc.eth_submitHashrate(toJS((u256)rate), "0x" + id.hex());
  470. }
  471. catch (jsonrpc::JsonRpcException const& _e)
  472. {
  473. cwarn << "Failed to submit hashrate.";
  474. cwarn << boost::diagnostic_information(_e);
  475. }
  476. }
  477. Json::Value v = rpc.eth_getWork();
  478. if (v[0].asString().empty())
  479. throw NoWork();
  480. h256 hh(v[0].asString());
  481. h256 newSeedHash(v[1].asString());
  482. if (current.seedHash != newSeedHash)
  483. minelog << "Grabbing DAG for" << newSeedHash;
  484. if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; })))
  485. BOOST_THROW_EXCEPTION(DAGCreationFailure());
  486. if (m_precompute)
  487. EthashAux::computeFull(sha3(newSeedHash), true);
  488. if (hh != current.headerHash)
  489. {
  490. current.headerHash = hh;
  491. current.seedHash = newSeedHash;
  492. current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight);
  493. minelog << "Got work package:";
  494. minelog << " Header-hash:" << current.headerHash.hex();
  495. minelog << " Seedhash:" << current.seedHash.hex();
  496. minelog << " Target: " << h256(current.boundary).hex();
  497. f.setWork(current);
  498. }
  499. this_thread::sleep_for(chrono::milliseconds(_recheckPeriod));
  500. }
  501. cnote << "Solution found; Submitting to" << _remote << "...";
  502. cnote << " Nonce:" << solution.nonce.hex();
  503. cnote << " Mixhash:" << solution.mixHash.hex();
  504. cnote << " Header-hash:" << current.headerHash.hex();
  505. cnote << " Seedhash:" << current.seedHash.hex();
  506. cnote << " Target: " << h256(current.boundary).hex();
  507. cnote << " Ethash: " << h256(EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value).hex();
  508. if (EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value < current.boundary)
  509. {
  510. bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash));
  511. if (ok)
  512. cnote << "B-) Submitted and accepted.";
  513. else
  514. cwarn << ":-( Not accepted.";
  515. }
  516. else
  517. cwarn << "FAILURE: GPU gave incorrect result!";
  518. current.reset();
  519. }
  520. catch (jsonrpc::JsonRpcException&)
  521. {
  522. for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1)))
  523. cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r";
  524. cerr << endl;
  525. }
  526. catch (NoWork&)
  527. {
  528. this_thread::sleep_for(chrono::milliseconds(100));
  529. }
  530. #endif // ETH_JSONRPC
  531. exit(0);
  532. }
  533. /// Operating mode.
  534. OperationMode mode;
  535. /// Mining options
  536. std::string m_minerType = "cpu";
  537. unsigned m_openclPlatform = 0;
  538. unsigned m_openclDevice = 0;
  539. unsigned m_miningThreads = UINT_MAX;
  540. bool m_shouldListDevices = false;
  541. bool m_clAllowCPU = false;
  542. #if ETH_ETHASHCL
  543. unsigned m_globalWorkSizeMultiplier = ethash_cl_miner::c_defaultGlobalWorkSizeMultiplier;
  544. unsigned m_localWorkSize = ethash_cl_miner::c_defaultLocalWorkSize;
  545. unsigned m_msPerBatch = ethash_cl_miner::c_defaultMSPerBatch;
  546. #endif // ETH_ETHASHCL
  547. uint64_t m_currentBlock = 0;
  548. // default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.)
  549. unsigned m_extraGPUMemory = 350000000;
  550. /// DAG initialisation param.
  551. unsigned m_initDAG = 0;
  552. /// Benchmarking params
  553. unsigned m_benchmarkWarmup = 3;
  554. unsigned m_benchmarkTrial = 3;
  555. unsigned m_benchmarkTrials = 5;
  556. /// Farm params
  557. string m_farmURL = "http://127.0.0.1:8545";
  558. unsigned m_farmRecheckPeriod = 500;
  559. bool m_precompute = true;
  560. bool m_submitHashrate = true;
  561. };