/* 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 . */ /** @file Miner.h * @author Alex Leverington * @author Gav Wood * @date 2014 */ #pragma once #include #include #include #include #include #include "State.h" namespace eth { /** * @brief Describes the progress of a mining operation. */ struct MineProgress { double requirement; ///< The PoW requirement - as the second logarithm of the minimum acceptable hash. double best; ///< The PoW achievement - as the second logarithm of the minimum found hash. double current; ///< The most recent PoW achievement - as the second logarithm of the presently found hash. uint hashes; ///< Total number of hashes computed. uint ms; ///< Total number of milliseconds of mining thus far. }; /** * @brief Class for hosting one or more Miners. * @warning Must be implemented in a threadsafe manner since it will be called from multiple * miner threads. */ class MinerHost { public: virtual void setupState(State& _s) = 0; ///< Reset the given State object to the one that should be being mined. virtual void onProgressed() {} ///< Called once some progress has been made. virtual void onComplete() {} ///< Called once a block is found. virtual bool turbo() const = 0; ///< @returns true iff the Miner should mine as fast as possible. virtual bool force() const = 0; ///< @returns true iff the Miner should mine regardless of the number of transactions. }; /** * @brief Implements Miner. * To begin mining, use start() & stop(). restart() can be used to reset the mining and set up the * State object according to the host. Use isRunning() to determine if the miner has been start()ed. * Use isComplete() to determine if the miner has finished mining. * * blockData() can be used to retrieve the complete block, ready for insertion into the BlockChain. * * Information on the mining can be queried through miningProgress() and miningHistory(). * @threadsafe * @todo signal from child->parent thread to wait on exit; refactor redundant dagger/miner stats */ class Miner { public: /// Constructor. Starts miner. Miner(MinerHost* _host, unsigned _id = 0); /// Destructor. Stops miner. ~Miner() { stop(); } /// Start mining. void start(); /// Stop mining. void stop(); /// Restart mining (and start if not already running). void restart() { start(); m_miningStatus = Preparing; } /// @returns true iff the mining has been start()ed. It may still not be actually mining, depending on the host's turbo() & force(). bool isRunning() { return !!m_work; } /// @returns true if mining is complete. bool isComplete() const { return m_miningStatus == Mined; } /// @returns the internal State object. bytes const& blockData() { return m_mineState.blockData(); } /// Check the progress of the mining. MineProgress miningProgress() const { Guard l(x_mineInfo); return m_mineProgress; } /// Get and clear the mining history. std::list miningHistory() { Guard l(x_mineInfo); auto ret = m_mineHistory; m_mineHistory.clear(); return ret; } private: /// Do some work on the mining. void work(); MinerHost* m_host; ///< Our host. unsigned m_id; ///< Our identity; std::mutex x_work; ///< Mutex protecting the creation of the work thread. std::unique_ptr m_work; ///< The work thread. bool m_stop = false; ///< Stop working? enum MiningStatus { Preparing, Mining, Mined, Stopping, Stopped }; MiningStatus m_miningStatus = Preparing;///< TODO: consider mutex/atomic variable. State m_mineState; ///< The state on which we are mining, generally equivalent to m_postMine. mutable unsigned m_pendingCount = 0; ///< How many pending transactions are there in m_mineState? mutable std::mutex x_mineInfo; ///< Lock for the mining progress & history. MineProgress m_mineProgress; ///< What's our progress? std::list m_mineHistory; ///< What the history of our mining? }; }