From 2b7b4f625dd5ad17f47e25ba4f4bb5bdb64b99dd Mon Sep 17 00:00:00 2001 From: Genoil Date: Tue, 10 May 2016 14:12:28 +0200 Subject: [PATCH] stale shares --- ethminer/MinerAux.h | 40 +++++++++++++++++++++------------ ethminer/main.cpp | 2 +- libethcore/Farm.h | 22 ++++++++++++++---- libethcore/Miner.h | 23 ++++++++++++++----- libstratum/EthStratumClient.cpp | 38 ++++++++++++++++++++++++++----- libstratum/EthStratumClient.h | 9 ++++++++ 6 files changed, 104 insertions(+), 30 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 9f5bc3fe2..f464daf52 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -872,7 +872,8 @@ private: f.start("opencl"); else if (_m == MinerType::CUDA) f.start("cuda"); - EthashProofOfWork::WorkPackage current, solved; + EthashProofOfWork::WorkPackage current, previous; + boost::mutex x_current; EthashAux::FullType dag; while (m_running) try @@ -882,9 +883,6 @@ private: f.onSolutionFound([&](EthashProofOfWork::Solution sol) { solution = sol; - solved.headerHash = current.headerHash; - solved.boundary = current.boundary; - solved.seedHash = current.seedHash; return completed = true; }); for (unsigned i = 0; !completed; ++i) @@ -925,6 +923,7 @@ private: } if (hh != current.headerHash) { + x_current.lock(); current.headerHash = hh; current.seedHash = newSeedHash; current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); @@ -933,26 +932,39 @@ private: minelog << " Seedhash:" << current.seedHash.hex(); minelog << " Target: " << h256(current.boundary).hex(); f.setWork(current); + x_current.unlock(); } this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); } cnote << "Solution found; Submitting to" << _remote << "..."; cnote << " Nonce:" << solution.nonce.hex(); - cnote << " Mixhash:" << solution.mixHash.hex(); - cnote << " Header-hash:" << solved.headerHash.hex(); - cnote << " Seedhash:" << solved.seedHash.hex(); - cnote << " Target: " << h256(solved.boundary).hex(); - cnote << " Ethash: " << h256(EthashAux::eval(solved.seedHash, solved.headerHash, solution.nonce).value).hex(); - if (EthashAux::eval(solved.seedHash, solved.headerHash, solution.nonce).value < solved.boundary) + //cnote << " Mixhash:" << solution.mixHash.hex(); + //cnote << " Header-hash:" << current.headerHash.hex(); + //cnote << " Seedhash:" << solved.seedHash.hex(); + //cnote << " Target: " << h256(solved.boundary).hex(); + //cnote << " Ethash: " << h256(EthashAux::eval(solved.seedHash, solved.headerHash, solution.nonce).value).hex(); + if (EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value < current.boundary) { - bool ok = prpc->eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(solved.headerHash), "0x" + toString(solution.mixHash)); + bool ok = prpc->eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); if (ok) { cnote << "B-) Submitted and accepted."; - f.acceptedSolution(); + f.acceptedSolution(false); } else { cwarn << ":-( Not accepted."; - f.rejectedSolution(); + f.rejectedSolution(false); + } + } + else if (EthashAux::eval(previous.seedHash, previous.headerHash, solution.nonce).value < previous.boundary) + { + bool ok = prpc->eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(previous.headerHash), "0x" + toString(solution.mixHash)); + if (ok) { + cnote << "B-) Submitted and accepted."; + f.acceptedSolution(true); + } + else { + cwarn << ":-( Not accepted."; + f.rejectedSolution(true); } } else { @@ -1042,7 +1054,7 @@ private: { if (client.current()) minelog << "Mining on PoWhash" << "#"+(client.currentHeaderHash().hex().substr(0,8)) << ": " << mp << f.getSolutionStats(); - else + else if (client.waitState() == MINER_WAIT_STATE_WORK) minelog << "Waiting for work package..."; } this_thread::sleep_for(chrono::milliseconds(m_farmRecheckPeriod)); diff --git a/ethminer/main.cpp b/ethminer/main.cpp index f31622c45..dcf2bdaf5 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -72,7 +72,7 @@ int main(int argc, char** argv) cout << "=====================================================================" << endl; cout << "Forked from github.com/ethereum/cpp-ethereum" << endl; cout << "CUDA kernel ported from Tim Hughes' OpenCL kernel" << endl; - cout << "With contributions from RoBiK, tpruvot and sp_ " << endl << endl; + cout << "With contributions from nerdralph, RoBiK, tpruvot and sp_ " << endl << endl; cout << "Please consider a donation to:" << endl; cout << "ETH: 0xeb9310b185455f863f526dab3d245809f6854b4d" << endl << endl; diff --git a/libethcore/Farm.h b/libethcore/Farm.h index 5650a31b7..7953770dd 100644 --- a/libethcore/Farm.h +++ b/libethcore/Farm.h @@ -154,12 +154,26 @@ public: m_solutionStats.failed(); } - void acceptedSolution() { - m_solutionStats.accepted(); + void acceptedSolution(bool _stale) { + if (!_stale) + { + m_solutionStats.accepted(); + } + else + { + m_solutionStats.acceptedStale(); + } } - void rejectedSolution() { - m_solutionStats.rejected(); + void rejectedSolution(bool _stale) { + if (!_stale) + { + m_solutionStats.rejected(); + } + else + { + m_solutionStats.rejectedStale(); + } } using SolutionFound = std::function; diff --git a/libethcore/Miner.h b/libethcore/Miner.h index 795f7f11c..080b422f5 100644 --- a/libethcore/Miner.h +++ b/libethcore/Miner.h @@ -30,6 +30,10 @@ #include #include +#define MINER_WAIT_STATE_UNKNOWN 0 +#define MINER_WAIT_STATE_WORK 1 +#define MINER_WAIT_STATE_DAG 2 + namespace dev { @@ -60,20 +64,29 @@ public: void rejected() { rejects++; } void failed() { failures++; } - void reset() { accepts = rejects = failures = 0; } + void acceptedStale() { acceptedStales++; } + void rejectedStale() { rejectedStales++; } + - unsigned getAccepts() { return accepts; } - unsigned getRejects() { return rejects; } - unsigned getFailures() { return failures; } + void reset() { accepts = rejects = failures = acceptedStales = rejectedStales = 0; } + + unsigned getAccepts() { return accepts; } + unsigned getRejects() { return rejects; } + unsigned getFailures() { return failures; } + unsigned getAcceptedStales() { return acceptedStales; } + unsigned getRejectedStales() { return rejectedStales; } private: unsigned accepts = 0; unsigned rejects = 0; unsigned failures = 0; + + unsigned acceptedStales = 0; + unsigned rejectedStales = 0; }; inline std::ostream& operator<<(std::ostream& os, SolutionStats s) { - return os << "[A" << s.getAccepts() << ":R" << s.getRejects() << ":F" << s.getFailures() << "]"; + return os << "[A" << s.getAccepts() << "+" << s.getAcceptedStales() << ":R" << s.getRejects() << "+" << s.getRejectedStales() << ":F" << s.getFailures() << "]"; } template class GenericMiner; diff --git a/libstratum/EthStratumClient.cpp b/libstratum/EthStratumClient.cpp index 6b5139be1..44183b7fd 100644 --- a/libstratum/EthStratumClient.cpp +++ b/libstratum/EthStratumClient.cpp @@ -268,6 +268,7 @@ void EthStratumClient::processReponse(Json::Value& responseObject) m_authorized = responseObject.get("result", Json::Value::null).asBool(); if (!m_authorized) { + cnote << "Worker not authorized:" << p_active->user; disconnect(); return; } @@ -276,11 +277,11 @@ void EthStratumClient::processReponse(Json::Value& responseObject) case 4: if (responseObject.get("result", false).asBool()) { cnote << "B-) Submitted and accepted."; - p_farm->acceptedSolution(); + p_farm->acceptedSolution(m_stale); } else { cwarn << ":-( Not accepted."; - p_farm->rejectedSolution(); + p_farm->rejectedSolution(m_stale); } break; default: @@ -290,7 +291,7 @@ void EthStratumClient::processReponse(Json::Value& responseObject) params = responseObject.get("params", Json::Value::null); if (params.isArray()) { - m_job = params.get((Json::Value::ArrayIndex)0, "").asString(); + string job = params.get((Json::Value::ArrayIndex)0, "").asString(); string sHeaderHash = params.get((Json::Value::ArrayIndex)1, "").asString(); string sSeedHash = params.get((Json::Value::ArrayIndex)2, "").asString(); string sShareTarget = params.get((Json::Value::ArrayIndex)3, "").asString(); @@ -304,7 +305,7 @@ void EthStratumClient::processReponse(Json::Value& responseObject) if (sHeaderHash != "" && sSeedHash != "" && sShareTarget != "") { - cnote << "Received new job #" + m_job.substr(0,8); + cnote << "Received new job #" + job.substr(0,8); //cnote << "Header hash: " + sHeaderHash; //cnote << "Seed hash: " + sSeedHash; //cnote << "Share target: " + sShareTarget; @@ -318,7 +319,7 @@ void EthStratumClient::processReponse(Json::Value& responseObject) { cnote << "Grabbing DAG for" << seedHash; } - if (!(dag = EthashAux::full(seedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) + if (!(dag = EthashAux::full(seedHash, true, [&](unsigned _pc){ m_waitState = _pc < 100 ? MINER_WAIT_STATE_DAG : MINER_WAIT_STATE_WORK; cnote << "Creating DAG. " << _pc << "% done..."; return 0; }))) { BOOST_THROW_EXCEPTION(DAGCreationFailure()); } @@ -332,9 +333,16 @@ void EthStratumClient::processReponse(Json::Value& responseObject) if (p_worktimer) p_worktimer->cancel(); + m_previous.headerHash = m_current.headerHash; + m_previous.seedHash = m_current.seedHash; + m_previous.boundary = m_current.boundary; + m_previousJob = m_job; + m_current.headerHash = h256(sHeaderHash); m_current.seedHash = seedHash; m_current.boundary = h256(sShareTarget);// , h256::AlignRight); + m_job = job; + p_farm->setWork(m_current); x_current.unlock(); p_worktimer = new boost::asio::deadline_timer(m_io_service, boost::posix_time::seconds(m_worktimeout)); @@ -369,6 +377,7 @@ void EthStratumClient::work_timeout_handler(const boost::system::error_code& ec) bool EthStratumClient::submit(EthashProofOfWork::Solution solution) { x_current.lock(); + x_stale.lock(); cnote << "Solution found; Submitting to" << p_active->host << "..."; cnote << " Nonce:" << "0x"+solution.nonce.hex(); //cnote << " Mixhash:" << "0x" + solution.mixHash.hex(); @@ -382,6 +391,21 @@ bool EthStratumClient::submit(EthashProofOfWork::Solution solution) { string json = "{\"id\": 4, \"method\": \"mining.submit\", \"params\": [\"" + p_active->user + "\",\"" + m_job + "\",\"0x" + solution.nonce.hex() + "\",\"0x" + m_current.headerHash.hex() + "\",\"0x" + solution.mixHash.hex() + "\"]}\n"; std::ostream os(&m_requestBuffer); os << json; + m_stale = false; + x_stale.unlock(); + x_current.unlock(); + async_write(m_socket, m_requestBuffer, + boost::bind(&EthStratumClient::handleResponse, this, + boost::asio::placeholders::error)); + return true; + } + else if (EthashAux::eval(m_previous.seedHash, m_previous.headerHash, solution.nonce).value < m_previous.boundary) + { + string json = "{\"id\": 4, \"method\": \"mining.submit\", \"params\": [\"" + p_active->user + "\",\"" + m_previousJob + "\",\"0x" + solution.nonce.hex() + "\",\"0x" + m_previous.headerHash.hex() + "\",\"0x" + solution.mixHash.hex() + "\"]}\n"; + std::ostream os(&m_requestBuffer); + os << json; + m_stale = true; + x_stale.unlock(); x_current.unlock(); async_write(m_socket, m_requestBuffer, boost::bind(&EthStratumClient::handleResponse, this, @@ -389,9 +413,11 @@ bool EthStratumClient::submit(EthashProofOfWork::Solution solution) { return true; } else { + m_stale = false; + x_stale.unlock(); x_current.unlock(); cwarn << "FAILURE: GPU gave incorrect result!"; - p_farm->rejectedSolution(); + p_farm->failedSolution(); } return false; diff --git a/libstratum/EthStratumClient.h b/libstratum/EthStratumClient.h index 02a254376..61b2155e8 100644 --- a/libstratum/EthStratumClient.h +++ b/libstratum/EthStratumClient.h @@ -37,6 +37,7 @@ public: bool isConnected() { return m_connected; } h256 currentHeaderHash() { return m_current.headerHash; } bool current() { return m_current; } + unsigned waitState() { return m_waitState; } bool submit(EthashProofOfWork::Solution solution); void reconnect(); private: @@ -67,6 +68,8 @@ private: int m_maxRetries; int m_worktimeout = 60; + int m_waitState = MINER_WAIT_STATE_WORK; + boost::mutex x_pending; int m_pending; string m_response; @@ -74,7 +77,13 @@ private: GenericFarm * p_farm; boost::mutex x_current; EthashProofOfWork::WorkPackage m_current; + EthashProofOfWork::WorkPackage m_previous; + + boost::mutex x_stale; + bool m_stale = false; + string m_job; + string m_previousJob; EthashAux::FullType m_dag; boost::asio::io_service m_io_service;