mirror of
https://github.com/xmrig/xmrig.git
synced 2025-03-20 22:28:50 +00:00
Allow result submission to origin daemon with self-select
With `self-select` mode enabled, the `submit-to-origin` config option will let the `SelfSelectClient` submit the solution to both the daemon where it got the template from as well as to the connected pool, for miners that want to do pool minining with Monero and solo mining with an altcoin (merged mining variant). Thank you and special credit to @StriderDM (https://github.com/StriderDM)!
This commit is contained in:
parent
d2f01cfa86
commit
3b87cd97ce
12 changed files with 86 additions and 9 deletions
|
@ -36,6 +36,12 @@ const char *xmrig::Tags::network()
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* xmrig::Tags::origin()
|
||||||
|
{
|
||||||
|
static const char* tag = YELLOW_BG_BOLD(WHITE_BOLD_S " origin ");
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
const char *xmrig::Tags::signal()
|
const char *xmrig::Tags::signal()
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,7 @@ class Tags
|
||||||
public:
|
public:
|
||||||
static const char *config();
|
static const char *config();
|
||||||
static const char *network();
|
static const char *network();
|
||||||
|
static const char *origin();
|
||||||
static const char *signal();
|
static const char *signal();
|
||||||
|
|
||||||
# ifdef XMRIG_MINER_PROJECT
|
# ifdef XMRIG_MINER_PROJECT
|
||||||
|
|
|
@ -260,6 +260,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
|
||||||
case IConfig::DryRunKey: /* --dry-run */
|
case IConfig::DryRunKey: /* --dry-run */
|
||||||
case IConfig::HttpEnabledKey: /* --http-enabled */
|
case IConfig::HttpEnabledKey: /* --http-enabled */
|
||||||
case IConfig::DaemonKey: /* --daemon */
|
case IConfig::DaemonKey: /* --daemon */
|
||||||
|
case IConfig::SubmitToOriginKey: /* --submit-to-origin */
|
||||||
case IConfig::VerboseKey: /* --verbose */
|
case IConfig::VerboseKey: /* --verbose */
|
||||||
case IConfig::PauseOnBatteryKey: /* --pause-on-battery */
|
case IConfig::PauseOnBatteryKey: /* --pause-on-battery */
|
||||||
case IConfig::PauseOnActiveKey: /* --pause-on-active */
|
case IConfig::PauseOnActiveKey: /* --pause-on-active */
|
||||||
|
@ -291,6 +292,8 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b
|
||||||
case IConfig::TlsKey: /* --tls */
|
case IConfig::TlsKey: /* --tls */
|
||||||
return add(doc, Pools::kPools, Pool::kTls, enable);
|
return add(doc, Pools::kPools, Pool::kTls, enable);
|
||||||
|
|
||||||
|
case IConfig::SubmitToOriginKey: /* --submit-to-origin */
|
||||||
|
return add(doc, Pools::kPools, Pool::kSubmitToOrigin, enable);
|
||||||
# ifdef XMRIG_FEATURE_HTTP
|
# ifdef XMRIG_FEATURE_HTTP
|
||||||
case IConfig::DaemonKey: /* --daemon */
|
case IConfig::DaemonKey: /* --daemon */
|
||||||
return add(doc, Pools::kPools, Pool::kDaemon, enable);
|
return add(doc, Pools::kPools, Pool::kDaemon, enable);
|
||||||
|
|
|
@ -73,6 +73,7 @@ public:
|
||||||
DaemonKey = 1018,
|
DaemonKey = 1018,
|
||||||
DaemonPollKey = 1019,
|
DaemonPollKey = 1019,
|
||||||
SelfSelectKey = 1028,
|
SelfSelectKey = 1028,
|
||||||
|
SubmitToOriginKey = 1049,
|
||||||
DataDirKey = 1035,
|
DataDirKey = 1035,
|
||||||
TitleKey = 1037,
|
TitleKey = 1037,
|
||||||
NoTitleKey = 1038,
|
NoTitleKey = 1038,
|
||||||
|
|
|
@ -79,6 +79,7 @@ const char *Pool::kNicehash = "nicehash";
|
||||||
const char *Pool::kPass = "pass";
|
const char *Pool::kPass = "pass";
|
||||||
const char *Pool::kRigId = "rig-id";
|
const char *Pool::kRigId = "rig-id";
|
||||||
const char *Pool::kSelfSelect = "self-select";
|
const char *Pool::kSelfSelect = "self-select";
|
||||||
|
const char* Pool::kSubmitToOrigin = "submit-to-origin";
|
||||||
const char *Pool::kSOCKS5 = "socks5";
|
const char *Pool::kSOCKS5 = "socks5";
|
||||||
const char *Pool::kTls = "tls";
|
const char *Pool::kTls = "tls";
|
||||||
const char *Pool::kUrl = "url";
|
const char *Pool::kUrl = "url";
|
||||||
|
@ -138,6 +139,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
|
||||||
|
|
||||||
if (m_daemon.isValid()) {
|
if (m_daemon.isValid()) {
|
||||||
m_mode = MODE_SELF_SELECT;
|
m_mode = MODE_SELF_SELECT;
|
||||||
|
m_submit_to_origin = Json::getBool(object, kSubmitToOrigin, false);
|
||||||
}
|
}
|
||||||
else if (Json::getBool(object, kDaemon)) {
|
else if (Json::getBool(object, kDaemon)) {
|
||||||
m_mode = MODE_DAEMON;
|
m_mode = MODE_DAEMON;
|
||||||
|
@ -237,7 +239,7 @@ xmrig::IClient *xmrig::Pool::createClient(int id, IClientListener *listener) con
|
||||||
client = new DaemonClient(id, listener);
|
client = new DaemonClient(id, listener);
|
||||||
}
|
}
|
||||||
else if (m_mode == MODE_SELF_SELECT) {
|
else if (m_mode == MODE_SELF_SELECT) {
|
||||||
client = new SelfSelectClient(id, Platform::userAgent(), listener);
|
client = new SelfSelectClient(id, Platform::userAgent(), listener, m_submit_to_origin);
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
# ifdef XMRIG_ALGO_KAWPOW
|
# ifdef XMRIG_ALGO_KAWPOW
|
||||||
|
@ -301,6 +303,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
obj.AddMember(StringRef(kSelfSelect), m_daemon.url().toJSON(), allocator);
|
obj.AddMember(StringRef(kSelfSelect), m_daemon.url().toJSON(), allocator);
|
||||||
|
obj.AddMember(StringRef(kSubmitToOrigin), m_submit_to_origin, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -319,7 +322,7 @@ std::string xmrig::Pool::printableName() const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_mode == MODE_SELF_SELECT) {
|
if (m_mode == MODE_SELF_SELECT) {
|
||||||
out += std::string(" self-select ") + CSI "1;" + std::to_string(m_daemon.isTLS() ? 32 : 36) + "m" + m_daemon.url().data() + CLEAR;
|
out += std::string(" self-select ") + CSI "1;" + std::to_string(m_daemon.isTLS() ? 32 : 36) + "m" + m_daemon.url().data() + WHITE_BOLD_S + (m_submit_to_origin ? " submit-to-origin" : "") + CLEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
|
@ -72,6 +72,7 @@ public:
|
||||||
static const char *kPass;
|
static const char *kPass;
|
||||||
static const char *kRigId;
|
static const char *kRigId;
|
||||||
static const char *kSelfSelect;
|
static const char *kSelfSelect;
|
||||||
|
static const char* kSubmitToOrigin;
|
||||||
static const char *kSOCKS5;
|
static const char *kSOCKS5;
|
||||||
static const char *kTls;
|
static const char *kTls;
|
||||||
static const char *kUrl;
|
static const char *kUrl;
|
||||||
|
@ -156,6 +157,7 @@ private:
|
||||||
uint64_t m_pollInterval = kDefaultPollInterval;
|
uint64_t m_pollInterval = kDefaultPollInterval;
|
||||||
Url m_daemon;
|
Url m_daemon;
|
||||||
Url m_url;
|
Url m_url;
|
||||||
|
bool m_submit_to_origin = false;
|
||||||
|
|
||||||
# ifdef XMRIG_FEATURE_BENCHMARK
|
# ifdef XMRIG_FEATURE_BENCHMARK
|
||||||
std::shared_ptr<BenchConfig> m_benchmark;
|
std::shared_ptr<BenchConfig> m_benchmark;
|
||||||
|
|
|
@ -31,9 +31,12 @@
|
||||||
#include "base/io/json/Json.h"
|
#include "base/io/json/Json.h"
|
||||||
#include "base/io/json/JsonRequest.h"
|
#include "base/io/json/JsonRequest.h"
|
||||||
#include "base/io/log/Log.h"
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/io/log/Tags.h"
|
||||||
#include "base/net/http/Fetch.h"
|
#include "base/net/http/Fetch.h"
|
||||||
#include "base/net/http/HttpData.h"
|
#include "base/net/http/HttpData.h"
|
||||||
#include "base/net/stratum/Client.h"
|
#include "base/net/stratum/Client.h"
|
||||||
|
#include "net/JobResult.h"
|
||||||
|
#include "base/tools/Cvt.h"
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
@ -54,8 +57,8 @@ static const char * const required_fields[] = { kBlocktemplateBlob, kBlockhashin
|
||||||
} /* namespace xmrig */
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
xmrig::SelfSelectClient::SelfSelectClient(int id, const char *agent, IClientListener *listener) :
|
xmrig::SelfSelectClient::SelfSelectClient(int id, const char *agent, IClientListener *listener, bool submit_to_origin) :
|
||||||
m_listener(listener)
|
m_listener(listener), m_submit_to_origin(submit_to_origin)
|
||||||
{
|
{
|
||||||
m_httpListener = std::make_shared<HttpListener>(this);
|
m_httpListener = std::make_shared<HttpListener>(this);
|
||||||
m_client = new Client(id, agent, this);
|
m_client = new Client(id, agent, this);
|
||||||
|
@ -201,6 +204,9 @@ void xmrig::SelfSelectClient::submitBlockTemplate(rapidjson::Value &result)
|
||||||
Document doc(kObjectType);
|
Document doc(kObjectType);
|
||||||
auto &allocator = doc.GetAllocator();
|
auto &allocator = doc.GetAllocator();
|
||||||
|
|
||||||
|
m_blocktemplate = Json::getString(result,kBlocktemplateBlob);
|
||||||
|
m_blockdiff = Json::getUint64(result, kDifficulty);
|
||||||
|
|
||||||
Value params(kObjectType);
|
Value params(kObjectType);
|
||||||
params.AddMember(StringRef(kId), m_job.clientId().toJSON(), allocator);
|
params.AddMember(StringRef(kId), m_job.clientId().toJSON(), allocator);
|
||||||
params.AddMember(StringRef(kJobId), m_job.id().toJSON(), allocator);
|
params.AddMember(StringRef(kJobId), m_job.id().toJSON(), allocator);
|
||||||
|
@ -235,6 +241,50 @@ void xmrig::SelfSelectClient::submitBlockTemplate(rapidjson::Value &result)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t xmrig::SelfSelectClient::submit(const JobResult& result)
|
||||||
|
{
|
||||||
|
if (m_submit_to_origin) {
|
||||||
|
submitOriginDaemon(result);
|
||||||
|
}
|
||||||
|
return m_client->submit(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xmrig::SelfSelectClient::submitOriginDaemon(const JobResult& result)
|
||||||
|
{
|
||||||
|
if (result.diff == 0 || m_blockdiff == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.actualDiff() < m_blockdiff) {
|
||||||
|
m_origin_not_submitted++;
|
||||||
|
LOG_DEBUG("%s " RED_BOLD("not submitted to origin daemon, difficulty too low") " (%" PRId64 "/%" PRId64 ") "
|
||||||
|
BLACK_BOLD(" diff ") BLACK_BOLD("%" PRIu64) BLACK_BOLD(" vs. ") BLACK_BOLD("%" PRIu64),
|
||||||
|
Tags::origin(), m_origin_submitted, m_origin_not_submitted, m_blockdiff, result.actualDiff());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *data = m_blocktemplate.data();
|
||||||
|
Cvt::toHex(data + 78, 8, reinterpret_cast<const uint8_t*>(&result.nonce), 4);
|
||||||
|
|
||||||
|
using namespace rapidjson;
|
||||||
|
Document doc(kObjectType);
|
||||||
|
|
||||||
|
Value params(kArrayType);
|
||||||
|
params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator());
|
||||||
|
|
||||||
|
JsonRequest::create(doc, m_sequence, "submitblock", params);
|
||||||
|
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), 0, result.backend);
|
||||||
|
|
||||||
|
FetchRequest req(HTTP_POST, pool().daemon().host(), pool().daemon().port(), "/json_rpc", doc, pool().daemon().isTLS(), isQuiet());
|
||||||
|
fetch(tag(), std::move(req), m_httpListener);
|
||||||
|
|
||||||
|
m_origin_submitted++;
|
||||||
|
LOG_INFO("%s " GREEN_BOLD("submitted to origin daemon") " (%" PRId64 "/%" PRId64 ") "
|
||||||
|
" diff " WHITE("%" PRIu64) " vs. " WHITE("%" PRIu64),
|
||||||
|
Tags::origin(), m_origin_submitted, m_origin_not_submitted, m_blockdiff, result.actualDiff(), result.diff);
|
||||||
|
|
||||||
|
// Ensure that the latest block template is available after block submission
|
||||||
|
getBlockTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
void xmrig::SelfSelectClient::onHttpData(const HttpData &data)
|
void xmrig::SelfSelectClient::onHttpData(const HttpData &data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
@ -45,7 +46,7 @@ class SelfSelectClient : public IClient, public IClientListener, public IHttpLis
|
||||||
public:
|
public:
|
||||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(SelfSelectClient)
|
XMRIG_DISABLE_COPY_MOVE_DEFAULT(SelfSelectClient)
|
||||||
|
|
||||||
SelfSelectClient(int id, const char *agent, IClientListener *listener);
|
SelfSelectClient(int id, const char *agent, IClientListener *listener, bool submit_to_origin);
|
||||||
~SelfSelectClient() override;
|
~SelfSelectClient() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -65,7 +66,7 @@ protected:
|
||||||
inline int64_t send(const rapidjson::Value &obj, Callback callback) override { return m_client->send(obj, callback); }
|
inline int64_t send(const rapidjson::Value &obj, Callback callback) override { return m_client->send(obj, callback); }
|
||||||
inline int64_t send(const rapidjson::Value &obj) override { return m_client->send(obj); }
|
inline int64_t send(const rapidjson::Value &obj) override { return m_client->send(obj); }
|
||||||
inline int64_t sequence() const override { return m_client->sequence(); }
|
inline int64_t sequence() const override { return m_client->sequence(); }
|
||||||
inline int64_t submit(const JobResult &result) override { return m_client->submit(result); }
|
inline int64_t submit(const JobResult &result) override;
|
||||||
inline void connect() override { m_client->connect(); }
|
inline void connect() override { m_client->connect(); }
|
||||||
inline void connect(const Pool &pool) override { m_client->connect(pool); }
|
inline void connect(const Pool &pool) override { m_client->connect(pool); }
|
||||||
inline void deleteLater() override { m_client->deleteLater(); }
|
inline void deleteLater() override { m_client->deleteLater(); }
|
||||||
|
@ -105,7 +106,7 @@ private:
|
||||||
void retry();
|
void retry();
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
void submitBlockTemplate(rapidjson::Value &result);
|
void submitBlockTemplate(rapidjson::Value &result);
|
||||||
|
inline void submitOriginDaemon(const JobResult &result);
|
||||||
bool m_active = false;
|
bool m_active = false;
|
||||||
bool m_quiet = false;
|
bool m_quiet = false;
|
||||||
IClient *m_client;
|
IClient *m_client;
|
||||||
|
@ -115,9 +116,15 @@ private:
|
||||||
int64_t m_sequence = 1;
|
int64_t m_sequence = 1;
|
||||||
Job m_job;
|
Job m_job;
|
||||||
State m_state = IdleState;
|
State m_state = IdleState;
|
||||||
|
String m_blocktemplate;
|
||||||
|
bool m_submit_to_origin = false;
|
||||||
|
std::map<int64_t, SubmitResult> m_results;
|
||||||
std::shared_ptr<IHttpListener> m_httpListener;
|
std::shared_ptr<IHttpListener> m_httpListener;
|
||||||
uint64_t m_retryPause = 5000;
|
uint64_t m_retryPause = 5000;
|
||||||
uint64_t m_timestamp = 0;
|
uint64_t m_timestamp = 0;
|
||||||
|
uint64_t m_blockdiff = 0;
|
||||||
|
uint64_t m_origin_submitted = 0;
|
||||||
|
uint64_t m_origin_not_submitted = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,8 @@
|
||||||
"tls-fingerprint": null,
|
"tls-fingerprint": null,
|
||||||
"daemon": false,
|
"daemon": false,
|
||||||
"socks5": null,
|
"socks5": null,
|
||||||
"self-select": null
|
"self-select": null,
|
||||||
|
"submit-to-origin": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"print-time": 60,
|
"print-time": 60,
|
||||||
|
|
|
@ -105,7 +105,8 @@ R"===(
|
||||||
"tls-fingerprint": null,
|
"tls-fingerprint": null,
|
||||||
"daemon": false,
|
"daemon": false,
|
||||||
"socks5": null,
|
"socks5": null,
|
||||||
"self-select": null
|
"self-select": null,
|
||||||
|
"submit-to-origin": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"print-time": 60,
|
"print-time": 60,
|
||||||
|
|
|
@ -57,6 +57,7 @@ static const option options[] = {
|
||||||
{ "daemon", 0, nullptr, IConfig::DaemonKey },
|
{ "daemon", 0, nullptr, IConfig::DaemonKey },
|
||||||
{ "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey },
|
{ "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey },
|
||||||
{ "self-select", 1, nullptr, IConfig::SelfSelectKey },
|
{ "self-select", 1, nullptr, IConfig::SelfSelectKey },
|
||||||
|
{ "submit-to-origin", 0, nullptr, IConfig::SubmitToOriginKey },
|
||||||
# endif
|
# endif
|
||||||
{ "av", 1, nullptr, IConfig::AVKey },
|
{ "av", 1, nullptr, IConfig::AVKey },
|
||||||
{ "background", 0, nullptr, IConfig::BackgroundKey },
|
{ "background", 0, nullptr, IConfig::BackgroundKey },
|
||||||
|
|
|
@ -64,6 +64,7 @@ static inline const std::string &usage()
|
||||||
u += " --daemon use daemon RPC instead of pool for solo mining\n";
|
u += " --daemon use daemon RPC instead of pool for solo mining\n";
|
||||||
u += " --daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n";
|
u += " --daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)\n";
|
||||||
u += " --self-select=URL self-select block templates from URL\n";
|
u += " --self-select=URL self-select block templates from URL\n";
|
||||||
|
u += " --submit-to-origin also submit solution back to self-select URL\n";
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
u += " -r, --retries=N number of times to retry before switch to backup server (default: 5)\n";
|
u += " -r, --retries=N number of times to retry before switch to backup server (default: 5)\n";
|
||||||
|
|
Loading…
Reference in a new issue