From 5c6ec587ac8020e8a84538105dab7226c415666c Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 14:51:05 +0700 Subject: [PATCH] Move selfTest to threads, remove legacy CryptoNight.cpp. --- CMakeLists.txt | 1 - src/App.cpp | 5 - src/crypto/CryptoNight.cpp | 189 ----------------------------------- src/crypto/CryptoNight.h | 15 --- src/interfaces/IWorker.h | 7 +- src/workers/DoubleWorker.cpp | 35 ++++++- src/workers/DoubleWorker.h | 3 +- src/workers/SingleWorker.cpp | 35 ++++++- src/workers/SingleWorker.h | 3 +- src/workers/Worker.h | 1 + src/workers/Workers.cpp | 9 +- 11 files changed, 85 insertions(+), 218 deletions(-) delete mode 100644 src/crypto/CryptoNight.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e2ac190..106ab30f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,7 +126,6 @@ set(SOURCES_CRYPTO src/crypto/c_blake256.c src/crypto/c_jh.c src/crypto/c_skein.c - src/crypto/CryptoNight.cpp ) if (WIN32) diff --git a/src/App.cpp b/src/App.cpp index 8c7a16ea..dc22836d 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -101,11 +101,6 @@ int App::exec() background(); - if (!CryptoNight::init(m_controller->config()->algorithm(), m_controller->config()->algoVariant(), m_controller->config()->isDoubleHash())) { - LOG_ERR("\"%s\" hash self-test failed.", m_controller->config()->algoName()); - return 1; - } - Mem::allocate(m_controller->config()->algorithm(), m_controller->config()->threadsCount(), m_controller->config()->isDoubleHash(), diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp deleted file mode 100644 index d817c152..00000000 --- a/src/crypto/CryptoNight.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* 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 2018 Lee Clagett - * Copyright 2016-2018 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 "crypto/CryptoNight.h" - - -#if defined(XMRIG_ARM) -# include "crypto/CryptoNight_arm.h" -#else -# include "crypto/CryptoNight_x86.h" -#endif - -#include "crypto/CryptoNight_test.h" -#include "net/Job.h" -#include "net/JobResult.h" -#include "xmrig.h" - - -void (*cryptonight_hash_ctx)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) = nullptr; - - -#define CRYPTONIGHT_HASH(NAME, ALGO, SOFT_AES) \ - switch (variant) { \ - case xmrig::VARIANT_V1: \ - return cryptonight_##NAME##_hash(input, size, output, ctx); \ - \ - case xmrig::VARIANT_NONE: \ - return cryptonight_##NAME##_hash(input, size, output, ctx); \ - \ - default: \ - break; \ - } - - -static void cryptonight_av1_aesni(const uint8_t *input, size_t size, uint8_t *output, struct cryptonight_ctx *ctx, int variant) { -# if !defined(XMRIG_ARMv7) - CRYPTONIGHT_HASH(single, xmrig::CRYPTONIGHT, false) -# endif -} - - -static void cryptonight_av2_aesni_double(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) { -# if !defined(XMRIG_ARMv7) - CRYPTONIGHT_HASH(double, xmrig::CRYPTONIGHT, false) -# endif -} - - -static void cryptonight_av3_softaes(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) { - CRYPTONIGHT_HASH(single, xmrig::CRYPTONIGHT, true) -} - - -static void cryptonight_av4_softaes_double(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) { - CRYPTONIGHT_HASH(double, xmrig::CRYPTONIGHT, true) -} - - -#ifndef XMRIG_NO_AEON -static void cryptonight_lite_av1_aesni(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) { -# if !defined(XMRIG_ARMv7) - CRYPTONIGHT_HASH(single, xmrig::CRYPTONIGHT_LITE, false) -# endif -} - - -static void cryptonight_lite_av2_aesni_double(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) { -# if !defined(XMRIG_ARMv7) - CRYPTONIGHT_HASH(double, xmrig::CRYPTONIGHT_LITE, false) -# endif -} - - -static void cryptonight_lite_av3_softaes(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) { - CRYPTONIGHT_HASH(single, xmrig::CRYPTONIGHT_LITE, true) -} - - -static void cryptonight_lite_av4_softaes_double(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) { - CRYPTONIGHT_HASH(double, xmrig::CRYPTONIGHT_LITE, true) -} - -void (*cryptonight_variations[8])(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) = { - cryptonight_av1_aesni, - cryptonight_av2_aesni_double, - cryptonight_av3_softaes, - cryptonight_av4_softaes_double, - cryptonight_lite_av1_aesni, - cryptonight_lite_av2_aesni_double, - cryptonight_lite_av3_softaes, - cryptonight_lite_av4_softaes_double - }; -#else -void (*cryptonight_variations[4])(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) = { - cryptonight_av1_aesni, - cryptonight_av2_aesni_double, - cryptonight_av3_softaes, - cryptonight_av4_softaes_double - }; -#endif - - -bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx) -{ - cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx, job.variant()); - - return *reinterpret_cast(result.result + 24) < job.target(); -} - - -bool CryptoNight::init(int algo, int variant, bool doubleHash) -{ - if (variant < 1 || variant > 4) { - return false; - } - -# ifndef XMRIG_NO_AEON - const int index = algo == xmrig::CRYPTONIGHT_LITE ? (variant + 3) : (variant - 1); -# else - const int index = variant - 1; -# endif - - cryptonight_hash_ctx = cryptonight_variations[index]; - - return selfTest(algo, doubleHash); -} - - -void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) -{ - cryptonight_hash_ctx(input, size, output, ctx, variant); -} - - -bool CryptoNight::selfTest(int algo, bool doubleHash) { - if (cryptonight_hash_ctx == nullptr) { - return false; - } - - uint8_t output[64]; - - struct cryptonight_ctx *ctx = static_cast(_mm_malloc(sizeof(cryptonight_ctx), 16)); - ctx->memory = static_cast(_mm_malloc(MONERO_MEMORY * 2, 16)); - - cryptonight_hash_ctx(test_input, 76, output, ctx, 0); - -# ifndef XMRIG_NO_AEON - bool rc = memcmp(output, algo == xmrig::CRYPTONIGHT_LITE ? test_output_v0_lite : test_output_v0, (doubleHash ? 64 : 32)) == 0; -# else - bool rc = memcmp(output, test_output_v0, (doubleHash ? 64 : 32)) == 0; -# endif - - if (rc) { - cryptonight_hash_ctx(test_input, 76, output, ctx, 1); - -# ifndef XMRIG_NO_AEON - rc = memcmp(output, algo == xmrig::CRYPTONIGHT_LITE ? test_output_v1_lite : test_output_v1, (doubleHash ? 64 : 32)) == 0; -# else - rc = memcmp(output, test_output_v1, (doubleHash ? 64 : 32)) == 0; -# endif - } - - _mm_free(ctx->memory); - _mm_free(ctx); - - return rc; -} diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h index eb17719e..d0d61ae3 100644 --- a/src/crypto/CryptoNight.h +++ b/src/crypto/CryptoNight.h @@ -46,19 +46,4 @@ struct cryptonight_ctx { }; -class Job; -class JobResult; - - -class CryptoNight -{ -public: - static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx); - static bool init(int algo, int variant, bool doubleHash); - static void hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant); - -private: - static bool selfTest(int algo, bool doubleHash); -}; - #endif /* __CRYPTONIGHT_H__ */ diff --git a/src/interfaces/IWorker.h b/src/interfaces/IWorker.h index b9b6eb0a..a90abe11 100644 --- a/src/interfaces/IWorker.h +++ b/src/interfaces/IWorker.h @@ -4,8 +4,8 @@ * Copyright 2014 Lucas Jones * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 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 @@ -33,9 +33,10 @@ class IWorker public: virtual ~IWorker() {} + virtual bool start() = 0; + virtual size_t id() const = 0; virtual uint64_t hashCount() const = 0; virtual uint64_t timestamp() const = 0; - virtual void start() = 0; }; diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index 8971f0c0..425dd0c2 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -26,6 +26,7 @@ #include +#include "crypto/CryptoNight_test.h" #include "workers/CpuThread.h" #include "workers/DoubleWorker.h" #include "workers/Workers.h" @@ -61,8 +62,12 @@ DoubleWorker::~DoubleWorker() } -void DoubleWorker::start() +bool DoubleWorker::start() { + if (!selfTest()) { + return false; + } + while (Workers::sequence() > 0) { if (Workers::isPaused()) { do { @@ -101,6 +106,8 @@ void DoubleWorker::start() consumeJob(); } + + return true; } @@ -115,6 +122,32 @@ bool DoubleWorker::resume(const Job &job) } +bool DoubleWorker::selfTest() +{ + if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) { + return false; + } + + m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_hash, m_ctx); + + if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_hash, test_output_v0, 64) == 0) { + m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx); + + return memcmp(m_hash, test_output_v1, 64) == 0; + } + +# ifndef XMRIG_NO_AEON + if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_hash, test_output_v0_lite, 64) == 0) { + m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx); + + return memcmp(m_hash, test_output_v1_lite, 64) == 0; + } +# endif + + return false; +} + + void DoubleWorker::consumeJob() { Job job = Workers::job(); diff --git a/src/workers/DoubleWorker.h b/src/workers/DoubleWorker.h index 57be59d0..e8847282 100644 --- a/src/workers/DoubleWorker.h +++ b/src/workers/DoubleWorker.h @@ -40,10 +40,11 @@ public: DoubleWorker(Handle *handle); ~DoubleWorker(); - void start() override; + bool start() override; private: bool resume(const Job &job); + bool selfTest(); void consumeJob(); void save(const Job &job); diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp index 6df44d9d..2ff356c8 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/SingleWorker.cpp @@ -26,6 +26,7 @@ #include +#include "crypto/CryptoNight_test.h" #include "workers/CpuThread.h" #include "workers/SingleWorker.h" #include "workers/Workers.h" @@ -37,8 +38,12 @@ SingleWorker::SingleWorker(Handle *handle) } -void SingleWorker::start() +bool SingleWorker::start() { + if (!selfTest()) { + return false; + } + while (Workers::sequence() > 0) { if (Workers::isPaused()) { do { @@ -71,6 +76,8 @@ void SingleWorker::start() consumeJob(); } + + return true; } @@ -87,6 +94,32 @@ bool SingleWorker::resume(const Job &job) } +bool SingleWorker::selfTest() +{ + if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) { + return false; + } + + m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_result.result, m_ctx); + + if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_result.result, test_output_v0, 32) == 0) { + m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctx); + + return memcmp(m_result.result, test_output_v1, 32) == 0; + } + +# ifndef XMRIG_NO_AEON + if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_result.result, test_output_v0_lite, 32) == 0) { + m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctx); + + return memcmp(m_result.result, test_output_v1_lite, 32) == 0; + } +# endif + + return false; +} + + void SingleWorker::consumeJob() { Job job = Workers::job(); diff --git a/src/workers/SingleWorker.h b/src/workers/SingleWorker.h index f7d9cff8..061f5084 100644 --- a/src/workers/SingleWorker.h +++ b/src/workers/SingleWorker.h @@ -39,10 +39,11 @@ class SingleWorker : public Worker public: SingleWorker(Handle *handle); - void start() override; + bool start() override; private: bool resume(const Job &job); + bool selfTest(); void consumeJob(); void save(const Job &job); diff --git a/src/workers/Worker.h b/src/workers/Worker.h index 9fbce1a2..88f6ee42 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -47,6 +47,7 @@ public: Worker(Handle *handle); ~Worker(); + inline size_t id() const override { return m_id; } inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); } inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); } diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 8ac256da..00941c7b 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -22,6 +22,7 @@ */ #include +#include #include "api/Api.h" @@ -171,7 +172,13 @@ void Workers::onReady(void *arg) handle->setWorker(new SingleWorker(handle)); } - handle->worker()->start(); + const bool rc = handle->worker()->start(); + + if (!rc) { + uv_mutex_lock(&m_mutex); + LOG_ERR("thread %zu error: \"hash self-test failed\".", handle->worker()->id()); + uv_mutex_unlock(&m_mutex); + } }