From a042cbf8856de5df95bac73d7413e63483a56db7 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 1 Apr 2018 22:49:21 +0700 Subject: [PATCH 01/13] Added classes IThread, CpuThread and API endpoint "GET /1/threads". --- CMakeLists.txt | 3 ++ src/App.cpp | 2 +- src/Mem.cpp | 2 +- src/Mem_win.cpp | 2 +- src/Summary.cpp | 2 +- src/api/ApiRouter.cpp | 26 ++++++++-- src/api/ApiRouter.h | 1 + src/core/CommonConfig.cpp | 6 +-- src/core/CommonConfig.h | 5 +- src/core/Config.cpp | 58 ++++++++++++---------- src/core/Config.h | 41 +++++++--------- src/crypto/CryptoNight.cpp | 6 +-- src/interfaces/IThread.h | 64 ++++++++++++++++++++++++ src/net/Job.cpp | 4 +- src/net/Url.cpp | 6 +-- src/net/strategies/DonateStrategy.cpp | 2 +- src/workers/CpuThread.cpp | 68 +++++++++++++++++++++++++ src/workers/CpuThread.h | 71 +++++++++++++++++++++++++++ src/xmrig.h | 29 ++++++++--- 19 files changed, 320 insertions(+), 78 deletions(-) create mode 100644 src/interfaces/IThread.h create mode 100644 src/workers/CpuThread.cpp create mode 100644 src/workers/CpuThread.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f42950ed..c9d6624fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ set(HEADERS src/interfaces/ILogBackend.h src/interfaces/IStrategy.h src/interfaces/IStrategyListener.h + src/interfaces/IThread.h src/interfaces/IWatcherListener.h src/interfaces/IWorker.h src/log/ConsoleLog.h @@ -52,6 +53,7 @@ set(HEADERS src/Platform.h src/Summary.h src/version.h + src/workers/CpuThread.h src/workers/DoubleWorker.h src/workers/Handle.h src/workers/Hashrate.h @@ -106,6 +108,7 @@ set(SOURCES src/net/Url.cpp src/Platform.cpp src/Summary.cpp + src/workers/CpuThread.cpp src/workers/DoubleWorker.cpp src/workers/Handle.cpp src/workers/Hashrate.cpp diff --git a/src/App.cpp b/src/App.cpp index 9bdd381ee..a9d107743 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -107,7 +107,7 @@ int App::exec() } Mem::allocate(m_controller->config()->algorithm(), - m_controller->config()->threads(), + m_controller->config()->threadsCount(), m_controller->config()->isDoubleHash(), m_controller->config()->isHugePages() ); diff --git a/src/Mem.cpp b/src/Mem.cpp index 991f4398d..f5da7865c 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -43,7 +43,7 @@ alignas(16) uint8_t *Mem::m_memory = nullptr; cryptonight_ctx *Mem::create(int threadId) { # ifndef XMRIG_NO_AEON - if (m_algo == xmrig::ALGO_CRYPTONIGHT_LITE) { + if (m_algo == xmrig::CRYPTONIGHT_LITE) { return createLite(threadId); } # endif diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index 1b35c7041..6cc0a6eee 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -151,7 +151,7 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) m_threads = threads; m_doubleHash = doubleHash; - const int ratio = (doubleHash && algo != xmrig::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; + const int ratio = (doubleHash && algo != xmrig::CRYPTONIGHT_LITE) ? 2 : 1; m_size = MONERO_MEMORY * (threads * ratio + 1); if (!enabled) { diff --git a/src/Summary.cpp b/src/Summary.cpp index 6aa42b745..7e341ce0a 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -101,7 +101,7 @@ static void print_threads(xmrig::Config *config) } Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s", - config->threads(), + config->threadsCount(), config->algoName(), config->algoVariant(), config->isColors() && config->donateLevel() == 0 ? "\x1B[01;31m" : "", diff --git a/src/api/ApiRouter.cpp b/src/api/ApiRouter.cpp index e1ba9e174..6c4f1f271 100644 --- a/src/api/ApiRouter.cpp +++ b/src/api/ApiRouter.cpp @@ -38,6 +38,7 @@ #include "core/Config.h" #include "core/Controller.h" #include "Cpu.h" +#include "interfaces/IThread.h" #include "Mem.h" #include "net/Job.h" #include "Platform.h" @@ -67,7 +68,7 @@ static inline double normalize(double d) ApiRouter::ApiRouter(xmrig::Controller *controller) : m_controller(controller) { - m_threads = controller->config()->threads(); + m_threads = controller->config()->threadsCount(); m_hashrate = new double[m_threads * 3](); memset(m_totalHashrate, 0, sizeof(m_totalHashrate)); @@ -87,7 +88,6 @@ ApiRouter::~ApiRouter() void ApiRouter::ApiRouter::get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const { rapidjson::Document doc; - doc.SetObject(); if (req.match("/1/config")) { if (req.isRestricted()) { @@ -100,6 +100,14 @@ void ApiRouter::ApiRouter::get(const xmrig::HttpRequest &req, xmrig::HttpReply & return finalize(reply, doc); } + if (req.match("/1/threads")) { + getThreads(doc); + + return finalize(reply, doc); + } + + doc.SetObject(); + getIdentify(doc); getMiner(doc); getHashrate(doc); @@ -144,7 +152,7 @@ void ApiRouter::tick(const NetworkState &network) void ApiRouter::onConfigChanged(xmrig::Config *config, xmrig::Config *previousConfig) { -// updateWorkerId(config->apiWorkerId(), previousConfig->apiWorkerId()); + updateWorkerId(config->apiWorkerId(), previousConfig->apiWorkerId()); } @@ -288,6 +296,18 @@ void ApiRouter::getResults(rapidjson::Document &doc) const } +void ApiRouter::getThreads(rapidjson::Document &doc) const +{ + doc.SetArray(); + + const std::vector &threads = m_controller->config()->threads(); + + for (const xmrig::IThread *thread : threads) { + doc.PushBack(thread->toAPI(doc), doc.GetAllocator()); + } +} + + void ApiRouter::setWorkerId(const char *id) { memset(m_workerId, 0, sizeof(m_workerId)); diff --git a/src/api/ApiRouter.h b/src/api/ApiRouter.h index 2ae1cc80c..e14f9e879 100644 --- a/src/api/ApiRouter.h +++ b/src/api/ApiRouter.h @@ -63,6 +63,7 @@ private: void getIdentify(rapidjson::Document &doc) const; void getMiner(rapidjson::Document &doc) const; void getResults(rapidjson::Document &doc) const; + void getThreads(rapidjson::Document &doc) const; void setWorkerId(const char *id); void updateWorkerId(const char *id, const char *previousId); diff --git a/src/core/CommonConfig.cpp b/src/core/CommonConfig.cpp index ea17342cd..514486547 100644 --- a/src/core/CommonConfig.cpp +++ b/src/core/CommonConfig.cpp @@ -51,6 +51,7 @@ static const char *algoNames[] = { xmrig::CommonConfig::CommonConfig() : + m_algorithm(CRYPTONIGHT), m_adjusted(false), m_apiIPv6(true), m_apiRestricted(true), @@ -63,7 +64,6 @@ xmrig::CommonConfig::CommonConfig() : m_fileName(nullptr), m_logFile(nullptr), m_userAgent(nullptr), - m_algorithm(ALGO_CRYPTONIGHT), m_apiPort(0), m_donateLevel(kDefaultDonateLevel), m_printTime(60), @@ -367,7 +367,7 @@ void xmrig::CommonConfig::setAlgo(const char *algo) if (strcasecmp(algo, "cryptonight-light") == 0) { fprintf(stderr, "Algorithm \"cryptonight-light\" is deprecated, use \"cryptonight-lite\" instead\n"); - m_algorithm = ALGO_CRYPTONIGHT_LITE; + m_algorithm = CRYPTONIGHT_LITE; return; } @@ -375,7 +375,7 @@ void xmrig::CommonConfig::setAlgo(const char *algo) for (size_t i = 0; i < size; i++) { if (algoNames[i] && strcasecmp(algo, algoNames[i]) == 0) { - m_algorithm = (int) i; + m_algorithm = static_cast(i); break; } } diff --git a/src/core/CommonConfig.h b/src/core/CommonConfig.h index ab840a48b..0f6f6b8c9 100644 --- a/src/core/CommonConfig.h +++ b/src/core/CommonConfig.h @@ -29,6 +29,7 @@ #include "interfaces/IConfig.h" +#include "xmrig.h" class Url; @@ -45,6 +46,7 @@ public: const char *algoName() const; + inline Algo algorithm() const { return m_algorithm; } inline bool isApiIPv6() const { return m_apiIPv6; } inline bool isApiRestricted() const { return m_apiRestricted; } inline bool isBackground() const { return m_background; } @@ -55,7 +57,6 @@ public: inline const char *logFile() const { return m_logFile; } inline const char *userAgent() const { return m_userAgent; } inline const std::vector &pools() const { return m_pools; } - inline int algorithm() const { return m_algorithm; } inline int apiPort() const { return m_apiPort; } inline int donateLevel() const { return m_donateLevel; } inline int printTime() const { return m_printTime; } @@ -75,6 +76,7 @@ protected: bool save() override; void setFileName(const char *fileName) override; + Algo m_algorithm; bool m_adjusted; bool m_apiIPv6; bool m_apiRestricted; @@ -87,7 +89,6 @@ protected: char *m_fileName; char *m_logFile; char *m_userAgent; - int m_algorithm; int m_apiPort; int m_donateLevel; int m_printTime; diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 49b40aa83..6bc2dc0fc 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -34,6 +34,7 @@ #include "rapidjson/document.h" #include "rapidjson/filewritestream.h" #include "rapidjson/prettywriter.h" +#include "workers/CpuThread.h" #include "xmrig.h" @@ -41,18 +42,17 @@ static char affinity_tmp[20] = { 0 }; xmrig::Config::Config() : xmrig::CommonConfig(), + m_algoVariant(AV_AUTO), m_doubleHash(false), m_dryRun(false), m_hugePages(true), m_safe(false), - m_algoVariant(0), m_maxCpuUsage(75), m_printTime(60), m_priority(-1), - m_threads(0), - m_affinity(-1L) + m_affinity(-1L), + m_threadsCount(0) { - } @@ -135,7 +135,7 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("retries", retries(), allocator); doc.AddMember("retry-pause", retryPause(), allocator); doc.AddMember("safe", m_safe, allocator); - doc.AddMember("threads", threads(), allocator); + doc.AddMember("threads", threadsCount(), allocator); doc.AddMember("user-agent", userAgent() ? rapidjson::Value(rapidjson::StringRef(userAgent())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator); # ifdef HAVE_SYSLOG_H @@ -159,20 +159,24 @@ bool xmrig::Config::adjust() } m_algoVariant = getAlgoVariant(); - if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) { + if (m_algoVariant == AV_DOUBLE || m_algoVariant == AV_DOUBLE_SOFT) { m_doubleHash = true; } - if (!m_threads) { - m_threads = Cpu::optimalThreadsCount(m_algorithm, m_doubleHash, m_maxCpuUsage); + if (!m_threadsCount) { + m_threadsCount = Cpu::optimalThreadsCount(m_algorithm, m_doubleHash, m_maxCpuUsage); } else if (m_safe) { - const int count = Cpu::optimalThreadsCount(m_algorithm, m_doubleHash, m_maxCpuUsage); - if (m_threads > count) { - m_threads = count; + const size_t count = Cpu::optimalThreadsCount(m_algorithm, m_doubleHash, m_maxCpuUsage); + if (m_threadsCount > count) { + m_threadsCount = count; } } + for (size_t i = 0; i < m_threadsCount; ++i) { + m_threads.push_back(CpuThread::createFromAV(i, m_algorithm, m_algoVariant, m_affinity, m_priority)); + } + return true; } @@ -225,7 +229,7 @@ bool xmrig::Config::parseString(int key, const char *arg) case xmrig::IConfig::ThreadsKey: /* --threads */ if (strncmp(arg, "all", 3) == 0) { - m_threads = Cpu::threads(); + m_threadsCount = Cpu::threads(); return true; } @@ -275,14 +279,14 @@ bool xmrig::Config::parseInt(int key, int arg) { switch (key) { case xmrig::IConfig::ThreadsKey: /* --threads */ - if (m_threads >= 0 && arg < 1024) { - m_threads = arg; + if (m_threadsCount >= 0 && arg < 1024) { + m_threadsCount = arg; } break; case xmrig::IConfig::AVKey: /* --av */ - if (arg >= AV0_AUTO && arg < AV_MAX) { - m_algoVariant = arg; + if (arg >= AV_AUTO && arg < AV_MAX) { + m_algoVariant = static_cast(arg); } break; @@ -306,20 +310,20 @@ bool xmrig::Config::parseInt(int key, int arg) } -int xmrig::Config::getAlgoVariant() const +xmrig::AlgoVariant xmrig::Config::getAlgoVariant() const { # ifndef XMRIG_NO_AEON - if (m_algorithm == xmrig::ALGO_CRYPTONIGHT_LITE) { + if (m_algorithm == xmrig::CRYPTONIGHT_LITE) { return getAlgoVariantLite(); } # endif - if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) { - return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES; + if (m_algoVariant <= AV_AUTO || m_algoVariant >= AV_MAX) { + return Cpu::hasAES() ? AV_SINGLE : AV_SINGLE_SOFT; } - if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) { - return m_algoVariant + 2; + if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV_DOUBLE) { + return static_cast(m_algoVariant + 2); } return m_algoVariant; @@ -327,14 +331,14 @@ int xmrig::Config::getAlgoVariant() const #ifndef XMRIG_NO_AEON -int xmrig::Config::getAlgoVariantLite() const +xmrig::AlgoVariant xmrig::Config::getAlgoVariantLite() const { - if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) { - return Cpu::hasAES() ? AV2_AESNI_DOUBLE : AV4_SOFT_AES_DOUBLE; + if (m_algoVariant <= AV_AUTO || m_algoVariant >= AV_MAX) { + return Cpu::hasAES() ? AV_DOUBLE : AV_DOUBLE_SOFT; } - if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) { - return m_algoVariant + 2; + if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV_DOUBLE) { + return static_cast(m_algoVariant + 2); } return m_algoVariant; diff --git a/src/core/Config.h b/src/core/Config.h index 110c61a74..536e1c012 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -29,8 +29,9 @@ #include -#include "rapidjson/fwd.h" #include "core/CommonConfig.h" +#include "rapidjson/fwd.h" +#include "xmrig.h" class Addr; @@ -41,6 +42,7 @@ namespace xmrig { class ConfigLoader; +class IThread; class IWatcherListener; @@ -57,18 +59,7 @@ class IWatcherListener; */ class Config : public CommonConfig { - friend class ConfigLoader; - public: - enum AlgoVariant { - AV0_AUTO, - AV1_AESNI, - AV2_AESNI_DOUBLE, - AV3_SOFT_AES, - AV4_SOFT_AES_DOUBLE, - AV_MAX - }; - Config(); ~Config(); @@ -76,14 +67,15 @@ public: void getJSON(rapidjson::Document &doc) const override; - inline bool isDoubleHash() const { return m_doubleHash; } - inline bool isDryRun() const { return m_dryRun; } - inline bool isHugePages() const { return m_hugePages; } - inline int algoVariant() const { return m_algoVariant; } - inline int printTime() const { return m_printTime; } - inline int priority() const { return m_priority; } - inline int threads() const { return m_threads; } - inline int64_t affinity() const { return m_affinity; } + inline AlgoVariant algoVariant() const { return m_algoVariant; } + inline bool isDoubleHash() const { return m_doubleHash; } + inline bool isDryRun() const { return m_dryRun; } + inline bool isHugePages() const { return m_hugePages; } + inline const std::vector &threads() const { return m_threads; } + inline int printTime() const { return m_printTime; } + inline int priority() const { return m_priority; } + inline int threadsCount() const { return m_threadsCount; } + inline int64_t affinity() const { return m_affinity; } static Config *load(int argc, char **argv, IWatcherListener *listener); @@ -97,21 +89,22 @@ protected: private: bool parseInt(int key, int arg); - int getAlgoVariant() const; + AlgoVariant getAlgoVariant() const; # ifndef XMRIG_NO_AEON - int getAlgoVariantLite() const; + AlgoVariant getAlgoVariantLite() const; # endif + AlgoVariant m_algoVariant; bool m_doubleHash; bool m_dryRun; bool m_hugePages; bool m_safe; - int m_algoVariant; int m_maxCpuUsage; int m_printTime; int m_priority; - int m_threads; int64_t m_affinity; + size_t m_threadsCount; + std::vector m_threads; }; diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index c9a2e499a..f7dc1a378 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -137,7 +137,7 @@ bool CryptoNight::init(int algo, int variant, bool doubleHash) } # ifndef XMRIG_NO_AEON - const int index = algo == xmrig::ALGO_CRYPTONIGHT_LITE ? (variant + 3) : (variant - 1); + const int index = algo == xmrig::CRYPTONIGHT_LITE ? (variant + 3) : (variant - 1); # else const int index = variant - 1; # endif @@ -167,7 +167,7 @@ bool CryptoNight::selfTest(int algo, bool doubleHash) { cryptonight_hash_ctx(test_input, 76, output, ctx, 0); # ifndef XMRIG_NO_AEON - bool rc = memcmp(output, algo == xmrig::ALGO_CRYPTONIGHT_LITE ? test_output_v0_lite : test_output_v0, (doubleHash ? 64 : 32)) == 0; + 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 @@ -176,7 +176,7 @@ bool CryptoNight::selfTest(int algo, bool doubleHash) { cryptonight_hash_ctx(test_input, 76, output, ctx, 1); # ifndef XMRIG_NO_AEON - rc = memcmp(output, algo == xmrig::ALGO_CRYPTONIGHT_LITE ? test_output_v1_lite : test_output_v1, (doubleHash ? 64 : 32)) == 0; + 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 diff --git a/src/interfaces/IThread.h b/src/interfaces/IThread.h new file mode 100644 index 000000000..e2325c729 --- /dev/null +++ b/src/interfaces/IThread.h @@ -0,0 +1,64 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * 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 . + */ + +#ifndef __ITHREAD_H__ +#define __ITHREAD_H__ + + +#include + + +#include "rapidjson/fwd.h" +#include "xmrig.h" + + +namespace xmrig { + + +class IThread +{ +public: + enum Type { + CPU, + OpenCL, + CUDA + }; + + virtual ~IThread() {} + + virtual Algo algorithm() const = 0; + virtual int multiway() const = 0; + virtual int priority() const = 0; + virtual int64_t affinity() const = 0; + virtual size_t index() const = 0; + virtual Type type() const = 0; + +# ifndef XMRIG_NO_API + virtual rapidjson::Value toAPI(rapidjson::Document &doc) const = 0; +# endif +}; + + +} /* namespace xmrig */ + + +#endif // __ITHREAD_H__ diff --git a/src/net/Job.cpp b/src/net/Job.cpp index 7d137fac9..e57143767 100644 --- a/src/net/Job.cpp +++ b/src/net/Job.cpp @@ -59,7 +59,7 @@ static inline char hf_bin2hex(unsigned char c) Job::Job() : m_nicehash(false), m_coin(), - m_algo(xmrig::ALGO_CRYPTONIGHT), + m_algo(xmrig::CRYPTONIGHT), m_poolId(-2), m_threadId(-1), m_variant(xmrig::VARIANT_AUTO), @@ -164,7 +164,7 @@ void Job::setCoin(const char *coin) } strncpy(m_coin, coin, sizeof(m_coin)); - m_algo = strcmp(m_coin, "AEON") == 0 ? xmrig::ALGO_CRYPTONIGHT_LITE : xmrig::ALGO_CRYPTONIGHT; + m_algo = strcmp(m_coin, "AEON") == 0 ? xmrig::CRYPTONIGHT_LITE : xmrig::CRYPTONIGHT; } diff --git a/src/net/Url.cpp b/src/net/Url.cpp index 8905e9190..3d5f2cdd1 100644 --- a/src/net/Url.cpp +++ b/src/net/Url.cpp @@ -41,7 +41,7 @@ Url::Url() : m_host(nullptr), m_password(nullptr), m_user(nullptr), - m_algo(xmrig::ALGO_CRYPTONIGHT), + m_algo(xmrig::CRYPTONIGHT), m_keepAlive(0), m_variant(xmrig::VARIANT_AUTO), m_url(nullptr), @@ -66,7 +66,7 @@ Url::Url(const char *url) : m_host(nullptr), m_password(nullptr), m_user(nullptr), - m_algo(xmrig::ALGO_CRYPTONIGHT), + m_algo(xmrig::CRYPTONIGHT), m_keepAlive(0), m_variant(xmrig::VARIANT_AUTO), m_url(nullptr), @@ -80,7 +80,7 @@ Url::Url(const char *host, uint16_t port, const char *user, const char *password m_nicehash(nicehash), m_password(password ? strdup(password) : nullptr), m_user(user ? strdup(user) : nullptr), - m_algo(xmrig::ALGO_CRYPTONIGHT), + m_algo(xmrig::CRYPTONIGHT), m_keepAlive(keepAlive), m_variant(variant), m_url(nullptr), diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index ae707e21f..495038207 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -59,7 +59,7 @@ DonateStrategy::DonateStrategy(int level, const char *user, int algo, IStrategyL keccak(reinterpret_cast(user), static_cast(strlen(user)), hash, sizeof(hash)); Job::toHex(hash, 32, userId); - if (algo == xmrig::ALGO_CRYPTONIGHT) { + if (algo == xmrig::CRYPTONIGHT) { m_pools.push_back(new Url(kDonatePool1, 6666, userId, nullptr, false, true)); m_pools.push_back(new Url(kDonatePool1, 80, userId, nullptr, false, true)); m_pools.push_back(new Url(kDonatePool2, 5555, "48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD", "emergency", false, false)); diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp new file mode 100644 index 000000000..ff3aaed73 --- /dev/null +++ b/src/workers/CpuThread.cpp @@ -0,0 +1,68 @@ +/* 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 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 "rapidjson/document.h" +#include "workers/CpuThread.h" + + +xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, int multiway, int64_t affinity, int priority, bool softAES, bool prefetch) : + m_algorithm(algorithm), + m_prefetch(prefetch), + m_softAES(softAES), + m_multiway(multiway), + m_priority(priority), + m_affinity(affinity), + m_index(index) +{ +} + + +xmrig::CpuThread::~CpuThread() +{ +} + + +xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority) +{ + return new CpuThread(index, algorithm, 1, affinity, priority, false, false); +} + + +#ifndef XMRIG_NO_API +rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const +{ + rapidjson::Value obj(rapidjson::kObjectType); + auto &allocator = doc.GetAllocator(); + + obj.AddMember("type", "cpu", allocator); + obj.AddMember("algo", algorithm(), allocator); + obj.AddMember("low_power_mode", multiway(), allocator); + obj.AddMember("affine_to_cpu", affinity(), allocator); + obj.AddMember("priority", priority(), allocator); + obj.AddMember("prefetch", isPrefetch(), allocator); + obj.AddMember("soft_aes", isSoftAES(), allocator); + + return obj; +} +#endif diff --git a/src/workers/CpuThread.h b/src/workers/CpuThread.h new file mode 100644 index 000000000..93ef50d59 --- /dev/null +++ b/src/workers/CpuThread.h @@ -0,0 +1,71 @@ +/* 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 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 . + */ + +#ifndef __CPUTHREAD_H__ +#define __CPUTHREAD_H__ + + +#include "interfaces/IThread.h" +#include "xmrig.h" + + +namespace xmrig { + + +class CpuThread : public IThread +{ +public: + CpuThread(size_t index, Algo algorithm, int multiway, int64_t affinity, int priority, bool softAES, bool prefetch); + ~CpuThread(); + + static CpuThread *createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority); + + inline bool isPrefetch() const { return m_prefetch; } + inline bool isSoftAES() const { return m_softAES; } + + inline Algo algorithm() const override { return m_algorithm; } + inline int multiway() const override { return m_multiway; } + inline int priority() const override { return m_priority; } + inline int64_t affinity() const override { return m_affinity; } + inline size_t index() const override { return m_affinity; } + inline Type type() const override { return CPU; } + +# ifndef XMRIG_NO_API + rapidjson::Value toAPI(rapidjson::Document &doc) const override; +# endif + +private: + const Algo m_algorithm; + const bool m_prefetch; + const bool m_softAES; + const int m_multiway; + const int m_priority; + const int64_t m_affinity; + const size_t m_index; +}; + + +} /* namespace xmrig */ + + +#endif /* __CPUTHREAD_H__ */ diff --git a/src/xmrig.h b/src/xmrig.h index 9cae73c77..805b7ceba 100644 --- a/src/xmrig.h +++ b/src/xmrig.h @@ -30,18 +30,35 @@ namespace xmrig enum Algo { - ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */ - ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ - ALGO_CRYPTONIGHT_HEAVY, /* CryptoNight-Heavy (SUMO) */ + CRYPTONIGHT, /* CryptoNight (Monero) */ + CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ + CRYPTONIGHT_HEAVY, /* CryptoNight-Heavy (SUMO) */ +}; + + +enum AlgoVariant { + AV_AUTO, + AV_SINGLE, + AV_DOUBLE, + AV_SINGLE_SOFT, + AV_DOUBLE_SOFT, + AV_TRIPLE, + AV_QUAD, + AV_PENTA, + AV_TRIPLE_SOFT, + AV_QUAD_SOFT, + AV_PENTA_SOFT, + AV_MAX }; enum Variant { - VARIANT_AUTO = -1, - VARIANT_NONE = 0, - VARIANT_V1 = 1 + VARIANT_AUTO = -1, // Autodetect + VARIANT_NONE = 0, // Original CryptoNight + VARIANT_V1 = 1 // Monero v7 PoW }; + } /* xmrig */ From 6c970612bfe22c9c61ba9caf3acea3664f1f2474 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 2 Apr 2018 14:05:16 +0700 Subject: [PATCH 02/13] Transform affinity and av to internal representation. --- src/core/CommonConfig.cpp | 4 +-- src/core/CommonConfig.h | 3 +- src/workers/CpuThread.cpp | 71 ++++++++++++++++++++++++++++++++++++--- src/workers/CpuThread.h | 13 +++++-- src/xmrig.h | 26 ++++++++------ 5 files changed, 96 insertions(+), 21 deletions(-) diff --git a/src/core/CommonConfig.cpp b/src/core/CommonConfig.cpp index 514486547..6a2c76ac5 100644 --- a/src/core/CommonConfig.cpp +++ b/src/core/CommonConfig.cpp @@ -95,9 +95,9 @@ xmrig::CommonConfig::~CommonConfig() } -const char *xmrig::CommonConfig::algoName() const +const char *xmrig::CommonConfig::algoName(Algo algorithm) { - return algoNames[m_algorithm]; + return algoNames[algorithm]; } diff --git a/src/core/CommonConfig.h b/src/core/CommonConfig.h index 0f6f6b8c9..ee9c7a20e 100644 --- a/src/core/CommonConfig.h +++ b/src/core/CommonConfig.h @@ -44,7 +44,7 @@ public: CommonConfig(); ~CommonConfig(); - const char *algoName() const; + static const char *algoName(Algo algorithm); inline Algo algorithm() const { return m_algorithm; } inline bool isApiIPv6() const { return m_apiIPv6; } @@ -52,6 +52,7 @@ public: inline bool isBackground() const { return m_background; } inline bool isColors() const { return m_colors; } inline bool isSyslog() const { return m_syslog; } + inline const char *algoName() const { return algoName(m_algorithm); } inline const char *apiToken() const { return m_apiToken; } inline const char *apiWorkerId() const { return m_apiWorkerId; } inline const char *logFile() const { return m_logFile; } diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index ff3aaed73..91e98a149 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -21,18 +21,22 @@ * along with this program. If not, see . */ +#include + +#include "core/CommonConfig.h" #include "rapidjson/document.h" #include "workers/CpuThread.h" -xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, int multiway, int64_t affinity, int priority, bool softAES, bool prefetch) : +xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch) : m_algorithm(algorithm), + m_av(av), m_prefetch(prefetch), m_softAES(softAES), - m_multiway(multiway), m_priority(priority), m_affinity(affinity), + m_multiway(multiway), m_index(index) { } @@ -45,7 +49,64 @@ xmrig::CpuThread::~CpuThread() xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority) { - return new CpuThread(index, algorithm, 1, affinity, priority, false, false); + assert(av > AV_AUTO && av < AV_MAX); + + Multiway multiway = SingleWay; + bool softAES = false; + + switch (av) { + case AV_SINGLE_SOFT: + softAES = true; + break; + + case AV_DOUBLE: + multiway = DoubleWay; + case AV_DOUBLE_SOFT: + softAES = true; + break; + + case AV_TRIPLE: + multiway = TripleWay; + case AV_TRIPLE_SOFT: + softAES = true; + break; + + case AV_QUAD: + multiway = QuadWay; + case AV_QUAD_SOFT: + softAES = true; + break; + + case AV_PENTA: + multiway = PentaWay; + case AV_PENTA_SOFT: + softAES = true; + break; + + default: + break; + } + + int64_t cpuId = -1L; + + if (affinity != -1L) { + size_t idx = 0; + + for (size_t i = 0; i < 64; i++) { + if (!(affinity & (1ULL << i))) { + continue; + } + + if (idx == index) { + cpuId = i; + break; + } + + idx++; + } + } + + return new CpuThread(index, algorithm, av, multiway, cpuId, priority, softAES, false); } @@ -56,11 +117,11 @@ rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const auto &allocator = doc.GetAllocator(); obj.AddMember("type", "cpu", allocator); - obj.AddMember("algo", algorithm(), allocator); + obj.AddMember("algo", rapidjson::StringRef(CommonConfig::algoName(algorithm())), allocator); + obj.AddMember("av", m_av, allocator); obj.AddMember("low_power_mode", multiway(), allocator); obj.AddMember("affine_to_cpu", affinity(), allocator); obj.AddMember("priority", priority(), allocator); - obj.AddMember("prefetch", isPrefetch(), allocator); obj.AddMember("soft_aes", isSoftAES(), allocator); return obj; diff --git a/src/workers/CpuThread.h b/src/workers/CpuThread.h index 93ef50d59..2b2144237 100644 --- a/src/workers/CpuThread.h +++ b/src/workers/CpuThread.h @@ -35,7 +35,15 @@ namespace xmrig { class CpuThread : public IThread { public: - CpuThread(size_t index, Algo algorithm, int multiway, int64_t affinity, int priority, bool softAES, bool prefetch); + enum Multiway { + SingleWay, + DoubleWay, + TripleWay, + QuadWay, + PentaWay + }; + + CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch); ~CpuThread(); static CpuThread *createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority); @@ -56,11 +64,12 @@ public: private: const Algo m_algorithm; + const AlgoVariant m_av; const bool m_prefetch; const bool m_softAES; - const int m_multiway; const int m_priority; const int64_t m_affinity; + const Multiway m_multiway; const size_t m_index; }; diff --git a/src/xmrig.h b/src/xmrig.h index 805b7ceba..eba72bb4e 100644 --- a/src/xmrig.h +++ b/src/xmrig.h @@ -36,18 +36,22 @@ enum Algo { }; +//--av=1 For CPUs with hardware AES. +//--av=2 Lower power mode (double hash) of 1. +//--av=3 Software AES implementation. +//--av=4 Lower power mode (double hash) of 3. enum AlgoVariant { - AV_AUTO, - AV_SINGLE, - AV_DOUBLE, - AV_SINGLE_SOFT, - AV_DOUBLE_SOFT, - AV_TRIPLE, - AV_QUAD, - AV_PENTA, - AV_TRIPLE_SOFT, - AV_QUAD_SOFT, - AV_PENTA_SOFT, + AV_AUTO, // --av=0 Automatic mode. + AV_SINGLE, // --av=1 Single hash mode + AV_DOUBLE, // --av=2 Double hash mode + AV_SINGLE_SOFT, // --av=3 Single hash mode (Software AES) + AV_DOUBLE_SOFT, // --av=4 Double hash mode (Software AES) + AV_TRIPLE, // --av=5 Triple hash mode + AV_QUAD, // --av=6 Quard hash mode + AV_PENTA, // --av=7 Penta hash mode + AV_TRIPLE_SOFT, // --av=8 Triple hash mode (Software AES) + AV_QUAD_SOFT, // --av=9 Quard hash mode (Software AES) + AV_PENTA_SOFT, // --av=10 Penta hash mode (Software AES) AV_MAX }; From 72cd6d168e94d3aa0632e214aba9401963bf1eef Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 2 Apr 2018 15:03:56 +0700 Subject: [PATCH 03/13] Now used IThread to start threads, cpu-affinity broken, nonce allocation in double mode probably broken too. --- src/workers/CpuThread.h | 4 ++-- src/workers/DoubleWorker.cpp | 8 ++++---- src/workers/Handle.cpp | 14 ++++++-------- src/workers/Handle.h | 22 +++++++++++----------- src/workers/SingleWorker.cpp | 4 ++-- src/workers/Worker.cpp | 10 +++++----- src/workers/Worker.h | 4 ++-- src/workers/Workers.cpp | 19 +++++++++++++++---- 8 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/workers/CpuThread.h b/src/workers/CpuThread.h index 2b2144237..ee0a3d575 100644 --- a/src/workers/CpuThread.h +++ b/src/workers/CpuThread.h @@ -36,7 +36,7 @@ class CpuThread : public IThread { public: enum Multiway { - SingleWay, + SingleWay = 1, DoubleWay, TripleWay, QuadWay, @@ -55,7 +55,7 @@ public: inline int multiway() const override { return m_multiway; } inline int priority() const override { return m_priority; } inline int64_t affinity() const override { return m_affinity; } - inline size_t index() const override { return m_affinity; } + inline size_t index() const override { return m_index; } inline Type type() const override { return CPU; } # ifndef XMRIG_NO_API diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index 46c8ed2ea..3dba4a9fb 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -134,12 +134,12 @@ void DoubleWorker::consumeJob() memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size()); if (m_state->job.isNicehash()) { - m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / (m_threads * 2) * m_id); - m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / (m_threads * 2) * (m_id + m_threads)); + m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / m_totalWays * m_id); + m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / m_totalWays * (m_id + m_totalWays)); } else { - m_state->nonce1 = 0xffffffffU / (m_threads * 2) * m_id; - m_state->nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads); + m_state->nonce1 = 0xffffffffU / m_totalWays * m_id; + m_state->nonce2 = 0xffffffffU / m_totalWays * (m_id + m_totalWays); } } diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp index c461cee75..6d7b969a3 100644 --- a/src/workers/Handle.cpp +++ b/src/workers/Handle.cpp @@ -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 @@ -25,12 +25,10 @@ #include "workers/Handle.h" -Handle::Handle(int threadId, int threads, int64_t affinity, int priority) : - m_priority(priority), - m_threadId(threadId), - m_threads(threads), - m_affinity(affinity), - m_worker(nullptr) +Handle::Handle(xmrig::IThread *config, size_t totalWays) : + m_worker(nullptr), + m_totalWays(totalWays), + m_config(config) { } diff --git a/src/workers/Handle.h b/src/workers/Handle.h index 9faae0d0c..d63dc0988 100644 --- a/src/workers/Handle.h +++ b/src/workers/Handle.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 @@ -29,30 +29,30 @@ #include +#include "interfaces/IThread.h" + + class IWorker; class Handle { public: - Handle(int threadId, int threads, int64_t affinity, int priority); + Handle(xmrig::IThread *config, size_t totalWays); void join(); void start(void (*callback) (void *)); - inline int priority() const { return m_priority; } - inline int threadId() const { return m_threadId; } - inline int threads() const { return m_threads; } - inline int64_t affinity() const { return m_affinity; } inline IWorker *worker() const { return m_worker; } + inline size_t threadId() const { return m_config->index(); } + inline size_t totalWays() const { return m_totalWays; } inline void setWorker(IWorker *worker) { m_worker = worker; } + inline xmrig::IThread *config() const { return m_config; } private: - int m_priority; - int m_threadId; - int m_threads; - int64_t m_affinity; IWorker *m_worker; + size_t m_totalWays; uv_thread_t m_thread; + xmrig::IThread *m_config; }; diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp index 9f4a7484c..9d47d947e 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/SingleWorker.cpp @@ -104,10 +104,10 @@ void SingleWorker::consumeJob() m_result = m_job; if (m_job.isNicehash()) { - m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_threads * m_id); + m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_totalWays * m_id); } else { - m_result.nonce = 0xffffffffU / m_threads * m_id; + m_result.nonce = 0xffffffffU / m_totalWays * m_id; } } diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index 7a7ff9865..648bf7edb 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -33,17 +33,17 @@ Worker::Worker(Handle *handle) : m_id(handle->threadId()), - m_threads(handle->threads()), + m_totalWays(handle->totalWays()), m_hashCount(0), m_timestamp(0), m_count(0), m_sequence(0) { - if (Cpu::threads() > 1 && handle->affinity() != -1L) { - Cpu::setAffinity(m_id, handle->affinity()); - } +// if (Cpu::threads() > 1 && handle->affinity() != -1L) { +// Cpu::setAffinity(m_id, handle->affinity()); +// } - Platform::setThreadPriority(handle->priority()); + Platform::setThreadPriority(handle->config()->priority()); m_ctx = Mem::create(m_id); } diff --git a/src/workers/Worker.h b/src/workers/Worker.h index 08a0551f1..a9c15ef40 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -49,8 +49,8 @@ protected: void storeStats(); cryptonight_ctx *m_ctx; - int m_id; - int m_threads; + size_t m_id; + size_t m_totalWays; std::atomic m_hashCount; std::atomic m_timestamp; uint64_t m_count; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 5642751a5..faa207a0a 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -25,7 +25,10 @@ #include "api/Api.h" +#include "core/Config.h" +#include "core/Controller.h" #include "interfaces/IJobResultListener.h" +#include "interfaces/IThread.h" #include "Mem.h" #include "workers/DoubleWorker.h" #include "workers/Handle.h" @@ -33,6 +36,8 @@ #include "workers/SingleWorker.h" #include "workers/Workers.h" +#include "log/Log.h" + bool Workers::m_active = false; bool Workers::m_enabled = true; @@ -104,8 +109,14 @@ void Workers::setJob(const Job &job, bool donate) void Workers::start(int64_t affinity, int priority, xmrig::Controller *controller) { - const int threads = Mem::threads(); - m_hashrate = new Hashrate(threads, controller); + const std::vector &threads = controller->config()->threads(); + + size_t totalWays = 0; + for (const xmrig::IThread *thread : threads) { + totalWays += thread->multiway(); + } + + m_hashrate = new Hashrate(threads.size(), controller); uv_mutex_init(&m_mutex); uv_rwlock_init(&m_rwlock); @@ -117,8 +128,8 @@ void Workers::start(int64_t affinity, int priority, xmrig::Controller *controlle uv_timer_init(uv_default_loop(), &m_timer); uv_timer_start(&m_timer, Workers::onTick, 500, 500); - for (int i = 0; i < threads; ++i) { - Handle *handle = new Handle(i, threads, affinity, priority); + for (xmrig::IThread *thread : threads) { + Handle *handle = new Handle(thread, totalWays); m_workers.push_back(handle); handle->start(Workers::onReady); } From 903b243308911d89de0c5a4e701f9b9a958a0494 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 02:55:28 +0700 Subject: [PATCH 04/13] New style function selector. --- CMakeLists.txt | 6 ++ src/crypto/CryptoNight.cpp | 22 +++--- src/crypto/CryptoNight_constants.h | 117 +++++++++++++++++++++++++++++ src/crypto/CryptoNight_x86.h | 31 +++++++- src/net/Job.cpp | 11 ++- src/net/Job.h | 4 +- src/workers/CpuThread.cpp | 87 +++++++++++++++++++++ src/workers/CpuThread.h | 23 ++++-- src/workers/SingleWorker.cpp | 5 +- src/workers/Worker.cpp | 4 +- src/workers/Worker.h | 6 ++ src/xmrig.h | 2 +- 12 files changed, 287 insertions(+), 31 deletions(-) create mode 100644 src/crypto/CryptoNight_constants.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c9d6624fc..5e2ac1907 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ project(xmrig) option(WITH_LIBCPUID "Use Libcpuid" ON) option(WITH_AEON "CryptoNight-Lite support" ON) +option(WITH_SUMO "CryptoNight-Heavy support" ON) option(WITH_HTTPD "HTTP REST API" ON) option(BUILD_STATIC "Build static binary" OFF) @@ -70,6 +71,7 @@ set(HEADERS_CRYPTO src/crypto/c_keccak.h src/crypto/c_skein.h src/crypto/CryptoNight.h + src/crypto/CryptoNight_constants.h src/crypto/CryptoNight_monero.h src/crypto/CryptoNight_test.h src/crypto/groestl_tables.h @@ -203,6 +205,10 @@ if (NOT WITH_AEON) add_definitions(/DXMRIG_NO_AEON) endif() +if (NOT WITH_SUMO) + add_definitions(/DXMRIG_NO_SUMO) +endif() + if (WITH_HTTPD) find_package(MHD) diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index f7dc1a378..d817c1522 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -41,13 +41,13 @@ void (*cryptonight_hash_ctx)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, int variant) = nullptr; -#define CRYPTONIGHT_HASH(NAME, ITERATIONS, MEM, MASK, SOFT_AES) \ +#define CRYPTONIGHT_HASH(NAME, ALGO, SOFT_AES) \ switch (variant) { \ case xmrig::VARIANT_V1: \ - return cryptonight_##NAME##_hash(input, size, output, ctx); \ + return cryptonight_##NAME##_hash(input, size, output, ctx); \ \ case xmrig::VARIANT_NONE: \ - return cryptonight_##NAME##_hash(input, size, output, ctx); \ + return cryptonight_##NAME##_hash(input, size, output, ctx); \ \ default: \ break; \ @@ -56,50 +56,50 @@ void (*cryptonight_hash_ctx)(const uint8_t *input, size_t size, uint8_t *output, 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, MONERO_ITER, MONERO_MEMORY, MONERO_MASK, false) + 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, MONERO_ITER, MONERO_MEMORY, MONERO_MASK, false) + 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, MONERO_ITER, MONERO_MEMORY, MONERO_MASK, true) + 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, MONERO_ITER, MONERO_MEMORY, MONERO_MASK, true) + 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, AEON_ITER, AEON_MEMORY, AEON_MASK, false) + 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, AEON_ITER, AEON_MEMORY, AEON_MASK, false) + 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, AEON_ITER, AEON_MEMORY, AEON_MASK, true) + 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, AEON_ITER, AEON_MEMORY, AEON_MASK, true) + 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) = { diff --git a/src/crypto/CryptoNight_constants.h b/src/crypto/CryptoNight_constants.h new file mode 100644 index 000000000..5d02baf9b --- /dev/null +++ b/src/crypto/CryptoNight_constants.h @@ -0,0 +1,117 @@ +/* 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 . + */ + +#ifndef __CRYPTONIGHT_CONSTANTS_H__ +#define __CRYPTONIGHT_CONSTANTS_H__ + + +#include + + +#include "xmrig.h" + + +namespace xmrig +{ + +constexpr const size_t CRYPTONIGHT_MEMORY = 2 * 1024 * 1024; +constexpr const uint32_t CRYPTONIGHT_MASK = 0x1FFFF0; +constexpr const uint32_t CRYPTONIGHT_ITER = 0x80000; + +constexpr const size_t CRYPTONIGHT_LITE_MEMORY = 1 * 1024 * 1024; +constexpr const uint32_t CRYPTONIGHT_LITE_MASK = 0xFFFF0; +constexpr const uint32_t CRYPTONIGHT_LITE_ITER = 0x40000; + +constexpr const size_t CRYPTONIGHT_HEAVY_MEMORY = 4 * 1024 * 1024; +constexpr const uint32_t CRYPTONIGHT_HEAVY_MASK = 0x3FFFF0; +constexpr const uint32_t CRYPTONIGHT_HEAVY_ITER = 0x40000; + + +template inline constexpr size_t cn_select_memory() { return 0; } +template<> inline constexpr size_t cn_select_memory() { return CRYPTONIGHT_MEMORY; } +template<> inline constexpr size_t cn_select_memory() { return CRYPTONIGHT_LITE_MEMORY; } +template<> inline constexpr size_t cn_select_memory() { return CRYPTONIGHT_HEAVY_MEMORY; } + +inline size_t cn_select_memory(Algo algorithm) +{ + switch(algorithm) + { + case CRYPTONIGHT: + return CRYPTONIGHT_MEMORY; + + case CRYPTONIGHT_LITE: + return CRYPTONIGHT_LITE_MEMORY; + + case CRYPTONIGHT_HEAVY: + return CRYPTONIGHT_HEAVY_MEMORY; + } +} + + +template inline constexpr uint32_t cn_select_mask() { return 0; } +template<> inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_MASK; } +template<> inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_LITE_MASK; } +template<> inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_HEAVY_MASK; } + +inline uint32_t cn_select_mask(Algo algorithm) +{ + switch(algorithm) + { + case CRYPTONIGHT: + return CRYPTONIGHT_MASK; + + case CRYPTONIGHT_LITE: + return CRYPTONIGHT_LITE_MASK; + + case CRYPTONIGHT_HEAVY: + return CRYPTONIGHT_HEAVY_MASK; + } +} + + +template inline constexpr uint32_t cn_select_iter() { return 0; } +template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; } +template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_LITE_ITER; } +template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HEAVY_ITER; } + +inline uint32_t cn_select_iter(Algo algorithm) +{ + switch(algorithm) + { + case CRYPTONIGHT: + return CRYPTONIGHT_ITER; + + case CRYPTONIGHT_LITE: + return CRYPTONIGHT_LITE_ITER; + + case CRYPTONIGHT_HEAVY: + return CRYPTONIGHT_HEAVY_ITER; + } +} + + +} /* namespace xmrig */ + + +#endif /* __CRYPTONIGHT_CONSTANTS_H__ */ diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index b7544dcc0..768b2a5bf 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -35,6 +35,7 @@ #include "crypto/CryptoNight.h" +#include "crypto/CryptoNight_constants.h" #include "crypto/CryptoNight_monero.h" #include "crypto/soft_aes.h" @@ -309,9 +310,13 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) } -template +template inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx *__restrict__ ctx) { + constexpr size_t MASK = xmrig::cn_select_mask(); + constexpr size_t ITERATIONS = xmrig::cn_select_iter(); + constexpr size_t MEM = xmrig::cn_select_memory(); + keccak(input, (int) size, ctx->state0, 200); VARIANT1_INIT(0); @@ -367,9 +372,13 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si } -template +template inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) { + constexpr size_t MASK = xmrig::cn_select_mask(); + constexpr size_t ITERATIONS = xmrig::cn_select_iter(); + constexpr size_t MEM = xmrig::cn_select_memory(); + keccak(input, (int) size, ctx->state0, 200); keccak(input + size, (int) size, ctx->state1, 200); @@ -464,4 +473,22 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, output + 32); } + +template +inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +{ +} + + +template +inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +{ +} + + +template +inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +{ +} + #endif /* __CRYPTONIGHT_X86_H__ */ diff --git a/src/net/Job.cpp b/src/net/Job.cpp index e57143767..17d8266f9 100644 --- a/src/net/Job.cpp +++ b/src/net/Job.cpp @@ -23,6 +23,7 @@ */ +#include #include @@ -62,11 +63,11 @@ Job::Job() : m_algo(xmrig::CRYPTONIGHT), m_poolId(-2), m_threadId(-1), - m_variant(xmrig::VARIANT_AUTO), m_size(0), m_diff(0), m_target(0), - m_blob() + m_blob(), + m_variant(xmrig::VARIANT_AUTO) { } @@ -77,12 +78,12 @@ Job::Job(int poolId, bool nicehash, int algo, int variant) : m_algo(algo), m_poolId(poolId), m_threadId(-1), - m_variant(variant), m_size(0), m_diff(0), m_target(0), m_blob() { + setVariant(variant); } @@ -174,10 +175,12 @@ void Job::setVariant(int variant) case xmrig::VARIANT_AUTO: case xmrig::VARIANT_NONE: case xmrig::VARIANT_V1: - m_variant = variant; + m_variant = static_cast(variant); break; default: + assert(false); + m_variant = xmrig::VARIANT_AUTO; break; } } diff --git a/src/net/Job.h b/src/net/Job.h index b8b9d6bcd..e89643140 100644 --- a/src/net/Job.h +++ b/src/net/Job.h @@ -55,7 +55,6 @@ public: inline const xmrig::Id &id() const { return m_id; } inline int poolId() const { return m_poolId; } inline int threadId() const { return m_threadId; } - inline int variant() const { return (m_variant == xmrig::VARIANT_AUTO ? (m_blob[0] > 6 ? 1 : 0) : m_variant); } inline size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } inline uint32_t diff() const { return (uint32_t) m_diff; } @@ -63,6 +62,7 @@ public: inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } inline void setPoolId(int poolId) { m_poolId = poolId; } inline void setThreadId(int threadId) { m_threadId = threadId; } + inline xmrig::Variant variant() const { return (m_variant == xmrig::VARIANT_AUTO ? (m_blob[0] > 6 ? xmrig::VARIANT_V1 : xmrig::VARIANT_NONE) : m_variant); } static bool fromHex(const char* in, unsigned int len, unsigned char* out); static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast(blob + 39); } @@ -78,12 +78,12 @@ private: int m_algo; int m_poolId; int m_threadId; - int m_variant; size_t m_size; uint64_t m_diff; uint64_t m_target; uint8_t m_blob[96]; // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. xmrig::Id m_id; + xmrig::Variant m_variant; }; #endif /* __JOB_H__ */ diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index 91e98a149..b8be966ff 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -29,6 +29,13 @@ #include "workers/CpuThread.h" +#if defined(XMRIG_ARM) +# include "crypto/CryptoNight_arm.h" +#else +# include "crypto/CryptoNight_x86.h" +#endif + + xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch) : m_algorithm(algorithm), m_av(av), @@ -47,6 +54,86 @@ xmrig::CpuThread::~CpuThread() } +xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant av, Variant variant) +{ + assert(variant == VARIANT_NONE || variant == VARIANT_V1); + + static const cn_hash_fun func_table[50] = { + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, + + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, + +# ifndef XMRIG_NO_AEON + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, + + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, +# else + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, +# endif + +# ifndef XMRIG_NO_SUMO + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_single_hash, + cryptonight_double_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, + cryptonight_triple_hash, + cryptonight_quad_hash, + cryptonight_penta_hash, +# else + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, +# endif + }; + +# ifndef XMRIG_NO_SUMO + if (algorithm == CRYPTONIGHT_HEAVY) { + variant = VARIANT_NONE; + } +# endif + + return func_table[20 * algorithm + 10 * variant + av - 1]; +} + + xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority) { assert(av > AV_AUTO && av < AV_MAX); diff --git a/src/workers/CpuThread.h b/src/workers/CpuThread.h index ee0a3d575..aef73719c 100644 --- a/src/workers/CpuThread.h +++ b/src/workers/CpuThread.h @@ -29,6 +29,9 @@ #include "xmrig.h" +struct cryptonight_ctx; + + namespace xmrig { @@ -46,17 +49,21 @@ public: CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch); ~CpuThread(); + typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx); + + static cn_hash_fun fn(Algo algorithm, AlgoVariant av, Variant variant); static CpuThread *createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority); - inline bool isPrefetch() const { return m_prefetch; } - inline bool isSoftAES() const { return m_softAES; } + inline bool isPrefetch() const { return m_prefetch; } + inline bool isSoftAES() const { return m_softAES; } + inline cn_hash_fun fn(Variant variant) const { return fn(m_algorithm, m_av, variant); } - inline Algo algorithm() const override { return m_algorithm; } - inline int multiway() const override { return m_multiway; } - inline int priority() const override { return m_priority; } - inline int64_t affinity() const override { return m_affinity; } - inline size_t index() const override { return m_index; } - inline Type type() const override { return CPU; } + inline Algo algorithm() const override { return m_algorithm; } + inline int multiway() const override { return m_multiway; } + inline int priority() const override { return m_priority; } + inline int64_t affinity() const override { return m_affinity; } + inline size_t index() const override { return m_index; } + inline Type type() const override { return CPU; } # ifndef XMRIG_NO_API rapidjson::Value toAPI(rapidjson::Document &doc) const override; diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp index 9d47d947e..6df44d9d0 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/SingleWorker.cpp @@ -26,7 +26,7 @@ #include -#include "crypto/CryptoNight.h" +#include "workers/CpuThread.h" #include "workers/SingleWorker.h" #include "workers/Workers.h" @@ -61,7 +61,8 @@ void SingleWorker::start() m_count++; *m_job.nonce() = ++m_result.nonce; - if (CryptoNight::hash(m_job, m_result, m_ctx)) { + m_thread->fn(m_job.variant())(m_job.blob(), m_job.size(), m_result.result, m_ctx); + if (*reinterpret_cast(m_result.result + 24) < m_job.target()) { Workers::submit(m_result); } diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index 648bf7edb..2672f49f6 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -27,6 +27,7 @@ #include "Cpu.h" #include "Mem.h" #include "Platform.h" +#include "workers/CpuThread.h" #include "workers/Handle.h" #include "workers/Worker.h" @@ -37,7 +38,8 @@ Worker::Worker(Handle *handle) : m_hashCount(0), m_timestamp(0), m_count(0), - m_sequence(0) + m_sequence(0), + m_thread(static_cast(handle->config())) { // if (Cpu::threads() > 1 && handle->affinity() != -1L) { // Cpu::setAffinity(m_id, handle->affinity()); diff --git a/src/workers/Worker.h b/src/workers/Worker.h index a9c15ef40..cb52c1492 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -36,6 +36,11 @@ struct cryptonight_ctx; class Handle; +namespace xmrig { + class CpuThread; +} + + class Worker : public IWorker { public: @@ -55,6 +60,7 @@ protected: std::atomic m_timestamp; uint64_t m_count; uint64_t m_sequence; + xmrig::CpuThread *m_thread; }; diff --git a/src/xmrig.h b/src/xmrig.h index eba72bb4e..f4ae81620 100644 --- a/src/xmrig.h +++ b/src/xmrig.h @@ -63,7 +63,7 @@ enum Variant { }; -} /* xmrig */ +} /* namespace xmrig */ #endif /* __XMRIG_H__ */ From c1bc6acd26045f5ec3382832a841733c3262c9e5 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 03:01:04 +0700 Subject: [PATCH 05/13] Fix DoubleWorker. --- src/workers/DoubleWorker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index 3dba4a9fb..7bde7df94 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -26,7 +26,7 @@ #include -#include "crypto/CryptoNight.h" +#include "workers/CpuThread.h" #include "workers/DoubleWorker.h" #include "workers/Workers.h" @@ -86,7 +86,7 @@ void DoubleWorker::start() *Job::nonce(m_state->blob) = ++m_state->nonce1; *Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2; - CryptoNight::hash(m_state->blob, m_state->job.size(), m_hash, m_ctx, m_state->job.variant()); + m_thread->fn(m_state->job.variant())(m_state->blob, m_state->job.size(), m_hash, m_ctx); if (*reinterpret_cast(m_hash + 24) < m_state->job.target()) { Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff())); From d7c56305094902818b47ac7714b2296d7f3e24c2 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 03:27:44 +0700 Subject: [PATCH 06/13] Fix nonce allocation in DoubleWorker. --- src/App.cpp | 2 +- src/Mem_unix.cpp | 2 +- src/workers/DoubleWorker.cpp | 4 ++-- src/workers/Handle.cpp | 3 ++- src/workers/Handle.h | 4 +++- src/workers/Worker.cpp | 1 + src/workers/Worker.h | 1 + src/workers/Workers.cpp | 4 ++-- src/workers/Workers.h | 2 +- 9 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/App.cpp b/src/App.cpp index a9d107743..8c7a16eac 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -136,7 +136,7 @@ int App::exec() m_httpd->start(); # endif - Workers::start(m_controller->config()->affinity(), m_controller->config()->priority(), m_controller); + Workers::start(m_controller); m_controller->network()->connect(); diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index 3b69f2679..7978d241f 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -46,7 +46,7 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) m_threads = threads; m_doubleHash = doubleHash; - const int ratio = (doubleHash && algo != xmrig::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; + const int ratio = (doubleHash && algo != xmrig::CRYPTONIGHT_LITE) ? 2 : 1; m_size = MONERO_MEMORY * (threads * ratio + 1); if (!enabled) { diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index 7bde7df94..8971f0c0a 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -135,11 +135,11 @@ void DoubleWorker::consumeJob() if (m_state->job.isNicehash()) { m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / m_totalWays * m_id); - m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / m_totalWays * (m_id + m_totalWays)); + m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / m_totalWays * (m_id + m_totalThreads)); } else { m_state->nonce1 = 0xffffffffU / m_totalWays * m_id; - m_state->nonce2 = 0xffffffffU / m_totalWays * (m_id + m_totalWays); + m_state->nonce2 = 0xffffffffU / m_totalWays * (m_id + m_totalThreads); } } diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp index 6d7b969a3..29f57fb25 100644 --- a/src/workers/Handle.cpp +++ b/src/workers/Handle.cpp @@ -25,8 +25,9 @@ #include "workers/Handle.h" -Handle::Handle(xmrig::IThread *config, size_t totalWays) : +Handle::Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays) : m_worker(nullptr), + m_totalThreads(totalThreads), m_totalWays(totalWays), m_config(config) { diff --git a/src/workers/Handle.h b/src/workers/Handle.h index d63dc0988..b3a7c76f7 100644 --- a/src/workers/Handle.h +++ b/src/workers/Handle.h @@ -38,18 +38,20 @@ class IWorker; class Handle { public: - Handle(xmrig::IThread *config, size_t totalWays); + Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays); void join(); void start(void (*callback) (void *)); inline IWorker *worker() const { return m_worker; } inline size_t threadId() const { return m_config->index(); } + inline size_t totalThreads() const { return m_totalThreads; } inline size_t totalWays() const { return m_totalWays; } inline void setWorker(IWorker *worker) { m_worker = worker; } inline xmrig::IThread *config() const { return m_config; } private: IWorker *m_worker; + size_t m_totalThreads; size_t m_totalWays; uv_thread_t m_thread; xmrig::IThread *m_config; diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index 2672f49f6..bf4f62da7 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -34,6 +34,7 @@ Worker::Worker(Handle *handle) : m_id(handle->threadId()), + m_totalThreads(handle->totalThreads()), m_totalWays(handle->totalWays()), m_hashCount(0), m_timestamp(0), diff --git a/src/workers/Worker.h b/src/workers/Worker.h index cb52c1492..9fbce1a24 100644 --- a/src/workers/Worker.h +++ b/src/workers/Worker.h @@ -55,6 +55,7 @@ protected: cryptonight_ctx *m_ctx; size_t m_id; + size_t m_totalThreads; size_t m_totalWays; std::atomic m_hashCount; std::atomic m_timestamp; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index faa207a0a..8ac256da3 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -107,7 +107,7 @@ void Workers::setJob(const Job &job, bool donate) } -void Workers::start(int64_t affinity, int priority, xmrig::Controller *controller) +void Workers::start(xmrig::Controller *controller) { const std::vector &threads = controller->config()->threads(); @@ -129,7 +129,7 @@ void Workers::start(int64_t affinity, int priority, xmrig::Controller *controlle uv_timer_start(&m_timer, Workers::onTick, 500, 500); for (xmrig::IThread *thread : threads) { - Handle *handle = new Handle(thread, totalWays); + Handle *handle = new Handle(thread, threads.size(), totalWays); m_workers.push_back(handle); handle->start(Workers::onReady); } diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 942a5b58a..ecec9e302 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -51,7 +51,7 @@ public: static void printHashrate(bool detail); static void setEnabled(bool enabled); static void setJob(const Job &job, bool donate); - static void start(int64_t affinity, int priority, xmrig::Controller *controller); + static void start(xmrig::Controller *controller); static void stop(); static void submit(const JobResult &result); From 5c6ec587ac8020e8a84538105dab7226c415666c Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 14:51:05 +0700 Subject: [PATCH 07/13] 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 5e2ac1907..106ab30fe 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 8c7a16eac..dc22836df 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 d817c1522..000000000 --- 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 eb17719ed..d0d61ae3b 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 b9b6eb0a0..a90abe11c 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 8971f0c0a..425dd0c2f 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 57be59d05..e8847282b 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 6df44d9d0..2ff356c88 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 f7d9cff88..061f50848 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 9fbce1a24..88f6ee424 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 8ac256da3..00941c7be 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); + } } From 7d5a97137d5804d16c1c6697c3b427859cbd241d Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 16:08:15 +0700 Subject: [PATCH 08/13] Fix autoconfig and memory allocation for heavy algo. --- src/Cpu.cpp | 19 +++++++++++++++---- src/Cpu.h | 9 ++++++--- src/Mem.cpp | 9 ++++++--- src/Mem.h | 5 ++++- src/Mem_unix.cpp | 6 +++++- src/Mem_win.cpp | 6 +++++- src/workers/SingleWorker.cpp | 2 +- 7 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/Cpu.cpp b/src/Cpu.cpp index eba993b37..f8fb092ca 100644 --- a/src/Cpu.cpp +++ b/src/Cpu.cpp @@ -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 @@ -39,7 +39,7 @@ int Cpu::m_totalCores = 0; int Cpu::m_totalThreads = 0; -int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) +int Cpu::optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage) { if (m_totalThreads == 1) { return 1; @@ -54,7 +54,18 @@ int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) } int count = 0; - const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1); + int size = 2048; + + if (algo == xmrig::CRYPTONIGHT_LITE) { + size = 1024; + } + else if (algo == xmrig::CRYPTONIGHT_HEAVY) { + size = 4096; + } + + if (doubleHash) { + size *= 2; + } if (cache) { count = cache / size; diff --git a/src/Cpu.h b/src/Cpu.h index 9444274d2..118c7b7d3 100644 --- a/src/Cpu.h +++ b/src/Cpu.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 @@ -28,6 +28,9 @@ #include +#include "xmrig.h" + + class Cpu { public: @@ -37,7 +40,7 @@ public: BMI2 = 4 }; - static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage); + static int optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage); static void init(); static void setAffinity(int id, uint64_t mask); diff --git a/src/Mem.cpp b/src/Mem.cpp index f5da7865c..9de79dbd5 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -27,8 +27,8 @@ #include "crypto/CryptoNight.h" +#include "crypto/CryptoNight_constants.h" #include "Mem.h" -#include "xmrig.h" bool Mem::m_doubleHash = false; @@ -48,10 +48,13 @@ cryptonight_ctx *Mem::create(int threadId) } # endif - cryptonight_ctx *ctx = reinterpret_cast(&m_memory[MONERO_MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]); + const size_t size = m_algo == xmrig::CRYPTONIGHT_HEAVY ? xmrig::cn_select_memory() + : xmrig::cn_select_memory(); + + cryptonight_ctx *ctx = reinterpret_cast(&m_memory[size - sizeof(cryptonight_ctx) * (threadId + 1)]); const int ratio = m_doubleHash ? 2 : 1; - ctx->memory = &m_memory[MONERO_MEMORY * (threadId * ratio + 1)]; + ctx->memory = &m_memory[size * (threadId * ratio + 1)]; return ctx; } diff --git a/src/Mem.h b/src/Mem.h index 18914d688..73947b42d 100644 --- a/src/Mem.h +++ b/src/Mem.h @@ -30,6 +30,9 @@ #include +#include "xmrig.h" + + struct cryptonight_ctx; @@ -42,7 +45,7 @@ public: Lock = 4 }; - static bool allocate(int algo, int threads, bool doubleHash, bool enabled); + static bool allocate(xmrig::Algo algo, int threads, bool doubleHash, bool enabled); static cryptonight_ctx *create(int threadId); static void *calloc(size_t num, size_t size); static void release(); diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index 7978d241f..0dd833d7f 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -40,7 +40,7 @@ #include "xmrig.h" -bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) +bool Mem::allocate(xmrig::Algo algo, int threads, bool doubleHash, bool enabled) { m_algo = algo; m_threads = threads; @@ -49,6 +49,10 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) const int ratio = (doubleHash && algo != xmrig::CRYPTONIGHT_LITE) ? 2 : 1; m_size = MONERO_MEMORY * (threads * ratio + 1); + if (algo == xmrig::CRYPTONIGHT_HEAVY) { + m_size *= 2; + } + if (!enabled) { m_memory = static_cast(_mm_malloc(m_size, 16)); return true; diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index 6cc0a6eee..ec30e3e82 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -145,7 +145,7 @@ static BOOL TrySetLockPagesPrivilege() { } -bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) +bool Mem::allocate(xmrig::Algo algo, int threads, bool doubleHash, bool enabled) { m_algo = algo; m_threads = threads; @@ -154,6 +154,10 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) const int ratio = (doubleHash && algo != xmrig::CRYPTONIGHT_LITE) ? 2 : 1; m_size = MONERO_MEMORY * (threads * ratio + 1); + if (algo == xmrig::CRYPTONIGHT_HEAVY) { + m_size *= 2; + } + if (!enabled) { m_memory = static_cast(_mm_malloc(m_size, 16)); return true; diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp index 2ff356c88..5757ef77e 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/SingleWorker.cpp @@ -116,7 +116,7 @@ bool SingleWorker::selfTest() } # endif - return false; + return true; } From dd6bc339bf04cf3dfbd2806ef4891e4f9cc05566 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 16:55:41 +0700 Subject: [PATCH 09/13] First working cryptonight-heavy. --- src/crypto/CryptoNight_x86.h | 129 ++++++++++++++++++++++++-- src/net/strategies/DonateStrategy.cpp | 4 + src/workers/DoubleWorker.cpp | 2 +- 3 files changed, 126 insertions(+), 9 deletions(-) diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 768b2a5bf..414a1f7fb 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -218,7 +218,21 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, } -template +inline void mix_and_propagate(__m128i& x0, __m128i& x1, __m128i& x2, __m128i& x3, __m128i& x4, __m128i& x5, __m128i& x6, __m128i& x7) +{ + __m128i tmp0 = x0; + x0 = _mm_xor_si128(x0, x1); + x1 = _mm_xor_si128(x1, x2); + x2 = _mm_xor_si128(x2, x3); + x3 = _mm_xor_si128(x3, x4); + x4 = _mm_xor_si128(x4, x5); + x5 = _mm_xor_si128(x5, x6); + x6 = _mm_xor_si128(x6, x7); + x7 = _mm_xor_si128(x7, tmp0); +} + + +template static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) { __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7; @@ -235,6 +249,23 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) xin6 = _mm_load_si128(input + 10); xin7 = _mm_load_si128(input + 11); + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + for (size_t i = 0; i < 16; i++) { + aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + + mix_and_propagate(xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7); + } + } + for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) { aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); @@ -259,7 +290,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) } -template +template static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) { __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; @@ -297,6 +328,51 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7); + } + } + + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) { + xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0); + xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1); + xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2); + xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3); + xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4); + xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5); + xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6); + xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7); + + aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + + mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7); + } + + for (size_t i = 0; i < 16; i++) { + aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + + mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7); + } } _mm_store_si128(output + 4, xout0); @@ -317,11 +393,16 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + if (VARIANT > 0 && size < 43) { + memset(output, 0, 32); + return; + } + keccak(input, (int) size, ctx->state0, 200); VARIANT1_INIT(0); - cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); + cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); const uint8_t* l0 = ctx->memory; uint64_t* h0 = reinterpret_cast(ctx->state0); @@ -363,9 +444,18 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si ah0 ^= ch; al0 ^= cl; idx0 = al0; + + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; + int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; + int64_t q = n / (d | 0x5); + + ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; + idx0 = d ^ q; + } } - cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0); + cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0); keccakf(h0, 24); extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output); @@ -379,6 +469,11 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + if (VARIANT > 0 && size < 43) { + memset(output, 0, 64); + return; + } + keccak(input, (int) size, ctx->state0, 200); keccak(input + size, (int) size, ctx->state1, 200); @@ -390,8 +485,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si uint64_t* h0 = reinterpret_cast(ctx->state0); uint64_t* h1 = reinterpret_cast(ctx->state1); - cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); - cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); uint64_t al0 = h0[0] ^ h0[4]; uint64_t al1 = h1[0] ^ h1[4]; @@ -446,6 +541,15 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si al0 ^= cl; idx0 = al0; + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; + int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; + int64_t q = n / (d | 0x5); + + ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; + idx0 = d ^ q; + } + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; ch = ((uint64_t*) &l1[idx1 & MASK])[1]; lo = __umul128(idx1, cl, &hi); @@ -461,10 +565,19 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ah1 ^= ch; al1 ^= cl; idx1 = al1; + + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + int64_t n = ((int64_t*)&l1[idx1 & MASK])[0]; + int32_t d = ((int32_t*)&l1[idx1 & MASK])[2]; + int64_t q = n / (d | 0x5); + + ((int64_t*)&l1[idx1 & MASK])[0] = n ^ q; + idx1 = d ^ q; + } } - cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); - cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); keccakf(h0, 24); keccakf(h1, 24); diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 495038207..6e7da0c4c 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -64,6 +64,10 @@ DonateStrategy::DonateStrategy(int level, const char *user, int algo, IStrategyL m_pools.push_back(new Url(kDonatePool1, 80, userId, nullptr, false, true)); m_pools.push_back(new Url(kDonatePool2, 5555, "48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD", "emergency", false, false)); } + else if (algo == xmrig::CRYPTONIGHT_HEAVY) { + m_pools.push_back(new Url(kDonatePool1, 8888, userId, nullptr, false, true)); + m_pools.push_back(new Url(kDonatePool1, 8889, userId, nullptr, false, true)); + } else { m_pools.push_back(new Url(kDonatePool1, 5555, userId, nullptr, false, true)); m_pools.push_back(new Url(kDonatePool1, 7777, userId, nullptr, false, true)); diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index 425dd0c2f..273f1555c 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -144,7 +144,7 @@ bool DoubleWorker::selfTest() } # endif - return false; + return true; } From d4123b8fa67d8e7709c1caa18b626a0ddf8db9c0 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 17:06:03 +0700 Subject: [PATCH 10/13] Quick fix, temporary use old style affinity. --- src/workers/Handle.cpp | 3 ++- src/workers/Handle.h | 4 +++- src/workers/Worker.cpp | 6 +++--- src/workers/Workers.cpp | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/workers/Handle.cpp b/src/workers/Handle.cpp index 29f57fb25..01d032e9b 100644 --- a/src/workers/Handle.cpp +++ b/src/workers/Handle.cpp @@ -25,7 +25,8 @@ #include "workers/Handle.h" -Handle::Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays) : +Handle::Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays, int64_t affinity) : + m_affinity(affinity), m_worker(nullptr), m_totalThreads(totalThreads), m_totalWays(totalWays), diff --git a/src/workers/Handle.h b/src/workers/Handle.h index b3a7c76f7..8a64922a5 100644 --- a/src/workers/Handle.h +++ b/src/workers/Handle.h @@ -38,10 +38,11 @@ class IWorker; class Handle { public: - Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays); + Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays, int64_t affinity); void join(); void start(void (*callback) (void *)); + inline int64_t affinity() const { return m_affinity; } inline IWorker *worker() const { return m_worker; } inline size_t threadId() const { return m_config->index(); } inline size_t totalThreads() const { return m_totalThreads; } @@ -50,6 +51,7 @@ public: inline xmrig::IThread *config() const { return m_config; } private: + int64_t m_affinity; IWorker *m_worker; size_t m_totalThreads; size_t m_totalWays; diff --git a/src/workers/Worker.cpp b/src/workers/Worker.cpp index bf4f62da7..f9162e3f6 100644 --- a/src/workers/Worker.cpp +++ b/src/workers/Worker.cpp @@ -42,9 +42,9 @@ Worker::Worker(Handle *handle) : m_sequence(0), m_thread(static_cast(handle->config())) { -// if (Cpu::threads() > 1 && handle->affinity() != -1L) { -// Cpu::setAffinity(m_id, handle->affinity()); -// } + if (Cpu::threads() > 1 && handle->affinity() != -1L) { + Cpu::setAffinity(m_id, handle->affinity()); + } Platform::setThreadPriority(handle->config()->priority()); m_ctx = Mem::create(m_id); diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 00941c7be..38965d8ad 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -130,7 +130,7 @@ void Workers::start(xmrig::Controller *controller) uv_timer_start(&m_timer, Workers::onTick, 500, 500); for (xmrig::IThread *thread : threads) { - Handle *handle = new Handle(thread, threads.size(), totalWays); + Handle *handle = new Handle(thread, threads.size(), totalWays, controller->config()->affinity()); m_workers.push_back(handle); handle->start(Workers::onReady); } From 26e1b1402024c673ad689d0e60221a39e6b45256 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 17:19:01 +0700 Subject: [PATCH 11/13] Added test hashes for self test. --- src/crypto/CryptoNight_test.h | 12 +++++++++++- src/workers/DoubleWorker.cpp | 2 +- src/workers/SingleWorker.cpp | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/crypto/CryptoNight_test.h b/src/crypto/CryptoNight_test.h index 0f7feda11..5717f1d35 100644 --- a/src/crypto/CryptoNight_test.h +++ b/src/crypto/CryptoNight_test.h @@ -66,7 +66,7 @@ const static uint8_t test_output_v0_lite[64] = { }; -// AEON v2 +// AEON v7 const static uint8_t test_output_v1_lite[64] = { 0x87, 0xC4, 0xE5, 0x70, 0x65, 0x3E, 0xB4, 0xC2, 0xB4, 0x2B, 0x7A, 0x0D, 0x54, 0x65, 0x59, 0x45, 0x2D, 0xFA, 0xB5, 0x73, 0xB8, 0x2E, 0xC5, 0x2F, 0x15, 0x2B, 0x7F, 0xF9, 0x8E, 0x79, 0x44, 0x6F, @@ -76,4 +76,14 @@ const static uint8_t test_output_v1_lite[64] = { #endif +#ifndef XMRIG_NO_SUMO +const static uint8_t test_output_heavy[64] = { + 0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A, + 0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D, + 0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64, + 0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2 +}; +#endif + + #endif /* __CRYPTONIGHT_TEST_H__ */ diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index 273f1555c..a61767431 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -144,7 +144,7 @@ bool DoubleWorker::selfTest() } # endif - return true; + return memcmp(m_hash, test_output_heavy, 64) == 0; } diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp index 5757ef77e..2d428fcbf 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/SingleWorker.cpp @@ -116,7 +116,7 @@ bool SingleWorker::selfTest() } # endif - return true; + return memcmp(m_result.result, test_output_heavy, 32) == 0; } From 4e8ef7c6ed05eb778ce6799ed674c1429659e9d7 Mon Sep 17 00:00:00 2001 From: XMRig Date: Tue, 3 Apr 2018 17:51:06 +0700 Subject: [PATCH 12/13] Added cryptonight-heavy support for ARM --- src/Cpu_arm.cpp | 2 +- src/crypto/CryptoNight_arm.h | 211 +++++++++++++++++++++++++++++++++-- 2 files changed, 202 insertions(+), 11 deletions(-) diff --git a/src/Cpu_arm.cpp b/src/Cpu_arm.cpp index c2047ffbb..1b3067894 100644 --- a/src/Cpu_arm.cpp +++ b/src/Cpu_arm.cpp @@ -37,7 +37,7 @@ int Cpu::m_totalCores = 0; int Cpu::m_totalThreads = 0; -int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) +int Cpu::optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage) { return m_totalThreads; } diff --git a/src/crypto/CryptoNight_arm.h b/src/crypto/CryptoNight_arm.h index 18408536c..fd8b58fff 100644 --- a/src/crypto/CryptoNight_arm.h +++ b/src/crypto/CryptoNight_arm.h @@ -35,6 +35,7 @@ #include "crypto/CryptoNight.h" +#include "crypto/CryptoNight_constants.h" #include "crypto/CryptoNight_monero.h" #include "crypto/soft_aes.h" @@ -206,7 +207,21 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, } -template +inline void mix_and_propagate(__m128i& x0, __m128i& x1, __m128i& x2, __m128i& x3, __m128i& x4, __m128i& x5, __m128i& x6, __m128i& x7) +{ + __m128i tmp0 = x0; + x0 = _mm_xor_si128(x0, x1); + x1 = _mm_xor_si128(x1, x2); + x2 = _mm_xor_si128(x2, x3); + x3 = _mm_xor_si128(x3, x4); + x4 = _mm_xor_si128(x4, x5); + x5 = _mm_xor_si128(x5, x6); + x6 = _mm_xor_si128(x6, x7); + x7 = _mm_xor_si128(x7, tmp0); +} + + +template static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) { __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7; @@ -223,6 +238,40 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) xin6 = _mm_load_si128(input + 10); xin7 = _mm_load_si128(input + 11); + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + for (size_t i = 0; i < 16; i++) { + if (!SOFT_AES) { + aes_round(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + } + + aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + + if (!SOFT_AES) { + xin0 ^= k9; + xin1 ^= k9; + xin2 ^= k9; + xin3 ^= k9; + xin4 ^= k9; + xin5 ^= k9; + xin6 ^= k9; + xin7 ^= k9; + } + else { + aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + } + + mix_and_propagate(xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7); + } + } + for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) { if (!SOFT_AES) { aes_round(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); @@ -264,7 +313,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) } -template +template static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) { __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; @@ -319,6 +368,85 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) else { aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); } + + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7); + } + } + + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) { + xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0); + xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1); + xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2); + xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3); + xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4); + xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5); + xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6); + xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7); + + if (!SOFT_AES) { + aes_round(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + } + + aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + + if (!SOFT_AES) { + xout0 ^= k9; + xout1 ^= k9; + xout2 ^= k9; + xout3 ^= k9; + xout4 ^= k9; + xout5 ^= k9; + xout6 ^= k9; + xout7 ^= k9; + } + else { + aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + } + + mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7); + } + + for (size_t i = 0; i < 16; i++) { + if (!SOFT_AES) { + aes_round(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + } + + aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + + if (!SOFT_AES) { + xout0 ^= k9; + xout1 ^= k9; + xout2 ^= k9; + xout3 ^= k9; + xout4 ^= k9; + xout5 ^= k9; + xout6 ^= k9; + xout7 ^= k9; + } + else { + aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + } + + mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7); + } } _mm_store_si128(output + 4, xout0); @@ -332,14 +460,23 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) } -template +template inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx *__restrict__ ctx) { + constexpr size_t MASK = xmrig::cn_select_mask(); + constexpr size_t ITERATIONS = xmrig::cn_select_iter(); + constexpr size_t MEM = xmrig::cn_select_memory(); + + if (VARIANT > 0 && size < 43) { + memset(output, 0, 32); + return; + } + keccak(input, (int) size, ctx->state0, 200); VARIANT1_INIT(0); - cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); + cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); const uint8_t* l0 = ctx->memory; uint64_t* h0 = reinterpret_cast(ctx->state0); @@ -384,18 +521,36 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si ah0 ^= ch; al0 ^= cl; idx0 = al0; + + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; + int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; + int64_t q = n / (d | 0x5); + + ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; + idx0 = d ^ q; + } } - cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0); + cn_implode_scratchpad((__m128i*) ctx->memory, (__m128i*) ctx->state0); keccakf(h0, 24); extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output); } -template +template inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) { + constexpr size_t MASK = xmrig::cn_select_mask(); + constexpr size_t ITERATIONS = xmrig::cn_select_iter(); + constexpr size_t MEM = xmrig::cn_select_memory(); + + if (VARIANT > 0 && size < 43) { + memset(output, 0, 64); + return; + } + keccak(input, (int) size, ctx->state0, 200); keccak(input + size, (int) size, ctx->state1, 200); @@ -407,8 +562,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si uint64_t* h0 = reinterpret_cast(ctx->state0); uint64_t* h1 = reinterpret_cast(ctx->state1); - cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); - cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); uint64_t al0 = h0[0] ^ h0[4]; uint64_t al1 = h1[0] ^ h1[4]; @@ -465,6 +620,15 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si al0 ^= cl; idx0 = al0; + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; + int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; + int64_t q = n / (d | 0x5); + + ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; + idx0 = d ^ q; + } + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; ch = ((uint64_t*) &l1[idx1 & MASK])[1]; lo = __umul128(idx1, cl, &hi); @@ -480,10 +644,19 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ah1 ^= ch; al1 ^= cl; idx1 = al1; + + if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + int64_t n = ((int64_t*)&l1[idx1 & MASK])[0]; + int32_t d = ((int32_t*)&l1[idx1 & MASK])[2]; + int64_t q = n / (d | 0x5); + + ((int64_t*)&l1[idx1 & MASK])[0] = n ^ q; + idx1 = d ^ q; + } } - cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); - cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); keccakf(h0, 24); keccakf(h1, 24); @@ -492,4 +665,22 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, output + 32); } + +template +inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +{ +} + + +template +inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +{ +} + + +template +inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +{ +} + #endif /* __CRYPTONIGHT_ARM_H__ */ From 6b710ff3b31e82f46995c83ce12a57793067b3e7 Mon Sep 17 00:00:00 2001 From: xmrig Date: Tue, 3 Apr 2018 18:12:24 +0700 Subject: [PATCH 13/13] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9f42d663..397d3b623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,10 @@ # v2.6.0-beta1 + - [#476](https://github.com/xmrig/xmrig/issues/476) **Added Cryptonight-Heavy support for Sumokoin ASIC resistance fork.** - HTTP server now runs in main loop, it make possible easy extend API without worry about thread synchronization. - Added initial graceful reload support, miner will reload configuration if config file changed, disabled by default until it will be fully implemented and tested. - Added API endpoint `PUT /1/config` to update current config. - Added API endpoint `GET /1/config` to get current active config. + - Added API endpoint `GET /1/threads` to get current active threads configuration. - API endpoint `GET /` now deprecated, use `GET /1/summary` instead. - Added `--api-no-ipv6` and similar config option to disable IPv6 support for HTTP API. - Added `--api-no-restricted` to enable full access to api, this option has no effect if `--api-access-token` not specified.