diff --git a/src/backend/common/Benchmark.cpp b/src/backend/common/Benchmark.cpp index 979c82b37..c2f675902 100644 --- a/src/backend/common/Benchmark.cpp +++ b/src/backend/common/Benchmark.cpp @@ -44,6 +44,7 @@ xmrig::Benchmark::Benchmark(const Job &job, size_t workers, const IBackend *back m_algo(job.algorithm()), m_backend(backend), m_workers(workers), + m_id(job.id()), m_token(job.benchToken()), m_end(job.benchSize()), m_hash(job.benchHash()) @@ -116,6 +117,10 @@ uint64_t xmrig::Benchmark::referenceHash() const return m_hash; } + if (!m_token.isEmpty()) { + return 0; + } + const uint32_t N = (m_end / 1000000) - 1; if (((m_algo == Algorithm::RX_0) || (m_algo == Algorithm::RX_WOW)) && ((m_end % 1000000) == 0) && (N < 10)) { return hashCheck[(m_algo == Algorithm::RX_0) ? 0 : 1][N]; diff --git a/src/backend/common/Benchmark.h b/src/backend/common/Benchmark.h index 2029f8ea0..e42526304 100644 --- a/src/backend/common/Benchmark.h +++ b/src/backend/common/Benchmark.h @@ -53,6 +53,7 @@ private: const Algorithm m_algo; const IBackend *m_backend; const size_t m_workers; + const String m_id; const String m_token; const uint64_t m_end; const uint64_t m_hash; diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index 82201a352..8e13a9a43 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -346,7 +346,13 @@ void xmrig::CpuBackend::setJob(const Job &job) const auto &cpu = d_ptr->controller->config()->cpu(); - std::vector threads = cpu.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->controller->config()->pools().benchSize()); +# ifdef XMRIG_FEATURE_BENCHMARK + uint32_t benchSize = job.benchSize(); +# else + constexpr uint32_t benchSize = 0; +# endif + + auto threads = cpu.get(d_ptr->controller->miner(), job.algorithm(), benchSize); if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) { return; } @@ -363,7 +369,7 @@ void xmrig::CpuBackend::setJob(const Job &job) stop(); # ifdef XMRIG_FEATURE_BENCHMARK - if (job.benchSize()) { + if (benchSize) { d_ptr->benchmark = std::make_shared(job, threads.size(), this); } # endif diff --git a/src/base/net/http/HttpData.cpp b/src/base/net/http/HttpData.cpp index 6e75e2ac6..10eace46b 100644 --- a/src/base/net/http/HttpData.cpp +++ b/src/base/net/http/HttpData.cpp @@ -1,6 +1,7 @@ /* XMRig - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2014-2019 heapwolf + * Copyright (c) 2018-2020 SChernykh + * Copyright (c) 2016-2020 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +19,14 @@ #include "base/net/http/HttpData.h" +#include "3rdparty/http-parser/http_parser.h" +#include "3rdparty/rapidjson/document.h" +#include "3rdparty/rapidjson/error/en.h" +#include "base/io/json/Json.h" + + +#include +#include namespace xmrig { @@ -42,3 +51,46 @@ bool xmrig::HttpData::isJSON() const return type == kApplicationJson || type == kTextPlain; } + + +const char *xmrig::HttpData::methodName() const +{ + return http_method_str(static_cast(method)); +} + + +const char *xmrig::HttpData::statusName() const +{ + if (status < 0) { + return uv_strerror(status); + } + + return http_status_str(static_cast(status)); +} + + +rapidjson::Document xmrig::HttpData::json() const +{ + if (status < 0) { + throw std::runtime_error(statusName()); + } + + if (!isJSON()) { + throw std::runtime_error("the response is not a valid JSON response"); + } + + using namespace rapidjson; + Document doc; + if (doc.Parse(body.c_str()).HasParseError()) { + throw std::runtime_error(GetParseError_En(doc.GetParseError())); + } + + if (doc.IsObject() && !doc.ObjectEmpty()) { + const char *error = Json::getString(doc, "error"); + if (error) { + throw std::runtime_error(error); + } + } + + return doc; +} diff --git a/src/base/net/http/HttpData.h b/src/base/net/http/HttpData.h index 2e8b78f8f..392c8bc84 100644 --- a/src/base/net/http/HttpData.h +++ b/src/base/net/http/HttpData.h @@ -1,13 +1,7 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2014-2019 heapwolf - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2014-2019 heapwolf + * Copyright (c) 2018-2020 SChernykh + * Copyright (c) 2016-2020 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +22,7 @@ #define XMRIG_HTTPDATA_H +#include "3rdparty/rapidjson/document.h" #include "base/tools/Object.h" @@ -63,6 +58,9 @@ public: virtual void write(std::string &&data, bool close) = 0; bool isJSON() const; + const char *methodName() const; + const char *statusName() const; + rapidjson::Document json() const; int method = 0; int status = 0; @@ -70,6 +68,7 @@ public: std::map headers; std::string body; std::string url; + uint64_t rpcId = 0; private: const uint64_t m_id; diff --git a/src/base/net/stratum/benchmark/BenchClient.cpp b/src/base/net/stratum/benchmark/BenchClient.cpp index 96c5982fe..4d5021c80 100644 --- a/src/base/net/stratum/benchmark/BenchClient.cpp +++ b/src/base/net/stratum/benchmark/BenchClient.cpp @@ -18,16 +18,22 @@ #include "base/net/stratum/benchmark/BenchClient.h" #include "3rdparty/rapidjson/document.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/http/Fetch.h" +#include "base/net/http/HttpData.h" #include "base/net/http/HttpListener.h" #include "base/net/stratum/benchmark/BenchConfig.h" +#include "version.h" xmrig::BenchClient::BenchClient(const std::shared_ptr &benchmark, IClientListener* listener) : m_listener(listener), m_benchmark(benchmark) { - m_httpListener = std::make_shared(this); + m_httpListener = std::make_shared(this, Tags::bench()); std::vector blob(112 * 2 + 1, '0'); blob.back() = '\0'; @@ -66,10 +72,17 @@ xmrig::BenchClient::BenchClient(const std::shared_ptr &benchmark, I void xmrig::BenchClient::connect() -{ - if (m_mode == STATIC_BENCH || m_mode == STATIC_VERIFY) { - m_listener->onLoginSuccess(this); - m_listener->onJobReceived(this, m_job, rapidjson::Value()); +{ + switch (m_mode) { + case STATIC_BENCH: + case STATIC_VERIFY: + return start(); + + case ONLINE_BENCH: + return createBench(); + + case ONLINE_VERIFY: + return getBench(); } } @@ -82,4 +95,85 @@ void xmrig::BenchClient::setPool(const Pool &pool) void xmrig::BenchClient::onHttpData(const HttpData &data) { + rapidjson::Document doc; + + try { + doc = data.json(); + } catch (const std::exception &ex) { + return setError(ex.what()); + } + + if (data.status != 200) { + return setError(data.statusName()); + } + + if (m_mode == ONLINE_BENCH) { + startBench(doc); + } + else { + startVerify(doc); + } +} + + +void xmrig::BenchClient::createBench() +{ + using namespace rapidjson; + + Document doc(kObjectType); + auto &allocator = doc.GetAllocator(); + + 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); + + FetchRequest req(HTTP_POST, BenchConfig::kApiHost, BenchConfig::kApiPort, "/1/benchmark", doc, BenchConfig::kApiTLS, true); + fetch(std::move(req), m_httpListener); +} + + +void xmrig::BenchClient::getBench() +{ + const auto path = std::string("/1/benchmark/") + m_job.id().data(); + + FetchRequest req(HTTP_GET, BenchConfig::kApiHost, BenchConfig::kApiPort, path.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::start() +{ + m_listener->onLoginSuccess(this); + m_listener->onJobReceived(this, m_job, rapidjson::Value()); +} + + +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(); } diff --git a/src/base/net/stratum/benchmark/BenchClient.h b/src/base/net/stratum/benchmark/BenchClient.h index 3013a1e93..f9070b346 100644 --- a/src/base/net/stratum/benchmark/BenchClient.h +++ b/src/base/net/stratum/benchmark/BenchClient.h @@ -75,6 +75,13 @@ private: ONLINE_VERIFY }; + void createBench(); + void getBench(); + void setError(const char *message); + void start(); + void startBench(const rapidjson::Value &value); + void startVerify(const rapidjson::Value &value); + IClientListener* m_listener; Job m_job; Pool m_pool; diff --git a/src/base/net/stratum/benchmark/BenchConfig.cpp b/src/base/net/stratum/benchmark/BenchConfig.cpp index 5be4cdddd..6d179cdcf 100644 --- a/src/base/net/stratum/benchmark/BenchConfig.cpp +++ b/src/base/net/stratum/benchmark/BenchConfig.cpp @@ -30,11 +30,18 @@ namespace xmrig { const char *BenchConfig::kAlgo = "algo"; const char *BenchConfig::kBenchmark = "benchmark"; const char *BenchConfig::kHash = "hash"; +const char *BenchConfig::kId = "id"; const char *BenchConfig::kSeed = "seed"; const char *BenchConfig::kSize = "size"; const char *BenchConfig::kSubmit = "submit"; +const char *BenchConfig::kToken = "token"; const char *BenchConfig::kVerify = "verify"; +#ifndef XMRIG_DEBUG_BENCHMARK_API +const char *BenchConfig::kApiHost = "api.xmrig.com"; +#else +const char *BenchConfig::kApiHost = "127.0.0.1"; +#endif } // namespace xmrig diff --git a/src/base/net/stratum/benchmark/BenchConfig.h b/src/base/net/stratum/benchmark/BenchConfig.h index ec9719ce2..3d9909e96 100644 --- a/src/base/net/stratum/benchmark/BenchConfig.h +++ b/src/base/net/stratum/benchmark/BenchConfig.h @@ -31,13 +31,24 @@ class BenchConfig { public: static const char *kAlgo; + static const char *kApiHost; static const char *kBenchmark; static const char *kHash; + static const char *kId; static const char *kSeed; static const char *kSize; static const char *kSubmit; + static const char *kToken; static const char *kVerify; +# ifndef XMRIG_DEBUG_BENCHMARK_API + static constexpr bool kApiTLS = true; + static constexpr const uint16_t kApiPort = 443; +# else + static constexpr bool kApiTLS = false; + static constexpr const uint16_t kApiPort = 18805; +# endif + BenchConfig(uint32_t size, const String &id, const rapidjson::Value &object); static BenchConfig *create(const rapidjson::Value &object);