diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e932cf0..c868a0da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v6.6.0 +- Online benchmark protocol upgraded to v2, validation not compatible with previous versions. + - Single thread benchmark now is cheat-resistant, not possible speedup it with multiple threads. + - RandomX dataset is now always initialized with static seed, to prevent time cheat by report slow dataset initialization. + - Zero delay online submission, to make time validation much more precise and strict. + - DNS cache for online benchmark to prevent unexpected delays. + # v6.5.3 - [#1946](https://github.com/xmrig/xmrig/pull/1946) Fixed MSR mod names in JSON API (v6.5.2 affected). diff --git a/src/backend/common/Benchmark.cpp b/src/backend/common/Benchmark.cpp deleted file mode 100644 index ba1daf1c..00000000 --- a/src/backend/common/Benchmark.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* XMRig - * 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 - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#include "backend/common/Benchmark.h" -#include "3rdparty/fmt/core.h" -#include "backend/common/interfaces/IBackend.h" -#include "backend/common/interfaces/IWorker.h" -#include "base/io/log/Log.h" -#include "base/io/log/Tags.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 "base/net/stratum/Job.h" -#include "base/tools/Chrono.h" - - -#include - - -namespace xmrig { - - -static const std::map > hashCheck = { - { Algorithm::RX_0, { - { 250000U, 0x7D6054757BB08A63ULL }, - { 500000U, 0x96607546DE1F5ECCULL }, - { 1000000U, 0x898B6E0431C28A6BULL }, - { 2000000U, 0xEE9468F8B40926BCULL }, - { 3000000U, 0xC2BC5D11724813C0ULL }, - { 4000000U, 0x3A2C7B285B87F941ULL }, - { 5000000U, 0x3B5BD2C3A16B450EULL }, - { 6000000U, 0x5CD0602F20C5C7C4ULL }, - { 7000000U, 0x101DE939474B6812ULL }, - { 8000000U, 0x52B765A1B156C6ECULL }, - { 9000000U, 0x323935102AB6B45CULL }, - { 10000000U, 0xB5231262E2792B26ULL } - }}, - { Algorithm::RX_WOW, { - { 250000U, 0xC7F712C9603E2603ULL }, - { 500000U, 0x21A0E5AAE6DA7D8DULL }, - { 1000000U, 0x0F3E5400B39EA96AULL }, - { 2000000U, 0x85944CCFA2752D1FULL }, - { 3000000U, 0x64AFFCAE991811BAULL }, - { 4000000U, 0x3E4D0B836D3B13BAULL }, - { 5000000U, 0xEB7417D621271166ULL }, - { 6000000U, 0x97FFE10C0949FFA5ULL }, - { 7000000U, 0x84CAC0F8879A4BA1ULL }, - { 8000000U, 0xA1B79F031DA2459FULL }, - { 9000000U, 0x9B65226DA873E65DULL }, - { 10000000U, 0x0F9E00C5A511C200ULL } - }} -}; - - -} // namespace xmrig - - -xmrig::Benchmark::Benchmark(const Job &job, size_t workers, const IBackend *backend) : - 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()) -{ -# ifdef XMRIG_FEATURE_HTTP - if (!m_token.isEmpty()) { - m_httpListener = std::make_shared(this, Tags::bench()); - } -# endif -} - - -bool xmrig::Benchmark::finish(uint64_t totalHashCount) -{ - m_reset = true; - m_current = totalHashCount; - - if (m_done < m_workers) { - return false; - } - - const double dt = static_cast(m_doneTime - m_startTime) / 1000.0; - uint64_t checkData = referenceHash(); - const char *color = checkData ? ((m_data == checkData) ? 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, Tags::bench(), dt, color, m_data); - -# ifdef XMRIG_FEATURE_HTTP - if (!m_token.isEmpty()) { - using namespace rapidjson; - - Document doc(kObjectType); - auto &allocator = doc.GetAllocator(); - - doc.AddMember("steady_done_ts", m_doneTime, allocator); - doc.AddMember(StringRef(BenchConfig::kHash), Value(fmt::format("{:016X}", m_data).c_str(), allocator), allocator); - doc.AddMember("backend", m_backend->toJSON(doc), allocator); - - send(doc); - } - else -# endif - { - printExit(); - } - - return true; -} - - -void xmrig::Benchmark::start() -{ - m_startTime = Chrono::steadyMSecs(); - -# ifdef XMRIG_FEATURE_HTTP - if (!m_token.isEmpty()) { - using namespace rapidjson; - - Document doc(kObjectType); - doc.AddMember("steady_start_ts", m_startTime, doc.GetAllocator()); - - send(doc); - } -# endif -} - - -void xmrig::Benchmark::printProgress() const -{ - if (!m_startTime || !m_current) { - return; - } - - const double dt = static_cast(Chrono::steadyMSecs() - m_startTime) / 1000.0; - const double percent = static_cast(m_current) / m_end * 100.0; - - LOG_NOTICE("%s " MAGENTA_BOLD("%5.2f%% ") CYAN_BOLD("%" PRIu64) CYAN("/%" PRIu64) BLACK_BOLD(" (%.3fs)"), Tags::bench(), percent, m_current, m_end, dt); -} - - -void xmrig::Benchmark::tick(IWorker *worker) -{ - if (m_reset) { - m_data = 0; - m_done = 0; - m_reset = false; - } - - const uint64_t doneTime = worker->benchDoneTime(); - if (!doneTime) { - return; - } - - ++m_done; - m_data ^= worker->benchData(); - m_doneTime = std::max(doneTime, m_doneTime); -} - - -void xmrig::Benchmark::onHttpData(const HttpData &data) -{ -# ifdef XMRIG_FEATURE_HTTP - 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_doneTime) { - LOG_NOTICE("%s " WHITE_BOLD("benchmark submitted ") CYAN_BOLD("https://xmrig.com/benchmark/%s"), Tags::bench(), m_id.data()); - printExit(); - } -# endif -} - - -uint64_t xmrig::Benchmark::referenceHash() const -{ - if (m_hash) { - return m_hash; - } - -# ifdef XMRIG_FEATURE_HTTP - if (!m_token.isEmpty()) { - return 0; - } -# endif - - uint64_t hash = 0; - - try { - hash = hashCheck.at(m_algo).at(m_end); - } catch (const std::exception &ex) {} - - return hash; -} - - -void xmrig::Benchmark::printExit() -{ - LOG_INFO("%s " WHITE_BOLD("press ") MAGENTA_BOLD("Ctrl+C") WHITE_BOLD(" to exit"), Tags::bench()); -} - - -#ifdef XMRIG_FEATURE_HTTP -void xmrig::Benchmark::send(const rapidjson::Value &body) -{ - FetchRequest req(HTTP_PATCH, BenchConfig::kApiHost, BenchConfig::kApiPort, fmt::format("/1/benchmark/{}", m_id).c_str(), body, BenchConfig::kApiTLS, true); - req.headers.insert({ "Authorization", fmt::format("Bearer {}", m_token)}); - - fetch(std::move(req), m_httpListener); -} - - -void xmrig::Benchmark::setError(const char *message) -{ - LOG_ERR("%s " RED("benchmark failed ") RED_BOLD("\"%s\""), Tags::bench(), message); -} -#endif diff --git a/src/backend/common/Worker.cpp b/src/backend/common/Worker.cpp index b642a25c..cf244ab3 100644 --- a/src/backend/common/Worker.cpp +++ b/src/backend/common/Worker.cpp @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2020 SChernykh + * Copyright 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 diff --git a/src/backend/common/Worker.h b/src/backend/common/Worker.h index ba00fa3f..23c592b9 100644 --- a/src/backend/common/Worker.h +++ b/src/backend/common/Worker.h @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2020 SChernykh + * Copyright 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,7 +28,6 @@ #include -#include #include "backend/common/interfaces/IWorker.h" @@ -49,11 +48,6 @@ public: void getHashrateData(uint64_t& hashCount, uint64_t& timeStamp) const override; -# ifdef XMRIG_FEATURE_BENCHMARK - inline uint64_t benchData() const override { return m_benchData; } - inline uint64_t benchDoneTime() const override { return m_benchDoneTime; } -# endif - protected: void storeStats(); @@ -64,11 +58,6 @@ protected: uint64_t m_count = 0; uint64_t m_hashCount[2] = {}; uint64_t m_timestamp[2] = {}; - -# ifdef XMRIG_FEATURE_BENCHMARK - uint64_t m_benchData = 0; - uint64_t m_benchDoneTime = 0; -# endif }; diff --git a/src/backend/common/Workers.cpp b/src/backend/common/Workers.cpp index 4413ece6..16265b0a 100644 --- a/src/backend/common/Workers.cpp +++ b/src/backend/common/Workers.cpp @@ -47,7 +47,7 @@ #ifdef XMRIG_FEATURE_BENCHMARK -# include "backend/common/Benchmark.h" +# include "backend/common/benchmark/Benchmark.h" #endif @@ -124,12 +124,6 @@ bool xmrig::Workers::tick(uint64_t) totalAvailable = false; } totalHashCount += n; - -# ifdef XMRIG_FEATURE_BENCHMARK - if (d_ptr->benchmark) { - d_ptr->benchmark->tick(worker); - } -# endif } } diff --git a/src/backend/common/benchmark/BenchState.cpp b/src/backend/common/benchmark/BenchState.cpp new file mode 100644 index 00000000..4fd5df82 --- /dev/null +++ b/src/backend/common/benchmark/BenchState.cpp @@ -0,0 +1,112 @@ +/* XMRig + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "backend/common/benchmark/BenchState.h" +#include "backend/common/benchmark/BenchState_test.h" +#include "backend/common/interfaces/IBenchListener.h" +#include "base/io/Async.h" +#include "base/tools/Chrono.h" + + +#include +#include +#include +#include + + +namespace xmrig { + + +static bool done = false; +static std::mutex mutex; +static std::shared_ptr async; +static uint32_t remaining = 0; +static uint64_t doneTime = 0; +static uint64_t result = 0; +static uint64_t topDiff = 0; + + +IBenchListener *BenchState::m_listener = nullptr; +uint32_t BenchState::m_size = 0; + + +} // namespace xmrig + + + +bool xmrig::BenchState::isDone() +{ + return xmrig::done; +} + + +uint64_t xmrig::BenchState::referenceHash(const Algorithm &algo, uint32_t size, uint32_t threads) +{ + uint64_t hash = 0; + + try { + const auto &h = (threads == 1) ? hashCheck1T : hashCheck; + hash = h.at(algo).at(size); + } catch (const std::exception &ex) {} + + return hash; +} + + +uint64_t xmrig::BenchState::start(size_t threads, const IBackend *backend) +{ + assert(m_listener != nullptr); + + remaining = static_cast(threads); + + async = std::make_shared([] { + m_listener->onBenchDone(result, topDiff, doneTime); + async.reset(); + xmrig::done = true; + }); + + const uint64_t ts = Chrono::steadyMSecs(); + m_listener->onBenchReady(ts, remaining, backend); + + return ts; +} + + +void xmrig::BenchState::destroy() +{ + xmrig::done = true; + async.reset(); +} + + +void xmrig::BenchState::done(uint64_t data, uint64_t diff, uint64_t ts) +{ + assert(async && remaining > 0); + + std::lock_guard lock(mutex); + + result ^= data; + doneTime = std::max(doneTime, ts); + topDiff = std::max(topDiff, diff); + --remaining; + + if (remaining == 0) { + async->send(); + } +} diff --git a/src/backend/common/benchmark/BenchState.h b/src/backend/common/benchmark/BenchState.h new file mode 100644 index 00000000..e451f4a7 --- /dev/null +++ b/src/backend/common/benchmark/BenchState.h @@ -0,0 +1,57 @@ +/* XMRig + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_BENCHSTATE_H +#define XMRIG_BENCHSTATE_H + + +#include +#include + + +namespace xmrig { + + +class Algorithm; +class IBackend; +class IBenchListener; + + +class BenchState +{ +public: + static bool isDone(); + static uint64_t referenceHash(const Algorithm &algo, uint32_t size, uint32_t threads); + static uint64_t start(size_t threads, const IBackend *backend); + static void destroy(); + static void done(uint64_t data, uint64_t diff, uint64_t ts); + + inline static uint32_t size() { return m_size; } + inline static void setListener(IBenchListener *listener) { m_listener = listener; } + inline static void setSize(uint32_t size) { m_size = size; } + +private: + static IBenchListener *m_listener; + static uint32_t m_size; +}; + + +} // namespace xmrig + + +#endif /* XMRIG_BENCHSTATE_H */ diff --git a/src/backend/common/benchmark/BenchState_test.h b/src/backend/common/benchmark/BenchState_test.h new file mode 100644 index 00000000..3aa6d87d --- /dev/null +++ b/src/backend/common/benchmark/BenchState_test.h @@ -0,0 +1,116 @@ +/* XMRig + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_BENCHSTATE_TEST_H +#define XMRIG_BENCHSTATE_TEST_H + + +#include "base/crypto/Algorithm.h" + + +#include + + +namespace xmrig { + + +static const std::map > hashCheck = { + { Algorithm::RX_0, { +# ifndef NDEBUG + { 10000U, 0x4A597463865ACF0EULL }, + { 20000U, 0xC82B490C757DA738ULL }, +# endif + { 250000U, 0x7D6054757BB08A63ULL }, + { 500000U, 0x96607546DE1F5ECCULL }, + { 1000000U, 0x898B6E0431C28A6BULL }, + { 2000000U, 0xEE9468F8B40926BCULL }, + { 3000000U, 0xC2BC5D11724813C0ULL }, + { 4000000U, 0x3A2C7B285B87F941ULL }, + { 5000000U, 0x3B5BD2C3A16B450EULL }, + { 6000000U, 0x5CD0602F20C5C7C4ULL }, + { 7000000U, 0x101DE939474B6812ULL }, + { 8000000U, 0x52B765A1B156C6ECULL }, + { 9000000U, 0x323935102AB6B45CULL }, + { 10000000U, 0xB5231262E2792B26ULL } + }}, + { Algorithm::RX_WOW, { +# ifndef NDEBUG + { 10000U, 0x6B0918757100B338ULL }, + { 20000U, 0x0B55785C1837F41BULL }, +# endif + { 250000U, 0xC7F712C9603E2603ULL }, + { 500000U, 0x21A0E5AAE6DA7D8DULL }, + { 1000000U, 0x0F3E5400B39EA96AULL }, + { 2000000U, 0x85944CCFA2752D1FULL }, + { 3000000U, 0x64AFFCAE991811BAULL }, + { 4000000U, 0x3E4D0B836D3B13BAULL }, + { 5000000U, 0xEB7417D621271166ULL }, + { 6000000U, 0x97FFE10C0949FFA5ULL }, + { 7000000U, 0x84CAC0F8879A4BA1ULL }, + { 8000000U, 0xA1B79F031DA2459FULL }, + { 9000000U, 0x9B65226DA873E65DULL }, + { 10000000U, 0x0F9E00C5A511C200ULL } + }} +}; + + +static const std::map > hashCheck1T = { + { Algorithm::RX_0, { +# ifndef NDEBUG + { 10000U, 0xADFC3A66F79BFE7FULL }, + { 20000U, 0x8ED578A60D55C0DBULL }, +# endif + { 250000U, 0x90A15B799486F3EBULL }, + { 500000U, 0xAA83118FEE570F9AULL }, + { 1000000U, 0x3DF47B0A427C93D9ULL }, + { 2000000U, 0xED4D639B0AEB85C6ULL }, + { 3000000U, 0x2D4F9B4275A713C3ULL }, + { 4000000U, 0xA9EBE4888377F8D3ULL }, + { 5000000U, 0xB92F81851E180454ULL }, + { 6000000U, 0xFB9F98F63C2F1B7DULL }, + { 7000000U, 0x2CC3D7A779D5AB35ULL }, + { 8000000U, 0x2EEF833EA462F4B1ULL }, + { 9000000U, 0xC6D39EF59213A07CULL }, + { 10000000U, 0x95E6BAE68DD779CDULL } + }}, + { Algorithm::RX_WOW, { +# ifndef NDEBUG + { 10000U, 0x9EC1B9B8C8C7F082ULL }, + { 20000U, 0xF1DA44FA2A20D730ULL }, +# endif + { 250000U, 0x7B409F096C863207ULL }, + { 500000U, 0x70B7B80D15654216ULL }, + { 1000000U, 0x31301CC550306A59ULL }, + { 2000000U, 0x92F65E9E31116361ULL }, + { 3000000U, 0x7FE8DF6F43BA5285ULL }, + { 4000000U, 0xD6CDA54FE4D9BBF7ULL }, + { 5000000U, 0x73AF673E1A38E2B4ULL }, + { 6000000U, 0x81FDC5C4B45D84E4ULL }, + { 7000000U, 0xAA08CA57666DC874ULL }, + { 8000000U, 0x9DCEFB833FC875BCULL }, + { 9000000U, 0x862F051352CFCA1FULL }, + { 10000000U, 0xC403F220189E8430ULL } + }} +}; + + +} // namespace xmrig + + + +#endif /* XMRIG_BENCHSTATE_TEST_H */ diff --git a/src/backend/common/benchmark/Benchmark.cpp b/src/backend/common/benchmark/Benchmark.cpp new file mode 100644 index 00000000..d94ab584 --- /dev/null +++ b/src/backend/common/benchmark/Benchmark.cpp @@ -0,0 +1,61 @@ +/* XMRig + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "backend/common/benchmark/Benchmark.h" +#include "backend/common/benchmark/BenchState.h" +#include "base/io/log/Log.h" +#include "base/io/log/Tags.h" +#include "base/tools/Chrono.h" + + +#include + + +xmrig::Benchmark::Benchmark(size_t workers, const IBackend *backend) : + m_backend(backend), + m_workers(workers) +{ +} + + +bool xmrig::Benchmark::finish(uint64_t totalHashCount) +{ + m_current = totalHashCount; + + return BenchState::isDone(); +} + + +void xmrig::Benchmark::start() +{ + m_startTime = BenchState::start(m_workers, m_backend); +} + + +void xmrig::Benchmark::printProgress() const +{ + if (!m_startTime || !m_current) { + return; + } + + const double dt = static_cast(Chrono::steadyMSecs() - m_startTime) / 1000.0; + const double percent = static_cast(m_current) / BenchState::size() * 100.0; + + LOG_NOTICE("%s " MAGENTA_BOLD("%5.2f%% ") CYAN_BOLD("%" PRIu64) CYAN("/%" PRIu64) BLACK_BOLD(" (%.3fs)"), Tags::bench(), percent, m_current, BenchState::size(), dt); +} diff --git a/src/backend/common/Benchmark.h b/src/backend/common/benchmark/Benchmark.h similarity index 58% rename from src/backend/common/Benchmark.h rename to src/backend/common/benchmark/Benchmark.h index b13748b4..df0e4f9c 100644 --- a/src/backend/common/Benchmark.h +++ b/src/backend/common/benchmark/Benchmark.h @@ -20,61 +20,31 @@ #define XMRIG_BENCHMARK_H -#include "base/crypto/Algorithm.h" -#include "base/kernel/interfaces/IHttpListener.h" #include "base/tools/Object.h" -#include "base/tools/String.h" - - -#include namespace xmrig { class IBackend; -class IWorker; -class Job; -class Benchmark : public IHttpListener +class Benchmark { public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(Benchmark) - Benchmark(const Job &job, size_t workers, const IBackend *backend); - ~Benchmark() override = default; + Benchmark(size_t workers, const IBackend *backend); + ~Benchmark() = default; bool finish(uint64_t totalHashCount); void printProgress() const; void start(); - void tick(IWorker *worker); - -protected: - void onHttpData(const HttpData &data) override; private: - uint64_t referenceHash() const; - void printExit(); - -# ifdef XMRIG_FEATURE_HTTP - void send(const rapidjson::Value &body); - void setError(const char *message); -# endif - - bool m_reset = false; - 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; - std::shared_ptr m_httpListener; - uint32_t m_done = 0; uint64_t m_current = 0; - uint64_t m_data = 0; - uint64_t m_doneTime = 0; uint64_t m_startTime = 0; }; diff --git a/src/backend/common/common.cmake b/src/backend/common/common.cmake index eb110933..95c72440 100644 --- a/src/backend/common/common.cmake +++ b/src/backend/common/common.cmake @@ -23,6 +23,15 @@ set(SOURCES_BACKEND_COMMON ) if (WITH_RANDOMX AND WITH_BENCHMARK) - list(APPEND HEADERS_BACKEND_COMMON src/backend/common/Benchmark.h) - list(APPEND SOURCES_BACKEND_COMMON src/backend/common/Benchmark.cpp) + list(APPEND HEADERS_BACKEND_COMMON + src/backend/common/benchmark/Benchmark.h + src/backend/common/benchmark/BenchState_test.h + src/backend/common/benchmark/BenchState.h + src/backend/common/interfaces/IBenchListener.h + ) + + list(APPEND SOURCES_BACKEND_COMMON + src/backend/common/benchmark/Benchmark.cpp + src/backend/common/benchmark/BenchState.cpp + ) endif() diff --git a/src/backend/common/interfaces/IBenchListener.h b/src/backend/common/interfaces/IBenchListener.h new file mode 100644 index 00000000..fe122df8 --- /dev/null +++ b/src/backend/common/interfaces/IBenchListener.h @@ -0,0 +1,48 @@ +/* XMRig + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_IBENCHLISTENER_H +#define XMRIG_IBENCHLISTENER_H + + +#include "base/tools/Object.h" + + +namespace xmrig { + + +class IBackend; + + +class IBenchListener +{ +public: + XMRIG_DISABLE_COPY_MOVE(IBenchListener) + + IBenchListener() = default; + virtual ~IBenchListener() = default; + + virtual void onBenchDone(uint64_t result, uint64_t diff, uint64_t ts) = 0; + virtual void onBenchReady(uint64_t ts, uint32_t threads, const IBackend *backend) = 0; +}; + + +} /* namespace xmrig */ + + +#endif // XMRIG_IBENCHLISTENER_H diff --git a/src/backend/common/interfaces/IWorker.h b/src/backend/common/interfaces/IWorker.h index dcc925dc..f528469a 100644 --- a/src/backend/common/interfaces/IWorker.h +++ b/src/backend/common/interfaces/IWorker.h @@ -5,8 +5,8 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 XMRig , + * Copyright 2018-2020 SChernykh + * Copyright 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 @@ -26,6 +26,9 @@ #define XMRIG_IWORKER_H +#include "base/tools/Object.h" + + #include #include @@ -40,7 +43,10 @@ class Job; class IWorker { public: - virtual ~IWorker() = default; + XMRIG_DISABLE_COPY_MOVE(IWorker) + + IWorker() = default; + virtual ~IWorker() = default; virtual bool selfTest() = 0; virtual const VirtualMemory *memory() const = 0; @@ -50,11 +56,6 @@ public: virtual void getHashrateData(uint64_t&, uint64_t&) const = 0; virtual void start() = 0; virtual void jobEarlyNotification(const Job&) = 0; - -# ifdef XMRIG_FEATURE_BENCHMARK - virtual uint64_t benchData() const = 0; - virtual uint64_t benchDoneTime() const = 0; -# endif }; diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index ecce64fe..a00b2653 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -56,7 +56,8 @@ #ifdef XMRIG_FEATURE_BENCHMARK -# include "backend/common/Benchmark.h" +# include "backend/common/benchmark/Benchmark.h" +# include "backend/common/benchmark/BenchState.h" #endif @@ -347,7 +348,7 @@ void xmrig::CpuBackend::setJob(const Job &job) const auto &cpu = d_ptr->controller->config()->cpu(); # ifdef XMRIG_FEATURE_BENCHMARK - uint32_t benchSize = job.benchSize(); + const uint32_t benchSize = BenchState::size(); # else constexpr uint32_t benchSize = 0; # endif @@ -370,7 +371,7 @@ void xmrig::CpuBackend::setJob(const Job &job) # ifdef XMRIG_FEATURE_BENCHMARK if (benchSize) { - d_ptr->benchmark = std::make_shared(job, threads.size(), this); + d_ptr->benchmark = std::make_shared(threads.size(), this); } # endif diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index 619813d2..5614ef61 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.cpp @@ -116,16 +116,17 @@ size_t xmrig::CpuConfig::memPoolSize() const std::vector xmrig::CpuConfig::get(const Miner *miner, const Algorithm &algorithm, uint32_t benchSize) const { std::vector out; - const CpuThreads &threads = m_threads.get(algorithm); + const auto &threads = m_threads.get(algorithm); if (threads.isEmpty()) { return out; } - out.reserve(threads.count()); + const size_t count = threads.count(); + out.reserve(count); - for (const CpuThread &thread : threads.data()) { - out.emplace_back(miner, algorithm, *this, thread, benchSize); + for (const auto &thread : threads.data()) { + out.emplace_back(miner, algorithm, *this, thread, benchSize, count); } return out; diff --git a/src/backend/cpu/CpuLaunchData.cpp b/src/backend/cpu/CpuLaunchData.cpp index 36928841..94628c84 100644 --- a/src/backend/cpu/CpuLaunchData.cpp +++ b/src/backend/cpu/CpuLaunchData.cpp @@ -32,7 +32,7 @@ #include -xmrig::CpuLaunchData::CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread, uint32_t benchSize) : +xmrig::CpuLaunchData::CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread, uint32_t benchSize, size_t threads) : algorithm(algorithm), assembly(config.assembly()), astrobwtAVX2(config.astrobwtAVX2()), @@ -43,6 +43,7 @@ xmrig::CpuLaunchData::CpuLaunchData(const Miner *miner, const Algorithm &algorit priority(config.priority()), affinity(thread.affinity()), miner(miner), + threads(threads), benchSize(benchSize), intensity(std::min(thread.intensity(), algorithm.maxIntensity())) { diff --git a/src/backend/cpu/CpuLaunchData.h b/src/backend/cpu/CpuLaunchData.h index 1bc9a7fd..8ba3180f 100644 --- a/src/backend/cpu/CpuLaunchData.h +++ b/src/backend/cpu/CpuLaunchData.h @@ -44,7 +44,7 @@ class Miner; class CpuLaunchData { public: - CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread, uint32_t benchSize); + CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread, uint32_t benchSize, size_t threads); bool isEqual(const CpuLaunchData &other) const; CnHash::AlgoVariant av() const; @@ -66,6 +66,7 @@ public: const int priority; const int64_t affinity; const Miner *miner; + const size_t threads; const uint32_t benchSize; const uint32_t intensity; }; diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index fd1a5932..d61e8038 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -30,6 +30,7 @@ #include "backend/cpu/CpuWorker.h" #include "base/tools/Chrono.h" +#include "core/config/Config.h" #include "core/Miner.h" #include "crypto/cn/CnCtx.h" #include "crypto/cn/CryptoNight_test.h" @@ -52,6 +53,11 @@ #endif +#ifdef XMRIG_FEATURE_BENCHMARK +# include "backend/common/benchmark/BenchState.h" +#endif + + namespace xmrig { static constexpr uint32_t kReserveCount = 32768; @@ -85,6 +91,7 @@ xmrig::CpuWorker::CpuWorker(size_t id, const CpuLaunchData &data) : m_av(data.av()), m_astrobwtMaxSize(data.astrobwtMaxSize * 1000), m_miner(data.miner), + m_threads(data.threads), m_benchSize(data.benchSize), m_ctx() { @@ -231,6 +238,19 @@ void xmrig::CpuWorker::start() current_job_nonces[i] = *m_job.nonce(i); } +# ifdef XMRIG_FEATURE_BENCHMARK + if (m_benchSize) { + if (current_job_nonces[0] >= m_benchSize) { + return BenchState::done(m_benchData, m_benchDiff, Chrono::steadyMSecs());; + } + + // Make each hash dependent on the previous one in single thread benchmark to prevent cheating with multiple threads + if (m_threads == 1) { + *(uint64_t*)(m_job.blob()) ^= m_benchData; + } + } +# endif + bool valid = true; # ifdef XMRIG_ALGO_RANDOMX @@ -273,10 +293,7 @@ void xmrig::CpuWorker::start() if (m_benchSize) { if (current_job_nonces[i] < m_benchSize) { m_benchData ^= value; - } - else { - m_benchDoneTime = Chrono::steadyMSecs(); - return; + m_benchDiff = std::max(m_benchDiff, Job::toDiff(value)); } } else @@ -380,6 +397,10 @@ void xmrig::CpuWorker::consumeJob() m_job.add(m_miner->job(), m_benchSize ? 1 : kReserveCount, Nonce::CPU); +# ifdef XMRIG_FEATURE_BENCHMARK + m_benchData = 0; +# endif + # ifdef XMRIG_ALGO_RANDOMX if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) { allocateRandomX_VM(); diff --git a/src/backend/cpu/CpuWorker.h b/src/backend/cpu/CpuWorker.h index 087156c2..6669f5db 100644 --- a/src/backend/cpu/CpuWorker.h +++ b/src/backend/cpu/CpuWorker.h @@ -82,6 +82,7 @@ private: const CnHash::AlgoVariant m_av; const int m_astrobwtMaxSize; const Miner *m_miner; + const size_t m_threads; const uint32_t m_benchSize; cryptonight_ctx *m_ctx[N]; VirtualMemory *m_memory = nullptr; @@ -90,6 +91,11 @@ private: # ifdef XMRIG_ALGO_RANDOMX randomx_vm *m_vm = nullptr; # endif + +# ifdef XMRIG_FEATURE_BENCHMARK + uint64_t m_benchData = 0; + uint64_t m_benchDiff = 0; +# endif }; diff --git a/src/base/io/Async.cpp b/src/base/io/Async.cpp index 5ee637f2..255be8c0 100644 --- a/src/base/io/Async.cpp +++ b/src/base/io/Async.cpp @@ -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(handle->data)->d_ptr->callback(); }); +} + + xmrig::Async::Async(IAsyncListener *listener) : d_ptr(new AsyncPrivate()) { d_ptr->listener = listener; diff --git a/src/base/io/Async.h b/src/base/io/Async.h index 4b8d1a7b..19491082 100644 --- a/src/base/io/Async.h +++ b/src/base/io/Async.h @@ -25,6 +25,9 @@ #include "base/tools/Object.h" +#include + + namespace xmrig { @@ -37,6 +40,9 @@ class Async public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(Async) + using Callback = std::function; + + Async(Callback callback); Async(IAsyncListener *listener); ~Async(); diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index f791a956..fc17b510 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -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 } diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index ac564d37..761b5af2 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -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 }; diff --git a/src/base/net/stratum/benchmark/BenchClient.cpp b/src/base/net/stratum/benchmark/BenchClient.cpp index bc71492b..71d6a183 100644 --- a/src/base/net/stratum/benchmark/BenchClient.cpp +++ b/src/base/net/stratum/benchmark/BenchClient.cpp @@ -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 &benchmark, IClientListener* listener) : m_listener(listener), - m_benchmark(benchmark) + m_benchmark(benchmark), + m_hash(benchmark->hash()) { std::vector blob(112 * 2 + 1, '0'); blob.back() = '\0'; @@ -42,8 +46,13 @@ xmrig::BenchClient::BenchClient(const std::shared_ptr &benchmark, I m_job.setAlgorithm(m_benchmark->algorithm()); m_job.setDiff(std::numeric_limits::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 &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(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(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(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(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 diff --git a/src/base/net/stratum/benchmark/BenchClient.h b/src/base/net/stratum/benchmark/BenchClient.h index 64bb481b..018bceaa 100644 --- a/src/base/net/stratum/benchmark/BenchClient.h +++ b/src/base/net/stratum/benchmark/BenchClient.h @@ -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 &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 m_benchmark; + std::shared_ptr m_dns; std::shared_ptr 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; }; diff --git a/src/base/net/stratum/benchmark/BenchConfig.cpp b/src/base/net/stratum/benchmark/BenchConfig.cpp index 8a524108..2e02755a 100644 --- a/src/base/net/stratum/benchmark/BenchConfig.cpp +++ b/src/base/net/stratum/benchmark/BenchConfig.cpp @@ -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 } diff --git a/src/crypto/randomx/jit_compiler_x86.cpp b/src/crypto/randomx/jit_compiler_x86.cpp index 88c1ce4e..182de1fa 100644 --- a/src/crypto/randomx/jit_compiler_x86.cpp +++ b/src/crypto/randomx/jit_compiler_x86.cpp @@ -297,7 +297,7 @@ namespace randomx { } void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) { - codePos = ((uint8_t*)randomx_program_prologue_first_load) - ((uint8_t*)randomx_program_prologue); + codePos = ADDR(randomx_program_prologue_first_load) - ADDR(randomx_program_prologue); code[codePos + 2] = 0xc0 + pcfg.readReg0; code[codePos + 5] = 0xc0 + pcfg.readReg1; *(uint32_t*)(code + codePos + 10) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 0995d62b..fb8b21b3 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -51,6 +51,11 @@ #endif +#ifdef XMRIG_FEATURE_BENCHMARK +# include "backend/common/benchmark/BenchState.h" +#endif + + #include #include #include @@ -260,24 +265,13 @@ void xmrig::Network::onRequest(IApiRequest &request) void xmrig::Network::setJob(IClient *client, const Job &job, bool donate) { - uint64_t diff = job.diff();; - const char *scale = NetworkState::scaleDiff(diff); - # ifdef XMRIG_FEATURE_BENCHMARK - const uint32_t size = job.benchSize(); - if (size) { - LOG_NOTICE("%s " MAGENTA_BOLD("start benchmark ") "hashes " CYAN_BOLD("%u%s") " algo " WHITE_BOLD("%s") " print_time " CYAN_BOLD("%us"), - Tags::bench(), - size < 1000000 ? size / 1000 : size / 1000000, - size < 1000000 ? "K" : "M", - job.algorithm().shortName(), - m_controller->config()->printTime()); - - LOG_NOTICE("%s " WHITE_BOLD("seed ") BLACK_BOLD("%s"), Tags::bench(), job.seed().toHex().data()); - } - else + if (!BenchState::size()) # endif { + uint64_t diff = job.diff();; + const char *scale = NetworkState::scaleDiff(diff); + LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), Tags::network(), client->pool().host().data(), client->pool().port(), diff, scale, job.algorithm().shortName(), job.height()); } diff --git a/src/version.h b/src/version.h index f8438d75..a9465a86 100644 --- a/src/version.h +++ b/src/version.h @@ -28,15 +28,15 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "6.5.3" +#define APP_VERSION "6.6.0-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2020 xmrig.com" #define APP_KIND "miner" #define APP_VER_MAJOR 6 -#define APP_VER_MINOR 5 -#define APP_VER_PATCH 3 +#define APP_VER_MINOR 6 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920)