From 6067c939cdb867d84f2b355acceb6834814aaf1f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 13 Apr 2015 22:49:17 +0200 Subject: [PATCH] Fix CPU mining deadlock bug. --- exp/main.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++- libethcore/Miner.h | 6 ++-- libethereum/Farm.h | 4 ++- 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/exp/main.cpp b/exp/main.cpp index 2055c49e1..54b75d0e2 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -25,6 +25,7 @@ #include "libethash-cl/cl.hpp" #endif #include +#include #include #include #include @@ -106,7 +107,7 @@ int main() cnote << "State after transaction: " << s; cnote << before.diff(s); } -#else +#elif 0 int main() { GenericFarm f; @@ -152,5 +153,76 @@ int main() return 0; } +#else + +void mine(State& s, BlockChain const& _bc) +{ + s.commitToMine(_bc); + GenericFarm f; + bool completed = false; + f.onSolutionFound([&](ProofOfWork::Solution sol) + { + return completed = s.completeMine(sol); + }); + f.setWork(s.info()); + f.startCPU(); + while (!completed) + this_thread::sleep_for(chrono::milliseconds(20)); +} + +int main() +{ + cnote << "Testing State..."; + + KeyPair me = sha3("Gav Wood"); + KeyPair myMiner = sha3("Gav's Miner"); +// KeyPair you = sha3("123"); + + Defaults::setDBPath(boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count())); + + OverlayDB stateDB = State::openDB(); + CanonBlockChain bc; + cout << bc; + + State s(stateDB, BaseState::CanonGenesis, myMiner.address()); + cout << s; + + // Sync up - this won't do much until we use the last state. + s.sync(bc); + + cout << s; + + // Mine to get some ether! + mine(s, bc); + + bc.attemptImport(s.blockData(), stateDB); + + cout << bc; + + s.sync(bc); + + cout << s; + + // Inject a transaction to transfer funds from miner to me. + Transaction t(1000, 10000, 30000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret()); + assert(t.sender() == myMiner.address()); + s.execute(bc.lastHashes(), t); + + cout << s; + + // Mine to get some ether and set in stone. + s.commitToMine(bc); + s.commitToMine(bc); + mine(s, bc); + bc.attemptImport(s.blockData(), stateDB); + + cout << bc; + + s.sync(bc); + + cout << s; + + return 0; +} #endif diff --git a/libethcore/Miner.h b/libethcore/Miner.h index 084cc59ff..a048b0238 100644 --- a/libethcore/Miner.h +++ b/libethcore/Miner.h @@ -69,11 +69,11 @@ public: /** * @brief Called from a Miner to note a WorkPackage has a solution. * @param _p The solution. - * @param _wp The WorkPackage that the Solution is for. + * @param _wp The WorkPackage that the Solution is for; this will be reset if the work is accepted. * @param _finder The miner that found it. * @return true iff the solution was good (implying that mining should be . */ - virtual bool submitProof(Solution const& _p, WorkPackage const& _wp, Miner* _finder) = 0; + virtual bool submitProof(Solution const& _p, WorkPackage& io_wp, Miner* _finder) = 0; }; /** @@ -139,10 +139,8 @@ protected: { if (m_farm) { - Guard l(x_work); if (!m_farm->submitProof(_s, m_work, this)) return false; - m_work.reset(); return true; } return true; diff --git a/libethereum/Farm.h b/libethereum/Farm.h index 6b65e37c2..56bbcb9df 100644 --- a/libethereum/Farm.h +++ b/libethereum/Farm.h @@ -136,8 +136,9 @@ private: * @param _wp The WorkPackage that the Solution is for. * @return true iff the solution was good (implying that mining should be . */ - bool submitProof(Solution const& _s, WorkPackage const& _wp, Miner* _m) override + bool submitProof(Solution const& _s, WorkPackage& _wp, Miner* _m) override { + ReadGuard l(x_work); if (_wp.headerHash != m_work.headerHash) return false; @@ -147,6 +148,7 @@ private: for (std::shared_ptr const& m: m_miners) if (m.get() != _m) m->setWork(); + _wp.reset(); m_work.reset(); return true; }