From ac1b554282ae1cc8b432f6e625334300781920fc Mon Sep 17 00:00:00 2001 From: SChernykh Date: Sat, 15 Jun 2019 22:53:03 +0200 Subject: [PATCH] RandomWOW support --- CMakeLists.txt | 4 +- cmake/FindRandomWOW.cmake | 25 +++++++++++ src/base/net/stratum/Client.cpp | 8 ++++ src/base/net/stratum/DaemonClient.cpp | 2 + src/base/net/stratum/Job.cpp | 11 +++++ src/base/net/stratum/Job.h | 3 ++ src/base/net/stratum/Pool.cpp | 1 + src/common/crypto/Algorithm.cpp | 4 +- src/common/xmrig.h | 1 + src/workers/CpuThread.cpp | 8 ++++ src/workers/MultiWorker.cpp | 16 ++++++- src/workers/MultiWorker.h | 3 ++ src/workers/Workers.cpp | 64 +++++++++++++++++++++++++++ src/workers/Workers.h | 10 +++++ 14 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 cmake/FindRandomWOW.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c7098f37..8f6e9226 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,6 +154,7 @@ add_definitions(/DUNICODE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") find_package(UV REQUIRED) +find_package(RANDOMWOW REQUIRED) include(cmake/flags.cmake) @@ -219,6 +220,7 @@ endif() include_directories(src) include_directories(src/3rdparty) include_directories(${UV_INCLUDE_DIR}) +include_directories(${RANDOMWOW_INCLUDE_DIR}) if (BUILD_STATIC) set(CMAKE_EXE_LINKER_FLAGS " -static") @@ -229,4 +231,4 @@ if (WITH_DEBUG_LOG) endif() add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTP_SOURCES} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES} ${CN_GPU_SOURCES}) -target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) +target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${RANDOMWOW_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) diff --git a/cmake/FindRandomWOW.cmake b/cmake/FindRandomWOW.cmake new file mode 100644 index 00000000..c1db649f --- /dev/null +++ b/cmake/FindRandomWOW.cmake @@ -0,0 +1,25 @@ +find_path( + RANDOMWOW_INCLUDE_DIR + NAMES randomwow.h + PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS" + PATH_SUFFIXES "include" + NO_DEFAULT_PATH +) + +find_path(RANDOMWOW_INCLUDE_DIR NAMES randomwow.h) + +find_library( + RANDOMWOW_LIBRARY + NAMES librandomwow.a randomwow librandomwow + PATHS "${XMRIG_DEPS}" ENV "XMRIG_DEPS" + PATH_SUFFIXES "lib" + NO_DEFAULT_PATH +) + +find_library(RANDOMWOW_LIBRARY NAMES librandomwow.a randomwow librandomwow) + +set(RANDOMWOW_LIBRARIES ${RANDOMWOW_LIBRARY}) +set(RANDOMWOW_INCLUDE_DIRS ${RANDOMWOW_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(RANDOMWOW DEFAULT_MSG RANDOMWOW_LIBRARY RANDOMWOW_INCLUDE_DIR) diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 1d448ddf..4941ca3a 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -344,6 +344,14 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) } } + if (params.HasMember("seed_hash")) { + const rapidjson::Value &variant = params["seed_hash"]; + + if (variant.IsString()) { + job.setSeedHash(variant.GetString()); + } + } + if (params.HasMember("height")) { const rapidjson::Value &variant = params["height"]; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 769e2116..e63c3271 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -220,6 +220,8 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) return false; } + job.setSeedHash(Json::getString(params, "seed_hash")); + job.setHeight(Json::getUint64(params, kHeight)); job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 1f1cd413..36098bfe 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -42,6 +42,7 @@ xmrig::Job::Job() : m_diff(0), m_height(0), m_target(0), + m_seedHash(), m_blob() { } @@ -58,6 +59,7 @@ xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const Str m_diff(0), m_height(0), m_target(0), + m_seedHash(), m_blob() { } @@ -175,6 +177,15 @@ void xmrig::Job::setDiff(uint64_t diff) } +bool xmrig::Job::setSeedHash(const char *hash) +{ + if (!hash || (strlen(hash) != sizeof(m_seedHash) * 2)) + return false; + + return Buffer::fromHex(hash, sizeof(m_seedHash) * 2, m_seedHash); +} + + xmrig::Variant xmrig::Job::variant() const { switch (m_algorithm.algo()) { diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 16e9a861..1c1b078b 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -55,6 +55,7 @@ public: bool setTarget(const char *target); void setAlgorithm(const char *algo); void setDiff(uint64_t diff); + bool setSeedHash(const char *hash); inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return m_size > 0 && m_diff > 0; } @@ -64,6 +65,7 @@ public: inline const String &id() const { return m_id; } inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); } inline const uint8_t *blob() const { return m_blob; } + inline const uint8_t *seed_hash() const { return m_seedHash; } inline int poolId() const { return m_poolId; } inline int threadId() const { return m_threadId; } inline size_t size() const { return m_size; } @@ -106,6 +108,7 @@ private: uint64_t m_diff; uint64_t m_height; uint64_t m_target; + uint8_t m_seedHash[32]; uint8_t m_blob[kMaxBlobSize]; # ifdef XMRIG_PROXY_PROJECT diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index f441ba63..d3b4b4a3 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -517,6 +517,7 @@ void xmrig::Pool::rebuild() addVariant(VARIANT_RWZ); addVariant(VARIANT_ZLS); addVariant(VARIANT_DOUBLE); + addVariant(VARIANT_RX_WOW); addVariant(VARIANT_AUTO); # endif } diff --git a/src/common/crypto/Algorithm.cpp b/src/common/crypto/Algorithm.cpp index d9d3ead9..af139ae3 100644 --- a/src/common/crypto/Algorithm.cpp +++ b/src/common/crypto/Algorithm.cpp @@ -69,6 +69,7 @@ static AlgoData const algorithms[] = { { "cryptonight/rwz", "cn/rwz", xmrig::CRYPTONIGHT, xmrig::VARIANT_RWZ }, { "cryptonight/zls", "cn/zls", xmrig::CRYPTONIGHT, xmrig::VARIANT_ZLS }, { "cryptonight/double", "cn/double", xmrig::CRYPTONIGHT, xmrig::VARIANT_DOUBLE }, + { "randomx/wow", "rx/wow", xmrig::CRYPTONIGHT, xmrig::VARIANT_RX_WOW }, # ifndef XMRIG_NO_AEON { "cryptonight-lite", "cn-lite", xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_AUTO }, @@ -138,7 +139,8 @@ static const char *variants[] = { "r", "rwz", "zls", - "double" + "double", + "rx/wow", }; diff --git a/src/common/xmrig.h b/src/common/xmrig.h index e8ca8857..49a8d1f7 100644 --- a/src/common/xmrig.h +++ b/src/common/xmrig.h @@ -79,6 +79,7 @@ enum Variant { VARIANT_RWZ = 14, // CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft) VARIANT_ZLS = 15, // CryptoNight variant 2 with 3/4 iterations (Zelerius) VARIANT_DOUBLE = 16, // CryptoNight variant 2 with double iterations (X-CASH) + VARIANT_RX_WOW = 17, // RandomX (Wownero) VARIANT_MAX }; diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index 2481162c..3bce832e 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -390,6 +390,8 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a cryptonight_quad_hash, cryptonight_penta_hash, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW + # ifndef XMRIG_NO_AEON cryptonight_single_hash, cryptonight_double_hash, @@ -428,6 +430,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # else nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 @@ -446,6 +449,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # endif # ifndef XMRIG_NO_SUMO @@ -498,6 +502,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # else nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 @@ -516,6 +521,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # endif # ifndef XMRIG_NO_CN_PICO @@ -547,6 +553,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # else nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 @@ -565,6 +572,7 @@ xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant a nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RX_WOW # endif }; diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index 8b9e0881..40caf380 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -38,6 +38,12 @@ MultiWorker::MultiWorker(ThreadHandle *handle) : Worker(handle) { m_memory = Mem::create(m_ctx, m_thread->algorithm(), N); + + const int flags = RANDOMX_FLAG_LARGE_PAGES | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT; + m_rx_vm = randomx_create_vm(static_cast(flags), nullptr, Workers::getDataset()); + if (!m_rx_vm) { + m_rx_vm = randomx_create_vm(static_cast(flags - RANDOMX_FLAG_LARGE_PAGES), nullptr, Workers::getDataset()); + } } @@ -45,6 +51,7 @@ template MultiWorker::~MultiWorker() { Mem::release(m_ctx, N, m_memory); + randomx_destroy_vm(m_rx_vm); } @@ -126,7 +133,14 @@ void MultiWorker::start() storeStats(); } - m_thread->fn(m_state.job.algorithm().variant())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height()); + const xmrig::Variant v = m_state.job.algorithm().variant(); + if (v == xmrig::VARIANT_RX_WOW) { + Workers::updateDataset(m_state.job.seed_hash(), m_totalWays); + randomx_calculate_hash(m_rx_vm, m_state.blob, m_state.job.size(), m_hash); + } + else { + m_thread->fn(v)(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height()); + } for (size_t i = 0; i < N; ++i) { if (*reinterpret_cast(m_hash + (i * 32) + 24) < m_state.job.target()) { diff --git a/src/workers/MultiWorker.h b/src/workers/MultiWorker.h index 99d37e44..98acded9 100644 --- a/src/workers/MultiWorker.h +++ b/src/workers/MultiWorker.h @@ -31,6 +31,7 @@ #include "Mem.h" #include "net/JobResult.h" #include "workers/Worker.h" +#include "randomwow.h" class Handle; @@ -70,6 +71,8 @@ private: State m_pausedState; State m_state; uint8_t m_hash[N * 32]; + + randomx_vm* m_rx_vm; }; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 53990135..54373cc9 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -59,6 +59,11 @@ uv_mutex_t Workers::m_mutex; uv_rwlock_t Workers::m_rwlock; uv_timer_t *Workers::m_timer = nullptr; xmrig::Controller *Workers::m_controller = nullptr; +uv_rwlock_t Workers::m_rx_dataset_lock; +randomx_cache *Workers::m_rx_cache = nullptr; +randomx_dataset *Workers::m_rx_dataset = nullptr; +uint8_t Workers::m_rx_seed_hash[32] = {}; +std::atomic Workers::m_rx_dataset_init_thread_counter = 0; xmrig::Job Workers::job() @@ -187,6 +192,7 @@ void Workers::start(xmrig::Controller *controller) uv_mutex_init(&m_mutex); uv_rwlock_init(&m_rwlock); + uv_rwlock_init(&m_rx_dataset_lock); m_sequence = 1; m_paused = 1; @@ -356,3 +362,61 @@ void Workers::start(IWorker *worker) worker->start(); } + +void Workers::updateDataset(const uint8_t* seed_hash, const uint32_t num_threads) +{ + // Check if we need to update cache and dataset + if (memcmp(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)) == 0) + return; + + const uint32_t thread_id = m_rx_dataset_init_thread_counter++; + LOG_NOTICE("Thread %u started updating RandomX dataset", thread_id); + + // Wait for all threads to get here + do { + std::this_thread::yield(); + } while (m_rx_dataset_init_thread_counter.load() != num_threads); + + // One of the threads updates cache + uv_rwlock_wrlock(&m_rx_dataset_lock); + if (memcmp(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)) != 0) { + memcpy(m_rx_seed_hash, seed_hash, sizeof(m_rx_seed_hash)); + randomx_init_cache(m_rx_cache, m_rx_seed_hash, sizeof(m_rx_seed_hash)); + } + uv_rwlock_wrunlock(&m_rx_dataset_lock); + + // All threads update dataset + const uint32_t a = (randomx_dataset_item_count() * thread_id) / num_threads; + const uint32_t b = (randomx_dataset_item_count() * (thread_id + 1)) / num_threads; + randomx_init_dataset(m_rx_dataset, m_rx_cache, a, b - a); + + LOG_NOTICE("Thread %u finished updating RandomX dataset", thread_id); + + // Wait for all threads to complete + --m_rx_dataset_init_thread_counter; + do { + std::this_thread::yield(); + } while (m_rx_dataset_init_thread_counter.load() != 0); +} + +randomx_dataset* Workers::getDataset() +{ + if (m_rx_dataset) + return m_rx_dataset; + + uv_rwlock_wrlock(&m_rx_dataset_lock); + if (!m_rx_dataset) { + randomx_dataset* dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES); + if (!dataset) { + dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT); + } + m_rx_cache = randomx_alloc_cache(static_cast(RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES)); + if (!m_rx_cache) { + m_rx_cache = randomx_alloc_cache(RANDOMX_FLAG_JIT); + } + m_rx_dataset = dataset; + } + uv_rwlock_wrunlock(&m_rx_dataset_lock); + + return m_rx_dataset; +} diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 5b084fc2..3f6e307d 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -34,6 +34,7 @@ #include "base/net/stratum/Job.h" #include "net/JobResult.h" #include "rapidjson/fwd.h" +#include "randomwow.h" class Hashrate; @@ -72,6 +73,9 @@ public: static void threadsSummary(rapidjson::Document &doc); # endif + static void updateDataset(const uint8_t* seed_hash, uint32_t num_threads); + static randomx_dataset* getDataset(); + private: static void onReady(void *arg); static void onResult(uv_async_t *handle); @@ -114,6 +118,12 @@ private: static uv_rwlock_t m_rwlock; static uv_timer_t *m_timer; static xmrig::Controller *m_controller; + + static uv_rwlock_t m_rx_dataset_lock; + static randomx_cache *m_rx_cache; + static randomx_dataset *m_rx_dataset; + static uint8_t m_rx_seed_hash[32]; + static std::atomic m_rx_dataset_init_thread_counter; };