/* 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 Ethash.h * @author Gav Wood <i@gavwood.com> * @date 2014 * * A proof of work algorithm. */ #pragma once #include <chrono> #include <thread> #include <cstdint> #include <libdevcore/CommonIO.h> #include "Common.h" #include "BlockInfo.h" #include "Miner.h" class ethash_cl_miner; namespace dev { namespace eth { class EthashCLHook; class Ethash { public: using Miner = GenericMiner<Ethash>; struct Solution { Nonce nonce; h256 mixHash; }; struct Result { h256 value; h256 mixHash; }; struct WorkPackage { WorkPackage() = default; void reset() { headerHash = h256(); } operator bool() const { return headerHash != h256(); } h256 boundary; h256 headerHash; ///< When h256() means "pause until notified a new work package is available". h256 seedHash; }; static const WorkPackage NullWorkPackage; static std::string name(); static unsigned revision(); static void prep(BlockInfo const& _header, std::function<int(unsigned)> const& _f = std::function<int(unsigned)>()); static void ensurePrecomputed(unsigned _number); static bool verify(BlockInfo const& _header); static bool preVerify(BlockInfo const& _header); static WorkPackage package(BlockInfo const& _header); static void assignResult(Solution const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixHash = _r.mixHash; } class CPUMiner: public Miner, Worker { public: CPUMiner(ConstructionInfo const& _ci): Miner(_ci), Worker("miner" + toString(index())) {} static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); } static std::string platformInfo(); static void listDevices() {} static bool configureGPU(unsigned, unsigned, bool, unsigned, bool, boost::optional<uint64_t>) { return false; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, std::thread::hardware_concurrency()); } protected: void kickOff() override { stopWorking(); startWorking(); } void pause() override { stopWorking(); } private: void workLoop() override; static unsigned s_numInstances; }; #if ETH_ETHASHCL || !ETH_TRUE class GPUMiner: public Miner, Worker { friend class dev::eth::EthashCLHook; public: GPUMiner(ConstructionInfo const& _ci); ~GPUMiner(); static unsigned instances() { return s_numInstances > 0 ? s_numInstances : 1; } static std::string platformInfo(); static unsigned getNumDevices(); static void listDevices(); static bool configureGPU( unsigned _platformId, unsigned _deviceId, bool _allowCPU, unsigned _extraGPUMemory, bool _forceSingleChunk, boost::optional<uint64_t> _currentBlock ); static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, getNumDevices()); } protected: void kickOff() override; void pause() override; private: void workLoop() override; bool report(uint64_t _nonce); using Miner::accumulateHashes; EthashCLHook* m_hook = nullptr; ethash_cl_miner* m_miner = nullptr; h256 m_minerSeed; ///< Last seed in m_miner static unsigned s_platformId; static unsigned s_deviceId; static unsigned s_numInstances; }; #else using GPUMiner = CPUMiner; #endif }; } }