GenericFarm.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file GenericFarm.h
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2015
  17. */
  18. #pragma once
  19. #include <thread>
  20. #include <list>
  21. #include <atomic>
  22. #include <libdevcore/Common.h>
  23. #include <libdevcore/Worker.h>
  24. #include <libethcore/Common.h>
  25. #include <libethereum/GenericMiner.h>
  26. #include <libethcore/BlockHeader.h>
  27. namespace dev
  28. {
  29. namespace eth
  30. {
  31. /**
  32. * @brief A collective of Miners.
  33. * Miners ask for work, then submit proofs
  34. * @threadsafe
  35. */
  36. template <class PoW>
  37. class GenericFarm: public GenericFarmFace<PoW>
  38. {
  39. public:
  40. using WorkPackage = typename PoW::WorkPackage;
  41. using Solution = typename PoW::Solution;
  42. using Miner = GenericMiner<PoW>;
  43. struct SealerDescriptor
  44. {
  45. std::function<unsigned()> instances;
  46. std::function<Miner*(typename Miner::ConstructionInfo ci)> create;
  47. };
  48. ~GenericFarm()
  49. {
  50. stop();
  51. }
  52. /**
  53. * @brief Sets the current mining mission.
  54. * @param _wp The work package we wish to be mining.
  55. */
  56. void setWork(WorkPackage const& _wp)
  57. {
  58. WriteGuard l(x_minerWork);
  59. if (_wp.headerHash == m_work.headerHash)
  60. return;
  61. m_work = _wp;
  62. for (auto const& m: m_miners)
  63. m->setWork(m_work);
  64. resetTimer();
  65. }
  66. void setSealers(std::map<std::string, SealerDescriptor> const& _sealers) { m_sealers = _sealers; }
  67. /**
  68. * @brief Start a number of miners.
  69. */
  70. bool start(std::string const& _sealer)
  71. {
  72. WriteGuard l(x_minerWork);
  73. if (!m_miners.empty() && m_lastSealer == _sealer)
  74. return true;
  75. if (!m_sealers.count(_sealer))
  76. return false;
  77. m_miners.clear();
  78. auto ins = m_sealers[_sealer].instances();
  79. m_miners.reserve(ins);
  80. for (unsigned i = 0; i < ins; ++i)
  81. {
  82. m_miners.push_back(std::shared_ptr<Miner>(m_sealers[_sealer].create(std::make_pair(this, i))));
  83. m_miners.back()->setWork(m_work);
  84. }
  85. m_isMining = true;
  86. m_lastSealer = _sealer;
  87. resetTimer();
  88. return true;
  89. }
  90. /**
  91. * @brief Stop all mining activities.
  92. */
  93. void stop()
  94. {
  95. WriteGuard l(x_minerWork);
  96. m_miners.clear();
  97. m_work.reset();
  98. m_isMining = false;
  99. }
  100. bool isMining() const
  101. {
  102. return m_isMining;
  103. }
  104. /**
  105. * @brief Get information on the progress of mining this work package.
  106. * @return The progress with mining so far.
  107. */
  108. WorkingProgress const& miningProgress() const
  109. {
  110. WorkingProgress p;
  111. p.ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_lastStart).count();
  112. {
  113. ReadGuard l2(x_minerWork);
  114. for (auto const& i: m_miners)
  115. p.hashes += i->hashCount();
  116. }
  117. WriteGuard l(x_progress);
  118. m_progress = p;
  119. return m_progress;
  120. }
  121. /**
  122. * @brief Reset the mining progess counter.
  123. */
  124. void resetMiningProgress()
  125. {
  126. DEV_READ_GUARDED(x_minerWork)
  127. for (auto const& i: m_miners)
  128. i->resetHashCount();
  129. resetTimer();
  130. }
  131. using SolutionFound = std::function<bool(Solution const&)>;
  132. /**
  133. * @brief Provides a valid header based upon that received previously with setWork().
  134. * @param _bi The now-valid header.
  135. * @return true if the header was good and that the Farm should pause until more work is submitted.
  136. */
  137. void onSolutionFound(SolutionFound const& _handler) { m_onSolutionFound = _handler; }
  138. WorkPackage work() const { ReadGuard l(x_minerWork); return m_work; }
  139. /**
  140. * @brief Called from a Miner to note a WorkPackage has a solution.
  141. * @param _p The solution.
  142. * @param _wp The WorkPackage that the Solution is for.
  143. * @return true iff the solution was good (implying that mining should be .
  144. */
  145. bool submitProof(Solution const& _s, Miner* _m) override
  146. {
  147. if (m_onSolutionFound && m_onSolutionFound(_s))
  148. if (x_minerWork.try_lock())
  149. {
  150. for (std::shared_ptr<Miner> const& m: m_miners)
  151. if (m.get() != _m)
  152. m->setWork();
  153. m_work.reset();
  154. x_minerWork.unlock();
  155. return true;
  156. }
  157. return false;
  158. }
  159. private:
  160. void resetTimer()
  161. {
  162. m_lastStart = std::chrono::steady_clock::now();
  163. }
  164. mutable SharedMutex x_minerWork;
  165. std::vector<std::shared_ptr<Miner>> m_miners;
  166. WorkPackage m_work;
  167. std::atomic<bool> m_isMining = {false};
  168. mutable SharedMutex x_progress;
  169. mutable WorkingProgress m_progress;
  170. std::chrono::steady_clock::time_point m_lastStart;
  171. SolutionFound m_onSolutionFound;
  172. std::map<std::string, SealerDescriptor> m_sealers;
  173. std::string m_lastSealer;
  174. };
  175. }
  176. }