diff --git a/src/server/poolserver/DataMgr/DataMgr.cpp b/src/server/poolserver/DataMgr/DataMgr.cpp index 5d07b32..af5734e 100644 --- a/src/server/poolserver/DataMgr/DataMgr.cpp +++ b/src/server/poolserver/DataMgr/DataMgr.cpp @@ -9,12 +9,14 @@ void DataMgr::Upload() { sLog.Info(LOG_SERVER, "We have %u shares", Size()); - while (Size() > BULK_MIN) + uint32 bulkCount = sConfig.Get("ShareUploadBulkCount"); + + while (Size() > sConfig.Get("ShareUploadMinCount")) { sLog.Info(LOG_SERVER, "Uploading %u shares to database", Size()); std::string query("INSERT INTO `shares` (`rem_host`, `username`, `our_result`, `upstream_result`, `reason`, `time`, `difficulty`) VALUES "); - for (int i = 0; i < BULK_COUNT; ++i) + for (int i = 0; i < bulkCount; ++i) { Share share = Pop(); @@ -23,7 +25,7 @@ void DataMgr::Upload() if (!Size()) break; - if (i != BULK_COUNT-1) + if (i != bulkCount-1) query += ','; } diff --git a/src/server/poolserver/DataMgr/DataMgr.h b/src/server/poolserver/DataMgr/DataMgr.h index 8b93878..f61f9a7 100644 --- a/src/server/poolserver/DataMgr/DataMgr.h +++ b/src/server/poolserver/DataMgr/DataMgr.h @@ -7,9 +7,7 @@ #include "Util.h" #include "Share.h" - -#define BULK_MIN 1 -#define BULK_COUNT 50 +#include "Config.h" using namespace boost; @@ -58,7 +56,7 @@ public: void UploadTimerStart() { - _uploadTimer.expires_from_now(boost::posix_time::seconds(3)); + _uploadTimer.expires_from_now(boost::posix_time::seconds(sConfig.Get("ShareUploadInterval"))); _uploadTimer.async_wait(boost::bind(&DataMgr::UploadTimerExpired, this, boost::asio::placeholders::error)); } diff --git a/src/server/poolserver/Main.cpp b/src/server/poolserver/Main.cpp index 8b60fde..ac36887 100644 --- a/src/server/poolserver/Main.cpp +++ b/src/server/poolserver/Main.cpp @@ -34,8 +34,11 @@ bool InitConfig(int argc, char *argv[]) // Server descServer.add_options() ("ServerThreads", boost::program_options::value()->default_value(2), "How many threads to use") - ("MiningAddress", boost::program_options::value()->default_value("n1w8gkPXdNGb6edm4vujBn71A72eQFCNCw"), "Address to send coins to") + ("MiningAddress", boost::program_options::value(), "Address to send coins to") ("BitcoinRPC", boost::program_options::value >()->multitoken(), "Bitcoin RPC login credentials") + ("ShareUploadMinCount", boost::program_options::value()->default_value(2), "Minimum share count to upload to database") + ("ShareUploadBulkCount", boost::program_options::value()->default_value(50), "How many shares to upload in one query") + ("ShareUploadInterval", boost::program_options::value()->default_value(3), "How often to upload shares") ; // Stratum @@ -43,7 +46,12 @@ bool InitConfig(int argc, char *argv[]) ("StratumHost,sh", boost::program_options::value()->default_value("0.0.0.0"), "Stratum server host") ("StratumPort,sp", boost::program_options::value()->default_value(3333), "Stratum server port") ("StratumBlockCheckTime", boost::program_options::value()->default_value(2000), "Time between block checks in ms") - ("StratumMinDifficulty", boost::program_options::value()->default_value(1), "The difficulty on which a new miner starts") + ("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") + ("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") ; // Logging diff --git a/src/server/poolserver/Stratum/Client.cpp b/src/server/poolserver/Stratum/Client.cpp index bddcedb..ccf837a 100644 --- a/src/server/poolserver/Stratum/Client.cpp +++ b/src/server/poolserver/Stratum/Client.cpp @@ -93,7 +93,7 @@ namespace Stratum // check username std::string username = params[0].GetString(); if (!_workers.count(username)) { - sLog.Error(LOG_SERVER, "Worker not authenticated"); + sLog.Error(LOG_STRATUM, "%s: Worker not authenticated", username.c_str()); JSON response; response["id"] = msg["id"]; response["result"]; @@ -125,7 +125,7 @@ namespace Stratum BinaryData extranonce2 = Util::ASCIIToBin(params[2].GetString()); if (extranonce2.size() != 4) { - sLog.Error(LOG_SERVER, "Wrong extranonce size"); + sLog.Error(LOG_STRATUM, "Wrong extranonce size"); JSON response; response["id"] = msg["id"]; response["result"]; @@ -138,7 +138,7 @@ namespace Stratum ByteBuffer timebuf(Util::Reverse(Util::ASCIIToBin(params[3].GetString()))); if (timebuf.Size() != 4) { - sLog.Error(LOG_SERVER, "Wrong ntime size"); + sLog.Error(LOG_STRATUM, "Wrong ntime size"); JSON response; response["id"] = msg["id"]; response["result"]; @@ -151,7 +151,7 @@ namespace Stratum ByteBuffer noncebuf(Util::Reverse(Util::ASCIIToBin(params[4].GetString()))); if (noncebuf.Size() != 4) { - sLog.Error(LOG_SERVER, "Wrong nonce size"); + sLog.Error(LOG_STRATUM, "Wrong nonce size"); JSON response; response["id"] = msg["id"]; response["result"]; @@ -168,7 +168,7 @@ namespace Stratum ByteBuffer share; share << extranonce2 << timebuf << noncebuf; if (!job.SubmitShare(share.Binary())) { - sLog.Error(LOG_SERVER, "Duplicate share"); + sLog.Error(LOG_STRATUM, "%s: Duplicate share", username.c_str()); DataMgr::Instance()->Push(Share(_ip, username, false, "Duplicate share", Util::Date(), job.diff)); _shareLimiter.LogBad(); @@ -207,17 +207,9 @@ namespace Stratum // Get block target BigInt target(Util::BinToASCII(Util::Reverse(hash)), 16); - // Network target criteria - BigInt criteria(Bitcoin::TargetFromBits(block.bits)); - - BigInt diff = Bitcoin::TargetToDiff(criteria); - std::cout << "Target: " << target << std::endl; - std::cout << "Criteria: " << criteria << std::endl; - std::cout << "Diff: " << diff << std::endl; - // Check if difficulty meets job diff - if (target > Bitcoin::DiffToTarget(job.diff)) { - sLog.Error(LOG_SERVER, "Share above target"); + if (target > job.target) { + sLog.Error(LOG_STRATUM, "%s: Share above target", username.c_str()); DataMgr::Instance()->Push(Share(_ip, username, false, "Share above target", Util::Date(), job.diff)); _shareLimiter.LogBad(); @@ -232,7 +224,7 @@ namespace Stratum } // Check if block meets criteria - if (target <= criteria) { + if (target <= job.blockCriteria) { sLog.Info(LOG_SERVER, "We have found a block candidate!"); if (_server->SubmitBlock(block)) { @@ -292,11 +284,17 @@ namespace Stratum std::string username = msg["params"][0].GetString(); std::string password = msg["params"][1].GetString(); - MySQL::QueryResult result = sDatabase.Query(Util::FS("SELECT * FROM `pool_worker` WHERE `username` = '%s' and `password` = '%s'", sDatabase.Escape(username).c_str(), sDatabase.Escape(password).c_str()).c_str()); + MySQL::QueryResult result = sDatabase.Query(Util::FS("SELECT `id`, `mindiff` FROM `pool_worker` WHERE `username` = '%s' and `password` = '%s'", sDatabase.Escape(username).c_str(), sDatabase.Escape(password).c_str()).c_str()); if (result) { _workers.insert(username); + MySQL::Field* fields = result->FetchRow(); + _minDiff = fields[1].Get(); + + if (_diff < _minDiff) + SetDifficulty(_minDiff); + JSON response; response["id"] = msg["id"].GetInt(); response["error"]; @@ -317,7 +315,8 @@ namespace Stratum { Job job; job.block = _server->GetWork(); - job.diff = 1; + job.diff = _diff; + job.target = Bitcoin::DiffToTarget(job.diff); // Serialize transaction ByteBuffer coinbasebuf; @@ -334,6 +333,8 @@ namespace Stratum job.coinbase1 = BinaryData(coinbase.begin(), coinbase.begin() + cbsplit); job.coinbase2 = BinaryData(coinbase.begin() + cbsplit + 8, coinbase.end()); // plus extranonce size + job.blockCriteria = Bitcoin::TargetFromBits(job.block->bits); + return job; } diff --git a/src/server/poolserver/Stratum/Client.h b/src/server/poolserver/Stratum/Client.h index ebf3032..d7b6e8a 100644 --- a/src/server/poolserver/Stratum/Client.h +++ b/src/server/poolserver/Stratum/Client.h @@ -27,8 +27,8 @@ namespace Stratum public: Client(Server* server, asio::io_service& io_service, uint64 id) : _io_service(io_service), _server(server), _socket(io_service), _ioStrand(io_service), _id(id), _subscribed(false), _jobid(0), _shareLimiter(this) { - _diff = sConfig.Get("StratumMinDifficulty"); - _minDiff = _diff; + _diff = sConfig.Get("RetargetMinDiff"); + _minDiff = sConfig.Get("RetargetMinDiff"); } ~Client() @@ -98,6 +98,12 @@ namespace Stratum } void SetDifficulty(uint64 diff, bool resendJob = false) { + if (diff < _minDiff) + diff = _minDiff; + + if (diff == _diff) + return; + _diff = diff; // Send difficulty update diff --git a/src/server/poolserver/Stratum/Job.h b/src/server/poolserver/Stratum/Job.h index 2585b45..e6d8e41 100644 --- a/src/server/poolserver/Stratum/Job.h +++ b/src/server/poolserver/Stratum/Job.h @@ -4,6 +4,7 @@ #include "Bitcoin.h" #include "Crypto.h" #include "Util.h" +#include "BigNum.h" #include namespace Stratum @@ -16,6 +17,8 @@ namespace Stratum BinaryData coinbase1; BinaryData coinbase2; std::set shares; + BigInt blockCriteria; + BigInt target; // Submits share to a job // Returns false if the same share already exists diff --git a/src/server/poolserver/Stratum/Server.h b/src/server/poolserver/Stratum/Server.h index 4b2cd12..edfe9d4 100644 --- a/src/server/poolserver/Stratum/Server.h +++ b/src/server/poolserver/Stratum/Server.h @@ -82,7 +82,7 @@ namespace Stratum // Block template update event void BlockNotify(Bitcoin::BlockPtr block, bool newBlock) { - sLog.Debug(LOG_SERVER, "Received block template update"); + sLog.Debug(LOG_STRATUM, "Received block template update"); _mtxCurrentWork.lock(); _currentWork = block; _mtxCurrentWork.unlock(); diff --git a/src/server/poolserver/Stratum/ShareLimiter.cpp b/src/server/poolserver/Stratum/ShareLimiter.cpp index d291296..d15cdb9 100644 --- a/src/server/poolserver/Stratum/ShareLimiter.cpp +++ b/src/server/poolserver/Stratum/ShareLimiter.cpp @@ -1,6 +1,7 @@ #include "ShareLimiter.h" #include "Server.h" #include "Client.h" +#include "Config.h" #include "Log.h" namespace Stratum @@ -15,42 +16,44 @@ namespace Stratum _shares.push_back(curTime); - if (sinceLast < RETARGET_INTERVAL) + if (sinceLast < sConfig.Get("RetargetInterval")) return true; _lastRetarget = curTime; // Check if miner is ok - if (_totalShares > 50 && (double(_totalBadShares)/double(_totalShares)) > 0.8) - _client->Ban(60); + if (_totalShares > 50 && (double(_totalBadShares)/double(_totalShares)) > 0.8) { + _client->Ban(600); + return false; + } while (_shares.size()) { - if (_shares.front() > curTime - RETARGET_TIME_BUFFER) + if (_shares.front() > curTime - sConfig.Get("RetargetTimeBuffer")) break; _shares.pop_front(); } - uint32 interval = std::min(curTime - _startTime, uint64(RETARGET_TIME_BUFFER)); + uint32 interval = std::min(curTime - _startTime, uint64(sConfig.Get("RetargetTimeBuffer"))); // Calculate shares/min double speed = double(_shares.size()*60) / double(interval); // Calculate difference from pool target in % - double variance = speed / double(RETARGET_SHARES_PER_MIN); + double variance = speed / double(sConfig.Get("RetargetSharesPerMin")); - sLog.Info(LOG_SERVER, "Miner variance: %f speed: %f", variance, speed); + sLog.Debug(LOG_STRATUM, "Miner variance: %f speed: %f", variance, speed); // Check if we need to retarget - if (variance*100 < RETARGET_VARIANCE) + if (variance*100 < sConfig.Get("RetargetVariance")) return true; uint64 newDiff = double(_client->GetDifficulty()) * variance; - if (newDiff < 1) - newDiff = 1; + if (newDiff < sConfig.Get("RetargetMinDiff")) + newDiff = sConfig.Get("RetargetMinDiff"); - if (newDiff > RETARGET_MAXDIFF) - newDiff = RETARGET_MAXDIFF; + if (newDiff > sConfig.Get("RetargetMaxDiff")) + newDiff = sConfig.Get("RetargetMaxDiff"); _client->SetDifficulty(newDiff, true); diff --git a/src/server/poolserver/Stratum/ShareLimiter.h b/src/server/poolserver/Stratum/ShareLimiter.h index b450b2b..a053b55 100644 --- a/src/server/poolserver/Stratum/ShareLimiter.h +++ b/src/server/poolserver/Stratum/ShareLimiter.h @@ -6,12 +6,6 @@ #include -#define RETARGET_INTERVAL 20 -#define RETARGET_TIME_BUFFER 60*5 -#define RETARGET_SHARES_PER_MIN 15 -#define RETARGET_VARIANCE 40 -#define RETARGET_MAXDIFF 1000000 - namespace Stratum { class Client; diff --git a/src/server/shared/Configuration/Config.h b/src/server/shared/Configuration/Config.h index 12b05b0..4cc165d 100644 --- a/src/server/shared/Configuration/Config.h +++ b/src/server/shared/Configuration/Config.h @@ -5,6 +5,7 @@ #include #include #include +#include "Log.h" class Config { @@ -16,7 +17,15 @@ public: template T Get(std::string key) { - return vm[key].as(); + T tmp; + + try { + tmp = vm[key].as(); + } catch(std::exception& e) { + sLog.Error(LOG_GENERAL, "Failed to get config value for key '%s'", key.c_str()); + } + + return tmp; } // Containers