diff --git a/CHANGELOG.md b/CHANGELOG.md index 6242bbee..e71916fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# v6.16.3 +- [#2778](https://github.com/xmrig/xmrig/pull/2778) Fixed `READY threads X/X` display after algorithm switching. +- [#2782](https://github.com/xmrig/xmrig/pull/2782) Updated GhostRider documentation. +- [#2815](https://github.com/xmrig/xmrig/pull/2815) Fixed `cn-heavy` in 32-bit builds. +- [#2827](https://github.com/xmrig/xmrig/pull/2827) GhostRider: set correct priority for helper threads. +- [#2837](https://github.com/xmrig/xmrig/pull/2837) RandomX: don't restart mining threads when the seed changes. +- [#2848](https://github.com/xmrig/xmrig/pull/2848) GhostRider: added support for `client.reconnect` method. +- [#2856](https://github.com/xmrig/xmrig/pull/2856) Fix for short responses from some Raptoreum pools. +- [#2873](https://github.com/xmrig/xmrig/pull/2873) Fixed GhostRider benchmark on single-core systems. +- [#2882](https://github.com/xmrig/xmrig/pull/2882) Fixed ARMv7 compilation. +- [#2893](https://github.com/xmrig/xmrig/pull/2893) KawPow OpenCL: use separate UV loop for building programs. + # v6.16.2 - [#2751](https://github.com/xmrig/xmrig/pull/2751) Fixed crash on CPUs supporting VAES and running GCC-compiled xmrig. - [#2761](https://github.com/xmrig/xmrig/pull/2761) Fixed broken auto-tuning in GCC Windows build. diff --git a/README.md b/README.md index 30c37197..36e3740c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![GitHub stars](https://img.shields.io/github/stars/xmrig/xmrig.svg)](https://github.com/MoneroOcean/xmrig/stargazers) [![GitHub forks](https://img.shields.io/github/forks/xmrig/xmrig.svg)](https://github.com/MoneroOcean/xmrig/network) -XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and AstroBWT unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD. +XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight, AstroBWT and [GhostRider](https://github.com/xmrig/xmrig/tree/master/src/crypto/ghostrider#readme) unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD. ## Mining backends - **CPU** (x64/ARMv8) diff --git a/scripts/rtm_ghostrider_example.cmd b/scripts/rtm_ghostrider_example.cmd index f4c4342e..8b1f4999 100644 --- a/scripts/rtm_ghostrider_example.cmd +++ b/scripts/rtm_ghostrider_example.cmd @@ -16,5 +16,8 @@ :: Smaller pools also often have smaller fees/payout limits. cd %~dp0 +:: Use this command line to connect to non-SSL port xmrig.exe -a gr -o raptoreumemporium.com:3008 -u WALLET_ADDRESS -p x +:: Or use this command line to connect to an SSL port +:: xmrig.exe -a gr -o rtm.suprnova.cc:4273 --tls -u WALLET_ADDRESS -p x pause diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index 849728b2..d0cc67a3 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -76,12 +76,13 @@ public: { m_workersMemory.clear(); m_hugePages.reset(); - m_memory = memory; - m_started = 0; - m_errors = 0; - m_threads = threads.size(); - m_ways = 0; - m_ts = Chrono::steadyMSecs(); + m_memory = memory; + m_started = 0; + m_totalStarted = 0; + m_errors = 0; + m_threads = threads.size(); + m_ways = 0; + m_ts = Chrono::steadyMSecs(); } inline bool started(IWorker *worker, bool ready) diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index 232940f5..6901426b 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -100,7 +100,7 @@ xmrig::CpuWorker::CpuWorker(size_t id, const CpuLaunchData &data) : } # ifdef XMRIG_ALGO_GHOSTRIDER - m_ghHelper = ghostrider::create_helper_thread(affinity(), data.affinities); + m_ghHelper = ghostrider::create_helper_thread(affinity(), data.priority, data.affinities); # endif } @@ -134,7 +134,7 @@ void xmrig::CpuWorker::allocateRandomX_VM() RxDataset *dataset = Rx::dataset(m_job.currentJob(), node()); while (dataset == nullptr) { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); if (Nonce::sequence(Nonce::CPU) == 0) { return; @@ -256,7 +256,7 @@ void xmrig::CpuWorker::start() while (Nonce::sequence(Nonce::CPU) > 0) { if (Nonce::isPaused()) { do { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); } while (Nonce::isPaused() && Nonce::sequence(Nonce::CPU) > 0); diff --git a/src/backend/opencl/runners/tools/OclKawPow.cpp b/src/backend/opencl/runners/tools/OclKawPow.cpp index 40b2b979..a7e8df3a 100644 --- a/src/backend/opencl/runners/tools/OclKawPow.cpp +++ b/src/backend/opencl/runners/tools/OclKawPow.cpp @@ -153,9 +153,35 @@ static KawPowCache cache; #define mix_dst() ("mix[" + std::to_string(mix_seq_dst[(mix_seq_dst_cnt++) % KPHash::REGS]) + "]") #define mix_cache() ("mix[" + std::to_string(mix_seq_cache[(mix_seq_cache_cnt++) % KPHash::REGS]) + "]") +class KawPowBaton : public Baton +{ +public: + inline KawPowBaton(const IOclRunner& runner, uint64_t period, uint32_t worksize) : + runner(runner), + period(period), + worksize(worksize) + {} + + const IOclRunner& runner; + const uint64_t period; + const uint32_t worksize; +}; + + class KawPowBuilder { public: + ~KawPowBuilder() + { + if (m_loop) { + uv_async_send(&m_shutdownAsync); + uv_thread_join(&m_loopThread); + delete m_loop; + } + } + + void build_async(const IOclRunner& runner, uint64_t period, uint32_t worksize); + cl_kernel build(const IOclRunner &runner, uint64_t period, uint32_t worksize) { std::lock_guard lock(m_mutex); @@ -368,40 +394,54 @@ private: st.jcong = 69069 * st.jcong + 1234567; return ((MWC ^ st.jcong) + st.jsr); } -}; +private: + uv_loop_t* m_loop = nullptr; + uv_thread_t m_loopThread = {}; + uv_async_t m_shutdownAsync = {}; -class KawPowBaton : public Baton -{ -public: - inline KawPowBaton(const IOclRunner &runner, uint64_t period, uint32_t worksize) : - runner(runner), - period(period), - worksize(worksize) - {} - - const IOclRunner &runner; - const uint64_t period; - const uint32_t worksize; + static void loop(void* data) + { + KawPowBuilder* builder = static_cast(data); + uv_run(builder->m_loop, UV_RUN_DEFAULT); + uv_loop_close(builder->m_loop); + } }; static KawPowBuilder builder; +void KawPowBuilder::build_async(const IOclRunner& runner, uint64_t period, uint32_t worksize) +{ + std::lock_guard lock(m_mutex); + + if (!m_loop) { + m_loop = new uv_loop_t{}; + uv_loop_init(m_loop); + uv_async_init(m_loop, &m_shutdownAsync, [](uv_async_t* handle) { uv_close(reinterpret_cast(handle), nullptr); }); + uv_thread_create(&m_loopThread, loop, this); + } + + KawPowBaton* baton = new KawPowBaton(runner, period, worksize); + + uv_queue_work(m_loop, &baton->req, + [](uv_work_t* req) { + KawPowBaton* baton = static_cast(req->data); + builder.build(baton->runner, baton->period, baton->worksize); + }, + [](uv_work_t* req, int) { delete static_cast(req->data); } + ); +} + + cl_kernel OclKawPow::get(const IOclRunner &runner, uint64_t height, uint32_t worksize) { const uint64_t period = height / KPHash::PERIOD_LENGTH; - KawPowBaton* baton = new KawPowBaton(runner, period + 1, worksize); - - uv_queue_work(uv_default_loop(), &baton->req, - [](uv_work_t *req) { - KawPowBaton* baton = static_cast(req->data); - builder.build(baton->runner, baton->period, baton->worksize); - }, - [](uv_work_t *req, int) { delete static_cast(req->data); } - ); + if (!cache.search(runner, period + 1, worksize)) { + builder.build_async(runner, period + 1, worksize); + } cl_kernel kernel = cache.search(runner, period, worksize); if (kernel) { diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 0d9d46c6..186e9a9c 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef XMRIG_FEATURE_TLS @@ -662,7 +663,7 @@ void xmrig::Client::parse(char *line, size_t len) LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast(len), line); - if (len < 32 || line[0] != '{') { + if (len < 22 || line[0] != '{') { if (!isQuiet()) { LOG_ERR("%s " RED("JSON decode failed"), tag()); } @@ -685,12 +686,48 @@ void xmrig::Client::parse(char *line, size_t len) const auto &id = Json::getValue(doc, "id"); const auto &error = Json::getValue(doc, "error"); + const char *method = Json::getString(doc, "method"); + + if (method && strcmp(method, "client.reconnect") == 0) { + const auto ¶ms = Json::getValue(doc, "params"); + if (!params.IsArray()) { + LOG_ERR("%s " RED("invalid client.reconnect notification: params is not an array"), tag()); + return; + } + + auto arr = params.GetArray(); + + if (arr.Empty()) { + LOG_ERR("%s " RED("invalid client.reconnect notification: params array is empty"), tag()); + return; + } + + if (arr.Size() != 2) { + LOG_ERR("%s " RED("invalid client.reconnect notification: params array has wrong size"), tag()); + return; + } + + if (!arr[0].IsString()) { + LOG_ERR("%s " RED("invalid client.reconnect notification: host is not a string"), tag()); + return; + } + + if (!arr[1].IsString()) { + LOG_ERR("%s " RED("invalid client.reconnect notification: port is not a string"), tag()); + return; + } + + std::stringstream s; + s << arr[0].GetString() << ":" << arr[1].GetString(); + LOG_WARN("%s " YELLOW("client.reconnect to %s"), tag(), s.str().c_str()); + setPoolUrl(s.str().c_str()); + return reconnect(); + } if (id.IsInt64()) { return parseResponse(id.GetInt64(), Json::getValue(doc, "result"), error); } - const char *method = Json::getString(doc, "method"); if (!method) { return; } diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index e1f5d756..300db138 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -84,6 +84,7 @@ protected: inline const char *url() const { return m_pool.url(); } inline const String &rpcId() const { return m_rpcId; } inline void setRpcId(const char *id) { m_rpcId = id; } + inline void setPoolUrl(const char *url) { m_pool.setUrl(url); } virtual bool parseLogin(const rapidjson::Value &result, int *code); virtual void login(); diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index b4a68dcc..5df020d5 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -113,6 +113,7 @@ public: inline int zmq_port() const { return m_zmqPort; } inline uint64_t pollInterval() const { return m_pollInterval; } inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; } + inline void setUrl(const char *url) { m_url = Url(url); } inline void setPassword(const String &password) { m_password = password; } inline void setProxy(const ProxyUrl &proxy) { m_proxy = proxy; } inline void setRigId(const String &rigId) { m_rigId = rigId; } diff --git a/src/config.json b/src/config.json index 7d489d3d..834c2ba5 100644 --- a/src/config.json +++ b/src/config.json @@ -97,6 +97,10 @@ "ciphersuites": null, "dhparam": null }, + "dns": { + "ipv6": false, + "ttl": 30 + }, "user-agent": null, "verbose": 0, "watch": true, diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index 78ed1f6a..8bfccd64 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -553,7 +553,13 @@ void xmrig::Miner::setJob(const Job &job, bool donate) # ifdef XMRIG_ALGO_RANDOMX if (job.algorithm().family() == Algorithm::RANDOM_X && !Rx::isReady(job)) { - stop(); + if (d_ptr->algorithm != job.algorithm()) { + stop(); + } + else { + Nonce::pause(true); + Nonce::touch(); + } } # endif diff --git a/src/crypto/cn/CryptoNight_x86.h b/src/crypto/cn/CryptoNight_x86.h index 961afaac..6ed88e94 100644 --- a/src/crypto/cn/CryptoNight_x86.h +++ b/src/crypto/cn/CryptoNight_x86.h @@ -821,7 +821,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si int64_t d5; -# if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 8)) +# if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 8)) || !defined(XMRIG_64_BIT) d5 = d | 5; # else // Workaround for stupid GCC which converts to 32 bit before doing "| 5" and then converts back to 64 bit diff --git a/src/crypto/cn/sse2neon.h b/src/crypto/cn/sse2neon.h index e41d8c18..36bc1685 100644 --- a/src/crypto/cn/sse2neon.h +++ b/src/crypto/cn/sse2neon.h @@ -344,7 +344,7 @@ typedef union ALIGN_STRUCT(16) SIMDVec { // Older gcc does not define vld1q_u8_x4 type #if defined(__GNUC__) && !defined(__clang__) && \ - ((__GNUC__ <= 10 && defined(__arm__)) || \ + ((__GNUC__ <= 11 && defined(__arm__)) || \ (__GNUC__ == 10 && __GNUC_MINOR__ < 3 && defined(__aarch64__)) || \ (__GNUC__ <= 9 && defined(__aarch64__))) FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p) diff --git a/src/crypto/ghostrider/README.md b/src/crypto/ghostrider/README.md index b1614abd..4a34f076 100644 --- a/src/crypto/ghostrider/README.md +++ b/src/crypto/ghostrider/README.md @@ -6,12 +6,12 @@ No tuning is required - auto-config works well on most CPUs! ### Sample command line (non-SSL port) ``` -xmrig -a gr -o raptoreumemporium.com:3008 -u WALLET_ADDRESS +xmrig -a gr -o raptoreumemporium.com:3008 -u WALLET_ADDRESS -p x ``` ### Sample command line (SSL port) ``` -xmrig -a gr -o us.flockpool.com:5555 --tls -u WALLET_ADDRESS +xmrig -a gr -o rtm.suprnova.cc:4273 --tls -u WALLET_ADDRESS -p x ``` You can use **rtm_ghostrider_example.cmd** as a template and put pool URL and your wallet address there. The general XMRig documentation is available [here](https://xmrig.com/docs/miner). diff --git a/src/crypto/ghostrider/ghostrider.cpp b/src/crypto/ghostrider/ghostrider.cpp index 9f403d3a..505378c0 100644 --- a/src/crypto/ghostrider/ghostrider.cpp +++ b/src/crypto/ghostrider/ghostrider.cpp @@ -166,7 +166,7 @@ static struct AlgoTune struct HelperThread { - HelperThread(hwloc_bitmap_t cpu_set, bool is8MB) : m_cpuSet(cpu_set), m_is8MB(is8MB) + HelperThread(hwloc_bitmap_t cpu_set, int priority, bool is8MB) : m_cpuSet(cpu_set), m_priority(priority), m_is8MB(is8MB) { uv_mutex_init(&m_mutex); uv_cond_init(&m_cond); @@ -241,6 +241,8 @@ struct HelperThread } } + Platform::setThreadPriority(m_priority); + uv_mutex_lock(&m_mutex); m_ready = true; @@ -268,6 +270,7 @@ struct HelperThread volatile bool m_ready = false; volatile bool m_finished = false; hwloc_bitmap_t m_cpuSet = {}; + int m_priority = -1; bool m_is8MB = false; std::thread* m_thread = nullptr; @@ -290,13 +293,14 @@ void benchmark() hwloc_obj_t pu = hwloc_get_pu_obj_by_os_index(topology, thread_index1); hwloc_obj_t pu2; hwloc_get_closest_objs(topology, pu, &pu2, 1); - uint32_t thread_index2 = pu2->os_index; + uint32_t thread_index2 = pu2 ? pu2->os_index : thread_index1; if (thread_index2 < thread_index1) { std::swap(thread_index1, thread_index2); } Platform::setThreadAffinity(thread_index1); + Platform::setThreadPriority(3); constexpr uint32_t N = 1U << 21; @@ -375,7 +379,7 @@ void benchmark() hwloc_bitmap_t helper_set = hwloc_bitmap_alloc(); hwloc_bitmap_set(helper_set, thread_index2); - HelperThread* helper = new HelperThread(helper_set, false); + HelperThread* helper = new HelperThread(helper_set, 3, false); for (uint32_t algo = 0; algo < 6; ++algo) { for (uint64_t step : { 1, 2, 4}) { @@ -465,7 +469,7 @@ static inline bool findByType(hwloc_obj_t obj, hwloc_obj_type_t type, func lambd } -HelperThread* create_helper_thread(int64_t cpu_index, const std::vector& affinities) +HelperThread* create_helper_thread(int64_t cpu_index, int priority, const std::vector& affinities) { #ifndef XMRIG_ARM hwloc_bitmap_t helper_cpu_set = hwloc_bitmap_alloc(); @@ -520,7 +524,7 @@ HelperThread* create_helper_thread(int64_t cpu_index, const std::vector }); if (hwloc_bitmap_weight(helper_cpu_set) > 0) { - return new HelperThread(helper_cpu_set, is8MB); + return new HelperThread(helper_cpu_set, priority, is8MB); } } } @@ -761,7 +765,7 @@ void hash_octa(const uint8_t* data, size_t size, uint8_t* output, cryptonight_ct void benchmark() {} -HelperThread* create_helper_thread(int64_t, const std::vector&) { return nullptr; } +HelperThread* create_helper_thread(int64_t, int, const std::vector&) { return nullptr; } void destroy_helper_thread(HelperThread*) {} diff --git a/src/crypto/ghostrider/ghostrider.h b/src/crypto/ghostrider/ghostrider.h index 081e4f6f..e6c08df1 100644 --- a/src/crypto/ghostrider/ghostrider.h +++ b/src/crypto/ghostrider/ghostrider.h @@ -39,7 +39,7 @@ namespace ghostrider struct HelperThread; void benchmark(); -HelperThread* create_helper_thread(int64_t cpu_index, const std::vector& affinities); +HelperThread* create_helper_thread(int64_t cpu_index, int priority, const std::vector& affinities); void destroy_helper_thread(HelperThread* t); void hash_octa(const uint8_t* data, size_t size, uint8_t* output, cryptonight_ctx** ctx, HelperThread* helper, bool verbose = true); diff --git a/src/crypto/rx/RxQueue.cpp b/src/crypto/rx/RxQueue.cpp index 86b63327..489a7bc7 100644 --- a/src/crypto/rx/RxQueue.cpp +++ b/src/crypto/rx/RxQueue.cpp @@ -154,6 +154,8 @@ void xmrig::RxQueue::backgroundInit() continue; } + // Update seed here again in case there was more than one item in the queue + m_seed = item.seed; m_state = STATE_IDLE; m_async->send(); } diff --git a/src/version.h b/src/version.h index 2596a8a9..c9226587 100644 --- a/src/version.h +++ b/src/version.h @@ -22,7 +22,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "6.16.2-mo2" +#define APP_VERSION "6.16.3-mo1" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2021 xmrig.com" @@ -30,7 +30,7 @@ #define APP_VER_MAJOR 6 #define APP_VER_MINOR 16 -#define APP_VER_PATCH 2 +#define APP_VER_PATCH 3 #ifdef _MSC_VER # if (_MSC_VER >= 1920)