Browse Source

Merge branch 'master' into peercoin

peercoin
Intel 11 years ago
parent
commit
ec1ba456e1
  1. 8
      src/server/poolserver/DataMgr/DataMgr.cpp
  2. 6
      src/server/poolserver/DataMgr/DataMgr.h
  3. 12
      src/server/poolserver/Main.cpp
  4. 37
      src/server/poolserver/Stratum/Client.cpp
  5. 10
      src/server/poolserver/Stratum/Client.h
  6. 3
      src/server/poolserver/Stratum/Job.h
  7. 2
      src/server/poolserver/Stratum/Server.h
  8. 27
      src/server/poolserver/Stratum/ShareLimiter.cpp
  9. 6
      src/server/poolserver/Stratum/ShareLimiter.h
  10. 11
      src/server/shared/Configuration/Config.h

8
src/server/poolserver/DataMgr/DataMgr.cpp

@ -9,12 +9,14 @@ void DataMgr::Upload()
{ {
sLog.Info(LOG_SERVER, "We have %u shares", Size()); sLog.Info(LOG_SERVER, "We have %u shares", Size());
while (Size() > BULK_MIN) uint32 bulkCount = sConfig.Get<uint32>("ShareUploadBulkCount");
while (Size() > sConfig.Get<uint32>("ShareUploadMinCount"))
{ {
sLog.Info(LOG_SERVER, "Uploading %u shares to database", Size()); 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 "); 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(); Share share = Pop();
@ -23,7 +25,7 @@ void DataMgr::Upload()
if (!Size()) if (!Size())
break; break;
if (i != BULK_COUNT-1) if (i != bulkCount-1)
query += ','; query += ',';
} }

6
src/server/poolserver/DataMgr/DataMgr.h

@ -7,9 +7,7 @@
#include "Util.h" #include "Util.h"
#include "Share.h" #include "Share.h"
#include "Config.h"
#define BULK_MIN 1
#define BULK_COUNT 50
using namespace boost; using namespace boost;
@ -58,7 +56,7 @@ public:
void UploadTimerStart() void UploadTimerStart()
{ {
_uploadTimer.expires_from_now(boost::posix_time::seconds(3)); _uploadTimer.expires_from_now(boost::posix_time::seconds(sConfig.Get<uint32>("ShareUploadInterval")));
_uploadTimer.async_wait(boost::bind(&DataMgr::UploadTimerExpired, this, boost::asio::placeholders::error)); _uploadTimer.async_wait(boost::bind(&DataMgr::UploadTimerExpired, this, boost::asio::placeholders::error));
} }

12
src/server/poolserver/Main.cpp

@ -34,8 +34,11 @@ bool InitConfig(int argc, char *argv[])
// Server // Server
descServer.add_options() descServer.add_options()
("ServerThreads", boost::program_options::value<uint32_t>()->default_value(2), "How many threads to use") ("ServerThreads", boost::program_options::value<uint32_t>()->default_value(2), "How many threads to use")
("MiningAddress", boost::program_options::value<std::string>()->default_value("n1w8gkPXdNGb6edm4vujBn71A72eQFCNCw"), "Address to send coins to") ("MiningAddress", boost::program_options::value<std::string>(), "Address to send coins to")
("BitcoinRPC", boost::program_options::value<std::vector<std::string> >()->multitoken(), "Bitcoin RPC login credentials") ("BitcoinRPC", boost::program_options::value<std::vector<std::string> >()->multitoken(), "Bitcoin RPC login credentials")
("ShareUploadMinCount", boost::program_options::value<uint32>()->default_value(2), "Minimum share count to upload to database")
("ShareUploadBulkCount", boost::program_options::value<uint32>()->default_value(50), "How many shares to upload in one query")
("ShareUploadInterval", boost::program_options::value<uint32>()->default_value(3), "How often to upload shares")
; ;
// Stratum // Stratum
@ -43,7 +46,12 @@ bool InitConfig(int argc, char *argv[])
("StratumHost,sh", boost::program_options::value<std::string>()->default_value("0.0.0.0"), "Stratum server host") ("StratumHost,sh", boost::program_options::value<std::string>()->default_value("0.0.0.0"), "Stratum server host")
("StratumPort,sp", boost::program_options::value<uint16_t>()->default_value(3333), "Stratum server port") ("StratumPort,sp", boost::program_options::value<uint16_t>()->default_value(3333), "Stratum server port")
("StratumBlockCheckTime", boost::program_options::value<uint32>()->default_value(2000), "Time between block checks in ms") ("StratumBlockCheckTime", boost::program_options::value<uint32>()->default_value(2000), "Time between block checks in ms")
("StratumMinDifficulty", boost::program_options::value<uint32>()->default_value(1), "The difficulty on which a new miner starts") ("RetargetInterval", boost::program_options::value<uint32>()->default_value(20), "Time between difficulty checks in seconds")
("RetargetTimeBuffer", boost::program_options::value<uint32>()->default_value(60*5), "Buffer of shares to keep (in seconds)")
("RetargetSharesPerMin", boost::program_options::value<uint32>()->default_value(15), "How many shares per min to target for")
("RetargetVariance", boost::program_options::value<uint32>()->default_value(40), "Maximum allowed variance in percent before difficulty change")
("RetargetMinDiff", boost::program_options::value<uint32>()->default_value(1), "Minimum difficulty (also starting difficulty)")
("RetargetMaxDiff", boost::program_options::value<uint32>()->default_value(1000000), "Maximum difficulty we can reach")
; ;
// Logging // Logging

37
src/server/poolserver/Stratum/Client.cpp

@ -93,7 +93,7 @@ namespace Stratum
// check username // check username
std::string username = params[0].GetString(); std::string username = params[0].GetString();
if (!_workers.count(username)) { if (!_workers.count(username)) {
sLog.Error(LOG_SERVER, "Worker not authenticated"); sLog.Error(LOG_STRATUM, "%s: Worker not authenticated", username.c_str());
JSON response; JSON response;
response["id"] = msg["id"]; response["id"] = msg["id"];
response["result"]; response["result"];
@ -125,7 +125,7 @@ namespace Stratum
BinaryData extranonce2 = Util::ASCIIToBin(params[2].GetString()); BinaryData extranonce2 = Util::ASCIIToBin(params[2].GetString());
if (extranonce2.size() != 4) { if (extranonce2.size() != 4) {
sLog.Error(LOG_SERVER, "Wrong extranonce size"); sLog.Error(LOG_STRATUM, "Wrong extranonce size");
JSON response; JSON response;
response["id"] = msg["id"]; response["id"] = msg["id"];
response["result"]; response["result"];
@ -138,7 +138,7 @@ namespace Stratum
ByteBuffer timebuf(Util::Reverse(Util::ASCIIToBin(params[3].GetString()))); ByteBuffer timebuf(Util::Reverse(Util::ASCIIToBin(params[3].GetString())));
if (timebuf.Size() != 4) { if (timebuf.Size() != 4) {
sLog.Error(LOG_SERVER, "Wrong ntime size"); sLog.Error(LOG_STRATUM, "Wrong ntime size");
JSON response; JSON response;
response["id"] = msg["id"]; response["id"] = msg["id"];
response["result"]; response["result"];
@ -151,7 +151,7 @@ namespace Stratum
ByteBuffer noncebuf(Util::Reverse(Util::ASCIIToBin(params[4].GetString()))); ByteBuffer noncebuf(Util::Reverse(Util::ASCIIToBin(params[4].GetString())));
if (noncebuf.Size() != 4) { if (noncebuf.Size() != 4) {
sLog.Error(LOG_SERVER, "Wrong nonce size"); sLog.Error(LOG_STRATUM, "Wrong nonce size");
JSON response; JSON response;
response["id"] = msg["id"]; response["id"] = msg["id"];
response["result"]; response["result"];
@ -168,7 +168,7 @@ namespace Stratum
ByteBuffer share; ByteBuffer share;
share << extranonce2 << timebuf << noncebuf; share << extranonce2 << timebuf << noncebuf;
if (!job.SubmitShare(share.Binary())) { 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)); DataMgr::Instance()->Push(Share(_ip, username, false, "Duplicate share", Util::Date(), job.diff));
_shareLimiter.LogBad(); _shareLimiter.LogBad();
@ -207,17 +207,9 @@ namespace Stratum
// Get block target // Get block target
BigInt target(Util::BinToASCII(Util::Reverse(hash)), 16); 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 // Check if difficulty meets job diff
if (target > Bitcoin::DiffToTarget(job.diff)) { if (target > job.target) {
sLog.Error(LOG_SERVER, "Share above 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)); DataMgr::Instance()->Push(Share(_ip, username, false, "Share above target", Util::Date(), job.diff));
_shareLimiter.LogBad(); _shareLimiter.LogBad();
@ -232,7 +224,7 @@ namespace Stratum
} }
// Check if block meets criteria // Check if block meets criteria
if (target <= criteria) { if (target <= job.blockCriteria) {
sLog.Info(LOG_SERVER, "We have found a block candidate!"); sLog.Info(LOG_SERVER, "We have found a block candidate!");
if (_server->SubmitBlock(block)) { if (_server->SubmitBlock(block)) {
@ -292,11 +284,17 @@ namespace Stratum
std::string username = msg["params"][0].GetString(); std::string username = msg["params"][0].GetString();
std::string password = msg["params"][1].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) { if (result) {
_workers.insert(username); _workers.insert(username);
MySQL::Field* fields = result->FetchRow();
_minDiff = fields[1].Get<uint32>();
if (_diff < _minDiff)
SetDifficulty(_minDiff);
JSON response; JSON response;
response["id"] = msg["id"].GetInt(); response["id"] = msg["id"].GetInt();
response["error"]; response["error"];
@ -317,7 +315,8 @@ namespace Stratum
{ {
Job job; Job job;
job.block = _server->GetWork(); job.block = _server->GetWork();
job.diff = 1; job.diff = _diff;
job.target = Bitcoin::DiffToTarget(job.diff);
// Serialize transaction // Serialize transaction
ByteBuffer coinbasebuf; ByteBuffer coinbasebuf;
@ -334,6 +333,8 @@ namespace Stratum
job.coinbase1 = BinaryData(coinbase.begin(), coinbase.begin() + cbsplit); job.coinbase1 = BinaryData(coinbase.begin(), coinbase.begin() + cbsplit);
job.coinbase2 = BinaryData(coinbase.begin() + cbsplit + 8, coinbase.end()); // plus extranonce size job.coinbase2 = BinaryData(coinbase.begin() + cbsplit + 8, coinbase.end()); // plus extranonce size
job.blockCriteria = Bitcoin::TargetFromBits(job.block->bits);
return job; return job;
} }

10
src/server/poolserver/Stratum/Client.h

@ -27,8 +27,8 @@ namespace Stratum
public: 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) 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<uint32>("StratumMinDifficulty"); _diff = sConfig.Get<uint32>("RetargetMinDiff");
_minDiff = _diff; _minDiff = sConfig.Get<uint32>("RetargetMinDiff");
} }
~Client() ~Client()
@ -98,6 +98,12 @@ namespace Stratum
} }
void SetDifficulty(uint64 diff, bool resendJob = false) void SetDifficulty(uint64 diff, bool resendJob = false)
{ {
if (diff < _minDiff)
diff = _minDiff;
if (diff == _diff)
return;
_diff = diff; _diff = diff;
// Send difficulty update // Send difficulty update

3
src/server/poolserver/Stratum/Job.h

@ -4,6 +4,7 @@
#include "Bitcoin.h" #include "Bitcoin.h"
#include "Crypto.h" #include "Crypto.h"
#include "Util.h" #include "Util.h"
#include "BigNum.h"
#include <set> #include <set>
namespace Stratum namespace Stratum
@ -16,6 +17,8 @@ namespace Stratum
BinaryData coinbase1; BinaryData coinbase1;
BinaryData coinbase2; BinaryData coinbase2;
std::set<std::string> shares; std::set<std::string> shares;
BigInt blockCriteria;
BigInt target;
// Submits share to a job // Submits share to a job
// Returns false if the same share already exists // Returns false if the same share already exists

2
src/server/poolserver/Stratum/Server.h

@ -82,7 +82,7 @@ namespace Stratum
// Block template update event // Block template update event
void BlockNotify(Bitcoin::BlockPtr block, bool newBlock) 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(); _mtxCurrentWork.lock();
_currentWork = block; _currentWork = block;
_mtxCurrentWork.unlock(); _mtxCurrentWork.unlock();

27
src/server/poolserver/Stratum/ShareLimiter.cpp

@ -1,6 +1,7 @@
#include "ShareLimiter.h" #include "ShareLimiter.h"
#include "Server.h" #include "Server.h"
#include "Client.h" #include "Client.h"
#include "Config.h"
#include "Log.h" #include "Log.h"
namespace Stratum namespace Stratum
@ -15,42 +16,44 @@ namespace Stratum
_shares.push_back(curTime); _shares.push_back(curTime);
if (sinceLast < RETARGET_INTERVAL) if (sinceLast < sConfig.Get<uint32>("RetargetInterval"))
return true; return true;
_lastRetarget = curTime; _lastRetarget = curTime;
// Check if miner is ok // Check if miner is ok
if (_totalShares > 50 && (double(_totalBadShares)/double(_totalShares)) > 0.8) if (_totalShares > 50 && (double(_totalBadShares)/double(_totalShares)) > 0.8) {
_client->Ban(60); _client->Ban(600);
return false;
}
while (_shares.size()) { while (_shares.size()) {
if (_shares.front() > curTime - RETARGET_TIME_BUFFER) if (_shares.front() > curTime - sConfig.Get<uint32>("RetargetTimeBuffer"))
break; break;
_shares.pop_front(); _shares.pop_front();
} }
uint32 interval = std::min(curTime - _startTime, uint64(RETARGET_TIME_BUFFER)); uint32 interval = std::min(curTime - _startTime, uint64(sConfig.Get<uint32>("RetargetTimeBuffer")));
// Calculate shares/min // Calculate shares/min
double speed = double(_shares.size()*60) / double(interval); double speed = double(_shares.size()*60) / double(interval);
// Calculate difference from pool target in % // Calculate difference from pool target in %
double variance = speed / double(RETARGET_SHARES_PER_MIN); double variance = speed / double(sConfig.Get<uint32>("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 // Check if we need to retarget
if (variance*100 < RETARGET_VARIANCE) if (variance*100 < sConfig.Get<uint32>("RetargetVariance"))
return true; return true;
uint64 newDiff = double(_client->GetDifficulty()) * variance; uint64 newDiff = double(_client->GetDifficulty()) * variance;
if (newDiff < 1) if (newDiff < sConfig.Get<uint32>("RetargetMinDiff"))
newDiff = 1; newDiff = sConfig.Get<uint32>("RetargetMinDiff");
if (newDiff > RETARGET_MAXDIFF) if (newDiff > sConfig.Get<uint32>("RetargetMaxDiff"))
newDiff = RETARGET_MAXDIFF; newDiff = sConfig.Get<uint32>("RetargetMaxDiff");
_client->SetDifficulty(newDiff, true); _client->SetDifficulty(newDiff, true);

6
src/server/poolserver/Stratum/ShareLimiter.h

@ -6,12 +6,6 @@
#include <deque> #include <deque>
#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 namespace Stratum
{ {
class Client; class Client;

11
src/server/shared/Configuration/Config.h

@ -5,6 +5,7 @@
#include <cstring> #include <cstring>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "Log.h"
class Config class Config
{ {
@ -16,7 +17,15 @@ public:
template<class T> template<class T>
T Get(std::string key) T Get(std::string key)
{ {
return vm[key].as<T>(); T tmp;
try {
tmp = vm[key].as<T>();
} catch(std::exception& e) {
sLog.Error(LOG_GENERAL, "Failed to get config value for key '%s'", key.c_str());
}
return tmp;
} }
// Containers // Containers

Loading…
Cancel
Save