diff --git a/src/server/poolserver/Main.cpp b/src/server/poolserver/Main.cpp index 417b6f0..8da653a 100644 --- a/src/server/poolserver/Main.cpp +++ b/src/server/poolserver/Main.cpp @@ -49,7 +49,7 @@ bool InitConfig(int argc, char *argv[]) ("StratumBlockCheckTime", boost::program_options::value()->default_value(2000), "Time between block checks in ms") ("RetargetInterval", boost::program_options::value()->default_value(20), "Time between difficulty checks in seconds") ("RetargetTimeBuffer", boost::program_options::value()->default_value(60*5), "Buffer of shares to keep (in seconds)") - ("RetargetSharesPerMin", boost::program_options::value()->default_value(15), "How many shares per min to target for") + ("RetargetTimePerShare", boost::program_options::value()->default_value(10), "Target in seconds between shares") ("RetargetVariance", boost::program_options::value()->default_value(40), "Maximum allowed variance in percent before difficulty change") ("RetargetMinDiff", boost::program_options::value()->default_value(1), "Minimum difficulty (also starting difficulty)") ("RetargetMaxDiff", boost::program_options::value()->default_value(1000000), "Maximum difficulty we can reach") diff --git a/src/server/poolserver/Stratum/Client.cpp b/src/server/poolserver/Stratum/Client.cpp index 697cba5..4bf1906 100644 --- a/src/server/poolserver/Stratum/Client.cpp +++ b/src/server/poolserver/Stratum/Client.cpp @@ -79,18 +79,6 @@ namespace Stratum { JSON params = msg["params"]; - // Share limiter - if (!_shareLimiter.Submit()) { - JSON response; - response["id"] = msg["id"]; - response["result"]; - response["error"].Add(int64(20)); - response["error"].Add("Blocked by share limiter"); - response["error"].Add(JSON()); - SendMessage(response); - return; - } - // check username std::string username = params[0].GetString(); if (!_workers.count(username)) { @@ -124,6 +112,21 @@ namespace Stratum return; } + // Get job + Job& job = _jobs[jobid]; + + // Share limiter + if (!_shareLimiter.Submit(job.diff)) { + JSON response; + response["id"] = msg["id"]; + response["result"]; + response["error"].Add(int64(20)); + response["error"].Add("Blocked by share limiter"); + response["error"].Add(JSON()); + SendMessage(response); + return; + } + BinaryData extranonce2 = Util::ASCIIToBin(params[2].GetString()); if (extranonce2.size() != 4) { sLog.Error(LOG_STRATUM, "Wrong extranonce size"); @@ -162,9 +165,6 @@ namespace Stratum SendMessage(response); return; } - - // Get job - Job& job = _jobs[jobid]; ByteBuffer share; share << extranonce2 << timebuf << noncebuf; diff --git a/src/server/poolserver/Stratum/Client.h b/src/server/poolserver/Stratum/Client.h index cb85372..854ecf6 100644 --- a/src/server/poolserver/Stratum/Client.h +++ b/src/server/poolserver/Stratum/Client.h @@ -143,7 +143,6 @@ namespace Stratum _socket, boost::asio::buffer(redirect.c_str(), redirect.length()), _ioStrand.wrap(boost::bind(&Client::_OnSend, shared_from_this(), boost::asio::placeholders::error))); - Disconnect(); } void CloseSocket() diff --git a/src/server/poolserver/Stratum/ShareLimiter.cpp b/src/server/poolserver/Stratum/ShareLimiter.cpp index d064c98..03041f3 100644 --- a/src/server/poolserver/Stratum/ShareLimiter.cpp +++ b/src/server/poolserver/Stratum/ShareLimiter.cpp @@ -7,14 +7,14 @@ namespace Stratum { // Returning false will stop any further share verifications (DoS prevention, etc) - bool ShareLimiter::Submit() + bool ShareLimiter::Submit(uint64 diff) { ++_totalShares; uint64 curTime = Util::Date(); uint64 sinceLast = curTime - _lastRetarget; - _shares.push_back(curTime); + _shares.push_back(ShareLimiterRecord(diff, curTime)); if (sinceLast < sConfig.Get("RetargetInterval")) return true; @@ -27,34 +27,40 @@ namespace Stratum return false; } + // Drop old shares while (_shares.size()) { - if (_shares.front() > curTime - sConfig.Get("RetargetTimeBuffer")) + if (_shares.front().time > curTime - sConfig.Get("RetargetTimeBuffer")) break; _shares.pop_front(); } - uint32 interval = sConfig.Get("RetargetTimeBuffer"); + double totalWeighted = 0; + for (uint32 i = 0; i < _shares.size(); ++i) + totalWeighted += _shares[i].diff; - // Calculate shares/min - double speed = double(_shares.size()*60) / double(interval); + double interval = std::min(curTime - _startTime, uint64(sConfig.Get("RetargetTimeBuffer"))); - // Calculate difference from pool target in % - double variance = speed / double(sConfig.Get("RetargetSharesPerMin")); + // Calculate hashrate in MH/s + double hashrate = (MEGAHASHCONST*totalWeighted)/interval; - sLog.Debug(LOG_STRATUM, "Miner variance: %f speed: %f", variance, speed); - - // Check if we need to retarget - if (variance*100 < sConfig.Get("RetargetVariance")) - return true; - - uint64 newDiff = double(_client->GetDifficulty()) * variance; + // Calculate new diff + uint64 newDiff = (hashrate * sConfig.Get("RetargetTimePerShare")) / MEGAHASHCONST; + // Check Limits if (newDiff < sConfig.Get("RetargetMinDiff")) newDiff = sConfig.Get("RetargetMinDiff"); - if (newDiff > sConfig.Get("RetargetMaxDiff")) newDiff = sConfig.Get("RetargetMaxDiff"); + // Calculate variance in % + uint32 variance = abs(((newDiff - _client->GetDifficulty()) * 100) / _client->GetDifficulty()); + + sLog.Debug(LOG_STRATUM, "Miner new diff: %u Variance: %u%% Hashrate: %f MH/s", newDiff, variance, hashrate); + + // Check if we need to retarget + if (variance < sConfig.Get("RetargetVariance")) + return true; + _client->SetDifficulty(newDiff, true); return true; diff --git a/src/server/poolserver/Stratum/ShareLimiter.h b/src/server/poolserver/Stratum/ShareLimiter.h index a053b55..6299a39 100644 --- a/src/server/poolserver/Stratum/ShareLimiter.h +++ b/src/server/poolserver/Stratum/ShareLimiter.h @@ -6,20 +6,31 @@ #include +// 2^32 * 10^-6 +#define MEGAHASHCONST 4294.967296 + namespace Stratum { class Client; + struct ShareLimiterRecord + { + ShareLimiterRecord(uint64 adiff, uint64 atime) : diff(adiff), time(atime) {} + uint64 diff; + uint64 time; + }; + class ShareLimiter { public: ShareLimiter(Client* client) : _client(client), _totalShares(0), _totalBadShares(0) { - _startTime = Util::Date(); + // Minus one to prevent crash when interval is zero + _startTime = Util::Date()-1; _lastRetarget = _startTime; } - bool Submit(); + bool Submit(uint64 diff); void LogBad() { @@ -27,7 +38,7 @@ namespace Stratum } private: - std::deque _shares; + std::deque _shares; Client* _client; uint64 _lastRetarget; uint64 _startTime;