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__ */