diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index f3b4d1b18..ac54ebe4d 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -59,6 +59,15 @@ unsigned Ethash::revision() return ETHASH_REVISION; } +Ethash::WorkPackage Ethash::package(BlockInfo const& _bi) +{ + WorkPackage ret; + ret.boundary = _bi.boundary(); + ret.headerHash = _bi.headerHash(WithNonce); + ret.seedHash = _bi.seedHash(); + return ret; +} + void Ethash::prep(BlockInfo const& _header) { if (_header.number % ETHASH_EPOCH_LENGTH == 1) diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index b87f06549..458cb4e6c 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -68,10 +68,11 @@ public: static std::string name(); static unsigned revision(); + static void prep(BlockInfo const& _header); 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; } - static void prep(BlockInfo const& _header); class CPUMiner: public Miner, Worker { @@ -125,8 +126,5 @@ public: #endif }; -using ProofOfWork = Ethash; -using Solution = Ethash::Solution; - } } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 0ff0a3628..b73a79c49 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include "GenesisInfo.h" #include "State.h" @@ -336,7 +335,7 @@ ImportRoute BlockChain::attemptImport(bytes const& _block, OverlayDB const& _sta catch (...) { cwarn << "Unexpected exception! Could not import block!" << boost::current_exception_diagnostic_information(); - return make_pair(h256s(), h256()); + return make_pair(h256s(), h256s()); } } diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index cdff566fb..8b4a3dce4 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -68,7 +68,7 @@ ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0); using BlocksHash = std::map; using TransactionHashes = h256s; using UncleHashes = h256s; -using ImportRoute = std::pair; +using ImportRoute = std::pair; enum { ExtraDetails = 0, diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 15a7c9bec..81023f9ef 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -404,14 +404,17 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 return ret; } -pair Client::getWork() +ProofOfWork::WorkPackage Client::getWork() { Guard l(x_remoteMiner); + BlockInfo bi; { ReadGuard l(x_stateDB); m_remoteMiner.update(m_postMine, m_bc); + m_postMine.commitToMine(m_bc); + bi = m_postMine.info(); } - return make_pair(m_remoteMiner.workHash(), m_remoteMiner.difficulty()); + return ProofOfWork::package(bi); } bool Client::submitWork(ProofOfWork::Solution const& _solution) diff --git a/libethereum/Client.h b/libethereum/Client.h index a136033e5..9f6bbfeb6 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -73,28 +73,6 @@ private: std::string m_path; }; -class RemoteMiner: public OldMiner -{ -public: - RemoteMiner() {} - - void update(State const& _provisional, BlockChain const& _bc) { m_state = _provisional; m_state.commitToMine(_bc); } - - h256 workHash() const { return m_state.info().headerHash(IncludeNonce::WithoutNonce); } - u256 const& difficulty() const { return m_state.info().difficulty; } - - bool submitWork(ProofOfWork::Solution const& _result) { return (m_isComplete = m_state.completeMine(_result)); } - - virtual bool isComplete() const override { return m_isComplete; } - virtual bytes const& blockData() const { return m_state.blockData(); } - - virtual void noteStateChange() override {} - -private: - bool m_isComplete = false; - State m_state; -}; - class BasicGasPricer: public GasPricer { public: @@ -209,7 +187,7 @@ public: /// Update to the latest transactions and get hash of the current block to be mined minus the /// nonce (the 'work hash') and the difficulty to be met. - virtual std::pair getWork() override; + virtual ProofOfWork::WorkPackage getWork() override; /** @brief Submit the proof for the proof-of-work. * @param _s A valid solution. diff --git a/libethereum/Farm.h b/libethereum/Farm.h index 39988c8d7..137c137d3 100644 --- a/libethereum/Farm.h +++ b/libethereum/Farm.h @@ -53,9 +53,7 @@ public: { WriteGuard l(x_work); m_header = _bi; - m_work.boundary = _bi.boundary(); - m_work.headerHash = _bi.headerHash(WithNonce); - m_work.seedHash = _bi.seedHash(); + m_work = PoW::package(m_header); ReadGuard l(x_miners); for (auto const& m: miners) m->setWork(m_work); diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 134bed53b..0ab81728b 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -26,11 +26,11 @@ #include #include #include +#include #include "LogFilter.h" #include "Transaction.h" #include "AccountDiff.h" #include "BlockDetails.h" -#include "Miner.h" namespace dev { @@ -188,7 +188,7 @@ public: virtual bool submitWork(ProofOfWork::Solution const& _proof) = 0; /// Check the progress of the mining. - virtual MineProgress miningProgress() const = 0; + virtual MiningProgress miningProgress() const = 0; protected: int m_default = PendingBlock; diff --git a/libethereum/Miner.cpp b/libethereum/Miner.cpp index b386fe868..e69de29bb 100644 --- a/libethereum/Miner.cpp +++ b/libethereum/Miner.cpp @@ -1,94 +0,0 @@ -/* - 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.cpp - * @author Gav Wood - * @author Giacomo Tazzari - * @date 2014 - */ - -#include "Miner.h" - -#include -#include "State.h" -using namespace std; -using namespace dev; -using namespace dev::eth; - -OldMiner::~OldMiner() {} - -LocalMiner::LocalMiner(MinerHost* _host, unsigned _id) -{ - setup(_host, _id); -} - -void LocalMiner::setup(MinerHost* _host, unsigned _id) -{ - AsyncMiner::setup(_host, _id); - setName("miner-" + toString(m_id)); - m_pow.reset(_host->turbo() ? new Ethash : (Ethash*)new EthashCPU); -} - -void LocalMiner::doWork() -{ - // Do some mining. - if (m_miningStatus != Waiting && m_miningStatus != Mined) - { - if (m_miningStatus == Preparing) - { - m_host->setupState(m_mineState); - if (m_host->force() || m_mineState.pending().size()) - m_miningStatus = Mining; - else - m_miningStatus = Waiting; - - { - Guard l(x_mineInfo); - m_mineProgress.best = (double)-1; - m_mineProgress.hashes = 0; - m_mineProgress.ms = 0; - } - } - - if (m_miningStatus == Mining) - { - // Mine for a while. - MineInfo mineInfo = m_mineState.mine(m_pow.get()); - - { - Guard l(x_mineInfo); - m_mineProgress.best = min(m_mineProgress.best, mineInfo.best); - m_mineProgress.current = mineInfo.best; - m_mineProgress.requirement = mineInfo.requirement; - m_mineProgress.ms += 100; - m_mineProgress.hashes += mineInfo.hashes; - m_mineHistory.push_back(mineInfo); - } - if (mineInfo.completed) - { - m_mineState.completeMine(); - m_host->onComplete(); - m_miningStatus = Mined; - } - else - m_host->onProgressed(); - } - } - else - { - this_thread::sleep_for(chrono::milliseconds(100)); - } -} diff --git a/libethereum/Miner.h b/libethereum/Miner.h index 3abf93770..e69de29bb 100644 --- a/libethereum/Miner.h +++ b/libethereum/Miner.h @@ -1,166 +0,0 @@ -/* - 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 -#include -#include "State.h" - -namespace dev -{ - -namespace eth -{ - -/** - * @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 force() const = 0; ///< @returns true iff the Miner should mine regardless of the number of transactions. - virtual bool turbo() const = 0; ///< @returns true iff the Miner should use GPU if possible. -}; - -class OldMiner -{ -public: - virtual ~OldMiner(); - - virtual void noteStateChange() = 0; - virtual bool isComplete() const = 0; - virtual bytes const& blockData() const = 0; -}; - -class AsyncMiner: public OldMiner -{ -public: - /// Null constructor. - AsyncMiner(): m_host(nullptr) {} - - /// Constructor. - AsyncMiner(MinerHost* _host, unsigned _id = 0): m_host(_host), m_id(_id) {} - - /// Setup its basics. - void setup(MinerHost* _host, unsigned _id = 0) { m_host = _host; m_id = _id; } - - /// Start mining. - virtual void start() {} - - /// Stop mining. - virtual void stop() {} - - /// @returns true iff the mining has been start()ed. It may still not be actually mining, depending on the host's turbo() & force(). - virtual bool isRunning() const { return false; } - -protected: - MinerHost* m_host = nullptr; ///< Our host. - unsigned m_id = 0; ///< Our unique id. -}; - -/** - * @brief Implements Miner. - * To begin mining, use start() & stop(). noteStateChange() 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 Miner to restart once with condition variables. - */ -class LocalMiner: public AsyncMiner, Worker -{ -public: - /// Null constructor. - LocalMiner() {} - - /// Constructor. - LocalMiner(MinerHost* _host, unsigned _id = 0); - - /// Move-constructor. - LocalMiner(LocalMiner&& _m): Worker((Worker&&)_m) { std::swap(m_host, _m.m_host); std::swap(m_pow, _m.m_pow); } - - /// Move-assignment. - LocalMiner& operator=(LocalMiner&& _m) { Worker::operator=((Worker&&)_m); std::swap(m_host, _m.m_host); std::swap(m_pow, _m.m_pow); return *this; } - - /// Destructor. Stops miner. - ~LocalMiner() { stop(); } - - /// Setup its basics. - void setup(MinerHost* _host, unsigned _id = 0); - - /// Start mining. - void start() { startWorking(); } - - /// Stop mining. - void stop() { stopWorking(); } - - /// Call to notify Miner of a state change. - virtual void noteStateChange() override { 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() const override { return isWorking(); } - - /// @returns true if mining is complete. - virtual bool isComplete() const override { return m_miningStatus == Mined; } - - /// @returns the internal State object. - virtual bytes const& blockData() const override { 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; } - - /// @returns the state on which we mined. - State const& state() const { return m_mineState; } - -private: - /// Do some work on the mining. - virtual void doWork(); - - enum MiningStatus { Waiting, Preparing, Mining, Mined, Stopping, Stopped }; - MiningStatus m_miningStatus = Waiting; ///< TODO: consider mutex/atomic variable. - State m_mineState; ///< The state on which we are mining, generally equivalent to m_postMine. - std::unique_ptr m_pow; ///< Our miner. - - mutable 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? -}; - -} -}