Merge xmrig v6.6.0 into master

This commit is contained in:
MoneroOcean 2020-11-23 15:09:11 +00:00
commit 54e736aaaa
29 changed files with 794 additions and 454 deletions

View file

@ -119,6 +119,7 @@ namespace xmrig {
class AsyncPrivate
{
public:
Async::Callback callback;
IAsyncListener *listener = nullptr;
uv_async_t *async = nullptr;
};
@ -127,6 +128,16 @@ public:
} // namespace xmrig
xmrig::Async::Async(Callback callback) : d_ptr(new AsyncPrivate())
{
d_ptr->callback = std::move(callback);
d_ptr->async = new uv_async_t;
d_ptr->async->data = this;
uv_async_init(uv_default_loop(), d_ptr->async, [](uv_async_t *handle) { static_cast<Async *>(handle->data)->d_ptr->callback(); });
}
xmrig::Async::Async(IAsyncListener *listener) : d_ptr(new AsyncPrivate())
{
d_ptr->listener = listener;

View file

@ -25,6 +25,9 @@
#include "base/tools/Object.h"
#include <functional>
namespace xmrig {
@ -37,6 +40,9 @@ class Async
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Async)
using Callback = std::function<void()>;
Async(Callback callback);
Async(IAsyncListener *listener);
~Async();

View file

@ -174,12 +174,6 @@ void xmrig::Job::copy(const Job &other)
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
# endif
# ifdef XMRIG_FEATURE_BENCHMARK
m_benchSize = other.m_benchSize;
m_benchHash = other.m_benchHash;
m_benchToken = other.m_benchToken;
# endif
}
@ -211,10 +205,4 @@ void xmrig::Job::move(Job &&other)
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
# endif
# ifdef XMRIG_FEATURE_BENCHMARK
m_benchSize = other.m_benchSize;
m_benchHash = other.m_benchHash;
m_benchToken = std::move(other.m_benchToken);
# endif
}

View file

@ -111,15 +111,6 @@ public:
inline Job &operator=(const Job &other) { copy(other); return *this; }
inline Job &operator=(Job &&other) noexcept { move(std::move(other)); return *this; }
# ifdef XMRIG_FEATURE_BENCHMARK
inline const String &benchToken() const { return m_benchToken; }
inline uint32_t benchSize() const { return m_benchSize; }
inline uint64_t benchHash() const { return m_benchHash; }
inline void setBenchHash(uint64_t benchHash) { m_benchHash = benchHash; }
inline void setBenchSize(uint32_t size) { m_benchSize = size; }
inline void setBenchToken(const String &token) { m_benchToken = token; }
# endif
private:
void copy(const Job &other);
void move(Job &&other);
@ -144,12 +135,6 @@ private:
char m_rawTarget[24]{};
String m_rawSeedHash;
# endif
# ifdef XMRIG_FEATURE_BENCHMARK
String m_benchToken;
uint32_t m_benchSize = 0;
uint64_t m_benchHash = 0;
# endif
};

View file

@ -19,11 +19,14 @@
#include "base/net/stratum/benchmark/BenchClient.h"
#include "3rdparty/fmt/core.h"
#include "3rdparty/rapidjson/document.h"
#include "backend/common/benchmark/BenchState.h"
#include "backend/common/interfaces/IBackend.h"
#include "backend/cpu/Cpu.h"
#include "base/io/json/Json.h"
#include "base/io/log/Log.h"
#include "base/io/log/Tags.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/dns/Dns.h"
#include "base/net/http/Fetch.h"
#include "base/net/http/HttpData.h"
#include "base/net/http/HttpListener.h"
@ -33,7 +36,8 @@
xmrig::BenchClient::BenchClient(const std::shared_ptr<BenchConfig> &benchmark, IClientListener* listener) :
m_listener(listener),
m_benchmark(benchmark)
m_benchmark(benchmark),
m_hash(benchmark->hash())
{
std::vector<char> blob(112 * 2 + 1, '0');
blob.back() = '\0';
@ -42,8 +46,13 @@ xmrig::BenchClient::BenchClient(const std::shared_ptr<BenchConfig> &benchmark, I
m_job.setAlgorithm(m_benchmark->algorithm());
m_job.setDiff(std::numeric_limits<uint64_t>::max());
m_job.setHeight(1);
m_job.setBenchSize(m_benchmark->size());
m_job.setBenchHash(m_benchmark->hash());
m_job.setId("00000000");
blob[Job::kMaxSeedSize * 2] = '\0';
m_job.setSeedHash(blob.data());
BenchState::setListener(this);
BenchState::setSize(m_benchmark->size());
# ifdef XMRIG_FEATURE_HTTP
if (m_benchmark->isSubmit()) {
@ -54,43 +63,42 @@ xmrig::BenchClient::BenchClient(const std::shared_ptr<BenchConfig> &benchmark, I
if (!m_benchmark->id().isEmpty()) {
m_job.setId(m_benchmark->id());
m_job.setBenchToken(m_benchmark->token());
m_mode = ONLINE_VERIFY;
m_token = m_benchmark->token();
m_mode = ONLINE_VERIFY;
return;
}
# endif
m_job.setId("00000000");
if (m_job.benchHash() && m_job.setSeedHash(m_benchmark->seed())) {
if (m_hash && setSeed(m_benchmark->seed())) {
m_mode = STATIC_VERIFY;
return;
}
}
blob[Job::kMaxSeedSize * 2] = '\0';
m_job.setSeedHash(blob.data());
xmrig::BenchClient::~BenchClient()
{
BenchState::destroy();
}
const char *xmrig::BenchClient::tag() const
{
return Tags::bench();
}
void xmrig::BenchClient::connect()
{
# ifdef XMRIG_FEATURE_HTTP
switch (m_mode) {
case STATIC_BENCH:
case STATIC_VERIFY:
return start();
case ONLINE_BENCH:
return createBench();
case ONLINE_VERIFY:
return getBench();
if (m_mode == ONLINE_BENCH || m_mode == ONLINE_VERIFY) {
return resolve();
}
# else
start();
# endif
start();
}
@ -100,6 +108,43 @@ void xmrig::BenchClient::setPool(const Pool &pool)
}
void xmrig::BenchClient::onBenchDone(uint64_t result, uint64_t diff, uint64_t ts)
{
m_result = result;
m_diff = diff;
m_doneTime = ts;
# ifdef XMRIG_FEATURE_HTTP
if (!m_token.isEmpty()) {
send(DONE_BENCH);
}
# endif
const uint64_t ref = referenceHash();
const char *color = ref ? ((result == ref) ? GREEN_BOLD_S : RED_BOLD_S) : BLACK_BOLD_S;
LOG_NOTICE("%s " WHITE_BOLD("benchmark finished in ") CYAN_BOLD("%.3f seconds") WHITE_BOLD_S " hash sum = " CLEAR "%s%016" PRIX64 CLEAR, tag(), static_cast<double>(ts - m_readyTime) / 1000.0, color, result);
if (m_token.isEmpty()) {
printExit();
}
}
void xmrig::BenchClient::onBenchReady(uint64_t ts, uint32_t threads, const IBackend *backend)
{
m_readyTime = ts;
m_threads = threads;
m_backend = backend;
# ifdef XMRIG_FEATURE_HTTP
if (m_mode == ONLINE_BENCH) {
send(CREATE_BENCH);
}
# endif
}
void xmrig::BenchClient::onHttpData(const HttpData &data)
{
# ifdef XMRIG_FEATURE_HTTP
@ -115,18 +160,97 @@ void xmrig::BenchClient::onHttpData(const HttpData &data)
return setError(data.statusName());
}
if (m_mode == ONLINE_BENCH) {
startBench(doc);
}
else {
startVerify(doc);
switch (m_request) {
case GET_BENCH:
return onGetReply(doc);
case CREATE_BENCH:
return onCreateReply(doc);
case DONE_BENCH:
return onDoneReply(doc);
default:
break;
}
# endif
}
void xmrig::BenchClient::onResolved(const Dns &dns, int status)
{
# ifdef XMRIG_FEATURE_HTTP
assert(!m_httpListener);
if (status < 0) {
return setError(dns.error(), "DNS error");
}
m_ip = dns.get().ip();
m_httpListener = std::make_shared<HttpListener>(this, tag());
if (m_mode == ONLINE_BENCH) {
start();
}
else {
send(GET_BENCH);
}
# endif
}
bool xmrig::BenchClient::setSeed(const char *seed)
{
if (!seed) {
return false;
}
size_t size = strlen(seed);
if (size % 2 != 0) {
return false;
}
size /= 2;
if (size < 4 || size >= m_job.size()) {
return false;
}
if (!Buffer::fromHex(seed, size * 2, m_job.blob())) {
return false;
}
LOG_NOTICE("%s " WHITE_BOLD("seed ") BLACK_BOLD("%s"), tag(), seed);
return true;
}
uint64_t xmrig::BenchClient::referenceHash() const
{
if (m_hash || m_mode == ONLINE_BENCH) {
return m_hash;
}
return BenchState::referenceHash(m_job.algorithm(), BenchState::size(), m_threads);
}
void xmrig::BenchClient::printExit()
{
LOG_INFO("%s " WHITE_BOLD("press ") MAGENTA_BOLD("Ctrl+C") WHITE_BOLD(" to exit"), tag());
}
void xmrig::BenchClient::start()
{
const uint32_t size = BenchState::size();
LOG_NOTICE("%s " MAGENTA_BOLD("start benchmark ") "hashes " CYAN_BOLD("%u%s") " algo " WHITE_BOLD("%s"),
tag(),
size < 1000000 ? size / 1000 : size / 1000000,
size < 1000000 ? "K" : "M",
m_job.algorithm().shortName());
m_listener->onLoginSuccess(this);
m_listener->onJobReceived(this, m_job, rapidjson::Value());
}
@ -134,69 +258,118 @@ void xmrig::BenchClient::start()
#ifdef XMRIG_FEATURE_HTTP
void xmrig::BenchClient::createBench()
void xmrig::BenchClient::onCreateReply(const rapidjson::Value &value)
{
createHttpListener();
m_startTime = Chrono::steadyMSecs();
m_token = Json::getString(value, BenchConfig::kToken);
m_job.setId(Json::getString(value, BenchConfig::kId));
setSeed(Json::getString(value, BenchConfig::kSeed));
m_listener->onJobReceived(this, m_job, rapidjson::Value());
send(START_BENCH);
}
void xmrig::BenchClient::onDoneReply(const rapidjson::Value &)
{
LOG_NOTICE("%s " WHITE_BOLD("benchmark submitted ") CYAN_BOLD("https://xmrig.com/benchmark/%s"), tag(), m_job.id().data());
printExit();
}
void xmrig::BenchClient::onGetReply(const rapidjson::Value &value)
{
const char *hash = Json::getString(value, BenchConfig::kHash);
if (hash) {
m_hash = strtoull(hash, nullptr, 16);
}
m_job.setAlgorithm(Json::getString(value, BenchConfig::kAlgo));
setSeed(Json::getString(value, BenchConfig::kSeed));
BenchState::setSize(Json::getUint(value, BenchConfig::kSize));
start();
}
void xmrig::BenchClient::resolve()
{
m_dns = std::make_shared<Dns>(this);
if (!m_dns->resolve(BenchConfig::kApiHost)) {
setError(m_dns->error(), "getaddrinfo error");
}
}
void xmrig::BenchClient::send(Request request)
{
using namespace rapidjson;
Document doc(kObjectType);
auto &allocator = doc.GetAllocator();
m_request = request;
doc.AddMember(StringRef(BenchConfig::kSize), m_benchmark->size(), allocator);
doc.AddMember(StringRef(BenchConfig::kAlgo), m_benchmark->algorithm().toJSON(), allocator);
doc.AddMember("version", APP_VERSION, allocator);
doc.AddMember("cpu", Cpu::toJSON(doc), allocator);
switch (m_request) {
case GET_BENCH:
{
FetchRequest req(HTTP_GET, m_ip, BenchConfig::kApiPort, fmt::format("/1/benchmark/{}", m_job.id()).c_str(), BenchConfig::kApiTLS, true);
fetch(std::move(req), m_httpListener);
}
break;
FetchRequest req(HTTP_POST, BenchConfig::kApiHost, BenchConfig::kApiPort, "/1/benchmark", doc, BenchConfig::kApiTLS, true);
fetch(std::move(req), m_httpListener);
}
case CREATE_BENCH:
{
doc.AddMember(StringRef(BenchConfig::kSize), m_benchmark->size(), allocator);
doc.AddMember(StringRef(BenchConfig::kAlgo), m_benchmark->algorithm().toJSON(), allocator);
doc.AddMember("version", APP_VERSION, allocator);
doc.AddMember("threads", m_threads, allocator);
doc.AddMember("steady_ready_ts", m_readyTime, allocator);
doc.AddMember("cpu", Cpu::toJSON(doc), allocator);
FetchRequest req(HTTP_POST, m_ip, BenchConfig::kApiPort, "/1/benchmark", doc, BenchConfig::kApiTLS, true);
fetch(std::move(req), m_httpListener);
}
break;
void xmrig::BenchClient::createHttpListener()
{
if (!m_httpListener) {
m_httpListener = std::make_shared<HttpListener>(this, Tags::bench());
case START_BENCH:
doc.AddMember("steady_start_ts", m_startTime, allocator);
update(doc);
break;
case DONE_BENCH:
doc.AddMember("steady_done_ts", m_doneTime, allocator);
doc.AddMember("hash", Value(fmt::format("{:016X}", m_result).c_str(), allocator), allocator);
doc.AddMember("diff", m_diff, allocator);
doc.AddMember("backend", m_backend->toJSON(doc), allocator);
update(doc);
break;
case NO_REQUEST:
break;
}
}
void xmrig::BenchClient::getBench()
void xmrig::BenchClient::setError(const char *message, const char *label)
{
createHttpListener();
LOG_ERR("%s " RED("%s: ") RED_BOLD("\"%s\""), tag(), label ? label : "benchmark failed", message);
printExit();
BenchState::destroy();
}
void xmrig::BenchClient::update(const rapidjson::Value &body)
{
assert(!m_token.isEmpty());
FetchRequest req(HTTP_PATCH, m_ip, BenchConfig::kApiPort, fmt::format("/1/benchmark/{}", m_job.id()).c_str(), body, BenchConfig::kApiTLS, true);
req.headers.insert({ "Authorization", fmt::format("Bearer {}", m_token)});
FetchRequest req(HTTP_GET, BenchConfig::kApiHost, BenchConfig::kApiPort, fmt::format("/1/benchmark/{}", m_job.id()).c_str(), BenchConfig::kApiTLS, true);
fetch(std::move(req), m_httpListener);
}
void xmrig::BenchClient::setError(const char *message)
{
LOG_ERR("%s " RED("benchmark failed ") RED_BOLD("\"%s\""), Tags::bench(), message);
}
void xmrig::BenchClient::startBench(const rapidjson::Value &value)
{
m_job.setId(Json::getString(value, BenchConfig::kId));
m_job.setSeedHash(Json::getString(value, BenchConfig::kSeed));
m_job.setBenchToken(Json::getString(value, BenchConfig::kToken));
start();
}
void xmrig::BenchClient::startVerify(const rapidjson::Value &value)
{
const char *hash = Json::getString(value, BenchConfig::kHash);
if (hash) {
m_job.setBenchHash(strtoull(hash, nullptr, 16));
}
m_job.setAlgorithm(Json::getString(value, BenchConfig::kAlgo));
m_job.setSeedHash(Json::getString(value, BenchConfig::kSeed));
m_job.setBenchSize(Json::getUint(value, BenchConfig::kSize));
start();
}
#endif

View file

@ -20,27 +20,28 @@
#define XMRIG_BENCHCLIENT_H
#include "base/net/stratum/Client.h"
#include "backend/common/interfaces/IBenchListener.h"
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/net/stratum/Client.h"
namespace xmrig {
class BenchClient : public IClient, public IHttpListener
class BenchClient : public IClient, public IHttpListener, public IBenchListener, public IDnsListener
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(BenchClient)
BenchClient(const std::shared_ptr<BenchConfig> &benchmark, IClientListener* listener);
~BenchClient() override = default;
~BenchClient() override;
inline bool disconnect() override { return true; }
inline bool hasExtension(Extension) const noexcept override { return false; }
inline bool isEnabled() const override { return true; }
inline bool isTLS() const override { return false; }
inline const char *mode() const override { return "benchmark"; }
inline const char *tag() const override { return "null"; }
inline const char *tlsFingerprint() const override { return nullptr; }
inline const char *tlsVersion() const override { return nullptr; }
inline const Job &job() const override { return m_job; }
@ -52,7 +53,7 @@ public:
inline int64_t sequence() const override { return 0; }
inline int64_t submit(const JobResult &) override { return 0; }
inline void connect(const Pool &pool) override { setPool(pool); }
inline void deleteLater() override {}
inline void deleteLater() override { delete this; }
inline void setAlgo(const Algorithm &algo) override {}
inline void setEnabled(bool enabled) override {}
inline void setProxy(const ProxyUrl &proxy) override {}
@ -61,11 +62,15 @@ public:
inline void setRetryPause(uint64_t ms) override {}
inline void tick(uint64_t now) override {}
const char *tag() const override;
void connect() override;
void setPool(const Pool &pool) override;
protected:
void onBenchDone(uint64_t result, uint64_t diff, uint64_t ts) override;
void onBenchReady(uint64_t ts, uint32_t threads, const IBackend *backend) override;
void onHttpData(const HttpData &data) override;
void onResolved(const Dns &dns, int status) override;
private:
enum Mode : uint32_t {
@ -75,24 +80,47 @@ private:
ONLINE_VERIFY
};
enum Request : uint32_t {
NO_REQUEST,
GET_BENCH,
CREATE_BENCH,
START_BENCH,
DONE_BENCH
};
bool setSeed(const char *seed);
uint64_t referenceHash() const;
void printExit();
void start();
# ifdef XMRIG_FEATURE_HTTP
void createBench();
void createHttpListener();
void getBench();
void setError(const char *message);
void startBench(const rapidjson::Value &value);
void startVerify(const rapidjson::Value &value);
void onCreateReply(const rapidjson::Value &value);
void onDoneReply(const rapidjson::Value &value);
void onGetReply(const rapidjson::Value &value);
void resolve();
void send(Request request);
void setError(const char *message, const char *label = nullptr);
void update(const rapidjson::Value &body);
# endif
const IBackend *m_backend = nullptr;
IClientListener* m_listener;
Job m_job;
Mode m_mode = STATIC_BENCH;
Pool m_pool;
Request m_request = NO_REQUEST;
std::shared_ptr<BenchConfig> m_benchmark;
std::shared_ptr<Dns> m_dns;
std::shared_ptr<IHttpListener> m_httpListener;
String m_ip;
Mode m_mode = STATIC_BENCH;
String m_token;
uint32_t m_threads = 0;
uint64_t m_diff = 0;
uint64_t m_doneTime = 0;
uint64_t m_hash = 0;
uint64_t m_readyTime = 0;
uint64_t m_result = 0;
uint64_t m_startTime = 0;
};

View file

@ -137,5 +137,9 @@ uint32_t xmrig::BenchConfig::getSize(const char *benchmark)
return strcasecmp(benchmark, fmt::format("{}K", size).c_str()) == 0 ? size * 1000 : 0;
}
# ifndef NDEBUG
return size >= 10000 ? size : 0;
# else
return 0;
# endif
}